Zend Framework 2 устанавливает пользовательский макет и задает проблему

Я не знаю, является ли это ошибкой 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; 

это просто отобразит ваши действия и переопределит ваш базовый макет 🙂