1

我目前参与开发一个用 PHP 编写的更大的 Web 应用程序,它基于一个 MVC 框架,在架构方面与 Zend 框架有很多相似之处。

当用户登录时,我有一个地方应该显示当前用户虚拟积分的余额。此显示需要在每个控制器的每个页面上。

您将用于获取横向模型数据的代码放在哪里,这不是特定于控制器的,但需要在每个页面视图的站点范围布局中进行,独立于当前控制器?MVC 或 ZF 负责人将如何做到这一点?你们其他人呢?

我考虑在用户登录时加载余额并将其存储在会话中,但由于余额经常更改,这似乎不正确 - 几乎在每次页面加载时都需要检查和更新它。我还考虑通过向每个控制器添加获取例程来做到这一点,但这似乎也不正确,因为它会导致代码重复。

4

3 回答 3

3

好吧,你是对的,每个控制器都有例程将是代码重复,不会使你的代码可重用。

与您的问题评论中建议的不同,我不会选择基本控制器,因为基本控制器不是一个好的实践(在大多数情况下),并且 Zend Framework 实现了Action Helpers以避免它们。

如果您的局部视图是站点范围的,为什么不编写自己的自定义视图助手并从视图助手中获取模型中的数据?然后你可以直接从你的布局中调用这个视图助手。在我看来,只要您不更新/编辑这些数据,从视图中通过模型获取数据根本不会破坏 MVC 设计模式。

您可以在/view/helpers/或您的库中添加您的视图助手(然后您也必须注册您的视图助手路径):

class Zend_View_Helper_Balance extends Zend_View_Helper_Abstract
{

    public function balance()
    {
        $html = '';
        if (Zend_Auth::getInstance()->hasIdentity()) {
            // pull data from your model
            $html .= ...;
        }
        return $html;
    }
}

请注意,如果您需要以特定方式格式化代码,您的视图助手也可以调用部分视图 ( render(), partial(), )。partialLoop()

这是一个非常简单的例子,但对我来说,你的情况就足够了。如果您想对这些数据进行更多控制并能够根据特定视图(或控制器)对其进行修改(或不修改),那么我建议您查看Placeholders。Zend在在线文档中有一个关于它们的非常好的示例。

更多关于自定义视图助手的信息在这里

当您执行这样的任务时,也请考虑使用Zend_Cache组件,这样您就不必在每次请求后查询数据库,而是每分钟查询一次(取决于您的需要)。

于 2012-04-05T19:27:32.077 回答
1

您正在寻找的是Zend_Registry。当您认为需要某种形式的全局变量时,这是您应该使用的组件。如果您在每个页面上都需要它,那么您最好将它添加到您的引导程序中,如果您只在某些地方需要它,请将它添加到相关控制器的 init 方法中。

应用程序/Bootstrap.php

public _initUserBalance() 
{
    $userId = Zend_Auth::getInstance()->getIdentity()->userId;
    $user = UserService::getUser($userId);
    Zend_Registry::set('balance', $user->getBalance());
}

应用程序/布局/default.phtml

echo 'Balance = ' . Zend_Registry::get('balance');

那个小片段应该给你正确的想法!

于 2012-04-05T19:20:44.193 回答
1

在这种情况下,我通常使用带有钩子的前端控制器插件dispatchLoopShutdown(),该钩子执行所需的数据访问并将数据添加到视图/布局中。然后布局脚本呈现该数据。

可根据要求提供更多详细信息。

[更新]

假设您想在布局中显示来自您的数据库(或 Web 服务或 RSS 提要)的最后 X 个新闻项目,与请求的控制器无关

您的前端控制器插件可能如下所示application/plugins/SidebarNews.php

class My_Plugin_SidebarNews
{
    public function dispatchLoopShutdown()
    {
        $front = Zend_Controller_Front::getInstance();
        $view = $front->getParam('bootstrap')->getResource('view');
        $view->sidebarNews = $this->getNewsItems();
    }

    protected function getNewsItems()
    {
        // Access your datasource (db, web service, RSS feed, etc)
        // and return an iterable collection of news items
    }
}

确保使用前端控制器注册插件,通常在application/configs/application.ini

resource.frontController.plugins.sidebarNews = "My_Plugin_SidebarNews"

然后在你的布局中,像往常一样渲染,也许在application/layouts/scripts/layout.phtml

<?php if (isset($this->sidebarNews) && is_array($this->sidebarNews) && count($this->sidebarNews) > 0): ?>
<div id="sidebarNews">
<?php foreach ($this->sidebarNews as $newsItem): ?>
<div class="sidebarNewsItem">
   <h3><?= $this->escape($newsItem['headline']) ?></h3>
   <p><?= $this->escape($newsItem['blurb']) ?></p>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>

明白了吗?

于 2012-04-06T17:08:00.850 回答