【问题标题】:Magento - Passing data between a controller and a blockMagento - 在控制器和块之间传递数据
【发布时间】:2011-04-29 16:52:21
【问题描述】:

非常快速和简单的问题,但我找不到合适的答案 - 将数据从控制器传递到 Magento 中的块的最佳方法是什么。

如果有什么不同,我将按如下方式加载布局:

 $this->loadLayout(array('default', 'myModule_default'));

    $this->_initLayoutMessages('customer/session')
         ->_initLayoutMessages('catalog/session')
         ->renderLayout();

我应该补充一下,我一直使用注册表如下:

在控制器中:

Mage::register('data', $data);

在区块中:

$data = Mage::registry('data');

不确定这是否是最好的方法。

【问题讨论】:

    标签: php variables magento model session-variables


    【解决方案1】:

    使用Mage::registry() 方法,您走在了正确的轨道上。另一种选择是使用自动 getter 和 setter,例如$this->setRandomVariableName($data) 在控制器中,然后在块中使用 $this->getRandomVariableName()。我没有调查它们是否最终位于堆栈中的同一位置(我假设在会话中,因为它们是特定于请求的),但它们在代码中实现了相同的目标。

    使用 getter 和 setter 有时会让人感到困惑,因为您可能看起来像是通过 ORM 而不是“临时”会话变量访问数据,因此您可能会做出编码风格的一致性决定以使用 Mage::registry那些类型的变量。真的是你的选择。

    【讨论】:

    • 我之前尝试过这个,假设会有魔法 getter 和 setter - 不过我总是得到一个未定义的方法错误。
    • 嗯,也许您需要一个实例化的模型来执行自动魔术获取/设置。它可能不适用于控制器上下文中的 $this。如果你的控制器已经有一个由 `Mage::getModel('module/model') 创建的对象,那么你应该可以使用它。它可能还为变量提供了更多上下文,这是一件好事......
    • Magic getPropName 和 setPropName 仅适用于从 Varien_Object 继承的对象。
    • @Alan 谢谢,这很有意义。您是否会说在某些情况下,拥有一个模型会增加更多不必要的复杂性,而使用前面描述的注册表就足够了。或者,您是否总是主张坚持模式并始终对任何数据使用模型?
    • @Drew 这是我很难有太多意见的任意事情之一。我认为注册表就像全局变量,“如果没有其他办法,这是最后的手段”。需要考虑的两个随机事项“如果您的视图/块在尚未设置注册表变量的上下文中使用会发生什么。第二,值得注意的是,目前,Magneto 的 getSingleton 是通过将初始对象实例化缓存到注册表。所以我坚持使用模型方法,因为我有一个更大的理念,即“像核心团队一样做事”。
    【解决方案2】:

    对我有用的是通过以下方式在控制器中设置变量:

    Mage::register('variable', 'value');
    

    然后在视图中,您将使用以下代码检索该值:

    $variable = $this->getVariable();
    

    【讨论】:

      【解决方案3】:

      你没有。

      在 Magento 的 MVC 方法中,控制器不负责为视图设置变量(在 Magento 的情况下,视图是布局和块)。控制器在模型上设置值,然后块从这些相同的模型中读取。在 Magento 的世界观中,让一个 Block 依赖于控制器做特定的事情是紧耦合的,应该避免。

      控制器的工作是对模型做某些事情,然后告诉系统它的布局渲染时间。而已。根据系统模型的状态以某种方式显示 HTML 页面是您的布局/块工作。

      所以,如果我想模拟传统的 PHP MVC 行为,我会

      1. 创建一个简单的模型类,继承自Varien_Object

      2. 在控制器中,使用Mage::getSingleton('foo/bar')实例化该对象

      3. 使用魔术 getter/setter 在模型上设置值(您可以在继承自 Varien_Object 的对象中获取这些值)或 setData 等。

      4. 在块中,使用Mage::getSingleton('foo/bar') 再次实例化模型并读回值。

      当您使用Mage::getSingleton(...) 实例化模型时,Magento 会将对象实例化为作为单例。因此,如果您重新实例化一个对象(再次使用Mage::getSingleton('foo/bar')),您将获得相同的对象。

      【讨论】:

      • 谢谢,这解决了我在使用标准 Zend MVC 应用程序后的困惑。
      • @Neil 是的,那里有很多混乱。 Magento 使用一些 zend 框架组件,但它本身就是一个框架。
      • 对此答案+1。但是,我认为 Vinai 的回答也很好,尤其是当您处于开发的初始阶段并且您需要看到您的数据正在正确加载和传递时。就个人而言,我建议在后期使用“超解耦”方法,以避免一次测试太多东西。
      • @AlanStorm : 请您以参考代码为例进行详细说明。(或任何链接)
      • @Nikhil_K_R 对于 StackOverflow 或 Magento StackExchange 来说,这听起来像是一个很好的新问题。
      【解决方案4】:

      如果您使用继承 Mage_Core_Block_Template 的块(即使用模板显示),您可以使用 assign() 方法分配数据,一旦块已被 loadLayout()

      实例化
      $this->loadLayout(array('default', 'myModule_default'));
      
      $this->getLayout()->getBlock('your.block.name.in.the.layout')->assign('data', $data);
      

      那么,在.phtml模板中,就可以简单的使用

      <?php echo $data ?>
      

      这在 magento 中并不经常使用,但由于它被实现为公共方法并因此被声明为稳定,我相信这样做很好。 这也是约定在模板中声明的变量以下划线开头的原因(例如$_product = $this-&gt;getProduct()),因此可以将它们与分配的变量区分开来。

      【讨论】:

      • 有兴趣为什么使用assign() 比魔术二传手更好,例如setData()?
      • 不,我会说它们是等价的。
      • @JonathanDay 我避免使用像瘟疫这样的魔术方法,因为执行静态分析的现代 IDE 会扼杀没有注释补充的“魔术”代码(大多数 Magento)。 Intellisense 也是一个优点。
      【解决方案5】:

      您可以对某些值使用 setData / getData 对。 我在控制器中使用了 setData,在块中使用了 getData。

      【讨论】:

        【解决方案6】:

        @Drew 在 JavaServer Faces 方面有一些背景,在 PHP/Magento 方面比较新,我想说的是

        "PHP 的'share nothing'架构",

        请参阅PHP is not Java: Session Management Whitepaper",这导致 PHP 中的所有对象(甚至类)都具有“请求”范围。

        如果我得到了 Alans 点,那么他建议使用

        • “有状态”模型对象,其属性中包含一些不一定存储在数据库中的数据
        • 和单例模式,通过使用 Mage::getSingleton,使这个在控制器中实例化的有状态模型可访问块,因此可访问呈现输出的实际模板。

        而且由于像 MTool 这样的工具减少了创建新模型的时间,这似乎真的很有意义。

        【讨论】:

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