| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 | <?phpnamespace 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);	}}
 |