查看文章
 
理想的Controller
2009年05月25日 星期一 下午 7:40
作者:老王

现有的PHP框架,如CakePHP,其Controller的运作模式基本是类Rails的方式:

class ArticlesController extends AppController {
    function index() {}
    function view() {}
    function add() {}
    function edit() {}
    function delete(
) {
        if ($this->Article->del($this->params['id'])) {
            $this->redirect(array('action'=>'index'));
        }
    }
}


这样的Controller很难透明扩展,主要存在以下问题:

一:当一个请求到达时,比如说是delete,框架会实例化ArticlesController,然后调用delete方法,控制器里的其它代码如index, view, add, edit, delete,都是和delete无关的,对PHP这样的脚本语言来说,每个请求都需要重新初始化环境,从严格意义上讲,任何不必要的多余代码对性能都是有害的。

二:当处理redirect的时候,由于Action一般没有形参,也没有返回值,只能使用的是直接跳转的方式,相当于在方法里硬编码了exit(),这无疑是坏味道,如果我们想用Filter机制扩展delete的话,由于exit()的存在,后面的代码根本没有机会执行,扩展也就不可能了。

如果我设计PHP框架,我会这样设计Controller:

class DeleteController extends Controller implements Executable
{
    protected $filters = array('Transaction');

    public function execute($request, $response)
    {
        // $request->getParams('id');
        $response->setStatus('307 Temporary Redirect');
    }
}


一:一个Action就是一个Controller,多个Action文件可以放到一个文件夹里以模块方式存在。
二:对于redirect,不存在硬编码exit,而是引入response对象,在前端控制器里根据状态码来控制跳转。

乍一看上去,这样的Controller设计方式类似于Java,但用意有些许不同。在Java的一些框架中,如Struts,虽然也把request,response作为Controller形参,但之所以这样做是因为request,response都是有状态的,通过剥离它们,Controller对象本身就变成了无状态的,从而可以在各个请求间得以复用。但是PHP每次请求都要重新建立运行环境,所以本质上是不可能在各个请求间复用Controller对象的,对PHP而言,真正的意义在于,这样的设计给了Controller更灵活,更透明的扩展方式,比如说透明事务处理:

class TransactionFilter extends Decorator implements Executable
{
    public function execute($request, $response)
    {
        try {
            // Transaction begin
            $this->Controller->execute($request, $response);
            // Transaction commit
        } catch (Exception $e) {
            // Transaction rollback
        }
    }
}


在前端控制器里,利用装饰器等模式,可以很容易的把Controller和Filter整合到一起(参考链接),从而透明的给DeleteController加上事务处理的功能,类似的,还可以透明的加上更多的Filter,从而给了Controller无限扩展的能力。

类别:Php||添加到搜藏 |分享到i贴吧|浏览(1023)|评论 (0)
 
最近读者:
 
网友评论:
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
     

   
帮助中心 | 空间客服 | 投诉中心 | 空间协议
©2012 Baidu