Php 如何在Zend_应用程序中使用多个视图(使用Zend_布局)?

Php 如何在Zend_应用程序中使用多个视图(使用Zend_布局)?,php,zend-framework,Php,Zend Framework,我有一个包含4个独立“块”的布局。它们是: 带有菜单和面包屑的导航面板。这是使用Zend_导航构建的 侧边栏,默认情况下显示常规“新闻” 一个内容区,每个控制器操作的主要输出将放置在该区域 标题区域,位于导航上方,通常只显示一些股票文本和照片 内容区域符合Zend_应用程序文档中所述的传统单视图模型,但其他三个不符合。它们都有合理的默认视图可供使用,但如果需要,控制器需要能够覆盖它们。例如,管理页面覆盖“newsy”视图以显示最近在系统上执行的管理操作的日志是有意义的 但是,Zend_布局/

我有一个包含4个独立“块”的布局。它们是:

  • 带有菜单和面包屑的导航面板。这是使用Zend_导航构建的
  • 侧边栏,默认情况下显示常规“新闻”
  • 一个内容区,每个控制器操作的主要输出将放置在该区域
  • 标题区域,位于导航上方,通常只显示一些股票文本和照片
内容区域符合Zend_应用程序文档中所述的传统单视图模型,但其他三个不符合。它们都有合理的默认视图可供使用,但如果需要,控制器需要能够覆盖它们。例如,管理页面覆盖“newsy”视图以显示最近在系统上执行的管理操作的日志是有意义的

但是,
Zend_布局
/
Zend_应用程序
示例都采用单一视图(它们称为


如何实现这种布局覆盖?我想到的唯一解决方案是将覆盖的
Zend_视图
s存储在
Zend_注册表
中,但这似乎像是用管道胶带将东西固定在一起;)

通常,您会有一个包含标题区域、导航面板、,内容区和侧栏。内容区域将使用您包含的$this->layout()->内容片段加载,其他块可以在主布局中调用,也可以通过包含。分部。如果使用后一种方法,布局文件可能会如下所示:

<html>
<head>
<title><?=$this->headTitle()?></title>
</head>

<body>

<?=$this->render('_header.phtml')?>

<?=$this->render('_navigation.phtml')?>

<?=$this->render('_sidebar.phtml')?>

<?=$this->layout()->content?>

</body>
</html>

如果你发现你的部分包含了比HTML更多的PHP代码,你可以考虑写一个帮助器来代替。因此,您可以沿着以下几行创建侧栏辅助对象:

<?php
class My_View_Helper_Sidebar extends Zend_view_Helper_Abstract
{
    public function sidebar()
    {
        $html = '';

        // code to generate side bar here

        return $html;
    }
}
?>

然后,您可以调用侧边栏助手,而不是像上面那样渲染局部:

<?=$this->sidebar()?>

控制器很容易覆盖布局,因此您可以创建一个类似于上面示例的管理布局,但没有侧栏,并且可能有不同的标题。然后,您可以让您的管理员控制器使用此选项,而不是默认设置


我能想到一些需要配置多个Zend_View对象的情况,您暗示您正在考虑这些情况。

我相信您所指的是“命名段”。Zend Framework的响应对象支持这些所谓的“命名段”,并允许您将正文内容分隔为不同的段

例如,以以下布局文件为例:

<div id="nav">
    <?php echo $this->layout()->nav ?>
</div>
<div id="content">
    <?php echo $this->layout()->content ?>
</div>

这里有两个命名段,分别是“内容”和“导航”。默认情况下,视图脚本的输出将呈现到“内容”段。为了将输出渲染到“nav”段,可以在控制器中执行以下操作:

<?php

$response = $this->getResponse();
$response->insert('nav', $view->render('nav.phtml'));

?>

当与ActionStack动作助手结合使用时,此功能特别有用。例如,您在一个管理页面上,希望覆盖“nav”部分,然后您可以确定每个控制器要渲染到该段的哪个部分。解释这一点的最佳方法是通过代码示例:

<?php

class PageController extends Zend_Controller_Action
{
    public function barAction()
    {
        // this would render the output of NavController::menuAction()
        // to the "nav" segment (note how we set the response segment in the
        // NavController in order to do this)
        $this->_helper->actionStack('menu', 'nav');
    }
}

class NavController extends Zend_Controller_Action
{
    public function menuAction()
    {
        $this->_helper->viewRenderer->setResponseSegment('nav'); 
        // do stuff
    }
}

?>


操作堆栈上的一些注释:。如果有人真的想沿着创建页面块的路线走,我建议看一下占位符帮助器,但除非你需要复杂性,否则部分比较容易。我同意你在文章中提出的观点,上面概述的技术并不理想,但它们回答了最初的问题。+1,因为这看起来正是我需要做的。一个问题:是否可以以某种方式设置默认响应(即在
引导程序中设置)?只有少数动作控制器真正需要更改默认设置,复制所有这些设置似乎很丢脸。您可以使用控制器插件来设置默认设置。手册中有一个例子:啊-在这种情况下,我甚至不需要@Tim在这里翻录的“actionstack”。+1用于回答这个问题,但多个版面的问题是,它迫使我复制版面中的大量内容——复制/粘贴的代码是邪恶的;)你需要复制什么样的东西?通常情况下,这些内容可以集中在部分中,除非你说的是呈现部分调用本身被复制。我想在内容中转储的地方周围的事情相对复杂——所有的定位和那种我想抽象到布局中的设置。理想情况下,控制器只需要提供特定于其功能的项。Hmmm。。基本上布局不像导航,内容,侧边栏,更像导航