【问题标题】:How to insert database info into a layout with Zend Framework如何使用 Zend Framework 将数据库信息插入到布局中
【发布时间】:2011-05-13 16:38:22
【问题描述】:

我已经开始学习 Zend Framework。我已经完成了快速入门教程和 akrabat 教程。

现在我正在尝试使用 Zend Framework 处理我自己的一些项目,至少可以说这是一次令人沮丧的经历。

我创建了一个布局,可以创建显示在每个页面上的标准页眉。现在我想在从 mysql 数据库检索的标题中显示用户名。我不知道该怎么做。我是否与布局中的控制器和模型进行交互?

此外,对于此类信息,还有其他好的指南吗? zend 文档似乎对每个组件都非常详细,但不能很好地解释它们是如何协同工作的。

【问题讨论】:

    标签: php zend-framework


    【解决方案1】:

    在您的布局中,您将需要这个

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

    这将从您的视图脚本中输出任何内容。

    在您的项目结构中,您需要一个控制器和该控制器的视图脚本。如果您已完成本教程,您应该知道如何访问它。

    您的控制器应该从数据库中获取用户名并将其分配给视图,如下所示

     $this->view->username = "John";
    

    那么在你看来

     echo $this->username;
    

    编辑

    在你的 Bootstrap 类中注册一个新插件

     $plugin = new Default_Controller_Plugin_Username();
    
     Zend_Controller_Front::getInstance()->registerPlugin($plugin);
    

    这个插件可能看起来像这样

    class Default_Controller_Plugin_Username 
          extends Zend_Controller_Plugin_Abstract 
                 implements Lib_Observer_Observable
    {
            public function preDispatch(Zend_Controller_Request_Abstract $request)        
            {
                //Do things in here to get username
    
                //Then you can set it in the registry           
                Zend_Registry::set("username", $username);
            }
    }
    

    【讨论】:

    • 这可行,但我必须从我制作的每个控制器的数据库中获取名称。不应该有某种全局方式只做一次吗?
    • @Mike 您通常会创建一个 MasterController 并从该控制器扩展您的控制器。这使您可以放置​​应该在所有控制器上运行的代码。
    • 我认为如果我们只使用 Zend_Session 而不是制作插件,这会容易得多。恕我直言,这将减少资源消耗。您只需在用户登录后立即在会话中添加用户名。如果登录 id 是您要显示的用户名,并且如果您正在使用 Zend_Auth,那么您可以直接从 Zend_Auth 获取用户名使用 getIdentity() 方法。
    • @JohnP 我不确定制作 MasterController 是否是个好主意。我们有动作助手/插件来运行和使用常用功能
    【解决方案2】:

    如果您有来自某种身份验证/登录序列的$user,那么您可能正在使用Zend_Auth。身份数据的默认容器是基于会话的,因此根据您的会话处理设置,您可能不需要每次都访问数据库来获取该用户信息。

    对我来说更大的问题是您是否需要前端控制器插件将来自Zend_Auth$user 信息放入视图中(以在您的布局中呈现),或者布局是否可以直接从Zend_Auth 中提取。

    我都见过(也用过)。

    【讨论】:

      【解决方案3】:

      你的问题是页面上块组成的问题。您可能知道 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 循环真的是一个循环;它可以为一个请求运行多个操作。

      【讨论】:

      • downvoter 能否更详细地说明为什么这不是关于如何使用布局和重复块的好答案?
      • 所以,我们只能说很多人不喜欢 ActionStack,因为它让一些事情变得更难以理解......所以它就像 SO 上的一个禁忌词。
      • 您的解决方案看起来很有趣,不了解 ActionStack,也不明白为什么人们会遇到问题。
      • 小心,这是 2011 年的帖子,可能不再有效(或者可能无效)
      【解决方案4】:

      Zend_Auth 摇滚.. 你需要使用它。

      这里有一个很好的 Zend_Auth 教程:

      http://akrabat.com/zend-auth-tutorial/

      这包括创建 View Helper 以执行显示用户名、角色和注销链接的重复性任务的过程。

      花点时间掌握 View Helpers.. 在编写视图时,它们确实会提高您的工作效率和代码重用性。

      邓肯。

      【讨论】:

        【解决方案5】:

        @Mike,@jakenoble 的这个答案完全适合您的场景。 如果你想在你的控制器中执行一些全局操作,那么我建议创建你自己的从 Zend_Controller 继承的基本控制器类,比如 MyBaseController。 然后你可以从 MyBaseController 继承你所有的控制器,这样在 MyBaseController 的 init() 方法中执行的所有操作都将全局到你的整个项目。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-12-04
          • 1970-01-01
          相关资源
          最近更新 更多