Magento控制器
提到模型-视图-控制器这种MVC架构,要追溯到Smalltalk编程语言和Xerox Parc。从那个时候开始,就有许多系统将自己描述为MVC架构。这些系统虽然在某些地方有细微差别,但都实现了数据层,逻辑层和前段表现代码的分离。
大部分的PHP MVC框架都拥有以下基本特征,
- 所有的URL请求会被前端控制器解析
 - 前端控制器会检查请求的URL路径,并从中获取一个控制器和动作名(这个过程叫做路由)
 - 实例化从URL中获取的控制器
 - 该控制器中,与从URL里获取的动作名一致的方法会被调用
 - 根据请求的变量,该方法被实例化或调用方法获取模型
 - 该动作方法从模型中获取到数据,这些获取的信息会被传递到视图中
 - 使用从数据结构中获取到的信息,视图输出HTML代码
 
相对于“一个PHP文件对应一个页面”来说,这种MVC架构是个巨大的进步。然后对于一些软件工程师来说,它依然是个丑陋的架构。他们经常抱怨说,
- 前段控制器文件会在全局命名空间中运行
 - 约定型的架构没有配置型架构更具扩展性
 
比如说,
- URL路由规则通常是无法扩展的
 - 控制器被绑定在特定的视图
 - 即使该系统拥有重写核心代码的功能,程序员依然只能在无尽的重构中编写代码
 
Magento团队创建了一个更为抽象的MVC模式,大概的运行过程是,
- URL地址首先被一个PHP文件解析
 - 该PHP文件会根据解析情况实例化一个Magento应用
 - 这个Magento应用会实例化一个前端控制器对象
 - 接着,前端控制器实例化路由对象
 - 路由对象检查请求的URL地址,并作出相应的匹配
 - 如果匹配成功,相应的控制器和动作会被分发
 - 该控制器会被实例化,并且与动作同名的方法会被调用
 - 被调用的方法根据请求的类型,对相应的模型调用相应的方法以获取数据
 - 结束方法调用之后,控制器会实例化布局对象
 - 根据请求中包含的变量及系统属性(通常叫做句柄),布局对象会为该请求创建一系列的Block对象
 - 布局还会在相应的Block对象中调用输出方法,开始套嵌输出(Blocks之间的套嵌)
 - 每个Block都有相关联的模板文件,Blocks包含PHP逻辑代码,模板文件则负责生成HTML文件
 - Block从模型中获取相关数据,换句话说,控制器并不用来传递数据到视图中
 
万俟飞整理收集:Magento开发文档(三):Magento控制器
我们会在整个教程中介绍上面的所有部分,本章主要涉及到到前端控制器->路由->动作控制器环节。
Hello World
又到Hello World了,你懂的。这一节主要任务是
- 创建Hello World模块
 - 配置模块的路由规则
 - 为路由创建动作控制器
 
创建Hello World模块
首先,我们先为该模块创建好目录结构:
app/code/local/Magentotutorial/Helloworld/Block
app/code/local/Magentotutorial/Helloworld/controllers
app/code/local/Magentotutorial/Helloworld/etc
app/code/local/Magentotutorial/Helloworld/Helper
app/code/local/Magentotutorial/Helloworld/Model
app/code/local/Magentotutorial/Helloworld/sql
然后为这个模块创建配置文件,配置该配置文件路径位于,
app/code/local/Magentotutorial/Helloworld/etc/config.xml
并放入下列代码,
| 
 01 
02 
03 
04 
05 
06 
07 
 | 
<config>    <modules>        <Magentotutorial_Helloworld>            <version>0.1.0</version>        </Magentototurial_helloworld>    </modules></config> | 
和之前一样,需要创建一个文件激活该模块,该文件路径位于,
app/etc/modules/Magentotutorial_Helloworld.xml
放入如下代码,
| 
 01 
02 
03 
04 
05 
06 
07 
08 
 | 
