Я не знаю, является ли это ошибкой ZF2, или я просто не понимаю это хорошо, но я очень волнуюсь, почему это происходит.
Я использую решение для изменения макета каждого модуля в глобальном масштабе, добавив событие Dispatch. (например, из http://framework.zend.com/manual/2.1/en/modules/zend.view.quick-start.html#dealing-with-layouts , последний пример)
Он работает хорошо, но проблема в том, что в некоторых действиях я хочу установить Terminate (true); (для вызова Ajax) он не отображает только содержимое шаблона контроллера / действия , а только шаблон макета без содержимого! И этого я не ожидаю.
Вот как имитировать это, установить макет в функции отправки (вместо прикрепления события, сделать его более чистым), а затем установить Terminate в действии контроллера.
public function dispatch(Request $request, Response $response = null) { parent::dispatch($request, $response); $this->layout('layout/new'); } public function indexAction() { $model = new ViewModel(); $model->setTerminal(true); return $model; }
Опять же, я ожидаю, что это отобразит только контент шаблона controler / index , но вместо этого отобразит только содержимое макета / нового без содержимого.
Я попытался установить макет в действии, и он работает так, как я ожидаю.
public function indexAction() { $this->layout('layout/new'); $model = new ViewModel(); $model->setTerminal(true); return $model; }
Это работает, оно отображает только содержимое шаблона контроллера / индекса, а не макет.
Поэтому, если я изменяю макет globaly (путем добавления события отправки) для каждого контроллера, он работает, пока я не хочу использовать один из этих контроллеров для вызова Ajax и использовать setTerminate.
Спасибо за помощь в этом.
Когда вы отмечаете свою модель представления в качестве терминала, слушатель в событии отправки заменяет модель макета с возвращенной моделью представления.
Так что слишком поздно делать этот $this->layout('layout/new');
после отправки вы меняете шаблон своей модели представления.
Что вам нужно сделать, это приложить прослушиватель. Например, из самого контроллера:
protected function attachDefaultListeners() { //do not forget to call parent parent::attachDefaultListeners(); $events = $this->getEventManager(); //attach before action $events->attach(MvcEvent::EVENT_DISPATCH, array($this, 'changeLayout'), 10); } public function changeLayout(MvcEvent $event) { $this->layout('layout/new'); }
Это установит макет для вашего контроллера, но вы сможете изменить его из действия, а setTerminal()
будет работать как ожидалось
Если вы хотите показывать только контент из файла просмотра действий, вы можете использовать этот подход без проблем:
1) Создайте новый макет для вызовов ajax. Это заменит layout.phtml
Приложение / макет / Ajax-layout.phtml
<?php echo $this->content ?>
2) Измените действие, чтобы овервердить макет по умолчанию во время вызовов Ajax
Внутри вашего контроллера / действия:
// Don't render base layout if Ajax call if($this->getRequest()->isXmlHttpRequest()) { $this->layout('application/layout/ajax-layout'); } $model = new ViewModel(); return $model;
это просто отобразит ваши действия и переопределит ваш базовый макет 🙂