php - 在 Magento 中,从 POST 到 Controller 到模型到 block 到模板的正确数据流是什么?

标签 php magento http-post

当数据通过 GET 或 POST 发送到 Magento 扩展时,使用 MVC 验证数据、根据某些业务逻辑处理数据然后将结果输出到屏幕的正确方法是什么?

据我了解, Controller 是接收和验证提交数据的正确位置(可能调用模型进行实际验证)。模型是任何业务逻辑的正确位置,获取请求参数并处理它们。该 block 是准备输出数据的正确位置,它可以从模型中请求。

我了解 Controller 如何接收发布的数据并将其转发给模型

class Company_Project_IndexController extends Mage_Core_Controller_Front_Action
{
    public function receivePostedData()
    {
        $model = Mage::getModel('project/somemodel');
        if($model->validateData( $this->getRequest()->getPost('post_vars') )) {
            $model->processData( $this->getRequest()->getPost('post_vars') );
        }
    }
}

然后模型将处理
class Company_Project_Model_Somemodel extends Mage_Core_Model_Abstract
{
    public function validate( $data )
    {
        //return true of false if data is valid/invalid
    }

    public function processData( $data )
    {
        //Do something with the data
    }

    public function getData()
    {
        //return something
    }

}

我也了解 block 如何实例化模型并从中获取数据
class Company_Project_Block_Display extends Mage_Core_Block_Template
{
    public function getData()
    {
        $model = Mage::getModel('project/somemodel');
        return $model->getData();
    }
}

我遇到的问题是 Controller 和模型一起工作以及 block 和模型一起工作之间的断开连接。如果 Controller 将数据推送到正在更改模型状态的模型中,那么我如何根据该更改的状态将数据从模型中获取到 block 中?

在我看来,有以下可能的解决方案:
  • 使用 Mage::getSingleton 来获取我的模型,所以我指的是 Controller 中的同一个实例和 block
  • 直接引用模型内部的帖子数据或 block
  • 使用注册表存储一些模型状态

  • 我知道上述任何一项是否正确或我应该使用哪个。

    我已经查看了核心目录搜索模块,因为它完全符合我的需要,但我完全迷失在代码中。

    我知道已经提出并回答了其他几个与此非常相似的问题,但我仍然一无所知。

    最佳答案

    这是一个很好的问题,但没有一个明确的答案。如果您查看 Magento 核心本身,您会看到使用的各种方法。说了这么多,这里有一些关于权衡的一般建议/背景。

    根据使用情况,Magento 的 Controller 操作方法是 不是 旨在与 View 交互(或在 Magento 中称为布局)。相反, Controller 操作是作为特定 URL 的主要入口点,然后它应该与请求交互并与模型做一些事情。完成后, Controller 操作会告诉布局通过调用

    $this->loadLayout();
    $this->renderLayout();
    

    按照设计(这只是一种意见),布局与系统的其余部分完全分离。 CodeIgniter/Kohana 风格的系统具有“哑 View ”,它从 Controller 操作中获取变量并对其进行简单的模板替换。另一方面,Magento 布局是嵌套 block 对象的集合, block 对象方法旨在 直接查询机型当他们需要信息时。

    例如——看看Mage_Adminhtml_Block_Catalog_Product_Attribute_Set_Main_Formset堵塞
    #File: app/code/core/Mage/Adminhtml/Block/Catalog/Product/Attribute/Set/Main/Formset.php
    protected function _prepareForm()
    {
        $data = Mage::getModel('eav/entity_attribute_set')
            ->load($this->getRequest()->getParam('id'));
        //...
    }    
    

    这里的想法是,无论 Controller 操作中发生什么,Mage_Adminhtml_Block_Catalog_Product_Attribute_Set_Main_Formset block 将始终获取最新的 eav/entity_attribute_set渲染时的模型信息(访问请求对象以获取请求/发布数据,如上所述)。 Controller Action 和 View 彼此分离。

    按照设计,这是使用系统的正确方式。不幸的是,从性能的角度来看,它也是无效的。对于来自其他系统的开发人员来说, View 渲染启动另一轮 SQL 查询的想法似乎很疯狂。 Magento 著名的“开始拍摄并让缓存层”对其进行整理的方法遇到了好坏参半的结果。

    解决这种潜在性能问题的一种方法是在注册表中存储已经实例化的模型。您可以在管理控制台的产品编辑 Controller 中看到这样的示例
    #File: app/code/core/Mage/Adminhtml/controllers/Catalog/ProductController.php
    protected function _initProduct()
    {
        //...
        Mage::register('current_product', $product);
        //...
    }
    

    然后它在许多生成的 block 中使用,这些 block 呈现产品的编辑表单
    app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Js.php
    public function getProduct()
    {
        return Mage::registry('current_product');
    }    
    

    这里的权衡是更好的 SQL 性能(对 block 没有额外的查询),但是您基本上将这些 block 绑定(bind)到定义 current_product 的 Controller 操作。注册表项。 Magento 注册表(本质上)是一种处理全局变量的奇特方式,因此您会遇到全局变量固有的大部分问题。正如您所指出的,您可以使用 getSingleton 获得类似的结果。方法——但这可能不合适,具体取决于您要完成的任务。

    无论如何,注册表/单例方法似乎受到管理控制台应用程序(Mage_Adminhtml 模块)和 Magento Mobile Controller (Mage_XmlConnect 模块)的核心开发人员的青睐,而更偏执的“加载显式模型”模式在前端购物车应用程序中使用得更多。这是一个巧合,一个有意识的选择,或者只是核心团队本身在学习的过程中可能是那些无法回答的问题之一。

    最后,核心代码使用不多的一种技术,但当我在寻找更多“愚蠢的 View ”行为时,我有点喜欢这种技术。在加载布局之后,但在渲染它之前,您可以按名称访问特定 block 。这与魔法 getter 和 setter 的力量相结合,可以让你做这样的事情
    $this->loadLayout();
    
    $content = $this->getLayout()->getBlock('content');
    if($content)
    {
        $content->setSomeValue('Hello World');
    }
    
    $this->renderLayout();
    

    然后从 block 的模板中,您可以使用
    echo $this->getSomeValue();
    

    您仍在将 block 的实现与您的 Controller 操作联系起来,但以一种不那么全局化的方式进行。此外,解耦布局可能不包含您要查找的 block ,因此您需要小心处理。

    关于php - 在 Magento 中,从 POST 到 Controller 到模型到 block 到模板的正确数据流是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20316475/

    相关文章:

    php foreach 仅使用动态数据循环一次

    php - 使用 Composer 问题自动加载 GitHub 存储库

    php - laravel mongodb jenssegersallowDiskUse true

    magento - 所有结账页面的布局句柄..我认为这是默认的

    magento-1.4 - 在 Magento Admin 中禁用自动送货更新

    Python URL 请求

    PHP 7.4.1 - PECL 不起作用(尝试访问第 181 行 PEAR/REST.php 中 bool 类型值的数组偏移量)

    php - HTTP POST 到 IIS 和 PHP - 键/值对限制?

    php - 使用 cURL 发布数据时出现 "Positional Parameter"错误

    php - 不能从交互式 shell 中要求 mage.php