-
Notifications
You must be signed in to change notification settings - Fork 195
How to change layout of error pages with Zend View #360
Comments
Hello @pdrosos , I apologize in advance for the long answer. When you request an instance of Expressive error pages are handled by These factories request an instance of To solve your issue I found 2 solutions Using reflection :Inside namespace App\Factory;
use Interop\Container\ContainerInterface;
use Zend\Expressive\Template\TemplateRendererInterface;
use Zend\Expressive\TemplatedErrorHandler;
use Zend\ServiceManager\Factory\FactoryInterface;
use Zend\View\Resolver;
use Zend\View\Model\ViewModel;
class TemplatedErrorHandlerFactory 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->setTemplate('layout/error');
$prop = $r->getProperty('layout');
$prop->setAccessible(true);
$prop->setValue($template, $view);
return new TemplatedErrorHandler($template);
}
} Don't forget to map the final handler to this factory Inside 'factories' => [
'Zend\Expressive\FinalHandler' => App\Factory\TemplatedErrorHandlerFactory::class
], Without reflection :Inside // ...
templates' => [
'layout' => 'layout/default',
'layout_error' => 'layout/error',
'map' => [
...
'layout/error' => 'templates/layout/error.phtml',
...
],
// ...
] I created my own ZendViewRendererFactory. Depending on the requested service name, the right layout is used. The code is almost identical as the original factory : class ZendViewRendererFactory implements FactoryInterface
{
const DEFAULT_TEMPLATE = TemplateRendererInterface::class;
const ERROR_TEMPLATE = 'ERROR_TEMPLATE_RENDERER';
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
// ...
$view = new ZendViewRenderer($renderer, $this->getLayout($requestedName, $config));
// ...
}
private function getLayout($requestedName, $config)
{
switch($requestedName) {
case self::DEFAULT_TEMPLATE:
default:
return isset($config['layout']) ? $config['layout'] : null;
case self::ERROR_TEMPLATE:
return isset($config['layout_error']) ? $config['layout_error'] : null;
}
}
} Register my new factory as follow : 'factories' => [
Zend\Expressive\Template\TemplateRendererInterface::class =>
App\Factory\ZendViewRendererFactory::class,
App\Factory\ZendViewRendererFactory::ERROR_TEMPLATE =>App\Factory\ZendViewRendererFactory::class,
...
], Then my class TemplatedErrorHandlerFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$template = $container->has(ZendViewRendererFactory::ERROR_TEMPLATE)
? $container->get(ZendViewRendererFactory::ERROR_TEMPLATE)
: null;
return new TemplatedErrorHandler($template);
}
} For whoops is almost the same I can provide the snippet if you want. I hope this is clear enough, if not feel free to ask 😁 |
@sniphpet thank you for your answer! I like the approach you suggest and would use it in the future. |
Please see #314 as well, as it provides several succinct ways to accomplish this. |
This good workaround is not possible in expressive 2.x :-( Are there new approaches? Can not you simply extend the NotFoundDelegateFactory and the ErrorHandlerFactory by a parameter layout? should I create a feature request? |
Hi,
how can I change the layout of the Expressive error pages? For example 401 (Unauthorized), 404 (Not found), 405 (Method not allowed) etc. I am using Zend View.
Currently the error pages use the default layout, which is set in the templates configuration. But as I use the default layout on many other places too, I would like to set a different lightweight layout especially for the error pages without being forces to change the default layout and specifically set the layout everywhere else on rendering.
The text was updated successfully, but these errors were encountered: