I really like how symfony handles routing (internal URIs and external URLS, especially the "reverse lookup" side). I have been trying to implement a similar (standalone) routing as an exercise (and possible use in the future). However, after trying for hours, I am no-where close. :(
I can see that symfony uses a tokenizer to parse the uris. I am attempting a different approach (code below).
function url_for($page){
if($page[0] == '@'){
preg_match('/@([^\\.?]+)\??(.*)/', $page, $matches);
list(, $label, $params_str) = $matches;
parse_str($params_str, $params);
$package = isset(self::$routes[trim($label)]['params']['package']) ? self::$routes[trim($label)]['params']['package'] : (isset($params['package']) ? $params['package'] : NULL);
$module = isset(self::$routes[trim($label)]['params']['module']) ? self::$routes[trim($label)]['params']['module'] : (isset($params['module']) ? $params['module'] : NULL);
$action = isset(self::$routes[trim($label)]['params']['action']) ? self::$routes[trim($label)]['params']['action'] : (isset($params['action']) ? $params['action'] : NULL);
} else {
preg_match('/([^\\.]+)\\\\([^\\.]+)\\\\([^\\.?]+)\??(.*)/', $page, $matches);
list(, $package, $module, $action, $params_str) = $matches;
parse_str($params_str, $params);
}
array_shift($matches);
array_pop($matches);
if($action == NULL) return '';
$found = FALSE;
foreach($routes as $route){
preg_match_all('/:([^\\.\/]+)/', $route['pattern'], $possible_keys);
$possible_keys = array_merge($route['params'], array_flip($possible_keys[1]));
$given_keys = array_merge($route['params'], $params);
$intersection = array_intersect_key($possible_keys, $given_keys);
if(count($possible_keys) <= count($intersection)){
$found = TRUE;
break;
}
}
if($found){
return $route['pattern'];
}
return '';
}
Where the $routes array is as follows:
array(
'home' => array(
'pattern' => '/',
'params' => array(
'package' => 'Module',
'module' => 'Home',
'action' => 'Index'
)
),
'user' => array(
'pattern' => '/user/:action',
'params' => array(
'package' => 'Module',
'module' => 'User'
)
),
'default' => array(
'pattern' => '/:module/:action',
'params' => array(
'package' => 'Modul开发者_运维知识库e'
)
)
);
A few things confuse me:
1) How does symfony handle the asterisk ("*") pattern?
2) How does the router "determine" the correct route? For e.g. what happens to "extra" parameters sent as the internal URI?I hope some symfony guru can enlighten me! :p
Don't reinvent the wheel. If it's already written and it's good - use it! Symfony is an open source project. Look at the code ;)
Symfony 1.4 is far more decoupled than 1.0. In fact you're able to use routing without symfony. Check out this blog post: http://pookey.co.uk/wordpress/archives/80-playing-with-symfony-routing-without-symfony
精彩评论