<config>    <modules>        <Magentotutorial_Helloworld>            <active>true</active>            <codePool>local</codePool>        </Magentototurial_helloworld>    </modules></config> | 
最后,检查下我们是否成功建立Hello Wolrd模块并激活。
- 清空Magento缓存
 - 在管理员界面中,点击System->Configuration->Advanced.
 - 打开”Disable Modules Output”
 - 大概在底部,会显示Magentotutorial_Helloworld模块
 
配置模块的路由规则
接着,我们开始配置路由规则,路由会将请求的URL地址分发到一个控制器和它的方法上。不像其它约定型的PHP MVC框架,在Magento中,你需要明确的在全局配置文件中配置路由规则,来告诉URL地址如何匹配对应的控制器和方法。
在config.xml文件中,加入下列代码,
| 
 01 
02 
03 
04 
05 
06 
07 
08 
09 
10 
11 
 | 
<frontend>    <routers>        <helloworld>            <use>standard</use>            <args>                <module>Magentototurial_Helloworld</module>                <frontName>helloworld</frontName>            </args>        </helloworld>    </routers></frontend> | 
这块代码里边牵涉到很多术语,接下来一一解析。
<frontend>是什么?
该标签涉及到Magento的一个术语Area。可以将Areas视为一些独立的Magento应用。“frontend” Area是Magento购物车应用的前端表现。”admin” Area是后端管理员应用。”install” Area是用来安装Magento的应用。
为什么配置一个模块的路由要使用复数<routers>呢?
引用一句Phil Karlton关于计算机科学的著名论断:
There are only two hard things in Computer Science: cache invalidation and naming things
意思是说计算机科学中最棘手的两件事就是缓存验证和命名。和许多大型系统一样,Magento同样受到命名的困扰。在全局配置文件书中,可以看到许多这种甚至是丑陋的命名方式。<routers>便是其中之一。该标签通常会包括关于路由规则的配置信息,有时候又会包含实际的路由对象的配置信息。这种命名方式初看起来有些不爽,但是随着你对于Magento系统的深入学习,你会逐渐改变对它的看法。
<frontName>是什么?
当路由器解析URL时,会将URL分为以下几个部分,
http://www.moqifei.com/frontName/actionControllerName/actionMethod/
通过在<frontName>标签中定义”helloworld”值,Magento就能够响应所有以下列URL访问的地址
http://www.moqifei.com/helloworld/*
很多刚刚接触Magento的开发者都会将frontName与Magento的前端控制器对象搞混淆。实际上它们完全不是一回事。frontName只属于路由。
<helloworld>标签的作用?
该标签必须是当前模块名的小写形式。我们创建的模块是Helloworld,所以该标签应该是<helloworld>。可能你会注意到<frontName>标签中的值也于模块名一致。这个其实是一个不成为的规定,并非是必须一致的。在你的自定义模块中,最好使用模块名与命名空间的组合来命名,以避免命名冲突。
<module>Magentotutorial_Helloworld</module>
该标签的值必须是模块的全名,包含package/namespace名。该配置让系统能够正确定位到控制器文件。
创建动作控制器
完成配置文件之后,接下来需要做的就是创建控制器文件及类。在以下路径创建该类,
app/code/local/Magentotutorial/Helloworld/controllers/IndexController.php
包含以下内容,
| 
 01 
02 
03 
04 
05 
 | 
class Magentotutorial_Helloworld_IndexController extendsMage_Core_Controller_Front_Action {    public function indexAction() {        echo 'Hello Index';    }} | 
清空缓存,访问下列地址,
http://www.moqifei.com/helloworld/index/index
也可以访问以下地址,
http://www.moqifei.com/helloworld/index/index
http://www.moqifei.com/helloworld/
如果没有出错的话,页面中应该能显示”Hello World”。恭喜你,你已经成功搞定了第一个Magento控制器。
动作控制器文件路径
控制器应该放在模块的controllers文件夹中,系统会自动在这个路径中寻找控制器。
动作控制器命名方式
还记得在config.xml配置文件中的<module>标签吗?
| 01 | <module>Magentotutorial_Helloworld</module> | 
动作控制器的命名应该遵循以下规则,
- 以配置文件<module>标签中的值起头(Magentotutorial_Helloworld)
 - 紧接着一个下划线(Magentotutorial_Helloworld_)
 - 再接着是该控制器的名字(Magentotutorial_Helloworld_Index)
 - 最后,加上Controller(Magentotutorial_Helloworld_IndexController)
 
