ZF2 - How to change error response page / 404? Not only a template, but also the installation of a new ViewModel model

By default, the page is set this way in the Application module.config array:

 'template_map' => array( 'error/404' => __DIR__ . '/../view/error/404.phtml' 

I want to change the page. I want a new ViewModel for it full of variables. This means that simply changing the template is not enough:

 'error/404' => __DIR__ . '/../view/error/my_new_404_template.phtml' 

But I can’t figure out how to do this. I do not see how the request comes in 'error/404' .

  • How to create a new ViewModel for it?

  • How to connect variables to it?

  • How does a route reach 'error/404' to intercept it?

For example, I have a method for the 'error/404' page:

 public function pageNotFoundAction() { $view = new ViewModel(); $view->setTemplate('error/404'); // set my template $sm = $this->getServiceLocator()->get('SessionManager'); $cont = new Container('SomeNamespace', $sm); $view->var1 = $cont->offsetGet('someValue1'); // the "error/404" template $view->var2 = $cont->offsetGet('someValue2'); // is full of variables $view->var3 = $cont->offsetGet('someValue3'); $view->var4 = "One more view variable"; // And now I return it somewhere and want it to be called // in case of "the page is not found" return $view; } 

How to make such a change? I can’t get the system they created to deal with things like 'error/404' . Please, help.

UPD 1

An even more difficult task. How to have multiple 'error/404' pages? I would like to ask the guys who created the framework if they know that 'not_found_template' cannot have an array of pages 'error/404' . How can it be? If I set this parameter as follows:

 'template_map' => array( 'error/404' => __DIR__ . '/../view/error/404.phtml', 'my-page/one_more_error404' => __DIR__ . '/../view/my-page/my-page/one_more_error404.phtml', 'other_page/second_404' => __DIR__ . '/../view/other-page/one_more_error404.phtml', 'not_found_template' => array( 'error/404', 'my-page/one_more_error404', 'other-page/second_404', ); 

he gives an error. 'not_found_template' forces you to have only one 'error/404' template?

+4
source share
7 answers

There is another way. To catch EVENT_DISPATCH_ERROR and completely rebuild the viewModel . Cavern is the layout - this is the root viewModel , and the content added to the default layout is another viewModel (child). These points are not so clearly described in official documents.

Here's how it might look in your Module.php :

 public function onBootstrap(MvcEvent $event) { $app = $event->getParam( 'application' ); $eventManager = $app->getEventManager(); /** attach Front layout for 404 errors */ $eventManager->attach( MvcEvent::EVENT_DISPATCH_ERROR, function( MvcEvent $event ){ /** here you can retrieve anything from your serviceManager */ $serviceManager = $event->getApplication()->getServiceManager(); $someVar = $serviceManager->get( 'Some\Factory' )->getSomeValue(); /** here you redefine layout used to publish an error */ $layout = $serviceManager->get( 'viewManager' )->getViewModel(); $layout->setTemplate( 'layout/start' ); /** here you redefine template used to the error exactly and pass custom variable into ViewModel */ $viewModel = $event->getViewModel(); $viewModel->setVariables( array( 'someVar' => $someVar ) ) ->setTemplate( 'error/404' ); }); } 
+4
source

I'm not sure that I am following what you are trying to achieve, can you give a clear example of what you are trying to do?

If you are just trying to add variables to the passed view model, you can even do this in your controller, check AbstractActionController

 /** * Action called if matched action does not exist * * @return array */ public function notFoundAction() { $response = $this->response; $event = $this->getEvent(); $routeMatch = $event->getRouteMatch(); $routeMatch->setParam('action', 'not-found'); if ($response instanceof HttpResponse) { return $this->createHttpNotFoundModel($response); } return $this->createConsoleNotFoundModel($response); } /** * Create an HTTP view model representing a "not found" page * * @param HttpResponse $response * @return ViewModel */ protected function createHttpNotFoundModel(HttpResponse $response) { $response->setStatusCode(404); // Add in extra stuff from your ServiceLocator here... // $viewModel->setTemplate(..); return new ViewModel(array( 'content' => 'Page not found', )); } 
+2
source

The first thing to create:

Modules / Yourapplication / view / yourapplication / error / index.phtml

Modules / Yourapplication / view / yourapplication / error / 404.phtml

Secondly, you need to register the views in the module configuration:

In module.config.php of your application

 'view_manager' => array( //[...] 'not_found_template' => 'error/404', 'exception_template' => 'error/index', 'template_map' => array( //[...] 'error/404' => __DIR__ . '/../view/yourapplication/error/404.phtml', 'error/index' => __DIR__ . '/../view/yourapplication/error/index.phtml', ), // [...] ), 
+2
source

I used this to manage 404 error (I moved my site from spip to cms based on ZF2):

In the onBootstrap module:

 $eventManager->getSharedManager()->attach('*', MvcEvent::EVENT_DISPATCH_ERROR, array($this, 'onDispatchError'), -100); 

Then

 public function onDispatchError(MvcEvent $event) { $response = $event->getResponse(); if ($response->getStatusCode() == 404) { $url = $event->getRouter()->assemble(array(), array('name' => 'index')); $requestUri = $event->getRequest()->getRequestUri(); $response->getHeaders()->addHeaderLine('Location', "$url?url=$requestUri"); $response->setStatusCode(200); $response->sendHeaders(); $event->stopPropagation(true); } elseif($response->getStatusCode() == 500){ //DO SOMETHING else? return; } } 

In this code, we never return 404 error, we just call the route (in my example index) with the requested url as param

I hope this helps.

+2
source

in module.php you can also change the template and layout.

 function onBootstrap(EventInterface $e) { $app = $e->getApplication(); $evt = $app->getEventManager(); $evt->attach(MvcEvent::EVENT_DISPATCH_ERROR, array($this,'onDispatchError'), 100); } function onDispatchError(MvcEvent $e) { $vm = $e->getViewModel(); $vm->setTemplate('layout/blank'); } 
+1
source

Or simpler (where you want):

 /* @var \Zend\Mvc\View\Http\RouteNotFoundStrategy $strategy */ $strategy = $this->getServiceLocator()->get('HttpRouteNotFoundStrategy'); $strategy->setNotFoundTemplate('application/other/404'); $view = new ViewModel(); //$view->setTemplate('application/other/404'); return $view; 
+1
source

First, you must disable the standard notfoundstrategy in your Module.php, and in the case of 404, you must return a new view model from the controller. Please review this message: http://www.cagataygurturk.com/zf2-controller-specific-not-found-page/

0
source

All Articles