Router.php 4.3 KB
<?php
/**
 * The Router class
 */
class LtRouter
{
	public $configHandle;
	public $routingTable;
	public $module;
	public $action;

	public function __construct()
	{
		if (! $this->configHandle instanceof LtConfig)
		{
			if (class_exists("LtObjectUtil"))
			{
				$this->configHandle = LtObjectUtil::singleton("LtConfig");
			}
			else
			{
				$this->configHandle = new LtConfig;
			}
		}
	}

	public function init()
	{
		$this->routingTable = $this->configHandle->get("router.routing_table");
		if (empty($this->routingTable))
		{
			$this->routingTable = array('pattern' => ":module/:action/*",
				'default' => array('module' => 'default', 'action' => 'index'),
				'reqs' => array('module' => '[a-zA-Z0-9\.\-_]+',
					'action' => '[a-zA-Z0-9\.\-_]+'
					),
				'varprefix' => ':',
				'delimiter' => '/',
				'postfix' => '',
				'protocol' => 'PATH_INFO', // REWRITE STANDARD
				);
		}

		$delimiter = $this->routingTable['delimiter'];
		$postfix = $this->routingTable['postfix'];
		$protocol = strtoupper($this->routingTable['protocol']);
		$module = '';
		$action = '';
		$params = array();
		// HTTP HTTPS
		if (isset($_SERVER['SERVER_PROTOCOL']))
		{
			if (isset($_SERVER['PATH_INFO']) && !empty($_SERVER['PATH_INFO']))
			{ 
				// 忽略后缀
				$url = rtrim($_SERVER['PATH_INFO'], "$postfix");
				$url = explode($delimiter, trim($url, "/"));
			}
			else if (isset($_SERVER['REQUEST_URI']))
			{
				if ('REWRITE' == $protocol)
				{
					if (0 == strcmp($_SERVER['REQUEST_URI'], $_SERVER['SCRIPT_NAME']))
					{
						$url = array();
					}
					else
					{
						$url = substr($_SERVER['REQUEST_URI'], strlen(pathinfo($_SERVER['SCRIPT_NAME'], PATHINFO_DIRNAME)));
						$url = rtrim($url, "$postfix");
						$url = explode($delimiter, trim($url, "/"));
					}
				}
				else if ('PATH_INFO' == $protocol)
				{
					$url = substr($_SERVER['REQUEST_URI'], strlen($_SERVER['SCRIPT_NAME']));
					$url = rtrim($url, "$postfix");
					$url = explode($delimiter, trim($url, "/"));
				}
				else //STANDARD
				{
					$url = array();
					foreach($_GET as $v)
					{
						$url[] = $v;
					}
				}
			}
			else
			{
				$url = array();
				foreach($_GET as $v)
				{
					$url[] = $v;
				}
			}
			$params = $this->matchingRoutingTable($url);
			$module = $params['module'];
			$action = $params['action'];
		}
		else
		{ 
			// CLI
			$i = 0;
			while (isset($_SERVER['argv'][$i]) && isset($_SERVER['argv'][$i + 1]))
			{
				if (("-m" == $_SERVER['argv'][$i] || "--module" == $_SERVER['argv'][$i]))
				{
					$module = $_SERVER['argv'][$i + 1];
				}
				else if (("-a" == $_SERVER['argv'][$i] || "--action" == $_SERVER['argv'][$i]))
				{
					$action = $_SERVER['argv'][$i + 1];
				}
				else
				{
					$key = $_SERVER['argv'][$i];
					$params[$key] = $_SERVER['argv'][$i + 1];
				}
				$i = $i + 2;
			}
		}
		// 如果$_GET中不存在配置的变量则添加
		foreach($params as $k => $v)
		{
			!isset($_GET[$k]) && $_GET[$k] = $v;
		}
		$this->module = $module;
		$this->action = $action;
	}

	/**
	 * url 匹配路由表
	 * 
	 * @param  $ [string|array] $url
	 * @return 
	 * @todo 修复导致$_GET多出属性的BUG
	 * @todo 如果是rewrite或者path_info模式,可能需要unset module和action两个$_GET变量
	 */
	public function matchingRoutingTable($url)
	{
		$ret = $this->routingTable['default']; //初始化返回值为路由默认值
		$reqs = $this->routingTable['reqs'];
		$delimiter = $this->routingTable['delimiter'];
		$varprefix = $this->routingTable['varprefix'];
		$postfix = $this->routingTable['postfix'];
		$pattern = explode($delimiter, trim($this->routingTable['pattern'], $delimiter));

		/**
		 * 预处理url
		 */
		if (is_string($url))
		{
			$url = rtrim($url, $postfix); //忽略后缀
			$url = explode($delimiter, trim($url, $delimiter));
		}

		foreach($pattern as $k => $v)
		{
			if ($v[0] == $varprefix)
			{ 
				// 变量
				$varname = substr($v, 1); 
				// 匹配变量
				if (isset($url[$k]))
				{
					if (isset($reqs[$varname]))
					{
						$regex = "/^{$reqs[$varname]}\$/i";
						if (preg_match($regex, $url[$k]))
						{
							$ret[$varname] = $url[$k];
						}
					}
				}
			}
			else if ($v[0] == '*')
			{
				// 通配符
				$pos = $k;
				while (isset($url[$pos]) && isset($url[$pos + 1]))
				{
					$ret[$url[$pos ++]] = urldecode($url[$pos]);
					$pos++;
				}
			}
			else
			{ 
				// 静态
			}
		}
		return $ret;
	}
}