【发布时间】:2011-06-24 08:44:07
【问题描述】:
我正在寻找一种方法来提供类似于 Django 中的 URL 路由。我在网上查看了很多资源,我喜欢cobweb,但问题是我不想使用整个框架,我只想使用 URL 重新路由逻辑/代码。对于类似 Django 的 URL 路由逻辑是否有很好的资源?
【问题讨论】:
标签: php django url-rewriting url-routing
我正在寻找一种方法来提供类似于 Django 中的 URL 路由。我在网上查看了很多资源,我喜欢cobweb,但问题是我不想使用整个框架,我只想使用 URL 重新路由逻辑/代码。对于类似 Django 的 URL 路由逻辑是否有很好的资源?
【问题讨论】:
标签: php django url-rewriting url-routing
您可以查看CakePHP。我不知道将 URL 路由逻辑从框架的其余部分中提取出来是多么容易。
【讨论】:
我不认为是完全相同的,但是 Zend 框架具有您可能想要查看的非常好的下降路由功能。 Zend 框架是一种基于组件的框架,它不会强迫您使用整个框架。但我认为,如果您使用路由功能,您可能还需要使用它们的控制器机制,因为路由器是建立在顶部的。
【讨论】:
我看过 Limonade 微型 PHP 框架的 URL 路由发布了一个使用 limonade 代码库的回复。但是我回去查看了蜘蛛网代码,它有点漂亮和漂亮。所以我只是采用了 Cobweb 的 URL 路由并在 OOP PHP5.x 中对其进行了重构,以便在我自己的代码中使用。
比较参见:- http://docs.djangoproject.com/en/dev/topics/http/urls/ vs. http://www.limonade-php.net/README.htm
通常的免责声明已经到位
1) 我没有测试太多!
2) 它可能不具备 Django 的所有 URL 路由功能
<?php
/**
*
* @author rajeev jha (jha dot rajeev at gmail)
* Django style URL routing.
* Pattern matching logic of this code is copied from cobweb framework
* @see http://code.google.com/p/cobweb/source/browse/trunk/dispatch/url_resolver.class.php
*
*/
class Gloo_Core_Router {
private $table ;
function __construct() {
//initialize routing table
$this->table = new Gloo_Core_RoutingTable();
}
function getRoute($path,$domain=NULL){
if(empty($path)) {
$message = sprintf("Please supply a valid path to match :: got [%s] ", $path);
trigger_error($message,E_USER_ERROR);
}
//all rules for this domain
$rules = $this->table->getRules($domain);
$route = NULL ;
if($path == '/')
$route = $this->matchHome($rules);
else
$route = $this->match($rules,$path);
return $route ;
}
private function matchHome($rules) {
$route = NULL ;
foreach($rules as $rule) {
if($rule["pattern"] == '/') {
$route = $this->createRoute($rule,array());
}
}
return $route ;
}
private function match($rules,$path) {
$path = ltrim($path, '/');
$matches = array();
$route = NULL ;
foreach($rules as $rule) {
if(preg_match($this->patternize($rule["pattern"]),$path,$matches) != 0 ) {
//match happened
$matches = $this->sanitizeMatches($matches);
$route = $this->createRoute($rule,$matches);
}
}
return $route ;
}
private function createRoute($rule,$matches) {
$route = $rule ;
//add parameters
$route["params"] = $matches ;
return $route ;
}
private function sanitizeMatches($matches){
//discard the first one
if (count($matches) >= 1)
$matches = array_splice($matches,1);
$unset_next = false;
//group name match will create a string key as well as int key
// like match["token"] = soemthing and match[1] = something
// remove int key when string key is present for same value
foreach ($matches as $key => $value) {
if (is_string($key)){
$unset_next = true;
} else if (is_int($key) && $unset_next) {
unset($matches[$key]);
$unset_next = false;
}
}
return array_merge($matches);
}
private function patternize($pattern) {
//http://www.php.net/manual/en/reference.pcre.pattern.modifiers.php
//treat pattern as UTF-8
return '{'.$pattern.'}u' ;
}
}
?>
<?php
/**
*
* @author rajeev jha (jha dot rajeev at gmail)
* Django style URL routing.
* URL routing table
*
*/
class Gloo_Core_RoutingTable {
private $rules ;
private $splrules ;
const ANY_DOMAIN = '__ANY__' ;
function __construct() {
$this->rules = array();
$this->splrules = array();
//@todo inject from outside
$this->createRule(self::ANY_DOMAIN, '/', 'Gloo_Controller_Home');
//match alphanumeric + dashes
//a pcre word (\w) does not contain dashes
$this->createRule(self::ANY_DOMAIN, '^(?P<token>[-\w]+)$','Gloo_Controller_Post');
$this->createRule(self::ANY_DOMAIN, '^page/(?P<pagenum>\d+)$','Gloo_Controller_Home');
$this->createRule(self::ANY_DOMAIN, '^(?P<token>\w+)/page/(?P<pagenum>\d+)$','Gloo_Controller_Post');
$this->createRule(self::ANY_DOMAIN, '^category/(?P<name>\w+)$','Gloo_Controller_Category');
$this->createRule(self::ANY_DOMAIN, '^category/(?P<name>\w+)/page/(?P<pagenum>\d+)$','Gloo_Controller_Category');
//special rules
$this->createRule('www.test1.com','^(?P<token>\w+)$','Gloo_Controller_File', array("template" => "post.php"));
}
function createRule($domain,$pattern,$action,$options=NULL) {
if(empty($domain)) {
trigger_error("No domain supplied for rule" ,E_USER_ERROR);
}
$rule = array();
$rule["pattern"] = $pattern;
$rule["action"] = $action ;
//Add options
if(is_null($options))
$rule["options"] = array();
else
$rule["options"] = $options ;
$rule["domain"] = $domain ;
//add to generic or domain specific rules
if($domain == self::ANY_DOMAIN)
$this->rules[] = $rule ;
else
$this->splrules[$domain][] = $rule ;
}
function getRules($domain) {
if(empty($domain))
return $this->rules ;
//valid domain - rules as well
// add to existing rules
if(array_key_exists($domain,$this->splrules)) {
$splrules = $this->splrules[$domain];
$rules = array_merge($this->rules,$splrules);
return $rules ;
} else {
return $this->rules ;
}
}
}
?>
现在,您可以向路由表初始化添加任何规则。根据您提供给路由器的域+“路径”,您将获得“控制器”字符串以及“命名组”参数和其他匹配的参数。我不包括“控制器”字符串的类实例化逻辑,因为 1)那会很复杂 2) 如果您的目的只是获得类似 Django 的 URL 路由,那么这已经足够了。
参考文献
柠檬水代码在这里:- https://github.com/sofadesign/limonade/blob/master/lib/limonade.php
蜘蛛网代码在这里:- http://code.google.com/p/cobweb/source/browse/trunk/dispatch/url_resolver.class.php
$router = new Gloo_Core_Router();
$path = 'category/news/page/3' ;
printf("Now matching path [%s]" , $path);
$route = $router->getRoute($path);
print_r($route);
$path = '/category/Health/page' ;
printf("Now matching path [%s]" , $path);
$route = $router->getRoute($path);
print_r($route);
您必须更改类名并包含依赖项,但是嘿,您是程序员;D
【讨论】:
我用 codeigniter 和 django 资源开发了一个类似的框架,http://williamborba.github.io/willer/quick_start/
目前还是测试版,不过我正在逐步实现和改进 URL.php 文件与 URLS.py django 非常相似。
另一个亮点是模型和 ORM,很像 django,但与 codeigniter 活动记录类似。
【讨论】: