Zend Framework 2 - 用另一种布局包装 $this->content [英] Zend Framework 2 - Wrapping $this->content with another layout

查看:29
本文介绍了Zend Framework 2 - 用另一种布局包装 $this->content的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

但是,我希望模块的正文内容具有自定义布局.IE.用于自定义导航栏等

因此具有以下结构:

模块/模块名称/看法/布局/模块布局.phtml/模块名/指数/index.phtml看法/布局/layout.phtml

/view/layout/layout.phtml:

doctype();?><html lang="zh-cn"><头>...<身体><header>...</header><div id='body'><?= $this->content;?>

<页脚>...</页脚></html>

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

...

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

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

Hello World...

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

我在控制器的 dispatch 事件上创建了一个监听器来为所有控制器操作捕获它:

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

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

公共函数 dispatchControllerStrategy($e) {$controller = $e->getTarget();$layout = $controller->layout();$wrapper = new ViewModel();$wrapper->setTemplate('layout/modulelayout');$layout->addChild($wrapper, 'content');}

^^^ 子布局的添加好像没有以任何方式包裹$this->content,子布局也没有渲染.总而言之,这就是我希望最终来源的样子:

<html lang="zh-cn"><头>...<身体><header>...</header><div id='body'><div>...</div><div>你好,世界...

<页脚>...</页脚></html>

谢谢!

解决方案

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

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

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

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

private $renderdedOuterView = false;公共函数 renderViewStrategy($e) {如果 ($this->renderdedOuterView) {返回;} 别的 {$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 条件将失败并且没有其他模块将获得修改后的布局.

I am trying to create a wrapper for the $this->content of a specific Module.

What I have is a main layout (All the modules will follow this layout) which builds the base layout with headers and footers, etc. These will stay the same across all the Modules.

However I want to have modules with a custom layout for their body content. I.e. for custom nav bars, etc.

So with the following structure:

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

The /view/layout/layout.phtml:

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

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

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

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

<div>...</div>

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

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

Hello World
...

So I want all of the actions inside of ModuleName (their $this->content that is displayed), to be wrapped with the layout from modulelayout.phtml.

I created a listener on the dispatch event of a controller to capture it for all controller actions:

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

Now I need to know how to I retain the base layout, and add my module layout as a wrapper?

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

    $layout = $controller->layout();

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

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

^^^ The adding of the child layout does not seem to wrap $this->content in any way, and the child layout does not render. To bring it all together, this is what I expect the final source to look like:

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

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

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

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

Thanks!

解决方案

Well after a lot of messing around I finally found my solution. And it appears that comment of SlmThreeStepView user2257808 was what I wanted to begin with, but my solution fit my need exactly so I am just going to share it here:

I stopped worrying about trying to modify the layout on controller dispatch and focused on the View with the EVENT_RENDERER_POST event:

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

I then modify my model on render:

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

I used $renderedOuterView to only do any render modification for the main layout.

Then for the main layout, I get the Model, and grab the attached child which would be the layout for the current action.

I then clear the main template of that child and add my wrapper in its place. Then as a child of my wrapper, I add the layout for the current action I had just removed from the main template.

My not be the best option, but this solution fits exactly what I was trying to accomplish with my question.

UPDATE

I wanted to add that I found out another issue. All the onBootstraps for each Module get called, regardless if they are the active module.

This was causing a different module to get this layout. The change was adding an EVENT_DISPATCH first:

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

Then inside of the handleEventStrategy, I check to make sure that the active Module is the module's bootstrap that is being called. If it is, then I attach the EVENT_RENDER_POST and use the renderViewStrategy that I had defined.

If the active module is not the module with the render view strategy, the if condition will fail and no other module will get that modified layout.

这篇关于Zend Framework 2 - 用另一种布局包装 $this->content的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
PHP最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