По умолчанию страница задана так же в массиве Application
module.config:
'template_map' => array( 'error/404' => __DIR__ . '/../view/error/404.phtml'
Я хочу изменить страницу. Я хочу, чтобы новый ViewModel
заполнен переменными. Это означает, что просто изменить шаблон недостаточно:
'error/404' => __DIR__ . '/../view/error/my_new_404_template.phtml'
Но я не могу понять, как это сделать. Я не вижу, как запрос приходит к 'error/404'
.
Как создать для него новый ViewModel
?
Как подключить к нему переменные?
Как маршрут доходит до 'error/404'
чтобы перехватить его?
Например, у меня есть такой метод для страницы 'error/404'
:
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; }
Как сделать такое изменение? Я не могу получить систему, которую они создали, чтобы иметь дело с такими вещами, как 'error/404'
. Пожалуйста помоги.
UPD 1
Еще более сложная задача. Как получить несколько страниц 'error/404'
? Хотелось бы спросить ребят, которые создали фреймворк, знают ли они, что 'not_found_template'
не может иметь массив страниц 'error/404'
. Как это может быть? Если я задаю этот параметр следующим образом:
'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', );
он выдает ошибку. 'not_found_template'
заставляет вас иметь только один шаблон 'error/404'
?
Есть и другой способ. Чтобы поймать EVENT_DISPATCH_ERROR
и полностью перестроить viewModel
. Пещера – это макет – это root viewModel
, а контент, добавленный в макет по умолчанию, – это еще один viewModel
(child). Эти пункты не так четко описаны в официальных документах.
Вот как это может выглядеть в вашем 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' ); }); }
Я не уверен, что следую тому, чего вы пытаетесь достичь, можете ли вы дать ясный пример того, что вы пытаетесь сделать?
Если вы просто пытаетесь добавить переменные в переданную модель представления, вы можете даже сделать это в своем контроллере, проверьте 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', )); }
Первое состоит в создании представлений:
Модули / Yourapplication / просмотр / yourapplication / ошибка / index.phtml
Модули / Yourapplication / просмотр / yourapplication / ошибка / 404.phtml
Во-вторых, нужно зарегистрировать представления в конфигурации модуля:
В module.config.php вашего приложения
'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', ), // [...] ),
Я использовал это для управления ошибкой 404 (я переместил мой сайт с spip на cms на основе ZF2):
В модуле onBootstrap:
$eventManager->getSharedManager()->attach('*', MvcEvent::EVENT_DISPATCH_ERROR, array($this, 'onDispatchError'), -100);
затем
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; } }
В этом коде мы никогда не возвращаем ошибку 404, мы просто вызываем маршрут (в моем примере index) с запрошенным url как param
Надеюсь, это поможет вам.
в module.php
вы также можете изменить шаблон и макет.
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'); }
-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'); }
Или проще (где вы хотите):
/* @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;
Сначала вы должны отключить стандартную notfoundstrategy и в вашем Module.php, а в случае 404 вы должны вернуть новую модель просмотра из контроллера. Пожалуйста, смотрите это сообщение: http://www.cagataygurturk.com/zf2-controller-specific-not-found-page/