Dispatcher.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  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. $this->controllerCls = call_user_func_array(array($psr4, 'loadClass'), $funcArgs);
  86. //load beforeRun 不放到具体的Controller里边执行,要不这里的属性controllerCls获取不到值
  87. if(method_exists($this->controllerCls, 'beforeRun') && is_callable(array($this->controllerCls, 'beforeRun'))) {
  88. !$this->controllerCls->beforeRun() && exit();
  89. }
  90. /**middleWare**/
  91. $this->getMiddleWare($this->controllerCls)->gatherMiddleware();
  92. $next = array_reduce($this->requestMiddleWare,function ($carry, $item){
  93. return function () use ($carry, $item){
  94. return _loadClass($item)->handle(\Qii::getInstance()->request, $carry);
  95. };
  96. }, function(){
  97. return true;
  98. })();
  99. if ($next === false) {
  100. return false;
  101. }
  102. $method = new \ReflectionMethod($this, 'dispatch');
  103. foreach($method->getParameters() as $property)
  104. {
  105. $param = $property->getName();
  106. $this->request->setParam($param, $$param);
  107. }
  108. $this->controllerCls->setRequest($this->request);
  109. $this->controllerCls->controllerId = $controller;
  110. $this->controllerCls->actionId = $action;
  111. $realAction = $action . Register::get(Consts::APP_DEFAULT_ACTION_SUFFIX);
  112. //查看是否设置了当前action的对应关系,如果设置了就走对应关系里边的,否则走当前类中的
  113. if ($this->controllerCls->actions
  114. && isset($this->controllerCls->actions[$action])
  115. && $this->controllerCls->actions[$action]) {
  116. $actionArgs = array();
  117. $actionArgs[] = $this->controllerCls->actions[$action];
  118. $actionCls = call_user_func_array(array($psr4, 'loadClass'), $actionArgs);
  119. $this->actionCls = $actionCls;
  120. $this->actionCls->setRequest($this->request);
  121. $this->actionCls->controller = $this->controllerCls;
  122. $this->actionCls->actionId = $action;
  123. $this->actionCls->controllerId = $this->controllerCls->controllerId;
  124. //调用初始化方法
  125. if(method_exists($this->actionCls, 'initialization')) {
  126. call_user_func_array(array($this->actionCls, 'initialization'), array($this->actionCls));
  127. }
  128. //支持多个action对应到同一个文件,调用的方法为 ...Action,如果没有...Action就调用run
  129. if (method_exists($this->actionCls, $realAction)) {
  130. return $this->actionCls->setResponse(call_user_func_array(array($this->actionCls, $realAction), $funcArgs));
  131. }
  132. if (!method_exists($this->actionCls, 'run')) {
  133. throw new MethodNotFound(\Qii::i(1101, $this->controllerCls->actions[$action] . '->run'), __LINE__);
  134. }
  135. return $this->actionCls->setResponse(call_user_func_array(array($this->actionCls, 'run'), array_slice($funcArgs, 1)));
  136. }
  137. if(method_exists($this->controllerCls, 'initialization')) {
  138. call_user_func_array(array($this->controllerCls, 'initialization'), array($this->controllerCls));
  139. }
  140. array_shift($funcArgs);
  141. if (!method_exists($this->controllerCls, $realAction) && !method_exists($this->controllerCls, '__call')) {
  142. throw new MethodNotFound(\Qii::i(1101, $controller . '->' . $realAction), __LINE__);
  143. }
  144. return $this->controllerCls->setResponse(call_user_func_array(array($this->controllerCls, $realAction), $funcArgs));
  145. }
  146. }