Magento 请求分发与控制器

model-view-controller,现在有很多系统是基于mvc架构的,不同的系统实现mvc也略有不同

区别

传统的mvc框架

  1. 1) URL 请求被一个 PHP 文件拦截,通常称为前端控制器(Front Controller)
    2) 这个 PHP 文件分析这个 URL,获得一个控制器(Action Controller)的名字和一个执行方法(Action Method)

的名字,这个过程通常称为路由(Routing)

3) 实例化#2 获得的控制器
4) 调用控制器的执行方法
5) 执行方法中处理业务逻辑,比如获取数据
6) 控制器负责把数据传递给显示逻辑
7) 显示逻辑生成 HTML

这个架构相对于传统的“每个 php 都是一个页面”来讲已经是一个巨大的飞跃,但还是有很多不尽如人意的地方:

1) 前端控制器仍然以全局的方式运行
2) 基于配置的惯例导致了系统不够模块化

A.URL Routing 不够灵活。

B.控制器往往和视图绑定。

C.更改默认设置往往导致大量的重构。

Magento 创造了一个更抽象的 MVC 来解决上述问题。

magento的mvc加购

  1. url请求被一个php拦截
  2. 这个php文件实例化一个magento对象
  3. magento对象实例化前端控制器
  4. 前端控制器实例化全局配置中指定的路由对象,可以是多个
  5. 路由对象会逐个请求URL匹配
  6. 如果发现匹配,那么可以获得一个控制器和一个执行方法的名字
  7. 实例化#6获得的控制器,并调用相应的执行方法
  8. 执行方法中处理业务逻辑模型数据
  9. 控制器实例化布局对象(layout)
  10. 布局对象根据请求的参数,系统配置创建一个块对象(block)列表,并实例化
  11. 布局对象会调用块对象的output方法生成html这是一个递归过程,业务块对象可以嵌套块对象
  12. 每一个块对象都和一个模板文件teplate file对应.快对象包含了显式逻辑,模板文件包含了html和php输出代码
  13. 块对象直接从模型那里获得数据,换句话说,在magento的mvc架构中,控制器并不直接把数据传给视图

这里复杂,我们以后会详细解释每一个部分,我们先关注"前端控制器->路由对象->控制器"部分

hello world实例

我们讲了太多理论,现在让我们来实践一下,通过实践来加深理解,下面是我们将要做的事情

  1. 创建一个hello world模块
  2. 为这个模块配置路由
  3. 为这个模块创建控制器

首先,我们要创建一个模块的目录结构,这个我们以前已经做过了,就不再熬述

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

下面是config.xml的内容

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <modules>
        <Magentotutorial_Helloworld>
            <verson>0.2.0</verson>
        </Magentotutorial_Helloworld>
    </modules>
</config>

然后吗需要创建一个系统配置文件来激活这个模块

app/etc/modules/Magentotutorial_Helloworld.xml
<config>
    <modules>
        <Magentotutorial_Configviewer>
            <active>true</active>
            <codePool>local</codePool>
        </Magentotutorial_Configviewer>
    </modules>
</config>

最后让我们检查一下模块是不是已经被激活

确认 Infinity_Helloworld 显示出来了。

下面,我们需要配置一个路由.路由是一个用来把一个url请求转换成一个控制器和方法.和传统的phpmvc代码不同的是你需要在magento的全局配置中显式的定义你的路由.我们继续上面的例子,在config.xml中,添加如下代码

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <modules>
        <Magentotutorial_Helloworld>
            <verson>0.2.0</verson>
        </Magentotutorial_Helloworld>
    </modules>
    <frontend>
        <routers>
            <helloworld>
                <use>standard</use>
                <args>
                    <module>Magentotutorial_Helloworld</module><!--模块名-->
                    <frontName>helloworld</frontName> <!--控制器名-->
                    
                </args>
            </helloworld>
        </routers>
    </frontend>
</config>

在这里我们有许多名词要解释

什么是fronted

frontend标签指向一个magento区(Area),比如frontend就是指网站的前台,admin是指网站的后台,install是指magento的安装程序

这个有点像磁盘分区,区和区之间是相互独立的,但是都归操作系统能够管理,在这里归 Magento 管理。默认的 Magento 安装没有“install”这个区,frontend 区接管了

什么是routers

routes标签又是包含的是路由对象的定义,有时候包含的是路径的定义.路由对象是进行路由操作的实体,而路径仅仅是路由对象的一个参数

注: 如果你仔细看过那个全局配置 xml 的话,你会发现有两处地方出现 routers,一处是“web -> routers”,另外一处是“frontend-> routers”。你再仔细看看会发现两处 routers。包含的内容不一样。第一处包含的是路由对象的定义,第二处包含的是路径的定义。

什么是frontname

当一个router解析一个url时候,它是按照如下规则进行的

http://example.com/frontName(模块名)/actionControllerName(控制器)/actionMethod(方法)/

所以当我们在front标签里定义了hellworld以后,magento会把如下的url请求交给我们的模块

"Magentotutorial_Helloworld"来处理

有些人容易把frontname和前端控制器font controller(前端控制器混淆),它们是俩个不同的概念,frontname只跟路由有关,学过zf的人都知道,其实就是个模块名

根据我们之前讲过的amgento的mvc流程,前端控制器是用来实例化所有路由的,而这里frontname只是路由过程中的一个参数

helloworld这个标签的名字是模块名字的小写版本.我们的模块名字是helloworld,所以我们用helloworld你应该也已经注意到我们定义的frontname也是和我们模块向匹配的,这是一个不成文的规定,但是不是强制的要求.事实上,一个模块也可以定义多个,也就是可以有多个,也就是可以有多个frontname

为路由创建控制器

还记得 Magento 的 MVC 流程吗?路由会把控制权交给控制器。上面我们定义了路由,现在我们来定义我们的控制器。

首先创建文件

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

模块的控制器一个放在子目录controllers里面,这是规定.magento会在这个目录寻找模块的控制器文件.我们的第一个控制器包含以下内容

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

清空缓存访问

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

也可以访问

http://exmaple.com/helloworld/

如果没有出错的话,页面中应该能显示”Hello World”。恭喜你,你已经成功搞定了第一个Magento控制器。

动作控制器文件路径

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

动作控制器命名方式

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

<module>Magentotutorial_Helloworld</module>

动作控制器的命名应该遵循以下规则,

  • 以配置文件<module>标签中但值起头(Magentotutorial_helloworld)
  • 紧接着跟着一个下划线(Magentotutorial_helloworld_)
  • 再接着是该控制器的名字(Magentotutorial_helloworld_Index)
  • 最后加上Controller((Magentotutorial_helloworld)_IndexController)

index/index路径

上文中提到过,Magento的url地址按照以下规则进行路由解析

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

那么在下面这个地址中

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

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

如果URL地址中缺少控制器及方法部分,Magento默认使用index,所以下面地址访问的页面是相同的。

控制器路径

让我们试着添加一个非默认方法到控制器中,添加如下代码到indexcontroller.php

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

然后访问下面地址

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

结果

Param: foo
Value: bar
Param: baz
Value: eof

关于Magento控制器的介绍已经完成了。虽然看起来比其他的PHP MVC框架要复杂许多,它的高度可扩展性却允许你创建任何你想要的URL结构。

Last modification:April 20, 2022
如果觉得我的文章对你有用,请随意赞赏