Normal.php 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. <?php
  2. namespace Qii\Router\Parse;
  3. /**
  4. * Route规则文件
  5. * 兼容以前版本的匹配规则
  6. *
  7. * @author Jinhui Zhu<jinhui.zhu@live.cn>2015-10-24 23:11
  8. * @version 1.2
  9. */
  10. class Normal
  11. {
  12. const VERSION = '1.2';
  13. private $config;
  14. public function __construct()
  15. {
  16. }
  17. /**
  18. * 设置路由规则
  19. * @param Array $config 路由规则
  20. */
  21. public function setConfig($config)
  22. {
  23. $this->config = $config;
  24. }
  25. /**
  26. * 路由转发, 转发对应的规则中xx不能为*
  27. *
  28. * @param string $url url链接
  29. * @param String $controller
  30. * @param String $action
  31. * @return Array ($controller, $action);
  32. *
  33. * $rules = [
  34. * 'api:*' => 'api\client\*:*',
  35. * 'api:client:admin:*' => 'api\client\{2}:*',
  36. * 'api:admin:*' => 'api\admin\{2}:*',
  37. * 'admin:*' => 'admin\{1}:*',
  38. * 'udp:*' => 'udp\{1}:*',
  39. * 's:*' => 's:index',
  40. * 'index:*' => 'ip:*',
  41. * 'shortURL:*:*' => '\shortURL\*:*'
  42. * ];
  43. *
  44. * $urls = [
  45. * '/api/client/admin' => ['controller' => 'api\client\client', 'action' => 'index'],
  46. * '/api/client/admin/remove' => ['controller' => 'api\client', 'action' => 'remove'],
  47. * '/api/url/add' => ['controller' => 'api\url', 'action' => 'add'],
  48. * '/api/admin/free/add' => ['controller' => 'api\admin\free', 'action' => 'add'],
  49. * '/admin/index' => ['controller' => 'admin\index', 'action' => 'index'],
  50. * '/admin/dir/add' => ['controller' => 'admin\dir', 'action' => 'add'],
  51. * '/udp/index' => ['controller' => 'udp', 'action' => 'index'],
  52. * '/udp/add' => ['controller' => 'udp', 'action' => 'index'],
  53. * '/s/for' => ['controller' => 's', 'action' =>'index'],
  54. * '/index/for' => ['controller' => 'ip', 'action' =>'for'],
  55. * '/usr/login/check' => ['controller' => 'usr\login', 'action' => 'check'],
  56. * '/shortURL/free/sss' => ['controller' => '\shortURL\free', 'action' => 'sss'],
  57. * ];
  58. */
  59. public function parse($url, $controller, $action)
  60. {
  61. if (!$this->config) {
  62. return array('controller' => $controller, 'action' => $action);
  63. }
  64. if($url == '' || $url == '/') $url = 'index/index.html';
  65. $url = ltrim($url, '/');
  66. $dirName = pathinfo($url, PATHINFO_DIRNAME);
  67. $dirInfo = explode('/', $dirName);
  68. $fileName = pathinfo(ltrim($url, '/'), PATHINFO_FILENAME);
  69. if ($dirName == '.') {
  70. $dirInfo = array();
  71. }
  72. $dirInfo[] = $fileName;
  73. //补全路径
  74. if(count($dirInfo) == 1)
  75. {
  76. $dirInfo[] = 'index';
  77. }
  78. $dir = [];
  79. $match = ['url' => $url, 'controller' => $controller, 'action' => $action, 'dirInfo' => $dirInfo];
  80. if(isset($this->config['*:*'])) {
  81. list($controller, $action) = $arr = explode(':', $this->config['*:*']);
  82. preg_match_all("/\{[\d]{1,}\}|[\*]{1}/", $this->config['*:*'], $rules);
  83. if(!$rules) {
  84. $match['match'] = '*:*';
  85. $match['controller'] = $controller ? $controller : 'index';
  86. $match['action'] = $action ? $action : 'index';
  87. }
  88. return $this->matchVal($this->config['*:*'], $dirInfo);
  89. }
  90. $lastFound = [];
  91. //将内容和规则做匹配
  92. foreach ($dirInfo AS $key => $path) {
  93. $dir[] = $path;
  94. $register = [];
  95. $matchLen = 0;
  96. foreach($this->config as $config => $val) {
  97. //匹配规则
  98. $configArr = explode(':', $config);
  99. $interSet = array_intersect_assoc($configArr, $dir);
  100. if($interSet) {
  101. $countInterSet = count($interSet);
  102. if($configArr[$countInterSet] == '*' || $configArr[$countInterSet] == $dirInfo[$dirInfo[$key]]) {
  103. if($matchLen < $countInterSet) {
  104. $register = ['rule' => $config, 'val' => $val, 'interSet' => $interSet];
  105. }else{
  106. $matchLen = $countInterSet;
  107. }
  108. }
  109. }
  110. }
  111. }
  112. if(!empty($register)){
  113. $lastFound = $register;
  114. }
  115. $match['match'] = $lastFound;
  116. //没有匹配到就直接使用/url做匹配
  117. if(!$match['match']) {
  118. $info = $this->getInfoFromDirInfo($dirInfo);
  119. $match['controller'] = $info['controller'];
  120. $match['action'] = $info['action'];
  121. return $match;
  122. }
  123. //解析规则
  124. return $this->matchVal($match['match']['val'], $dirInfo);
  125. /*
  126. preg_match_all("/\{[\d]{1,}\}|[\*]{1}/", $rulesVal, $rules);
  127. if(empty($rules) || empty($rules[0])) {
  128. $info = $this->getInfoFromDirInfo($dirInfo);
  129. $match['controller'] = $info['controller'];
  130. $match['action'] = $info['action'];
  131. }
  132. $maxIndex = 0;
  133. //获取*位置最大值索引值
  134. if(preg_match("/[\*]{1}/", $rulesVal)) {
  135. foreach($rules[0] as $val) {
  136. $val = intval(str_replace(array('{', '}'), '', $val));
  137. if($val > $maxIndex) $maxIndex = $val;
  138. }
  139. $maxIndex++;
  140. }
  141. $replacements = $rules[0];
  142. foreach($rules[0] as $key => $val)
  143. {
  144. if(preg_match("/\{[\d]{1,}\}/", $val)) {
  145. $index = str_replace(array('{', '}'), '', $val);
  146. $replacements[$key] = $dirInfo[$index] ?? 'index';
  147. $rulesVal = preg_replace("/\{[\d]{1,}\}/", $replacements[$key], $rulesVal, 1);
  148. }else if($val == '*'){
  149. $replacements[$key] = $dirInfo[$maxIndex] ?? 'index';
  150. //一次只替换一个,用于匹配多次
  151. $rulesVal = preg_replace("/[\*]{1}/", $replacements[$key], $rulesVal, 1);
  152. $maxIndex++;
  153. }
  154. }
  155. list($controller, $action) = explode(":", $rulesVal);
  156. $match['controller'] = $controller;
  157. $match['action'] = $action ?? 'index';
  158. $match['replacements'] = $replacements;
  159. $match['rulesVal'] = $rulesVal;
  160. return $match;*/
  161. }
  162. /**
  163. * 从路径中获取controller和action
  164. *
  165. * @param array $dirInfo 目录路径
  166. * @return array
  167. */
  168. protected function getInfoFromDirInfo($dirInfo)
  169. {
  170. if(count($dirInfo) >= 2) {
  171. $action = array_pop($dirInfo);
  172. $controller = join("\\", $dirInfo);
  173. }else{
  174. $controller = join("\\", $dirInfo);
  175. $action = 'index';
  176. }
  177. return ['controller' => $controller, 'action' => $action];
  178. }
  179. protected function matchVal($rulesVal, $dirInfo) {
  180. if(!$rulesVal) return [];
  181. preg_match_all("/\{[\d]{1,}\}|[\*]{1}/", $rulesVal, $rules);
  182. $maxIndex = 0;
  183. //获取*位置最大值索引值
  184. if(preg_match("/[\*]{1}/", $rulesVal)) {
  185. foreach($rules[0] as $val) {
  186. $val = intval(str_replace(array('{', '}'), '', $val));
  187. if($val > $maxIndex) $maxIndex = $val;
  188. }
  189. $maxIndex++;
  190. }
  191. $replacements = $rules[0];
  192. foreach($rules[0] as $key => $val)
  193. {
  194. if(preg_match("/\{[\d]{1,}\}/", $val)) {
  195. $index = str_replace(array('{', '}'), '', $val);
  196. $replacements[$key] = $dirInfo[$index] ?? 'index';
  197. $rulesVal = preg_replace("/\{[\d]{1,}\}/", $replacements[$key], $rulesVal, 1);
  198. }else if($val == '*'){
  199. $replacements[$key] = $dirInfo[$maxIndex] ?? 'index';
  200. //一次只替换一个,用于匹配多次
  201. $rulesVal = preg_replace("/[\*]{1}/", $replacements[$key], $rulesVal, 1);
  202. $maxIndex++;
  203. }
  204. }
  205. list($controller, $action) = explode(":", $rulesVal);
  206. $match['controller'] = $controller;
  207. $match['action'] = $action ?? 'index';
  208. $match['replacements'] = $replacements;
  209. $match['rulesVal'] = $rulesVal;
  210. return $match;
  211. }
  212. }