Zend Framework - 从视图脚本中清除自定义占位符

Posted

技术标签:

【中文标题】Zend Framework - 从视图脚本中清除自定义占位符【英文标题】:Zend Framework - clear a custom placeholder from a viewscript 【发布时间】:2012-04-08 20:21:28 【问题描述】:

我正在尝试从视图脚本中清除自定义占位符,假设我有一个创建侧边栏的控制器插件:

    $bootstrap = Zend_Controller_Front::getInstance()->getParam('bootstrap');
    $view = $bootstrap->getResource('view');
    $partial = $view->render('partials/_sidebar.phtml');
    $view->placeholder('sidebar')->append($partial);

我的部分包含我的子菜单(通过 Zend_Navigation 视图助手呈现)。

为了呈现那个侧边栏,我的布局中有这个:

<?= $this->placeholder('sidebar'); ?>

但是如果在某些页面中我不想显示我的侧边栏(例如登录页面)怎么办?我该如何处理这些情况?

我以为我可以使用 $this-&gt;placeholder('sidebar')-&gt;exchangeArray(array()); 重置/清除占位符,但我似乎无法从视图脚本中访问占位符:

// in /application/modules/default/views/account/login.phtml
<?php $placeholder = $this->placeholder('sidebar');
Zend_Debug::dump($placeholder); ?>

// output:

object(Zend_View_Helper_Placeholder_Container)#217 (8) 
  ["_prefix":protected] => string(0) ""
  ["_postfix":protected] => string(0) ""
  ["_separator":protected] => string(0) ""
  ["_indent":protected] => string(0) ""
  ["_captureLock":protected] => bool(false)
  ["_captureType":protected] => NULL
  ["_captureKey":protected] => NULL
  ["storage":"ArrayObject":private] => array(0) 
  

知道如何做这样的事情吗?

谢谢。

编辑:

我的问题其实很简单,因为我的插件是在 postDispatch() 方法中注册和执行的,所以我的 viewscript 是在 before 插件执行的,而 layout 是在 after 执行的强>插件。

从现在开始,我有哪些选择?我无法在 preDispatch 方法中真正声明我的侧边栏,因为不会设置任何脚本目录,因此我无法确定在这一步执行哪个视图脚本。

我也可以使用action() 助手,你觉得呢?一个问题是already asked about it。我仍然觉得这不是正确的做法,而且对我来说听起来有点矫枉过正。

另外,另一个想法是将我的插件移动到我的控制器的 preDispatch() 方法中,但这会导致我在侧边栏的每个控制器上复制/粘贴,或者创建一个 baseController,但我仍然没有喜欢这个主意,感觉自己做错了。

有什么想法吗?

【问题讨论】:

一个想法是设置一个像$view-&gt;isSidebarRenderable这样的标志,并在渲染侧边栏之前在布局中检查它。不优雅,但应该可以。 我想过这个,但正如你所说,它似乎不优雅。无论如何,感谢您分享您的想法:) 确实如此。我有兴趣看看其他人是否想出了更清洁的东西。干杯! 发现我的问题,我已经编辑了我的问题。但我仍在寻找最好的解决方案。 【参考方案1】:

实际上,你很接近。在这种情况下,您只需添加占位符的名称 sidebar

$this-&gt;placeholder('sidebar')-&gt;exchangeArray(array()); 应该可以工作。

见http://framework.zend.com/manual/en/zend.view.helpers.html#zend.view.helpers.initial.placeholder

编辑:

很奇怪,上面的方法对你不起作用。我在我自己的 ZF 网站上对此进行了测试,并且成功了。可能是不同的场景。我不知道。

这是另一种选择,尽管涉及更多。

//Get the placeholder object directly
$placeholderObj = $this->getHelper('placeholder')

//This may be why you were getting null in your example above. Since your were using the magic method in the View class to call the placeholder view helper method directly.

//For example you could call the placeholder like so:
$placeholderObj->placeholder('sidebar')->set("Some value");

//Now the alternative way to remove the placeholder value is as follows.
$registry = $placeholderObj->getRegistry()
$registry->deleteContainer('sidebar');

EDIT3

它应该使用 preDispatch 钩子作为 Zend_Controller_Plugin 工作。我认为您唯一需要确保的是在设置视图脚本/帮助程序路径和布局路径后订购该插件。这可以在同一个插件或另一个插件中完成。

这是一个基于我在我的网站上使用的代码示例。相关部分只是我在 preDispatch 中设置视图脚本路径等的东西

class RT_Theme extends Zend_Controller_Plugin_Abstract

    private $_sitename;
    private $_assets;
    private $_appPath;
    private $_appLibrary;

    /**
     * Constructor
     * 
     * @param string $sitename
     * @param SM_Assets $assets
     * @param string $appPath
     * @param string $appLibrary
     */
    public function __construct($sitename, $assets, $appPath, $appLibrary)
    
        $this->_sitename = $sitename;
        $this->_assets = $assets;
        $this->_appPath = $appPath;
        $this->_appLibrary = $appLibrary;
    

    /**
     * Sets up theme
     * 
     * Sets up theme template directory and assets locations (js, css, images)
     * 
     * @param Zend_Controller_Request_Abstract $request
     */
    public function preDispatch(Zend_Controller_Request_Abstract $request)
    
        $module = $request->getModuleName();
        $controller = $request->getControllerName();
        $action = $request->getActionName();

        $layout = Zend_Layout::getMvcInstance();
        $view = $layout->getView();

        $view->sitename = $this->_sitename;
        $view->headTitle()->setSeparator(' - ')->headTitle($view->sitename);

        $layout->setLayoutPath($this->_appPath . "/html/$module/layout/");

        $view->setScriptPath($this->_appPath . "/html/$module/view/");
        $view->addScriptPath($this->_appPath . "/html/$module/view/_partials/");

        $view->addScriptPath($this->_appLibrary . '/RT/View/Partials/');
        $view->addHelperPath('RT/View/Helper', 'RT_View_Helper');

        $view->addHelperPath($this->_appPath . '/html/view/helpers','My_View_Helper');

        $viewRenderer =
            Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
        $viewRenderer->setView($view); 


        //Ignore this line. Not relevant to the question                 
        $this->_assets->loadFor($controller, $action);

        //Example: Now I can set the placeholder.
        $view->placeholder('header_title')->set($view->sitename);
    

【讨论】:

我编辑了我的帖子以正确书写(我第一次没有复制/粘贴)。请注意,如果我忘记了参数,我会收到警告。而且,如果您阅读我的整个问题,您会看到 Zend_Debug::dump($placeholder); 输出的是空对象。不过感谢您的回答。 嗯,我很惊讶它对你不起作用。这在我的一个网站上对我有用。我添加了我的原始答案,它有点罗嗦,但我想可以封装。它也可以解释为什么你得到一个空对象。 是的,我在想这可能是问题所在。无论如何,我用一个关于如何预先设置视图路径的示例编辑了我的问题,以便您可以使用 preDispatch 设置占位符。我几乎直接复制了这个,所以你需要根据你的设置进行一些调整。

以上是关于Zend Framework - 从视图脚本中清除自定义占位符的主要内容,如果未能解决你的问题,请参考以下文章

如何在控制器或视图之外使用 Zend Framework 部分视图助手?

在 Zend Framework 应用程序中从模型/视图/控制器中抛出异常

如何在Zend framework2中清除会话容器

我在 Zend Framework 中的哪里保存部分(视图),以便我的应用程序中的所有视图都可以访问?

Zend Framework:有没有办法获取视图模板目录的路径?

Zend Framework - 当 URL 在控制器/动作段上有 $$$ 或 ~ 时出错