当数据通过 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 中?
在我看来,有以下可能的解决方案:
我知道上述任何一项是否正确或我应该使用哪个。
我已经查看了核心目录搜索模块,因为它完全符合我的需要,但我完全迷失在代码中。
我知道已经提出并回答了其他几个与此非常相似的问题,但我仍然一无所知。
最佳答案
这是一个很好的问题,但没有一个明确的答案。如果您查看 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/