ThinkPHP3.2特殊控制器

Published on 2016 - 09 - 26

空操作

空操作是指系统在找不到请求的操作方法的时候,会定位到空操作(_empty)方法来执行,利用这个机制,我们可以实现错误页面和一些URL的优化。

例如,下面我们用空操作功能来实现一个城市切换的功能。 我们只需要给CityController类定义一个_empty(空操作)方法:

<?php
namespace Home\Controller;
use Think\Controller;
class CityController extends Controller{
    public function _empty($name){
        //把所有城市的操作解析到city方法
        $this->city($name);
    }

    //注意 city方法 本身是 protected 方法
    protected function city($name){
        //和$name这个城市相关的处理
         echo '当前城市' . $name;
    }
}

接下来,我们就可以在浏览器里面输入

http://serverName/index.php/Home/City/beijing/
http://serverName/index.php/Home/City/shanghai/
http://serverName/index.php/Home/City/shenzhen/

由于City控制器并没有定义beijing、shanghai或者shenzhen操作方法,因此系统会定位到空操作方法 _empty中去解析,_empty方法的参数就是当前URL里面的操作名,因此会看到依次输出的结果是:

当前城市:beijing
当前城市:shanghai
当前城市:shenzhen

注意:空操作方法仅在你的控制器类继承系统的Think\Controller类才有效,否则需要自己定义 __call 来实现。

空控制器

空控制器的概念是指当系统找不到请求的控制器名称的时候,系统会尝试定位空控制器(EmptyController),利用这个机制我们可以用来定制错误页面和进行URL的优化。

现在我们把前面的需求进一步,把URL由原来的

http://serverName/index.php/Home/City/shanghai/

变成

http://serverName/index.php/Home/shanghai/

这样更加简单的方式,如果按照传统的模式,我们必须给每个城市定义一个控制器类,然后在每个控制器类的index方法里面进行处理。可是如果使用空控制器功能,这个问题就可以迎刃而解了。

我们可以给项目定义一个EmptyController类

<?php
namespace Home\Controller;
use Think\Controller;
class EmptyController extends Controller{
    public function index(){
        //根据当前控制器名来判断要执行那个城市的操作
        $cityName = CONTROLLER_NAME;
        $this->city($cityName);
    }
    //注意 city方法 本身是 protected 方法
    protected function city($name){
        //和$name这个城市相关的处理
         echo '当前城市' . $name;
    }
}

接下来,我们就可以在浏览器里面输入

http://serverName/index.php/Home/beijing/
http://serverName/index.php/Home/shanghai/
http://serverName/index.php/Home/shenzhen/

由于系统并不存在beijing、shanghai或者shenzhen控制器,因此会定位到空控制器(EmptyController)去执行,会看到依次输出的结果是:

当前城市:beijing
当前城市:shanghai
当前城市:shenzhen

空控制器和空操作还可以同时使用,用以完成更加复杂的操作。

插件控制器

插件控制器可以更加方便的在控制器以外扩展你的功能,当URL中传入插件控制器变量的时候,会自动定位到插件控制器中的操作方法。

插件控制器的变量由参数 VAR_ADDON 进行设置,默认为addon,例如我们在URL中传入: http://serverName/Home/info/index/addon/SystemInfo

由于传入了addon参数,因此这里的Info控制器并非原来的 Home/Controller/InfoController.class.php

而是调用SystemInfo插件的InfoController控制器了,文件位于 Addon/SystemInfo/Controller/InfoController.class.php。

插件控制器本身的定义和普通的访问控制器一样,例如:

namespace Addon\SystemInfo\Controller;
class InfoController extends \Think\Controller{
    public function index(){
        echo 'Addon SystemInfo';
    }
}

这样,我们在访问http://serverName/Home/info/index/addon/SystemInfo的时候 就会输出 Addon

SystemInfo

如果我们的插件目录不是Addon,而是Plugin,那么需要在配置文件中定义:

'VAR_ADDON'    =>    'plugin'

然后访问URL地址就变成了 http://serverName/Home/info/index/plugin/SystemInfo

操作绑定到类

定义

ThinkPHP3.2版本提供了把每个操作方法定位到一个类的功能,可以让你的开发工作更细化,可以设置参数ACTION_BIND_CLASS,例如:

'ACTION_BIND_CLASS'    =>    True,

设置后,我们的控制器定义有所改变,以URL访问为 http://serverName/Home/Index/index为例,原来的控制器文件定义位置为:

Application/Home/Controller/IndexController.class.php

控制器类的定义如下:

namespace Home\Controller;
use Think\Controller;
class IndexController extends Controller{
    public function index(){
        echo '执行Index控制器的index操作';
    }
}

可以看到,实际上我们调用的是 Home\Controller\IndexController 类的index方法。

设置后,控制器文件位置改为:

Application/Home/Controller/Index/index.class.php

控制器类的定义如下:

namespace Home\Controller\Index;
use Think\Controller;
class index extends Controller{
    public function run(){
        echo '执行Index控制器的index操作';
    }
}

现在,我们调用的其实是 Home\Controller\Index\index 类的run方法。

前置和后置操作

当设置操作方法绑定到类后,前置和后置操作的定义有所改变,只需要在类里面定义_before_run和_after_run方法即可,例如:

namespace Home\Controller\Index;
use Think\Controller;
class index extends Controller{
    public function _before_run(){
        echo 'before_'.ACTION_NAME;
    }

    public function run(){
        echo '执行Index控制器的index操作';
    }

    public function _after_run(){
        echo 'after_'.ACTION_NAME;
    }
}

空控制器

操作方法绑定到类后,一样可以支持空控制器,我们可以创建 Application/Home/Controller/_empty目录,即表示如果找不到当前的控制器的话,会到_empty控制器目录下面定位操作方法。

例如,我们访问了URL地址 http://serverName/Home/Test/index,但并不存在 Application/Home/Controller/Test目录,但是有定义 Application/Home/Controller/_empty目录。

并且我们有定义:

Application/Home/Controller/_empty/index.class.php

控制器定义如下:

namespace Home\Controller\_empty;
use Think\Controller;
class index extends Controller{
    public function run(){
        echo '执行'CONTROLLER_NAME.'控制器的'.ACTION_NAME.'操作';
    }
}

访问http://serverName/Home/Test/index后 输出结果显示:

执行Test控制器的index操作

空操作

操作绑定到类后,我们依然可以实现空操作方法,我们只要定义一个 Home\Controller\Index_empty类,就可以支持Index控制器的空操作访问,例如: 控制器定义如下:

namespace Home\Controller\Index;
use Think\Controller;
class _empty extends Controller{
    public function run(){
        echo '执行Index控制器的'.ACTION_NAME.'操作';
    }
}

当我们访问http://serverName/Home/Index/test后 输出结果显示:

执行Index控制器的test操作

参考文献