123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- <?php
- namespace KIF;
- use KIF\Core\Request;
- use KIF\Core\Config;
- use KIF\String\String;
- use KIF\Math\Math;
- /**
- *
- * 路由类
- * @author gaoxiaogang
- *
- */
- class Route {
-
- /**
- *
- * Enter description here ...
- * @var array 格式:array(
- * $route_file => array(
- * 'instance' => (Route),
- * 'rules' => array(
- * (string) $rewrite_pattern => (array) $rule,
- * ... ,
- * ),
- * 'reverse_rules' => array(
- * (string)$fingerprint => (string)$rewrite_pattern,
- * ... ,
- * ),
- * ),
- * );
- */
- static private $structs;
-
- protected $struct;
-
- # 禁止被外部new
- private function __construct($route_file) {
- if (!file_exists($route_file) || !is_file($route_file)) {
- $route_rules = array();
- } else {
- $route_rules = include($route_file);
- }
- $rules = array();
- $reverse_rules = array();
- if (!$route_rules || !is_array($route_rules)) {
- self::$structs[$route_file]['rules'] = $rules;
- self::$structs[$route_file]['reverse_rules'] = $reverse_rules;
- return;
- }
-
- foreach ($route_rules as $rewrite_pattern => $rule) {
- if (!isset($rule['a']) || !$rule['a']) {
- $rule['a'] = 'default';
- }
- $fingerprint = $this->generateFingerprint($rule);
-
- $rules[$rewrite_pattern] = $rule;
- $reverse_rules[$fingerprint] = $rewrite_pattern;
- }
- self::$structs[$route_file]['rules'] = $rules;
- self::$structs[$route_file]['reverse_rules'] = $reverse_rules;
- }
-
- /**
- *
- * 生成指纹,方便反向rewrite时高效查找。
- * @param array $args
- * @return string
- */
- private function generateFingerprint($args) {
- if (!isset($args['a'])) {
- $args['a'] = 'default';
- }
- $arg_eles = array_combine(array_keys($args), array_fill(0, count($args), null));
- if (isset($args['a']))
- $arg_eles['a'] = $args['a'];
- if (isset($args['c']))
- $arg_eles['c'] = $args['c'];
- ksort($arg_eles);
- return Math::md5_16(print_r($arg_eles, true));
- }
-
- /**
- *
- * @return KIF\Route
- */
- static public function getInstance() {
- $route_file = Config::getInstance()->get('route_file');
- $route_file = realpath($route_file);
- if (!isset(self::$structs[$route_file])) {
- self::$structs[$route_file]['instance'] = new self($route_file);
- }
- self::$structs[$route_file]['instance']->struct = & self::$structs[$route_file];
- return self::$structs[$route_file]['instance'];
- }
-
- /**
- *
- * 实现细节:
- * 根据当前app的路由配置,查找到指定条目,并将当前path里携带的参数存放进 $_GET和$_REQUEST变量里
- * 对当前请求路由
- *
- */
- public function rewrite() {
- $path = Request::getInstance()->path();
- $rules = $this->struct['rules'];
- foreach ($rules as $pattern => $rule) {
- $pattern = "#^{$pattern}$#";
- if (preg_match($pattern, $path, $matches)) {
- foreach ($rule as $param => $paramVal) {
- if ($paramVal{0} != '$') {
- $_GET[$param] = $paramVal;
- $_REQUEST[$param] = $paramVal;
- } else {
- $match_pos = substr($paramVal, 1);
- if (Verify::naturalNumber($match_pos)) {
- $_GET[$param] = $matches[$match_pos];
- $_REQUEST[$param] = $matches[$match_pos];
- }
- }
-
- }
- break;
- }
- }
- }
-
- /**
- *
- * 获取经过路由后得到的请求参数。目前该方法被 Request::pageUrlTpl使用
- * @return array 如果没有对应的路由,返回空数组
- */
- public function getsRouteParams() {
- $route_params = array();
- $path = Request::getInstance()->path();
- $rules = $this->struct['rules'];
- foreach ($rules as $pattern => $rule) {
- $pattern = "#^{$pattern}$#";
- if (preg_match($pattern, $path, $matches)) {
- foreach ($rule as $param => $paramVal) {
- if ($paramVal{0} != '$') {
- $route_params[$param] = $paramVal;
- } else {
- $match_pos = substr($paramVal, 1);
- if (Verify::naturalNumber($match_pos)) {
- $route_params[$param] = $matches[$match_pos];
- }
- }
- }
- break;
- }
- }
-
- return $route_params;
- }
-
- /**
- *
- * 反向rewrite。通过 $args 给定的参数,逆向rewrite规则,获取rewrite的url
- * @param array $args 给定的参数值
- * @return String
- */
- public function reverse(array $args) {
- if (!$args) {
- return false;
- }
- if (!isset($args['a'])) {
- $args['a'] = 'default';
- }
- $arg_fingerprint = $this->generateFingerprint($args);
- if (isset($this->struct['reverse_rules'][$arg_fingerprint])) {
- $rewrite_pattern = $this->struct['reverse_rules'][$arg_fingerprint];
- if (strpos($rewrite_pattern, '(') === false) {
- return $rewrite_pattern;
- }
- $rule = $this->struct['rules'][$rewrite_pattern];
-
- $rule = array_filter($rule, function ($tmpV) {
- if ($tmpV{0} != '$') {
- return false;
- }
- return $tmpV;
- });
-
- $match_times = 0;
- $url = preg_replace_callback('#\([^)]+\)#', function ($matches) use (& $match_times, $rule, $args) {
- $match_times++;
- $key = array_search("\${$match_times}", $rule);
- if (!$key) {
- return false;
- }
- if (!isset($args[$key])) {
- return false;
- }
-
- return $args[$key];
- }, $rewrite_pattern);
-
- if (is_null($url)) {//说明发生错误了。
- return String::jointUrl('', $args);
- }
-
- return $url;
- }
-
- return String::jointUrl('', $args);
- }
- }
|