<?php
/**
* web20vn.com Router
*
* @author Le Khac Nhu <hide@address.com>
* @author brandlover <hide@address.com>
* @copyright http://web20vn.com
* @version 1.0 [20080128]
*/
$time_start = microtime(true);
class web20vnRouter
{
public static $uri = null;
public static $url_suffix = '.html';
public static $index_file = 'web20vn_router.php';
public static $routes = array();
public static $placeholder = array(
':any' => '.+',
':alias' => '[a-zA-Z0-9\_\-\.]+',
':num' => '[0-9]+',
':year' => '[0-9]{4}',
':month' => '[0-9]{2}',
':day' => '[0-9]{2}',
);
public static $routed = array(
'controller' => '',
'action' => '',
'args' => '',
);
public static $default = array(
'controller' => 'welcome',
'action' => 'index',
);
public static function call($uri = null)
{
if(empty($uri))
{
self::getUri();
}
self::start();
}
public static function getUri()
{
$temp_url = '';
if(isset($_GET['q']) && $_GET['q'] != '')
{
$temp_url = $_GET['q'];
}
elseif (isset($_SERVER['PATH_INFO']) && $_SERVER['PATH_INFO'])
{
$temp_url = $_SERVER['PATH_INFO'];
}
elseif (isset($_SERVER['ORIG_PATH_INFO']) && $_SERVER['ORIG_PATH_INFO'])
{
$temp_url = $_SERVER['ORIG_PATH_INFO'];
}
elseif (isset($_SERVER['PHP_SELF']) && $_SERVER['PHP_SELF'])
{
$temp_url = $_SERVER['PHP_SELF'];
}
$temp_url = trim($temp_url, '/');
if (($offset = strpos($temp_url, self::$index_file)) !== false)
{
$offset += strlen(self::$index_file);
$temp_url = substr($temp_url, $offset);
}
if (strpos($temp_url, self::$url_suffix) !== false)
{
$temp_url = preg_replace('#'.preg_quote(self::$url_suffix).'$#u', '', $temp_url);
//$temp_url = replace_once(self::$url_suffix, '', $temp_url);
}
self::$uri = preg_replace('#/+#', '/', $temp_url);
}
public static function start()
{
$is_routed = false;
// Neu rong => mac dinh (trang chu)
if (empty(self::$uri) || self::$uri === '/')
{
self::$routed['controller'] = self::$default['controller'];
self::$routed['action'] = self::$default['controller'];
$is_routed = true;
}
else
{
if(count(self::$routes) > 0)
{
foreach(self::$routes as $rule => &$route)
{
if(!isset($route['u']))
{
exit('Route khong hop le: '.$rule);
}
$routed_c = isset($route['c']) ? $route['c'] : self::$default['controller'];
$routed_a = isset($route['a']) ? $route['a'] : self::$default['action'];
if($route['u'] === self::$uri)
{
self::$routed['controller'] = $routed_c;
self::$routed['action'] = $routed_a;
$is_routed = true;
break;
}
if(strpos($route['u'], '?') !== false)
{
if(!isset($route['r']))
{
exit('Trong route ('.$rule.') chua co regex!!!');
}
// Tao params...
$i = 0;
foreach($route['r'] as $rr)
{
if($rr[0] == '(')
{
$p = isset($route['p'][$i]) ? $route['p'][$i] : 'p'.$i;
$route['r'][$i] = replace_once('(', '(?P<'.$p.'>', $rr);
}
++$i;
}
$r_ex = web20vnReplace($route['u'], $route['r']);
// Placeholder
if (strpos($r_ex, ':') !== false) {
$r_ex = strtr($r_ex, self::$placeholder);
}
if(preg_match('#^'.$r_ex.'$#ui', self::$uri, $matches))
{
self::$routed['args'] = array_slice($matches, 1);
self::$routed['controller'] = $routed_c;
self::$routed['action'] = $routed_a;
$is_routed = true;
break;
}
}
}
if(!$is_routed)
{
$rs = explode('/', self::$uri);
//Controller:
if (count($rs) && !empty($rs[0])) {
self::$routed['controller'] = array_shift($rs);
}
else
{
self::$routed['controller'] = self::$default['controller'];
}
//Action:
if (count($rs) && !empty($rs[0])) {
self::$routed['action'] = array_shift($rs);
}
else
{
self::$routed['action'] = self::$default['action'];
}
$segs = count($rs);
if($segs)
{
for ($i = 0; $i < $segs; ++$i)
{
$as[$i] = isset($rs[$i]) ? urldecode($rs[$i]) : null;
}
self::$routed['args'] = $as;
}
unset($rs, $as);
}
}
}
}
}
function web20vnReplace($str, $args = array(), $sc = '?')
{
if(strpos($str, $sc) !== false && !empty($args))
{
$s = '';
$arr = explode($sc, $str);
for($i = 0, $count = count($arr); $i < $count; $i++)
{
if(!isset($args[$i]))
{
$s .= $arr[$i];
continue;
}
$s .= $arr[$i].$args[$i];
}
return $s;
}
return $str;
}
function replace_once($search, $replace, $subject)
{
if(($pos = strpos($subject, $search)) !== false)
{
$ret = substr($subject, 0, $pos).$replace.substr($subject, $pos + strlen($search));
}
else
{
$ret = $subject;
}
return $ret;
}
/******************************************************
// Example
// http://localhost/web20vn_router.php?q=welcome/index
.htacess
RewriteEngine ON
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.*)$ web20vn_router.php?q=$1 [L,QSA]
*******************************************************/
web20vnRouter::$routes += array(
'blog1' => array(
'u' => 'blog/?/?',
'r' => array('(:year/:month/:day)', '(:alias)'),
'p' => array('ymd', 'alias'),
'c' => 'welcome', 'a' => 'view_blog',
)
);
web20vnRouter::call();
?>
<a href="/web20vn_router.php?q=welcome/index">Welcome => index</a>
<br />
<a href="/web20vn_router.php?q=blog/2008/02/07/chuc-mung-nam-moi.html">Blog => chuc-mung-nam-moi</a>
<br />
<?php
echo '<pre>';
echo web20vnRouter::$uri."\n";
print_r(web20vnRouter::$routed);
echo '</pre>';
$time_end = microtime(true);
$time = $time_end - $time_start;
exit('Time: '.$time);