Dispatcher.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. <?php
  2. namespace Qii\Base;
  3. use Qii\Autoloader\Psr4;
  4. use \Qii\Config\Register;
  5. use \Qii\Config\Consts;
  6. use Qii\Exceptions\MethodNotFound;
  7. use Qii\Request\Http;
  8. class Dispatcher
  9. {
  10. public $request;
  11. public $controllerCls = null;
  12. public $actionCls = null;
  13. private $requestMiddleWare = array();
  14. public function __construct()
  15. {
  16. }
  17. /**
  18. * 设置请求
  19. * @param Http $request 当前请求
  20. */
  21. public function setRequest(Http $request)
  22. {
  23. $this->request = $request;
  24. return $this;
  25. }
  26. /**
  27. * 设置中间件
  28. *
  29. * @param array $middleware 中间件
  30. * @return $this
  31. */
  32. public function setMiddleware($middleware) {
  33. if (!is_array($middleware)) {
  34. return $this;
  35. }
  36. $this->requestMiddleWare = array_merge($this->requestMiddleWare, $middleware);
  37. return $this;
  38. }
  39. /**
  40. * 获取 controller 设置的middleware
  41. * @param $controller
  42. * @return $this
  43. */
  44. public function getMiddleWare($controller)
  45. {
  46. if (method_exists($controller, 'getMiddleware')) {
  47. $this->requestMiddleWare = array_merge($this->requestMiddleWare, $controller->getMiddleware());
  48. }
  49. return $this;
  50. }
  51. /**
  52. * 整理 middleware
  53. * @return $this
  54. */
  55. public function gatherMiddleware()
  56. {
  57. if(count($this->requestMiddleWare) == 0) {
  58. return $this;
  59. }
  60. $this->requestMiddleWare = array_unique($this->requestMiddleWare);
  61. return $this;
  62. }
  63. /**
  64. * 转发
  65. * @param string $controller
  66. * @param string $action
  67. * @return mixed
  68. */
  69. public function dispatch($controller = '', $action = '')
  70. {
  71. $args = func_get_args();
  72. $controller = $controller != '' ? $controller : $this->request->getControllerName();
  73. $action = $action != '' ? $action : $this->request->getActionName();
  74. $controllerName = $controller;
  75. //如果controller以\开头,就不添加默认前缀 Update at 2018-05-29 13:50
  76. if(substr($controller,0, 1) != '\\') {
  77. $controllerName = Register::get(Consts::APP_DEFAULT_CONTROLLER_PREFIX) . '_' . $controller;
  78. }
  79. $funcArgs = array();
  80. if (count($args) > 2) {
  81. $funcArgs = array_slice($args, 2);
  82. }
  83. array_unshift($funcArgs, $controllerName);
  84. $psr4 = Psr4::getInstance();
  85. $controllerCls = call_user_func_array(array($psr4, 'loadClass'), $funcArgs);
  86. /**middleWare**/
  87. $this->getMiddleWare($controllerCls)->gatherMiddleware();
  88. $next = array_reduce($this->requestMiddleWare,function ($carry, $item){
  89. return function () use ($carry, $item){
  90. return _loadClass($item)->handle(\Qii::getInstance()->request, $carry);
  91. };
  92. }, function(){
  93. return true;
  94. })();
  95. if ($next === false) {
  96. return false;
  97. }
  98. $method = new \ReflectionMethod($this, 'dispatch');
  99. foreach($method->getParameters() as $property)
  100. {
  101. $param = $property->getName();
  102. $this->request->setParam($param, $$param);
  103. }
  104. $this->controllerCls = $controllerCls;
  105. $this->controllerCls->setRequest($this->request);
  106. $this->controllerCls->controller = $controllerCls;
  107. $this->controllerCls->controllerId = $controller;
  108. $this->controllerCls->actionId = $action;
  109. $realAction = $action . Register::get(Consts::APP_DEFAULT_ACTION_SUFFIX);
  110. //查看是否设置了当前action的对应关系,如果设置了就走对应关系里边的,否则走当前类中的
  111. if ($this->controllerCls->actions
  112. && isset($this->controllerCls->actions[$action])
  113. && $this->controllerCls->actions[$action]) {
  114. $actionArgs = array();
  115. $actionArgs[] = $this->controllerCls->actions[$action];
  116. $actionCls = call_user_func_array(array($psr4, 'loadClass'), $actionArgs);
  117. $this->actionCls = $actionCls;
  118. $this->actionCls->setRequest($this->request);
  119. $this->actionCls->controller = $this->controllerCls;
  120. $this->actionCls->actionId = $action;
  121. $this->actionCls->controllerId = $this->controllerCls->controllerId;
  122. //调用初始化方法
  123. if(method_exists($this->actionCls, 'initialization')) {
  124. call_user_func_array(array($this->actionCls, 'initialization'), array($this->actionCls));
  125. }
  126. //支持多个action对应到同一个文件,调用的方法为 ...Action,如果没有...Action就调用run
  127. if (method_exists($this->actionCls, $realAction)) {
  128. return $this->actionCls->setResponse(call_user_func_array(array($this->actionCls, $realAction), $funcArgs));
  129. }
  130. if (!method_exists($this->actionCls, 'run')) {
  131. throw new MethodNotFound(\Qii::i(1101, $this->controllerCls->actions[$action] . '->run'), __LINE__);
  132. }
  133. return $this->actionCls->setResponse(array($this->actionCls, 'run'), array_slice($funcArgs, 1));
  134. }
  135. if(method_exists($this->controllerCls, 'initialization')) {
  136. call_user_func_array(array($this->controllerCls, 'initialization'), array($this->controllerCls));
  137. }
  138. array_shift($funcArgs);
  139. if (!method_exists($this->controllerCls, $realAction) && !method_exists($this->controllerCls, '__call')) {
  140. throw new MethodNotFound(\Qii::i(1101, $controller . '->' . $realAction), __LINE__);
  141. }
  142. return $this->controllerCls->setResponse(call_user_func_array(array($this->controllerCls, $realAction), $funcArgs));
  143. }
  144. }