您的位置:首页 > 其它

Magento模块开发手册(三)magento控制器调度

2015-10-11 12:23 351 查看

模型 – 视图 – 控制器(MVC)体系结构的历史可以追溯到到Smalltalk编程语言和Xerox PARC。从那时起,已经有描述其架构MVC的许多系统。每个系统都略有不同,但都具有彼此分离的数据访问,业务逻辑和用户接口代码的结构。

大多数的PHP MVC框架都拥有以下执行过程

一个URL是由一个单一的PHP文件(通常称为前端控制器)截获。
这个PHP文件分析这个URL,然后得出一个控制器的名称和动作名称(这是通常被称为路由选择过程)。
派生控制器实例化。
与派生动作名一致的方法名叫做控制器
 根据不同的请求变量,此操作方法实例化并调用模型上的方法
 操作方法也将准备信息的数据结构。此数据结构传递给视图。
使用它从控制器接收到的所述数据结构中的信息将该视图呈现HTML
虽然这种模式是一个巨大的飞跃,从“每个PHP文件是一个网页”成立初期,一些软件工程师,它仍然是一个丑陋的黑客攻击模式。常见的抱怨是:

前端控制器的PHP文件仍然工作在全局命名空间。
约定优于配置会导致较少的模块化。
网址(URL)路由通常是不灵活的。
控制器通常绑定到特定的视图。
即使该系统拥有重写核心代码的功能,程序员依然只能在无尽的重构中编写代码。
 

正如你猜到的,Magento团队创建了一个更为抽象的MVC模式,大概的运行过程是:

一个URL是由一个单一的PHP文件拦截。
这个PHP文件实例化一个Magento的应用程序。
Magento的应用程序实例化一个前端控制器对象。
前端控制器实例化任意数量的路由对象(在全局配置中指定)。
路由器检查请求的URL的“匹配”。
如果发现匹配,动作控制器和动作将被执行。
该控制器会被实例化,并且与动作同名的方法会被调用
被调用的方法根据请求的类型,对相应的模型调用相应的方法以获取数据
这个动作控制器将实例化一个布局对象。
根据请求中包含的变量及系统属性(通常叫做句柄),布局对象会为该请求创建一系列的Block对象
布局还会在相应的Block对象中调用输出方法,开始套嵌输出(Blocks之间的套嵌)
每个Block都有相应的模板文件。Blocks包含PHP的逻辑,模板包含HTML和PHP输出代码。
Block从模型中获取相关数据,换句话说,控制器并不用来传递数据到视图中
我们最终会触及这一请求的每个部分,但现在我们关心的是前端控制器 – >路由器 – >动作控制器(Front Controller -> Routers -> Action Controller)部分。

Hello World

理论已经足够了,是时候Hello World了,我们将

在Magento系统中建立一个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

1
2
3
4
5
6

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):

<config>
<modules>
<Magentotutorial_Helloworld>
<version>0.1.0</version>
</Magentotutorial_Helloworld>
</modules>
</config>

1
2
3
4
5
6
7

<config>    
    <modules>
        <Magentotutorial_Helloworld>
            <version>0.1.0</version>
        </Magentotutorial_Helloworld>
    </modules>
</config>

在创建激活这个模块的文件 (at path app/etc/modules/Magentotutorial_Helloworld.xml):

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

1
2
3
4
5
6
7
8

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

 

最后,我们要确保这个模块激活状态:

清空Magento缓存
进入到Magento后台 System->Configuration->Advanced.
展开“Disable Modules Output”(如果还没有展开的话话)。
确保Magentotutorial_Helloworld显示出来。

配置路由

接着,我们开始配置路由规则,路由会将请求的URL地址分发到一个控制器和它的方法上。不像其它约定型的PHP MVC框架,在Magento中,你需要明确的在全局配置文件中配置路由规则,来告诉URL地址如何匹配对应的控制器和方法。

在你的config.xml文件,添加以下内容:

<config>
...
<frontend>
<routers>
<helloworld>
<use>standard</use>
<args>
<module>Magentotutorial_Helloworld</module>
<frontName>helloworld</frontName>
</args>
</helloworld>
</routers>
</frontend>
...
</config>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

<config>    
    ...
    <frontend>
        <routers>
            <helloworld>
                <use>standard</use>
                <args>
                    <module>Magentotutorial_Helloworld</module>
                    <frontName>helloworld</frontName>
                </args>
            </helloworld>
        </routers>  
    </frontend>
    ...
</config>

We have a lot of new terminology here, let’s break it down.

 

<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,它就会被分离出来,如下所示
http://example.com/frontName/actionControllerName/actionMethod/
1

http://example.com/frontName/actionControllerName/actionMethod/
通过在<frontName>标签中定义”helloworld”值,Magento就能够响应所有以下列URL访问的地址
http://example.com/helloworld/*
1

http://example.com/helloworld/*
许多开发Magento的新手容易混淆frontName与前端控制器对象。他们是不一样的东西。该frontName只属于路由。

 

<helloworld> tag作用是什么?

这个标签应该是你的模块名称的小写版本。我们的模块名称是的Helloworld,这个标签是helloword。从技术上讲这个标签定义了我们的路线名称