所有的Magento控制器都是继承自Mage_Core_Controller_Front_Action类。
index/index路径
上文中提到过,Magento的URL地址按照以下规则进行路由解析,
http://www.moqifei.com/frontName/actionControllerName/actionMethod/
那么在下面这个地址中,
http://www.moqifei.com/helloworld/index/index
URI中的”helloworld”是frontName,后面两个index分别是调用的控制器及方法名,即调用helloworld模块中的IndexController控制器中的indexAction方法。
如果URL地址中缺少控制器及方法部分,Magento默认使用index,所以下面地址访问的页面是相同的。
http://www.moqifei.com/helloworld/index
http://www.moqifei.com/helloworld
如果访问的URL地址如下,
http://www.moqifei.com/checkout/cart/add
Magento会做如下操作,
- 在全局配置文件中找到使用frontName为checkout的模块(Mage_Checkout)
 - 继续查询cart控制器(Mage_Checkout_CartController)
 - 调用cart控制器下的addAction()方法
 
控制器路径
让我们试着添加一个非默认方法到控制器中,添加如下代码到IndexController.php
| 
 01 
02 
03 
 | 
public function goodbyeAction() {    echo 'Goodbye World';} | 
然后访问下面的URL地址:
http://www.moqifei.com/helloworld/index/goodbye
IndexController继承自Mage_Core_Controller_Front_Action类,有很多方法可以直接使用。例如,除上述URI中提到的三部分之外,其它部分会自动传给一个键值对数组。添加如下代码到IndexController中。
| 
 01 
02 
03 
04 
05 
06 
07 
08 
 | 
public function paramsAction() {    echo '<dl>';    foreach ($this->getRequest()->getParams() as $key => $value) {        echo '<dt><strong>Param: </strong>'.$key.'</dt>';        echo '<dt><strong>Value: </strong>'.$value.'</dt>';    }    echo '</dl>';} | 
完成之后访问下面的URL地址
http://www.moqifei.com/helloworld/index/params?foo=bar&baz=eof
一切正常的话,页面中会显示该URL地址中的参数。最后,对于下面这个URL地址,系统应该如何响应呢?
http://www.moqifei.com/helloworld/messages/goodbye
该URL中,控制器的名字是messages,所以我们需要创建一个MessagesController控制器,在以下路径创建该文件
app/code/local/Magentotutorial/Helloworld/controllers/MessagesController.php
接着在该控制器中添加goodbyeAction()方法
| 
 01 
02 
03 
 | 
public function goodbyeAction() {    echo 'Another Goodbye';} | 
关于Magento控制器的介绍已经完成了。虽然看起来比其他的PHP MVC框架要复杂许多,它的高度可扩展性却允许你创建任何你想要的URL结构。
Magento控制器的更多相关文章
- 深入理解Magento – 第二章 – Magento请求分发与控制器
		
深入理解Magento 作者:Alan Storm 翻译:Hailong Zhang 第二章 – Magento请求分发与控制器 Model-View-Controller (MVC) ,模型-视图- ...
 - Magento开发文档(一):Magento入门
		
开始之前,首先声明下,Magento开发者手册由Alan Storm发表在Magento官方网站上.总共分八个部分,由浅入深的介绍了Magento的MVC架构及Magento中使用的比较特殊的EAV模 ...
 - Magento 使用心得
		
Modules->模块 Controller->控制器 Model->模型 Magento是这个星球上最强大的购物车网店平台.当然,你应该已经对此毫无疑问了.不过,你可能还不知道,M ...
 - Magento入门开发教程
		
