1

我正在尝试为特定模块的 $this->content 创建一个包装器。

我所拥有的是一个主布局(所有模块都将遵循此布局),它使用页眉和页脚等构建基本布局。这些在所有模块中都将保持不变。

但是,我想为其正文内容提供具有自定义布局的模块。即用于自定义导航栏等。

因此具有以下结构:

module
  / ModuleName
    / view
      / layout
        / modulelayout.phtml
      / modulename
        / index
          / index.phtml
view
  / layout
    / layout.phtml

/view/layout/layout.phtml:

<?= $this->doctype(); ?>
<html lang="en">
    <head>
      ...
    </head>
    <body>
        <header>...</header>

        <div id='body'>
            <?= $this->content; ?>
        </div>

           <footer>...</footer>
    </body>
</html>

/module/ModuleName/view/layout/modulelayout.phtml:

<div>...</div>

<div>
    <?= $this->content; ?>
</div>

/module/ModuleName/view/modulename/index/index.phtml:

Hello World
...

因此,我希望 ModuleName 中的所有操作(它们的 $this-> 显示的内容)都使用 modulelayout.phtml 中的布局进行包装。

我在控制器的调度事件上创建了一个侦听器,以便为所有控制器操作捕获它:

public function onBootstrap($e) {
    $app = $e->getApplication();
    $app->getEventManager()
        ->getSharedManager()
            ->attach('Zend\Mvc\Controller\AbstractActionController', 'dispatch', array($this, 'dispatchControllerStrategy'));
}

现在我需要知道如何保留基本布局,并将我的模块布局添加为包装器?

public function dispatchControllerStrategy($e) {
    $controller = $e->getTarget();

    $layout = $controller->layout();

    $wrapper = new ViewModel();
    $wrapper->setTemplate('layout/modulelayout');

    $layout->addChild($wrapper, 'content');
}

^^^ 子布局的添加似乎并没有以任何方式包装 $this->content ,并且子布局没有渲染。综合来看,这就是我期望的最终源代码的样子:

<!DOCTYPE html>
<html lang="en">
    <head>
      ...
    </head>
    <body>
        <header>...</header>

        <div id='body'>
            <div>...</div>

            <div>
              Hello World
              ...
            </div>
        </div>

           <footer>...</footer>
    </body>
</html>

谢谢!

4

2 回答 2

1

好吧,经过一番折腾,我终于找到了解决方案。看来 SlmThreeStepView user2257808 的评论是我想要开始的,但我的解决方案完全符合我的需要,所以我只想在这里分享:

我不再担心尝试修改控制器调度的布局,而是专注于使用 EVENT_RENDERER_POST 事件的视图:

->attach('Zend\View\View', \Zend\View\ViewEvent::EVENT_RENDERER_POST, array($this, 'renderViewStrategy'));

然后我在渲染上修改我的模型:

private $renderdedOuterView = false;
public function renderViewStrategy($e) {
    if ($this->renderdedOuterView) {
        return;
    } else {
        $this->renderdedOuterView = true;
    }

    $layout = $e->getModel();

    $children = $layout->getChildren();
    $layout->clearChildren();

    $wrapper = new ViewModel();
    $wrapper->setTemplate('layout/modulelayout');
    $wrapper->addChild($children[0], 'content');

    $layout->addChild($wrapper, 'content');
}

我使用 $renderedOuterView 只对主布局进行任何渲染修改。

然后对于主布局,我得到模型,并抓住附加的孩子,这将是当前动作的布局。

然后我清除那个孩子的主模板并在它的位置添加我的包装器。然后作为我的包装器的子组件,我为刚刚从主模板中删除的当前操作添加布局。

我不是最好的选择,但这个解决方案完全符合我想要解决的问题。

更新

我想补充一点,我发现了另一个问题。每个模块的所有 onBootstrap 都会被调用,无论它们是否是活动模块。

这导致不同的模块获得此布局。更改是首先添加一个 EVENT_DISPATCH:

$evtMgr = $e->getApplication()->getEventManager();
$evtMgr->attach(MvcEvent::EVENT_DISPATCH, array($this, 'handleEventStrategy'));

然后在 handleEventStrategy 内部,我检查以确保活动模块是正在调用的模块的引导程序。如果是,那么我附加 EVENT_RENDER_POST 并使用我定义的 renderViewStrategy。

如果活动模块不是具有渲染视图策略的模块,则 if 条件将失败,并且没有其他模块将获得该修改后的布局。

于 2013-08-02T13:48:14.173 回答
0

你试过这个模块吗:https ://github.com/EvanDotPro/EdpModuleLayouts

然后在你的模块配置文件中添加配置

array(
    'module_layouts' => array(
        'ModuleName' => 'layout/some-layout',
    ),
);
于 2013-08-02T02:59:31.087 回答