Alan Hou的个人博客

Magento开发系列之三 控制器

MVC结构可以追溯到Smalltalk编程语言和Xerox Parc时代,从那时起很多系统都自称采用了MVC结构。这些系统又都与其它有着些许差别,不过总体而言都会将获取数据、业务逻辑和用户界面的代码进行分离。PHP中常见的MVC框架如下图所示:

  1. 一个称为前台控制器的PHP文件获取到URL
  2. 该PHP文件检测URL并获取控制器名和Action名(这一步常被称为routing)
  3. 实例化所获取到的控制器
  4. 与获取的Action名相匹配的方法将会被调用
  5. 这个Action方法会根据请求的变量实例化/调用model中的方法
  6. 该Action方法准备好数据结构然后传送给view
  7. 视图根据从控制器那里获取的数据结构生成HTML

这种模式显然比早期的一个页面对应一个PHP文件要先进了很多,但软件工程师们在工作中会经常抱怨:

基于此,Magento团队创建了更为抽象的MVC模式

  1. 由一个PHP文件获取到URL
  2. 该PHP文件实例化一个Magento应用
  3. Magento应用实例化一个前台控制器对象
  4. 前台控制器实例化一到多个Router对象(通过全局配置文件指定)
  5. Router检测请求的URL是否匹配
  6. 如果发现到匹配,会获取到Action控制器和Action
  7. 实例化Action控制器并调用与Action名称相匹配的方法
  8. Action方法根据请求实例化模型及调用方法
  9. 该Action控制器实例化Layout对象
  10. Layout对象根据请求对象和系统属性(也称作指针)创建一系列Block对象
  11. Layout还会在某些Block对象(启动内层渲染)上调用输出方法
  12. 每个Block都有一个对应的模板文件,Block中包含PHP逻辑,模板中包含HTML和PHP输出代码
  13. Block从模型中调取数据,也就是说Action控制器并不会传输数据结构。

我们会逐步揭开层层面纱,不过本节我们主要讨论前台控制器 > Router > Action控制器几部分。

这么多理论,想必大家多年的失眠症都已经治愈了…(⊙_⊙;)… 还是老规矩,下面用实例来进行说明,主要有以下几步:

  1. 创建一个Hello World模块
  2. 使用Router配置该模块
  3. 为Router创建Action控制器

首先为Helloworld模块创建目录:

app/code/local/Alanhou/Helloworld/Block
app/code/local/Alanhou/Helloworld/controllers
app/code/local/Alanhou/Helloworld/etc
app/code/local/Alanhou/Helloworld/Helper
app/code/local/Alanhou/Helloworld/Model
app/code/local/Alanhou/Helloworld/sql

到这里大家估计已经是轻车熟路了,先创建app/code/local/Alanhou/Helloworld/etc/config.xml并加入如下代码:

<config>
	<modules>
		<Alanhou_Helloworld>
			<version>0.1.0</version>
		</Alanhou_Helloworld>
	</modules>
</config>

紧接着创建app/etc/modules/Alanhou_Helloworld.xml文件来激活这个模块,加入如下代码:

<config>
	<modules>
		<Alanhou_Helloworld>
			<active>true</active>
			<codePool>local</codePool>
		</Alanhou_Helloworld>
	</modules>
</config>

使用老方法确认一下模块是否配置成功

过上面基本的框架已经搭建好了,执行以下步骤

  1. 清除缓存
  2. 在后台中,点击System > Configuration > Advanced > Advanced
  3. 在Disable modules output面板中查看Alanhou_Helloworld是否出现

 

完成了模块的创建,下面我们就要进行Router的配置了,Router会将URL解释为Action控制器和方法,和传统PHP中的MVC系统不同,在Magento中需求明确地在全部配置中定义Router,打开config.xml,添加一段代码,修改为

<config>
	<modules>
		<Alanhou_Helloworld>
			<version>0.1.0</version>
		</Alanhou_Helloworld>
	</modules>
	<frontend>
		<routers>
			<helloworld>
				<use>standard</use>
				<args>
					<module>Alanhou_Helloworld</module>
					<frontName>helloworld</frontName>
				</args>
			</helloworld>
		</routers>
	</frontend>
