| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366 | 
							- <?php
 
- // +----------------------------------------------------------------------
 
- // | ThinkPHP [ WE CAN DO IT JUST THINK ]
 
- // +----------------------------------------------------------------------
 
- // | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
 
- // +----------------------------------------------------------------------
 
- // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 
- // +----------------------------------------------------------------------
 
- // | Author: liu21st <liu21st@gmail.com>
 
- // +----------------------------------------------------------------------
 
- namespace think\route;
 
- use think\App;
 
- use think\Container;
 
- use think\exception\ValidateException;
 
- use think\Request;
 
- use think\Response;
 
- abstract class Dispatch
 
- {
 
-     /**
 
-      * 应用对象
 
-      * @var App
 
-      */
 
-     protected $app;
 
-     /**
 
-      * 请求对象
 
-      * @var Request
 
-      */
 
-     protected $request;
 
-     /**
 
-      * 路由规则
 
-      * @var Rule
 
-      */
 
-     protected $rule;
 
-     /**
 
-      * 调度信息
 
-      * @var mixed
 
-      */
 
-     protected $dispatch;
 
-     /**
 
-      * 调度参数
 
-      * @var array
 
-      */
 
-     protected $param;
 
-     /**
 
-      * 状态码
 
-      * @var string
 
-      */
 
-     protected $code;
 
-     /**
 
-      * 是否进行大小写转换
 
-      * @var bool
 
-      */
 
-     protected $convert;
 
-     public function __construct(Request $request, Rule $rule, $dispatch, $param = [], $code = null)
 
-     {
 
-         $this->request  = $request;
 
-         $this->rule     = $rule;
 
-         $this->app      = Container::get('app');
 
-         $this->dispatch = $dispatch;
 
-         $this->param    = $param;
 
-         $this->code     = $code;
 
-         if (isset($param['convert'])) {
 
-             $this->convert = $param['convert'];
 
-         }
 
-     }
 
-     public function init()
 
-     {
 
-         // 执行路由后置操作
 
-         if ($this->rule->doAfter()) {
 
-             // 设置请求的路由信息
 
-             // 设置当前请求的参数
 
-             $this->request->setRouteVars($this->rule->getVars());
 
-             $this->request->routeInfo([
 
-                 'rule'   => $this->rule->getRule(),
 
-                 'route'  => $this->rule->getRoute(),
 
-                 'option' => $this->rule->getOption(),
 
-                 'var'    => $this->rule->getVars(),
 
-             ]);
 
-             $this->doRouteAfter();
 
-         }
 
-         return $this;
 
-     }
 
-     /**
 
-      * 检查路由后置操作
 
-      * @access protected
 
-      * @return void
 
-      */
 
-     protected function doRouteAfter()
 
-     {
 
-         // 记录匹配的路由信息
 
-         $option  = $this->rule->getOption();
 
-         $matches = $this->rule->getVars();
 
-         // 添加中间件
 
-         if (!empty($option['middleware'])) {
 
-             $this->app['middleware']->import($option['middleware']);
 
-         }
 
-         // 绑定模型数据
 
-         if (!empty($option['model'])) {
 
-             $this->createBindModel($option['model'], $matches);
 
-         }
 
-         // 指定Header数据
 
-         if (!empty($option['header'])) {
 
-             $header = $option['header'];
 
-             $this->app['hook']->add('response_send', function ($response) use ($header) {
 
-                 $response->header($header);
 
-             });
 
-         }
 
-         // 指定Response响应数据
 
-         if (!empty($option['response'])) {
 
-             foreach ($option['response'] as $response) {
 
-                 $this->app['hook']->add('response_send', $response);
 
-             }
 
-         }
 
-         // 开启请求缓存
 
-         if (isset($option['cache']) && $this->request->isGet()) {
 
-             $this->parseRequestCache($option['cache']);
 
-         }
 
-         if (!empty($option['append'])) {
 
-             $this->request->setRouteVars($option['append']);
 
-         }
 
-     }
 
-     /**
 
-      * 执行路由调度
 
-      * @access public
 
-      * @return mixed
 
-      */
 
-     public function run()
 
-     {
 
-         $option = $this->rule->getOption();
 
-         // 检测路由after行为
 
-         if (!empty($option['after'])) {
 
-             $dispatch = $this->checkAfter($option['after']);
 
-             if ($dispatch instanceof Response) {
 
-                 return $dispatch;
 
-             }
 
-         }
 
-         // 数据自动验证
 
-         if (isset($option['validate'])) {
 
-             $this->autoValidate($option['validate']);
 
-         }
 
-         $data = $this->exec();
 
-         return $this->autoResponse($data);
 
-     }
 
-     protected function autoResponse($data)
 
-     {
 
-         if ($data instanceof Response) {
 
-             $response = $data;
 
-         } elseif (!is_null($data)) {
 
-             // 默认自动识别响应输出类型
 
-             $isAjax = $this->request->isAjax();
 
-             $type   = $isAjax ? $this->rule->getConfig('default_ajax_return') : $this->rule->getConfig('default_return_type');
 
-             $response = Response::create($data, $type);
 
-         } else {
 
-             $data    = ob_get_clean();
 
-             $content = false === $data ? '' : $data;
 
-             $status  = '' === $content && $this->request->isJson() ? 204 : 200;
 
-             $response = Response::create($content, '', $status);
 
-         }
 
-         return $response;
 
-     }
 
-     /**
 
-      * 检查路由后置行为
 
-      * @access protected
 
-      * @param  mixed   $after 后置行为
 
-      * @return mixed
 
-      */
 
-     protected function checkAfter($after)
 
-     {
 
-         $this->app['log']->notice('路由后置行为建议使用中间件替代!');
 
-         $hook = $this->app['hook'];
 
-         $result = null;
 
-         foreach ((array) $after as $behavior) {
 
-             $result = $hook->exec($behavior);
 
-             if (!is_null($result)) {
 
-                 break;
 
-             }
 
-         }
 
-         // 路由规则重定向
 
-         if ($result instanceof Response) {
 
-             return $result;
 
-         }
 
-         return false;
 
-     }
 
-     /**
 
-      * 验证数据
 
-      * @access protected
 
-      * @param  array             $option
 
-      * @return void
 
-      * @throws ValidateException
 
-      */
 
-     protected function autoValidate($option)
 
-     {
 
-         list($validate, $scene, $message, $batch) = $option;
 
-         if (is_array($validate)) {
 
-             // 指定验证规则
 
-             $v = $this->app->validate();
 
-             $v->rule($validate);
 
-         } else {
 
-             // 调用验证器
 
-             $v = $this->app->validate($validate);
 
-             if (!empty($scene)) {
 
-                 $v->scene($scene);
 
-             }
 
-         }
 
-         if (!empty($message)) {
 
-             $v->message($message);
 
-         }
 
-         // 批量验证
 
-         if ($batch) {
 
-             $v->batch(true);
 
-         }
 
-         if (!$v->check($this->request->param())) {
 
-             throw new ValidateException($v->getError());
 
-         }
 
-     }
 
-     /**
 
-      * 处理路由请求缓存
 
-      * @access protected
 
-      * @param  Request       $request 请求对象
 
-      * @param  string|array  $cache  路由缓存
 
-      * @return void
 
-      */
 
-     protected function parseRequestCache($cache)
 
-     {
 
-         if (is_array($cache)) {
 
-             list($key, $expire, $tag) = array_pad($cache, 3, null);
 
-         } else {
 
-             $key    = str_replace('|', '/', $this->request->url());
 
-             $expire = $cache;
 
-             $tag    = null;
 
-         }
 
-         $cache = $this->request->cache($key, $expire, $tag);
 
-         $this->app->setResponseCache($cache);
 
-     }
 
-     /**
 
-      * 路由绑定模型实例
 
-      * @access protected
 
-      * @param  array|\Clousre    $bindModel 绑定模型
 
-      * @param  array             $matches   路由变量
 
-      * @return void
 
-      */
 
-     protected function createBindModel($bindModel, $matches)
 
-     {
 
-         foreach ($bindModel as $key => $val) {
 
-             if ($val instanceof \Closure) {
 
-                 $result = $this->app->invokeFunction($val, $matches);
 
-             } else {
 
-                 $fields = explode('&', $key);
 
-                 if (is_array($val)) {
 
-                     list($model, $exception) = $val;
 
-                 } else {
 
-                     $model     = $val;
 
-                     $exception = true;
 
-                 }
 
-                 $where = [];
 
-                 $match = true;
 
-                 foreach ($fields as $field) {
 
-                     if (!isset($matches[$field])) {
 
-                         $match = false;
 
-                         break;
 
-                     } else {
 
-                         $where[] = [$field, '=', $matches[$field]];
 
-                     }
 
-                 }
 
-                 if ($match) {
 
-                     $query  = strpos($model, '\\') ? $model::where($where) : $this->app->model($model)->where($where);
 
-                     $result = $query->failException($exception)->find();
 
-                 }
 
-             }
 
-             if (!empty($result)) {
 
-                 // 注入容器
 
-                 $this->app->instance(get_class($result), $result);
 
-             }
 
-         }
 
-     }
 
-     public function convert($convert)
 
-     {
 
-         $this->convert = $convert;
 
-         return $this;
 
-     }
 
-     public function getDispatch()
 
-     {
 
-         return $this->dispatch;
 
-     }
 
-     public function getParam()
 
-     {
 
-         return $this->param;
 
-     }
 
-     abstract public function exec();
 
-     public function __sleep()
 
-     {
 
-         return ['rule', 'dispatch', 'convert', 'param', 'code', 'controller', 'actionName'];
 
-     }
 
-     public function __wakeup()
 
-     {
 
-         $this->app     = Container::get('app');
 
-         $this->request = $this->app['request'];
 
-     }
 
-     public function __debugInfo()
 
-     {
 
-         $data = get_object_vars($this);
 
-         unset($data['app'], $data['request'], $data['rule']);
 
-         return $data;
 
-     }
 
- }
 
 
  |