zendframework / zend-expressive-zendviewrenderer

zend-view PhpRenderer integration for Expressive
BSD 3-Clause "New" or "Revised" License
11 stars 12 forks source link

Default Parameters are not being merged into layout, when using addDefaultParam to inject layout parameters #42

Closed dennis-fedco closed 6 years ago

dennis-fedco commented 6 years ago

I am trying to inject default parameters into my layout, on every request.

Currently I do this:

Pipe a custom layer middleware (before pipeRouting / dispatch):

$app->pipe(LayerMiddleware::class);

In my LayerMiddleware I use addDefaultParam like so:

class LayerMiddleware implements MiddlewareInterface
{

    private $templateRenderer;

    public function __construct(TemplateRendererInterface $renderer)
    {
        $this->templateRenderer = $renderer;
    }

    public function process(ServerRequestInterface $request, DelegateInterface $delegate)
    {
        $this->templateRenderer->addDefaultParam('layout::default', 'foo', 'bar');
        return $delegate->process($request);
    }
}

Then when rendering an action in my ActionMiddleware:

return new HtmlResponse($this->renderer->render('namespace::action'));

The layout is being rendered, but without any of the default parameters. i.e. the foo is not being merged/rendered.

Possible Cause

I suspect it is due to layout being created and set before my LayerMiddleware is called.

And that happens when ApplicationFactory is called before any middleware is piped:

https://github.com/zendframework/zend-expressive/blob/2.0.5/src/Container/ApplicationFactory.php#L69 https://github.com/zendframework/zend-expressive/blob/2.0.5/src/Container/NotFoundDelegateFactory.php#L25

So my addDefaultParam comes too late in the pipeline, when layout is already set in ZendViewRenderer, without any of my added default parameters.

Is there a way to add default params to the layout via MiddleWare? If there is a better way to do this, please let me know as well.

dennis-fedco commented 6 years ago

Suggested fix:

Consider the line https://github.com/zendframework/zend-expressive-zendviewrenderer/blob/master/src/ZendViewRenderer.php#L341

Add the line just before it to be:

$layout->setVariables(
    $this->mergeParams($layout->getTemplate(),
     get_object_vars($layout->getVariables())) //can be replaced by []
);

then the layout gets the default parameters. I'd add a PR for this but not entirely sure how to set up the tests, nor the way to verify if the tests will work.

Delegator Factory

Note too that using delegator factory in place of piping middleware produces the same results.

dennis-fedco commented 6 years ago

Fixed by https://github.com/zendframework/zend-expressive-zendviewrenderer/pull/51#event-1523813358