您还会注意到我们frontName符合我们的模块名称。这是有frontNames匹配模块名称宽松惯例,但它不是必需的。在你自己的模块,它可能是最好使用一个路由名称这是你的模块名称和包名的组合,以避免可能的命名空间冲突。

 <module>Magentotutorial_Helloworld</module>的作用是什么?

该模块的标签应该是你的模块的全名,包括包/命名空间名称。这是利用该系统来定位控制器的文件。

 

为我们的路由创建动作控制器

最后一步,我们需要有自己的动作控制器。创建一个文件

app/code/local/Magentotutorial/Helloworld/controllers/IndexController.php

1

app/code/local/Magentotutorial/Helloworld/controllers/IndexController.php

包含以下内容

class Magentotutorial_Helloworld_IndexController extends Mage_Core_Controller_Front_Action {

public function indexAction() {

echo 'Hello Index!';

}

}

1
2
3
4
5
6
7
8
9

class
Magentotutorial_Helloworld_IndexController
extends Mage_Core_Controller_Front_Action
{        
 
    public
function indexAction()
{
 
        echo
'Hello Index!';
 
    }
 
}

清除缓存配置,并加载以下网址
http://exmaple.com/helloworld/index/index
1

http://exmaple.com/helloworld/index/index
你也这样加载
http://exmaple.com/helloworld/index/ http://exmaple.com/helloworld/

1
2

http://exmaple.com/helloworld/index/ http://exmaple.com/helloworld/

您应该看到文本“Hello World”的一个空白页。恭喜你,你已经设置你的第一个Magento的控制器

 

动作控制器文件路径

控制器应该放在模块的controllers文件夹中,系统会自动在这个路径中寻找控制器。

 

控制器如何命名?

还记得在config.xml配置文件中的<module>标签吗?

<module>Magentotutorial_Helloworld</module>

1

<module>Magentotutorial_Helloworld</module>

控制器的命名应该:

以config.xml中指定该字符串开始(Magentotutorial_Helloworld)
后跟一个下划线 (Magentotutorial_Helloworld_)
这之后,就是动作控制器的名称 (Magentotutorial_Helloworld_Index)
最后,就是“控制器”的全名(Magentotutorial_Helloworld_IndexController)
所有的动作控制器需要继承Mage_Core_Controller_Front_Action。

 

没必要的”index/index”是什么?

正如我们前面所提到的,Magento的网址路由(默认情况下),如下所示
http://example.com/frontName/actionControllerName/actionMethod/
1

http://example.com/frontName/actionControllerName/actionMethod/
所以在URL中
http://example.com/helloworld/index/index
1

http://example.com/helloworld/index/index
URI中的”helloworld”是frontName,后面两个index分别是调用的控制器及方法名,即调用helloworld模块中的IndexController控制器中的indexAction方法。

 

如果URL是不完整的,Magento的采用“index”作为默认的,这就是为什么下面的网址是等价的。
http://example.com/helloworld/index http://example.com/helloworld

1
2

http://example.com/helloworld/index http://example.com/helloworld

如果我们有看起来像这样的网址
http://example.com/checkout/cart/add
1

http://example.com/checkout/cart/add
 

Magento 将做一下运行

在全局配置文件中找到使用frontName为checkout的模块(Mage_Checkout)
继续查询cart控制器 (Mage_Checkout_CartController)
调用cart控制器下的addAction()方法
 

其他动作控制器技巧

让我们尝试添加非默认的方法到我们的动作控制器。下面的代码添加到IndexController.php

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

1
2
3

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

然后访问URL来测试一下:
http://example.com/helloworld/index/goodbye
1

http://example.com/helloworld/index/goodbye
IndexController继承自Mage_Core_Controller_Front_Action类,有很多方法可以直接使用。例如,除上述URI中提到的三部分之外,其它部分会自动传给一个键值对数组。添加如下代码到IndexController中。

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>';
}

1
2
3
4
5
6
7
8

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://example.com/helloworld/index/params?foo=bar&baz=eof
1

http://example.com/helloworld/index/params?foo=bar&baz=eof
你应该可以看到每个参数和值打印出来。

最后,对于下面这个URL地址,系统应该如何响应呢?
http://example.com/helloworld/messages/goodbye
1

http://example.com/helloworld/messages/goodbye
该URL中,控制器的名字是messages,所以我们需要创建一个MessagesController控制器,在以下路径创建该文件

app/code/local/Magentotutorial/Helloworld/controllers/MessagesController.php

1

app/code/local/Magentotutorial/Helloworld/controllers/MessagesController.php

用动作控制器名为Magentotutorial_Helloworld_MessagesController和行动方法,看上去有点像

public function goodbyeAction()
{
echo 'Another Goodbye';
}

1
2
3
4

public
function goodbyeAction()        

{
    echo
'Another Goodbye';
}

到此,概括地说,就是Magento的是如何实现MVC的控制器部分。虽然这是一个有点比其他PHP MVC框架的更为复杂,这是一个高度灵活的系统,可以让你构建几乎任何你想要的URL结构。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: