logo
Ask your Symfony questions! Pay money and get answers fast! (more info)

Warning: Please do not give out any FTP or ssh credentials to anyone, unless you trust them completely. Giving out login details is dangerous.

If the asker does not get an answer then they have 10 days to request a refund.

$25
Themes in Symfony 2

Hi I am trying to create themes for a multitenant application in Symfony2. This is simple to do with Twig:

$loader = new Twig_Loader_Filesystem(array($templateDir1, $templateDir2))


But I'm not sure how to do this in Symfony2. I just need Symfony to check app/Resources/themes/{current theme} for the view.html.twig file, and then check the bundle for a default view.html.twig file.

I found the Liip Theme bundle but it is far more complex than I need (cookies, service config, etc). I just need to pass a theme value to Symfony's render function, and have Symfony check app/Resources/themes/{current theme} and then check the bundle Resources if there is no file in the theme. There's an element of this in the Liip bundle, but I'm not sure of the best way to implement this in a more direct way. Should I override the render function, or is there a way to set this through Twig in Symfony? Thanks for any help!

https://github.com/liip/LiipThemeBundle/blob/master/Locator/FileLocator.php

  foreach ($bundles as $bundle) {
$checkPaths = array();
if ($dir) {
$checkPaths[] = $dir.'/themes/'.$this->activeTheme.'/'.$bundle->getName().$overridePath;
$checkPaths[] = $dir.'/'.$bundle->getName().$overridePath;
}
$checkPaths[] = $bundle->getPath() . '/Resources/themes/'.$this->activeTheme.substr($path, 15);
foreach ($checkPaths as $checkPath) {
if (file_exists($file = $checkPath)) {
if (null !== $resourceBundle) {
throw new \RuntimeException(sprintf('"%s" resource is hidden by a resource from the "%s" derived bundle. Create a "%s" file to override the bundle resource.',
$file,
$resourceBundle,
$checkPath
));
}

if ($first) {
return $file;
}
$files[] = $file;
}
}

LearningSymfony | 08/02/11 at 6:49am Edit
Tutorial: How to assign prize money


(5) Responses

See a threaded view of answers?

Warning: Please do not give out any FTP or ssh credentials to anyone, unless you trust them completely. Giving out login details is dangerous.

  • avatar
    Last edited:
    08/03/11
    9:59am
    Jakub Zalas says:

    What's wrong with setting a theme name on the active theme service?

     $this->container->get('liip_theme.active_theme')->setName('my_theme');


    You might overload render() method but what for? render() method is a shortcut for:

    $this->container->get('templating')->renderResponse($view, $parameters, $response)


    It operates on a templating service.

    You might also use your own templating service which would accept liip_theme.active_theme service as a parameter. This way you could hide theme choosing details in the templating service. However, I don't see how it could be useful.

    What exactly are you trying to achieve?

    Edit: added more info about the way Symfony uses Twig.

    Twig is integrated in Symfony with TwigBundle. All the services are defined in the vendor/symfony/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml. Reviewing this file should clarify a lot.

    You'll notice that Symfony uses Symfony\Bundle\TwigBundle\Loader\FilesystemLoader class instead of Twig_Loader_Filesystem (actually first extends the later). To change this class you'd need to change the value of twig.loader.class parameter.

    Option 1

    One of your options might be changing the class back to Twig_Loader_Filesystem but I'm not sure if it's the best one.

    You can try it if it's sufficient for you than it's the best (and simplest).

    Option 2

    Symfony's FilesystemLoader has different constructor than original Twig_Loader_Filesystem:

    public function __construct(FileLocatorInterface $locator, TemplateNameParserInterface $parser);


    the service definition looks like this:


    <service id="twig.loader" class="%twig.loader.class%">
    <argument type="service" id="templating.locator" />
    <argument type="service" id="templating.name_parser" />
    </service>


    You can overload arguments passed to it by changing service definitions.

    The service you're looking for is either templating.locator or file.locator.
    You'll find their definitions in the vendor/symfony/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating.xml and vendor/symfony/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml files.

    Did I help or do you need further info?

    Previous versions of this answer: 08/02/11 at 4:10pm | 08/03/11 at 9:51am | 08/03/11 at 9:55am | 08/03/11 at 9:57am | 08/03/11 at 9:59am

  • avatar
    Last edited:
    08/05/11
    6:19am
    David Joos says:

    Hi LearningSymfony,

    I'm no expert in Symfony2, as currently I mainly work on 1.3 and 1.4 projects and I'm still getting up-to-speed with this new toy myself... :-)

    "I just need to pass a theme value to Symfony's render function, and have Symfony check app/Resources/themes/{current theme} and then check the bundle Resources if there is no file in the theme."
    What about the following approach? Use your bundle templates:
    {% extends current_theme.'::base.html.twig' %}
    ...where "current_theme" (eg. 'ThemesXBundle') is based upon a setting on eg. the user attribute? In that way your bundle template will be derived from a certain theme 'base', in this case ThemesXBundle's base.html.twig. This seems to be the easiest way to implement it, by actually not changing anything to the core code or setup.

    Here's something interesting in the Symfony documentation as well: http://symfony.com/doc/2.0/book/templating.html#overriding-bundle-templates

    Hope this helps!

  • avatar
    Last edited:
    08/03/11
    5:58am
    LearningSymfony says:

    Thank you for your reply. My goal is actually really simple, I just don't know how to best accomplish it in Symfony2.

    When Symfony2 goes to render templates, it checks /app/Resources/views and then path/to/bundle/Resources/views/.

    Instead, I want to check /app/Resources/themes/{some theme} and then the normal path/to/bundle/Resources/views/

    Twig provides with this with "Twig_Loader_Filesystem" but I'm not sure how to set that value in Symfony.

    Thanks!

  • avatar
    Last edited:
    09/15/11
    8:38am
    LearningSymfony says:

    All of these ideas are good, but I think this is the most straightforward approach. Thank you!

  • avatar
    Last edited:
    09/15/11
    8:41am
    LearningSymfony says:

    It isn't clear how to award the prize $. Ideally I could split it between both answers, both are thoughtful ways to solve the problem. I'm contacting site support on this, thanks.

This question has expired.





Current status of this question: Community pot



Please log in to add additional discourse to this page.





Warning: Please do not give out any FTP or ssh credentials to anyone, unless you trust them completely. Giving out login details is dangerous.

If the asker does not get an answer then they have 10 days to request a refund.