`
阿尔萨斯
  • 浏览: 4174597 次
社区版块
存档分类
最新评论

理想的Controller

 
阅读更多

作者:老王

现有的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无限扩展的能力。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics