你的问题是页面上块组成的问题。您可能知道 Zend Framework 只是一个框架,因此实际上有不止一种方法可以解决这个问题。
例如,要填充布局部分,您可以使用:
- 一些包含块的变量并提供给每个控制器的视图(带有控制器插件?所有控制器都继承的主控制器?
- 视图中的 Action Helper 将内部调用链接到布局的这一部分中的另一个 MVC 调用
-
操作堆栈
- 当然是其他的东西
我认为最好的是Action stack。它的工作方式是:
- 您对 MVC 事物进行主查询(您可以在控制器中调用 fooAction)
- 您在此操作中调用操作堆栈来告诉 ZF 应该对其他操作执行其他一些内部调用。在这里您可以列出所有应该在布局中填充的块
- 其他块由内部 MVC 循环调用。调用其他一些 barAction userAction 入口点,在这些操作中,您告诉布局布局的哪个键由 setResponseSegment 生成的视图渲染填充。
这是它在代码中的样子:
对于块操作(这里是 /modulefoo/titi/pilili 内部请求),它应该填充布局的 'foobar' 块:
public function pilipiliAction() {
(...) // do things
$this->_helper->viewRenderer->setResponseSegment('foobar');
}
在布局上,您会使用以下内容回显此块:
<?= $this->foobar ?>
现在这个动作必须由您的主动作调用(使用动作堆栈助手)。但最好的方法是使用一个新的自定义助手来堆叠所有的块动作。
这是控制器上的 fooAction,您的经典入口点。在动作结束时,会调用一个帮助器来构建布局块
public function fooAction() {
(...) // do things
// Build Main layout
$this->_helper->LayoutBuilder();
}
这是这个帮助器将做什么的示例(应该可以工作,它是现有帮助器的简化版本,可以做很多其他事情,比如管理块的缓存):
class My_Action_Helper_LayoutBuilder extends Zend_Controller_Action_Helper_Abstract
{
/**
* @var $actionStack
* local ActionStack builtin helper used to Stack several MVC actions,
* for action for each Layout block
*/
protected static $actionStack;
/**
* @var _layout
* reference to the general layout collecting view
*/
protected $_layout;
public function __construct() {
self::$actionStack = Zend_Controller_Action_HelperBroker::getStaticHelper('actionStack');
$this->_layout = Zend_Layout::getMvcInstance();
}
public function direct($blocklist = null) {
$layoutblocks = array(
array('module' => 'default',
'controller' => 'index',
'action' => 'nav')
,
array('module' => 'modulefoo',
'controller' => 'titi',
'action' => 'pilipili') // action given upper
);
$auth = Zend_Auth::getInstance();
if ($auth->hasIdentity()) {
$request = Zend_Registry::get('request');
$module = $request->getModuleName();
$layoutblocks[] = array('module' => $module,
'controller' => 'index',
'action' => 'modulenav');
}
if (isset($blocklist))
{ //user had his own blocklist to add
$layoutblocks = array_merge($layoutblocks,$blocklist);
}
$this->buildCompositeLayout($layoutblocks);
}
public function buildCompositeLayout($blocklist = null) {
foreach($blocklist as $MVCBlock) {
$block = $MVCBlock['action'];
if (!isset($MVCBlock['module'])) {
$module = $this->getRequest()->getModuleName();
$front = $this->getFrontController();
$module = $front->getDispatcher()->getDefaultModule();
} else {
$module = $MVCBlock['module'];
}
if (!isset($MVCBlock['controller'])) {
if (!isset($front)) {
$front = $this->getFrontController();
}
$controller = $front->getDispatcher()->getDefaultController();
} else {
$controller = $MVCBlock['controller'];
}
// Here we stack actions
self::$actionStack->actionToStack($block,
$controller,
$module,
);
}
}
但正如我之前所说,有不止一种方法可以做到这一点。我喜欢这种方式,因为我可以为某些请求交互地添加新块,在块渲染中添加一些缓存,并且我也可以 'forget' 为某些操作调用 LayoutBuilder 帮助程序,例如 ajax 的。秘诀在于 Zend Framework 的 MVC 循环真的是一个循环;它可以为一个请求运行多个操作。