作者:Alan Storm
翻译:zhlmmc
Model-View-Controller (MVC) ,模型-视图-控制器,源于Smalltalk编程语言和Xerox Parc。现在有很多系统是基于MVC架构的,不同的系统MVC的实现也略有不同,但都体现了MVC的精髓,分离数据,业务逻辑和显示逻辑。最常见的PHP MVC框架是这样的
URL请求被一个PHP文件拦截,通常称为前端控制器(Front Controller)
这个PHP文件分析这个URL,获得一个执行控制器(Action Controller)的名字和一个执行方法(Action Method)的名字,这个过程通常称为路由(Routing)
实例化#2获得的执行控制器
调用执行控制器的执行方法
执行方法中处理业务逻辑,比如获取数据
执行控制器负责把数据传递给显示逻辑
显示逻辑生成HTML
这个架构相对于传统的“每个php都是一个页面”来讲已经是一个巨大的飞跃,但还是有人抱怨【译者注: CodeIgniter就是这样一个MVC框架】
前端控制器仍然以全局的方式运行
基于配置的惯例导致了系统不够模块化
URL Routing不够灵活
控制器往往和视图绑定
更改默认设置往往导致大量的重构
Magento创造了一个更抽象的MVC来解决上述问题。
URL请求被一个PHP拦截
这个PHP文件实例化一个Magento对象
Magento对象实例化前端控制器
前端控制器实例化全局配置中指定的路由对象,可以是多个
路由对象会逐个与请求URL匹配
如果发现匹配,那么可以获得一个执行控制器和一个执行方法的名字
实例化#6获得的执行控制器,并调用相应的执行方法
执行方法中处理业务逻辑,模型数据
控制器实例化布局对象(Layout)
布局对象根据请求的参数,系统配置创建一个块对象(Block)列表,并实例化
布局对象会调用块对象的output方法生成HTML。这是一个递归的过程,因为块对象可以嵌套块对象
每一个块对象都和一个模板文件(Template File)对应。块对象包含了显示逻辑,模板文件包含了HTML和PHP输出代码
块对象直接从模型那里获得数据,换句话说,在Magento的MVC架构中,控制器并不直接把数据传给视图
这里很复杂,我们以后会详细解释每一个部分。我们先关注“前端控制器->路由对象->执行控制器”部分。
Hello World示例
我们讲了太多理论,现在让我们来实践一下,通过实践来加深理解。下面是我们将要做的事情
创建一个Hello World模块
为这个模块配置路由
为这个模块创建执行控制器
创建Hello World模块
首先,我们要创建一个模块的目录结构,这个我们以前已经做过了,就不再熬述
app/code/local/Alanstormdotcom/Helloworld/Block
<config> <modules> <Alanstormdotcom_Helloworld> <version>0.1.0</version> </Alanstormdotcom_Helloworld> </modules> </config>然后我们要创建一个系统配置文件来激活这个模块
<config> <modules> <Alanstormdotcom_Helloworld> <active>true</active> <codePool>local</codePool> </Alanstormdotcom_Helloworld> </modules> </config>
清空Magento缓存
在管理后台,进入 System->Configuration->Advanced
展开“Disable Modules Output”
确认Alanstormdotcom_Helloworld显示出来了
配置路由
下面,我们要配置一个路由。路由是用来把一个URL请求转换成一个执行控制器和方法。和传统的PHP MVC不同的是,你需要在Magento的全局配置中显式的定义你的路由。我们继续上面的例子,在config.xml中,添加如下代码
<config> ... <frontend> <routers> <helloworld> <use>standard</use> <args> <module>Alanstormdotcom_Helloworld</module> <frontName>helloworld</frontName> </args> </helloworld> </routers> </frontend> ... </config>
在这里,我们有很多新名词要解释。
什么是<frontend />?
<frontend />标签指向一个Magento区(Area),比如“frontend”就是指网站的前台,“admin”是指网站的后台,“install”是指Magento的安装程序。【译者注:这个有点像磁盘分区,区和区之间是相互独立的,但是都归操作系统能够管理,在这里归Magento管理。默认的Magento安装没有“install”这个区,frontend区接管了,全局配置中的以下代码可以解释这一点
<frontend> ... <install> <use>standard</use> <args> <module>Mage_Install</module> <frontName>install</frontName> </args> </install> ... </frontend>
class Alanstormdotcom_Helloworld_IndexController extends Mage_Core_Controller_Front_Action { public function indexAction() { echo 'Hello World!'; } }清空Magento缓存,请求如下URL
以<moudule>标签的内容开始 (Alanstormdotcom_Helloworld)
紧接一个下划线 (Alanstormdotcom_Helloworld_)
加上我们给控制器取的名字“Index”(Alanstormdotcom_Helloworld_Index)
最后加上关键词“Controller” (Alanstormdotcom_Helloworld_IndexController)
查询全局配置,找到frontName “checkout”对应的模块,Mage_Checkout
找到执行控制器 “Mage_Checkout_CartController”
调用执行控制器的“addAction”方法
public function goodbyeAction() { echo 'Goodbye World!'; }请求URL
public function paramsAction() { echo '<dl>'; foreach($this->getRequest()->getParams() as $key=>$value) { echo '<dt><strong>Param: </strong>'.$key.'</dt>'; echo '<dl><strong>Value: </strong>'.$value.'</dl>'; } echo '</dl>'; }请求如下URL
public function goodbyeAction() { echo 'Another Goodbye'; }