We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Setting templates dynamically in controller

Just starting to move an existing php project over to phalcon 1.2.6 and having some difficulty with volt templates. In the original project, layout choices are determined dynamically in the controller depending on login status and if logged in, the type of user (There are 2 types).

Examples of layout names being used are "one-column", "two-column" and "three-column" They are mostly the same. The difference is that each template has a content section that contains 1, 2 or 3 volt blocks to match the name.

If I declare extends at the top of my views like this {% extends "../layouts/two-column.phtml" %} That works fine.The blocks are recognised and everything is rendered as expected.

However I would like to determine the layout used from the controller. So in my controllers I've tried using $this->view->setMainView('two-column'); But doing that has no affect.

I think I must find a way to alter the extends "filename" value, but have been unable to do that by passing a string to the view and using it in the extends declaration.

If I leave the extends declaration out, then the blocks are not recognized.

Does anybody know of a way to handle a situation like this? Any ideas appreciated.

$this->view->setMainView("two-column"); 
//suggest you have your layout in app/views/two-column.phtml 

but

{% extends "../layouts/two-column.phtml" %}
//suggest you have your layout in app/views/layouts/two-column.phtml

Can you paste how you setup your view in DI, or try to copy app/views/layouts/two-column.phtml to app/views/two-column.phtml

I don't know about volt, but Twig (which is similar to volt) allows to use a variable or a ternary operator in the extends tag: https://twig.sensiolabs.org/doc/tags/extends.html#dynamic-inheritance

{% extends some_var %}
{# or #}
{% extends standalone ? "minimum.html" : "base.html" %}
edited Mar '14

Hi Karol. I think the view setup is working but since you asked, here is a copy

The view setup

    $di->set('view', function() use ($config) {
        $view = new Phalcon\Mvc\View();

        $view->setViewsDir(APPLICATION_PATH . $config->application->viewsDir);
        $view->setLayoutsDir('/../layouts/');

        $view->registerEngines(array(
            '.phtml' => function($view, $di) use ($config) {
                            $volt = new \Phalcon\Mvc\View\Engine\Volt($view, $di);
                            $volt->setOptions(array(
                                'compiledPath' => APPLICATION_PATH . $config->application->compiledDir,
                                'stat' => true,
                                'compileAlways' => (bool)$config->application->compileAlways,
                            ));
                            return $volt;
                        }
        ));
        return $view;
    });

and the prod config that goes with it

    [application]
    ; relative to APPLICATION_PATH
    controllersDir = /controllers/
    modelsDir      = /models/
    viewsDir       = /views/scripts/

    ; relative to viewsDr
    layoutsDir     = /../layouts/

    baseUri        = /
    compiledDir    = /../data/volt/
    compileAlways  = 0

Hi maxgalbu, Yes, I think Twig does allow for that. Which makes me wonder whether we should be using Twig, or stick with Volt in the hope that support will be added in the not too distant future

Thanks for your input guys. FYI we're going to stick with volt for now and just declare the layout extension in each view.