Search code examples
zend-frameworkmezziozf3

ZF3: set terminal / render view without layout (Zend-Expressive)


I have installed the skelleton app from ZF3 'zend-expressive'. In the routing config I have configured a few routes. Some of these routes should return a response without the layout. In ZF2 I simply used the ViewModel on which you could call "setTerminal". But now the ViewModel is not directy available in the Action, as it is nested as private property of the ZendViewRenderer. I cannot figure out how I can set the terminal, so the output is rendered without layout.

I have tried various options in the routing configuration, such as adding keys 'terminal', 'terminate' and 'may_terminate' with value true. Also have tried to make a seperate Factory, but ended up with the same problem that I cannot reach the ViewModel.. It also did not work to make a seperate ViewModel in the Action, when I setTerminal on true, and pass the object as 2nd parameter in the 'render' method of the ZendViewRenderer object, it fails when passing 'renderModal' of the same object: "Cannot render; encountered a child marked terminal"..

There must be a simple configuration that I am overlooking, so my question is. Does anyone know how I can set the view on terminal?

Hope that I explained my problem well. Many thanks in advance.


Solution

  • My solution!

    Yes! I found a "solution". Instead of pushing into terminal setting of the ViewModal, I have implemented a new layout called "layout/terminal". This layout only outputs the variable $content. Reference: https://github.com/zendframework/zend-expressive/issues/360

    To use this layout you should add a new Factory into the configuration.

    <?php
    namespace Factory;
    
    use Interop\Container\ContainerInterface;
    use Zend\Expressive\Template\TemplateRendererInterface;
    use Zend\ServiceManager\Factory\FactoryInterface;
    use Zend\View\Model\ViewModel;
    
    class RenderWithoutTemplate implements FactoryInterface
    {
        public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
        {
            $template = $container->has(TemplateRendererInterface::class)
                ? $container->get(TemplateRendererInterface::class)
                : null;
    
            $r = new \ReflectionClass($template);
            $view = new ViewModel();
            $view->setTerminal(true); // Does not affect any render behaviour (?)
            $view->setTemplate('layout/terminal');
    
            $prop = $r->getProperty('layout');
            $prop->setAccessible(true);
            $prop->setValue($template, $view);
    
            return $template;
        }
    }