Skip to content

Instantly share code, notes, and snippets.

@raphox
Last active November 7, 2019 16:01
Show Gist options
  • Save raphox/afcdef639981d38baac8 to your computer and use it in GitHub Desktop.
Save raphox/afcdef639981d38baac8 to your computer and use it in GitHub Desktop.
Symfony script to create dynamic routes to hotsite or subdomains #php #subdomain #routes #dynamic
<?php
namespace Acme\HotsiteBundle\EventListener;
use Acme\HotsiteBundle\Controller\HotsiteSignedController;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\RedirectResponse;
class HotsiteListener
{
private $session;
private $twig;
private $em;
public function __construct(Session $session, \Twig_Environment $twig, \Doctrine\ORM\EntityManager $em)
{
$this->session = $session;
$this->twig = $twig;
$this->em = $em;
}
public function onKernelController(FilterControllerEvent $event)
{
$controller = $event->getController();
$request = $event->getRequest();
/*
* $controller passed can be either a class or a Closure.
* This is not usual in Symfony but it may happen.
* If it is a class, it comes in array format
*/
if (!is_array($controller)) {
return;
}
if ($controller[0] instanceof HotsiteSignedController) {
if ($request->get('hotsite')) {
$this->session->set('hotsite_resource', $request->get('hotsite'));
}
$hotsite = $this->session->get('hotsite_resource');
if ($hotsite) {
$company = $this->em->getRepository('AcmeCompanyBundle:Profile')->findOneBy(array('hotsite' => $hotsite));
$this->twig->addGlobal('company', $company);
}
}
}
}
<?php
namespace Acme\HotsiteBundle\Routing;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\Config\Loader\LoaderResolverInterface;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
class HotsiteLoader implements LoaderInterface
{
private $loaded = false;
private $em;
public function __construct(\Doctrine\ORM\EntityManager $em)
{
$this->em = $em;
}
public function load($resource, $type = null)
{
if (true === $this->loaded) {
throw new \RuntimeException('Do not add the "hotsite" loader twice');
}
$routes = new RouteCollection();
// prepare a new route
$path = '/{hotsite}';
$defaults = array(
'_controller' => 'AcmeHotsiteBundle:Default:index',
);
$query = $this->em->createQueryBuilder('p')
->select('p.hotsite')
->from('AcmeCompanyBundle:Profile', 'p')
->where('p.hotsite IS NOT NULL and p.hotsite != \'\'')
->getQuery();
$companies = $query->getResult();
$hotsites = array();
foreach ($companies as $company) {
$hotsites[] = $company["hotsite"];
}
if (count($hotsites) <= 0) {
return $routes;
}
$requirements = array(
'hotsite' => implode("|", str_replace('.', '\.', $hotsites)), // my hotsite string is validate with /^$|[a-z0-9.-]/i
);
$route = new Route($path, $defaults, $requirements);
// add the new route to the route collection:
$routeName = 'acme_hotsite';
$routes->add($routeName, $route);
// statics pages
$routes->add('acme_hotsite_about', new Route($path . '/about', array('_controller' => 'AcmeHotsiteBundle:Default:about'), $requirements));
$routes->add('acme_hotsite_opinions', new Route($path . '/opinions', array('_controller' => 'AcmeHotsiteBundle:Default:opinions'), $requirements));
$routes->add('acme_hotsite_questions', new Route($path . '/questions', array('_controller' => 'AcmeHotsiteBundle:Default:questions'), $requirements));
$routes->add('acme_hotsite_contact', new Route($path . '/contact', array('_controller' => 'AcmeHotsiteBundle:Default:contact'), $requirements));
$this->loaded = true;
return $routes;
}
public function supports($resource, $type = null)
{
return 'hotsite' === $type;
}
public function getResolver()
{
// needed, but can be blank, unless you want to load other resources
// and if you do, using the Loader base class is easier (see below)
}
public function setResolver(LoaderResolverInterface $resolver)
{
// same as above
}
}
<?php
namespace Acme\HotsiteBundle\EventListener;
use Symfony\Component\Filesystem\Filesystem;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\LifecycleEventArgs;
// for Doctrine 2.4: Doctrine\Common\Persistence\Event\LifecycleEventArgs;
use Acme\CompanyBundle\Entity\Profile as Company;
class HotsiteSubscriber implements EventSubscriber
{
private $root_dir;
public function __construct($root_dir)
{
$this->root_dir = $root_dir;
}
public function getSubscribedEvents()
{
return array(
'prePersist',
'preUpdate',
'preRemove',
);
}
public function preUpdate(LifecycleEventArgs $args)
{
if ($args->hasChangedField('hotsite')) {
$this->updateCacheRoutes($args);
}
}
public function prePersist(LifecycleEventArgs $args)
{
$this->updateCacheRoutes($args);
}
public function preRemove(LifecycleEventArgs $args)
{
$this->updateCacheRoutes($args);
}
public function updateCacheRoutes(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
if ($entity instanceof Company) {
$fs = new Filesystem();
$path = $this->root_dir . '/cache/prod';
$fs->remove(array(
$path . '/appProdUrlGenerator.php',
$path . '/appProdUrlMatcher.php',
));
}
}
}
parameters:
acme_hotsite.routing.hotsite_loader.class: Acme\HotsiteBundle\Routing\HotsiteLoader
services:
acme_hotsite.routing.hotsite_loader:
class: %acme_hotsite.routing.hotsite_loader.class%
arguments: [@doctrine.orm.entity_manager]
tags:
- { name: routing.loader }
acme_hotsite.signed.action_listener:
class: Acme\HotsiteBundle\EventListener\HotsiteListener
arguments: [@session, @twig, @doctrine.orm.entity_manager]
tags:
- { name: kernel.event_listener, event: kernel.controller, method: onKernelController }
acme_hotsite.routing.hotsite_subscriber:
class: Acme\HotsiteBundle\EventListener\HotsiteSubscriber
arguments: ['%kernel.root_dir%']
tags:
- { name: doctrine.event_subscriber, connection: default }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment