Router.php 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. <?php
  2. /**
  3. * The Router class
  4. */
  5. class LtRouter
  6. {
  7. public $configHandle;
  8. public $routingTable;
  9. public $module;
  10. public $action;
  11. public function __construct()
  12. {
  13. if (! $this->configHandle instanceof LtConfig)
  14. {
  15. if (class_exists("LtObjectUtil"))
  16. {
  17. $this->configHandle = LtObjectUtil::singleton("LtConfig");
  18. }
  19. else
  20. {
  21. $this->configHandle = new LtConfig;
  22. }
  23. }
  24. }
  25. public function init()
  26. {
  27. $this->routingTable = $this->configHandle->get("router.routing_table");
  28. if (empty($this->routingTable))
  29. {
  30. $this->routingTable = array('pattern' => ":module/:action/*",
  31. 'default' => array('module' => 'default', 'action' => 'index'),
  32. 'reqs' => array('module' => '[a-zA-Z0-9\.\-_]+',
  33. 'action' => '[a-zA-Z0-9\.\-_]+'
  34. ),
  35. 'varprefix' => ':',
  36. 'delimiter' => '/',
  37. 'postfix' => '',
  38. 'protocol' => 'PATH_INFO', // REWRITE STANDARD
  39. );
  40. }
  41. $delimiter = $this->routingTable['delimiter'];
  42. $postfix = $this->routingTable['postfix'];
  43. $protocol = strtoupper($this->routingTable['protocol']);
  44. $module = '';
  45. $action = '';
  46. $params = array();
  47. // HTTP HTTPS
  48. if (isset($_SERVER['SERVER_PROTOCOL']))
  49. {
  50. if (isset($_SERVER['PATH_INFO']) && !empty($_SERVER['PATH_INFO']))
  51. {
  52. // 忽略后缀
  53. $url = rtrim($_SERVER['PATH_INFO'], "$postfix");
  54. $url = explode($delimiter, trim($url, "/"));
  55. }
  56. else if (isset($_SERVER['REQUEST_URI']))
  57. {
  58. if ('REWRITE' == $protocol)
  59. {
  60. if (0 == strcmp($_SERVER['REQUEST_URI'], $_SERVER['SCRIPT_NAME']))
  61. {
  62. $url = array();
  63. }
  64. else
  65. {
  66. $url = substr($_SERVER['REQUEST_URI'], strlen(pathinfo($_SERVER['SCRIPT_NAME'], PATHINFO_DIRNAME)));
  67. $url = rtrim($url, "$postfix");
  68. $url = explode($delimiter, trim($url, "/"));
  69. }
  70. }
  71. else if ('PATH_INFO' == $protocol)
  72. {
  73. $url = substr($_SERVER['REQUEST_URI'], strlen($_SERVER['SCRIPT_NAME']));
  74. $url = rtrim($url, "$postfix");
  75. $url = explode($delimiter, trim($url, "/"));
  76. }
  77. else //STANDARD
  78. {
  79. $url = array();
  80. foreach($_GET as $v)
  81. {
  82. $url[] = $v;
  83. }
  84. }
  85. }
  86. else
  87. {
  88. $url = array();
  89. foreach($_GET as $v)
  90. {
  91. $url[] = $v;
  92. }
  93. }
  94. $params = $this->matchingRoutingTable($url);
  95. $module = $params['module'];
  96. $action = $params['action'];
  97. }
  98. else
  99. {
  100. // CLI
  101. $i = 0;
  102. while (isset($_SERVER['argv'][$i]) && isset($_SERVER['argv'][$i + 1]))
  103. {
  104. if (("-m" == $_SERVER['argv'][$i] || "--module" == $_SERVER['argv'][$i]))
  105. {
  106. $module = $_SERVER['argv'][$i + 1];
  107. }
  108. else if (("-a" == $_SERVER['argv'][$i] || "--action" == $_SERVER['argv'][$i]))
  109. {
  110. $action = $_SERVER['argv'][$i + 1];
  111. }
  112. else
  113. {
  114. $key = $_SERVER['argv'][$i];
  115. $params[$key] = $_SERVER['argv'][$i + 1];
  116. }
  117. $i = $i + 2;
  118. }
  119. }
  120. // 如果$_GET中不存在配置的变量则添加
  121. foreach($params as $k => $v)
  122. {
  123. !isset($_GET[$k]) && $_GET[$k] = $v;
  124. }
  125. $this->module = $module;
  126. $this->action = $action;
  127. }
  128. /**
  129. * url 匹配路由表
  130. *
  131. * @param $ [string|array] $url
  132. * @return
  133. * @todo 修复导致$_GET多出属性的BUG
  134. * @todo 如果是rewrite或者path_info模式,可能需要unset module和action两个$_GET变量
  135. */
  136. public function matchingRoutingTable($url)
  137. {
  138. $ret = $this->routingTable['default']; //初始化返回值为路由默认值
  139. $reqs = $this->routingTable['reqs'];
  140. $delimiter = $this->routingTable['delimiter'];
  141. $varprefix = $this->routingTable['varprefix'];
  142. $postfix = $this->routingTable['postfix'];
  143. $pattern = explode($delimiter, trim($this->routingTable['pattern'], $delimiter));
  144. /**
  145. * 预处理url
  146. */
  147. if (is_string($url))
  148. {
  149. $url = rtrim($url, $postfix); //忽略后缀
  150. $url = explode($delimiter, trim($url, $delimiter));
  151. }
  152. foreach($pattern as $k => $v)
  153. {
  154. if ($v[0] == $varprefix)
  155. {
  156. // 变量
  157. $varname = substr($v, 1);
  158. // 匹配变量
  159. if (isset($url[$k]))
  160. {
  161. if (isset($reqs[$varname]))
  162. {
  163. $regex = "/^{$reqs[$varname]}\$/i";
  164. if (preg_match($regex, $url[$k]))
  165. {
  166. $ret[$varname] = $url[$k];
  167. }
  168. }
  169. }
  170. }
  171. else if ($v[0] == '*')
  172. {
  173. // 通配符
  174. $pos = $k;
  175. while (isset($url[$pos]) && isset($url[$pos + 1]))
  176. {
  177. $ret[$url[$pos ++]] = urldecode($url[$pos]);
  178. $pos++;
  179. }
  180. }
  181. else
  182. {
  183. // 静态
  184. }
  185. }
  186. return $ret;
  187. }
  188. }