Dispatcher.php 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. <?php
  2. namespace PhpLife\Frame;
  3. class Dispatcher
  4. {
  5. const CONFIG_PREFIX = '\\PhpLife\\Config';
  6. const CONTROLLER_ERROR = 'Error';
  7. const CONTROLLER_DEFAULT = 'Index';
  8. const METHOD_DEFAULT = 'main';
  9. /**
  10. * 使用方法
  11. * @param $customPrefix
  12. * @param string $pathInfo
  13. */
  14. public static function run($customPrefix, $pathInfo = '')
  15. {
  16. // 获取前缀
  17. $prefix = '\PhpLife\\App\\' . self::convertToClassName($customPrefix) . "\\Controller";
  18. if (!$pathInfo) {
  19. $pathInfo = self::getPathInfo();
  20. }
  21. $pathInfo = self::convertToClassName($pathInfo);
  22. $pathInfo = explode('\\', $pathInfo);
  23. if(count($pathInfo) > 1){
  24. $method = array_pop($pathInfo);
  25. }else{
  26. $method = self::METHOD_DEFAULT;
  27. }
  28. $controller = $prefix . '\\' . implode('\\', $pathInfo);
  29. // 加入一次出错重试的机会
  30. for ($i = 0; $i < 2; $i++) {
  31. try {
  32. // 判断是否是公开方法
  33. $reflection = new \ReflectionMethod($controller, $method);
  34. if ($reflection->isPublic() == false) {
  35. throw new \Exception($controller . "::$method is not public");
  36. }
  37. $controller = new $controller();
  38. $controller->$method();
  39. break;
  40. } catch (\Exception $ex) {
  41. Logger::emerg($ex, 'dispatcher.run');
  42. $controller = $prefix . '\\' . self::CONTROLLER_ERROR;
  43. $method = self::METHOD_DEFAULT;
  44. }
  45. }
  46. }
  47. /**
  48. * 分发请求
  49. * @param string $customPrefix
  50. * @param string $pathInfo
  51. */
  52. public static function dispatch($customPrefix, $pathInfo = '')
  53. {
  54. // 获取前缀
  55. $prefix = '\PhpLife\\App\\' . self::convertToClassName($customPrefix) . "\\Controller";
  56. if (!$pathInfo) {
  57. $pathInfo = self::getPathInfo();
  58. }
  59. $pathInfo = self::convertToClassName($pathInfo);
  60. try {
  61. $controller = $prefix . '\\' . $pathInfo;
  62. // 如果类不存在则使用默认的错误类
  63. if (!class_exists($controller)) {
  64. Logger::error($controller, 'dispatcher.controller_not_exist');
  65. $controller = $prefix . '\\' . self::CONTROLLER_ERROR;
  66. // 如果错误类也不存在,则抛出异常
  67. if (!class_exists($controller)) {
  68. throw new \Exception($controller . ' not exist');
  69. }
  70. }
  71. // 判断主方法
  72. if (!method_exists($controller, 'run')) {
  73. throw new \Exception($controller . ' has no method called "run"');
  74. }
  75. $controller = new $controller();
  76. $controller->run();
  77. } catch (\Exception $ex) {
  78. Logger::emerg($ex, 'dispatcher.dispatch');
  79. }
  80. }
  81. /**
  82. * 获取pathInfo, 兼容Apache, Nginx
  83. * 如果使用Apache的话可以直接使用 $_SERVER['PATH_INFO']的
  84. * @return string
  85. */
  86. protected static function getPathInfo()
  87. {
  88. //去掉uri中的PHP_SELF 信息
  89. $length = strlen($_SERVER['PHP_SELF']);
  90. if (substr($_SERVER['REQUEST_URI'], 0, $length) == $_SERVER['PHP_SELF']) {
  91. $request = substr($_SERVER['REQUEST_URI'], $length);
  92. } else {
  93. $request = $_SERVER['REQUEST_URI'];
  94. }
  95. // 去除 ?后面的部分
  96. $request = parse_url($request);
  97. $request = $request['path'];
  98. $request = urldecode($request);
  99. $request = trim($request, '/_ ');
  100. // 去掉 '.' 后缀
  101. if (strpos($request, '.') !== false) {
  102. $request = explode('.', $request);
  103. $request = array_shift($request);
  104. }
  105. if (empty($request)) {
  106. $request = self::CONTROLLER_DEFAULT;
  107. }
  108. return $request;
  109. }
  110. /**
  111. * 将字符串转成带命名空间的类名
  112. * @param $string
  113. * @return string
  114. */
  115. public static function convertToClassName($string)
  116. {
  117. $string = trim($string, '\\/_ ');
  118. $string = strtolower($string);
  119. $string = str_replace('/', '\\', $string);
  120. $string = str_replace(' ', '\\', ucwords(str_replace('\\', ' ', $string)));
  121. $string = str_replace(' ', '', ucwords(str_replace('_', ' ', $string)));
  122. return $string;
  123. }
  124. }