2

I have a symfony project with multiple skins/templates that have their own routes, does anyone have an idea for a correct setup?

  • Every skin/template is its own bundle, since its not just skins and assets, but maybe also services that might exist in some skins.
  • Hostname decides the skin.
  • Using a custom RouteLoader to load the route.yml of the target bundle.

The custom RouteLoader does the job--but the generated routes are getting cached, and as far as i understand, there is no way to prevent route caching.

Some suggestions are:

  • Creating a /{dynamic} route, so manually form routes.. But i dont want to throw away that piece of functionality of the router, or refactor the entire project..
  • Prefix the routes with the template identifier. This would require me to load all route.yml files, which isnt possible since their share paths.

Anyone? I cant go with multiple projects really, the amount of skins will be around 20-30~.

The reason for this setup is because its a target of Content-as-a-Service .. service, multiple clients use the project as a platform, and their setting decides which templates gets used.

Alt-rock ninja
  • 165
  • 1
  • 13

3 Answers3

1

It sounds like you want to dynamically load bundles based on the host name? Not going to happen with Symfony 2 because of the caching. Especially the services.

Your best bet is to setup an app for each skin and then do some url majic to execute the desired app.php file. Clearly since you have defined a bundle for each skin then there is a finite number so having multiple apps should not be much or a burden.

It's possible that you might be able to work around the template issue. You would still need to load all your skin bundles but you could futz around with the template names or paths and probably get something to work.

But services? Unless you start appending host names to service id's then I don't see any work around.

Cerad
  • 48,157
  • 8
  • 90
  • 92
  • I think you're right, too bad. Gonna have to fix some middleware and move on to a project-per-template. – Alt-rock ninja Nov 06 '15 at 16:25
  • I think you can make use of Modular Routing in Symfony, that allows you to load specific routes as you need: http://www.tomasvotruba.cz/blog/2016/02/25/modular-routing-in-symfony – Tomas Votruba Feb 27 '16 at 03:24
1

I think it's possible to load dynamically twig templates depending of your user by adding a listener on kernel requests.

I can give you a piece of code which, I hope, could help you :

        /**
         * On Kernel Request triggers the request to get the user config
         * then adds TWIG paths depending on user TemplateName
         */
        public function onKernelRequest(GetResponseEvent $event)
        {
            if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
                return;
            }
            //$userConfig = Retrieve your user config
            if (null === $userConfig->getTemplateConfig()->getTemplate()->getName()) 
            {
                throw new TemplateConfigNotFoundException(sprintf("Could not find TemplateConfig for %s", $userConfig->getName()));
            }

            $template = $userConfig->getTemplateConfig()->getTemplate()->getName();

            $path = sprintf('%s/../../%s/Resources/views', __DIR__, ucfirst($template));

            if (!is_dir($path)) {
                throw new TemplateNotFoundException(sprintf("Could not find template %s", $template));
            }

            $this->loader->prependPath($path);
            $this->loader->addPath(sprintf('%s/../Resources/views/Default', __DIR__));
       }

With $this->loader defined as \Twig_Loader_Filesystem in your Listener constructor

Hope it can give you a clue

Julien Bourdic
  • 1,398
  • 1
  • 12
  • 29
0

Symfony2 already supports host aware routing out-of-the-box, like this:

website_customer_1:
    path:     /
    host:     customer1.example.com
    defaults: { _controller: Customer1Bundle:Main:startPage, theme: template1 }

website_customer_2:
    path:     /
    host:     customer2.example.com
    defaults: { _controller: Customer1Bundle:Main:startPage, theme: template2 }
mblaettermann
  • 1,916
  • 2
  • 17
  • 23
  • I shouldve been more clear, sorry. With "hostname decides the skin", i mean: there is a database relation that tells which client uses which skin. So it needs atleast 1 database query to figure out which bundle to use.. There is no direct link between hostnames and bundles :( – Alt-rock ninja Nov 06 '15 at 15:56
  • I could actually solve it this way if i use parameters as the host option, but i just need to dynamically fill those parameters – Alt-rock ninja Nov 06 '15 at 15:58
  • Then maybe an additional listener after the routing event will do the trick? Or even you own ControllerResolverListener? It's not clear if you duplcate all the controllers to the customers bundles? – mblaettermann Nov 06 '15 at 16:06
  • Tried it, but then youre dealing with the parameter bag being frozen, cant adjust it. Only possible before compiling the container. Then i have to start dealing with the services... I think im stuck with separate projects for every skin/ – Alt-rock ninja Nov 06 '15 at 16:24