| hu's profile混吃等死滴高手PhotosBlogLists | Help |
|
|
November 30 DIY Route for PHP大多基于MVC模型的framework都有叫做route的东西来实现Controller层。
最近因为一个项目需要使用php4实现,Model层使用原有已经积累了的封装的数据处理层,View使用smarty模板,
但没有Controller层或现有的controller层比较薄并且松散凌厉。虽然用apache的rewrite机制实现了类似http://www.domian.com/book/item/123/review 这样搜索引擎友好的url。
好好的MVC少了一块多不爽,于是想实现个类似rails route的东西,能把用户的request转换成controller object的method call.
建个模先,
http://www.domian.com/book/ => $book->index()
http://www.domian.com/book/30 => $book->index(20), page = 30
http://www.domian.com/book/register => $book->register() http://www.domian.com/book/category/1 => $book->category(1) http://www.domian.com/book/category/3/20 => $book->category(3,20), page = 20 http://www.domian.com/book/item/123 => $book->item(123) http://www.domian.com/book/item/123/review => $book->item(123)->review() 前面的是设计好的url,后面是映射到的method call。url去掉域名既是参数,如/book/register。php中可以通过 $_SERVER['PATH_INFO']变量获取path_info。path_info中的参数可以按照:controller, :action, :param, :page, :nested_action进行分类。
=>后面是映射到的method call。注:path_info在apache2上需要配置AcceptPathInfo on 才可以。
现在两头的东西都有了,url参数可以通过path_info获取,被调用的method可以定义在一个类里,中间的映射怎么搞呢?
于是定义了个映射阵列,
var $_url_pattern = array( "c" => array("/\//", "%c->index()"), "c/n" => array("/\/(\d+)/", "%c->index('%n')"), // controller/page "c/a" => array("/\/[a-z](\w+)/", "%c->%a()"), // controller/action "c/a/p" => array("/\/[a-z](\w+)\/(\w+)/", "%c->%a('%p')"), // controller/action/param "c/a/p/n" => array("/\/[a-z](\w+)\/(\w+)\/(\d+)/", "%c->%a('%p', '%n')"), // controller/action/param/page "c/a/p/o" => array("/\/[a-z](\w+)\/(\w+)\/[a-z](\w+)/", "\$r = %c->%a('%p'); \$r->%o()") // controller/action/param/other.action ); url_pattern的key是个flag用来标识参数类型序列的,value分两部分,前面是定义的正则表达式用来匹配path_info,后面是method call的指令模板,确定这些实现这个route就不算什么问题了,对key按照字符长度进行逆序排序,然后匹配。把匹配了的参数带入指令模板然后eval就可以了。代码较长,不贴了.
route这样用,定义book.php,只是个入口,apache解析url最先找的是book.php.
<?
require_once 'route.php';
$controller = 'bookcontroller'; $rt = new CRoute(); $rt->dispatch($controller); ?>
定义mycontroller.php
<?
class BookController { function index($param = null){
print 'book.lindex and page='.$param; } function register(){ //do register print 'book.register'; } function category($param1 = null, $param2=null) { print 'category:'.$param1.' and '.$param2; } function item($param=null) { //do something print 'book item:'.$param.'</br>'; return new Item($param); // the object has a method named review() } } class Item {
var $param = null; function Item($param){ $this->param = $param; } function review(){ print 'review:'.$this->param; } } ?> |
|
|