</config>

标签起来越越多的,让我们来逐一介绍

<frontend>是做什么的?

<frontend>代表Magento中的区域,可以把区域看作一个Magento应用,frontend区域就是面向客户的前台,也称为shopping cart应用。admin区域是管理后台应用而install区域是在第一次安装Magento时用到的应用。

不论是一个Router还是多用到的标签都是复数的<routers>

<frontName>又是做什么的?

在Router解析URL时,会进行如下的分离

http://example.com/frontName/actionControllerName/actionMethod/

所以通过将<frontName>定义为helloworld,我们实际上是在告诉Magento系统对应的URL是http://example.com/helloworld/*

很多开发者在刚开始的时候容易把frontName和前台控制器对象搞混,实际上frontName只和routing有关

<helloworld>标签有什么作用?
这个标签是模块名称的小写形式,这个模块名称是Helloworld,所以标签名就是helloworld,这实际上定义的是Router名称。

你可能发现frontName和模块名也是相同的,这是一种习惯,但并非强制要求。在自己写的模块中,拼接模块名和命名空间也许更好,这样可以避免一些不必要的名称重复。

<module>Alanhou_Helloworld</module>有什么作用?

这个module标签需要是模块的全称,包含命名空间,系统通过这个标签来定义控制器文件

接下来我们就进入最后一步,为我们的Router创建Action控制器。首先创建一个文件app/code/local/Alanhou/Helloworld/controllers/IndexController.php并添加如下代码:

<php
class Alanhou_Helloworld_IndexController extends Mage_Core_Controller_Front_Action{
	public function indexAction(){
		echo 'Hello World!';
	}
}

清除缓存,然后在浏览器中访问http://localhost/magento/helloworld/index/index页面,就会发现屏幕上输出了Hello World!

 

Action控制器放在模块内controllers的文件夹内,其名称首先取自config.xml,本例中config.xml中有一段

后面紧接着Action控制器的名称(Alanhou_Helloworld_Index),再在最后添加Controller,这样就构成了Alanhou_Helloworld_IndexController。所有的Action控制器都继承Mage_Core_Controller_Front_Action。

那么URL中的index/index又代表什么意思呢?前面我们提到过Magento的URL是按照下面这样解析的

http://example.com/frontName/actionControllerName/actionMethod/

http://example.com/frontName/actionControllerName/actionMethod/

假设我们访问http://example.com/checkout/cart/add,Magento会去全局配置文件中查找Mage_Checkout模块,名称为Mage_Checkout_CartController的Action控制器以及该控制器中的addAction方法

下面使用非默认的名称来创建一个方法,在IndexController.php中添加如下方法:

public function goodbyeAction(){
		echo 'Goodbye World!';
	}

这时访问http://localhost/magento/helloworld/index/goodbye就会输出Goodbye World!

由于这里我们继承了Mage_Core_Controller_Front_Action类,就会自然地获取一些该类中的方法,比如URL中多余的元素会被自动解析为键值对,在Action控制器中添加如下方法:

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>


';
}

然后访问http://localhost/magento/helloworld/index/params?foo=bar&baz=eof就会输出如下结果

最后我们再来创建一个响应http://localhost/magento/helloworld/messages/goodbye的文件,所以我们需要创建一个app/code/local/Alanhou/Helloworld/controllers/MessagesController.php文件。在其出添加一个名为Alanhou_Helloworld_MessagesController的Action控制器并添加一个goodbyeAction方法,具体代码如下:

<?php
class Alanhou_Helloworld_MessagesController extends Mage_Core_Controller_Front_Action{
	public function goodbyeAction(){
		echo 'Another Goodbye!';
	}
}

访问http://localhost/magento/helloworld/messages/goodbye就会输出Another Goodbye!

以上就是如何在Magento添加MVC中的Controller,虽然比常见的MVC框架要复杂一些,但是具有超强的灵活性。

退出移动版