Zend框架2设置自定义布局和setTerminate问题


Zend Framework 2 set custom layout and setTerminate issue

我不知道这是ZF2的一个bug还是我只是不太理解它,但我很兴奋为什么会发生这种情况。

我正在使用一个解决方案,通过附加一个Dispatch事件来改变全局每个模块的布局。(例如从http://framework.zend.com/manual/2.1/en/modules/zend.view.quick-start.html#dealing-with-layouts,最后一个例子)

它工作得很好,但问题是,当在一些动作我想setTerminate(true); (Ajax调用)它不会只显示控制器/动作模板的内容,但只有布局模板没有内容!这是我没想到的。

这就是如何模拟这个,在调度函数中设置布局(而不是附加事件,使其更简洁),然后在控制器的动作中设置setTerminate。

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;
}

再一次,我期望这将只显示 controller/index模板的内容,但不是那样,它只显示layout/new的内容,没有内容。

我试着设置布局,它的工作方式是我所期望的。

public function indexAction()
{
    $this->layout('layout/new');
    $model = new ViewModel();
    $model->setTerminal(true);
    return $model;
}

这是工作,它只显示控制器/索引模板的内容,而不是布局。

所以如果我改变布局全局(通过附加调度事件)为每个控制器它工作,直到我想使用这些控制器中的一个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. php

应用程序/配置/ajax-layout.phtml

<?php echo $this->content ?>

2)修改您的操作,以覆盖Ajax调用期间的默认布局

在你的控制器/action中:

// Don't render base layout if Ajax call
if($this->getRequest()->isXmlHttpRequest()) {
    $this->layout('application/layout/ajax-layout');
}
$model = new ViewModel();
return $model;

这只会渲染你的动作内容,并覆盖你的基本布局:)