Modules->模块 Controller->控制器 Model->模型 Magento是这个星球上最强大的购物车网店平台.当然,你应该已经对此毫无疑问了.不过,你可能还不知道,M ...
 - 怎样改动、扩展并重写Magento代码
		
作为一个开发人员的你,肯定要改动Magento代码去适应你的业务需求,可是在非常多时候我们不希望改动Magento的核心代码,这里有非常多原因, 比如将来还希望升级Magento.还想使用很多其它的M ...
 - 深入理解Magento-第九章-修改、扩展、重写Magento代码
		
(博主提示:本章应该不是原作者的第九章,仅作补充和参考) 作为一个开发者的你,肯定要修改Magento代码去适应你的业务需求,但是在很多时候我们不希望修改Magento的核心代码,这里有很多原因,例如 ...
 - Magento请求分发与控制器
		
Magento请求分发与控制器 Magento使用的是MVC结构,模型-试图-控制器结构,这样更好的实现显示逻辑和数据,业务逻辑的分离,更好的适合开发! 下面为传统的mvc结构 URL请求被一个PHP ...
 - 以helloworld为例讲解magento中控制器的工作
		
1.下面介绍的前提是你已经安装了magento ,版本是1.9.1.0. 2.下面是实际步骤 ①在工程下面创建下面的文件目录 app/code/local/Magentotutorial/Hellow ...
 - Magento学习第一课——目录结构介绍
		
Magento学习第一课--目录结构介绍 一.Magento为何强大 Magento是在Zend框架基础上建立起来的,这点保证了代码的安全性及稳定性.选择Zend的原因有很多,但是最基本的是因为zen ...
 
随机推荐
- K2工作流的使用
			
K2的工作流作为工作流中的战斗机,被各大企业争相抢购着,当然我们公司也买了,用起来确实方便也的确很强大. 主要分两的模块: 一.K2.net 2003 Service Manager 以上是对配置用户 ...
 - mybatis 语句共享
			
在mybatis mapping文件中,有些情况下有些语句需要共享给其他sql语句使用. 在网上搜了一下没有结果. 自己动手做了一个单元测试. 示例如下: 比如我在sysuser.xml 中有如下语句 ...
 - 使用MediaPlayer播放音频-----之二
			
MediaPlayer播放不同来源的音频文件: 一.播放应用的资源文件 1.调用MediaPlayer的create(Context context , int resid)方法加载指定资源文件. ...
 - 绑定本地Service并与之通信-----之二
			
import android.os.Bundle;import android.os.IBinder;import android.app.Activity;import android.app.Se ...
 - C#Winform从页面获取数据,传入数据库
			
环境: 1.SQLite数据库新建数据表,设置相应的字段.(其他数据库形式都相似,using相应数据库的包即可) 2.页面有两个textBox:textBox1.textBox2, 3.一个保存按钮: ...
 - POJ 2992 求组合数的因子个数
			
求C(n,k)的因子个数 C(n,k) = (n*(n-1)*...*(n-k+1))/(1*2*...*k) = p1^k1 * p2^k2 * ... * pt^kt 这里只要计算出分子中素数因子 ...
 - powershell加win的dns服务器,解决网站负载均衡问题
			
用我发明的powershell填坑法,加windows的dns服务器.从调整dns服务器解析ip时间段的角度,解决网站负载均衡问题. ------------------------win2012r2 ...
 - android textview  跑马灯
			
<TextView android:layout_width="match_parent" android:layout_height="48dp" an ...
 - MYSQL数据库导入导出(可以跨平台)
			
MYSQL数据库导入导出.sql文件 转载地址:http://www.cnblogs.com/cnkenny/archive/2009/04/22/1441297.html 本人总结:直接复制数据库, ...
 - C++指针详解
			
指针的概念 指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址.要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的类型,指针的值或者叫指针所指向的内存区,还有指针本身所占 ...