作者 魏强

tongbu

@@ -39,11 +39,11 @@ class AdminFaultAuditController extends AdminBaseController{ @@ -39,11 +39,11 @@ class AdminFaultAuditController extends AdminBaseController{
39 ->field('a.*,b.serial_number,b.hospital,u.phone') 39 ->field('a.*,b.serial_number,b.hospital,u.phone')
40 ->join('equipment b','a.eq_name=b.name') 40 ->join('equipment b','a.eq_name=b.name')
41 ->join('users u','a.users_id=u.id') 41 ->join('users u','a.users_id=u.id')
  42 + ->where('b.is_delete',0)
42 ->where($where) 43 ->where($where)
43 ->order('a.state','ase') 44 ->order('a.state','ase')
44 ->order('a.create_time','desc') 45 ->order('a.create_time','desc')
45 ->paginate(10); 46 ->paginate(10);
46 -  
47 $this->assign('page',$data->render()); 47 $this->assign('page',$data->render());
48 $this->assign('data',$data); 48 $this->assign('data',$data);
49 $this->assign('fault_type', isset($param['fault_type']) ? $param['fault_type'] : ''); 49 $this->assign('fault_type', isset($param['fault_type']) ? $param['fault_type'] : '');
1 -<?php  
2 -// +----------------------------------------------------------------------  
3 -// | ThinkPHP [ WE CAN DO IT JUST THINK ]  
4 -// +----------------------------------------------------------------------  
5 -// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.  
6 -// +----------------------------------------------------------------------  
7 -// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )  
8 -// +----------------------------------------------------------------------  
9 -// | Author: liu21st <liu21st@gmail.com>  
10 -// +----------------------------------------------------------------------  
11 -  
12 -namespace think;  
13 -  
14 -use think\exception\ClassNotFoundException;  
15 -use think\exception\HttpException;  
16 -use think\exception\HttpResponseException;  
17 -use think\exception\RouteNotFoundException;  
18 -  
19 -/**  
20 - * App 应用管理  
21 - * @author liu21st <liu21st@gmail.com>  
22 - */  
23 -class App  
24 -{  
25 - /**  
26 - * @var bool 是否初始化过  
27 - */  
28 - protected static $init = false;  
29 -  
30 - /**  
31 - * @var string 当前模块路径  
32 - */  
33 - public static $modulePath;  
34 -  
35 - /**  
36 - * @var bool 应用调试模式  
37 - */  
38 - public static $debug = true;  
39 -  
40 - /**  
41 - * @var string 应用类库命名空间  
42 - */  
43 - public static $namespace = 'app';  
44 -  
45 - /**  
46 - * @var bool 应用类库后缀  
47 - */  
48 - public static $suffix = false;  
49 -  
50 - /**  
51 - * @var bool 应用路由检测  
52 - */  
53 - protected static $routeCheck;  
54 -  
55 - /**  
56 - * @var bool 严格路由检测  
57 - */  
58 - protected static $routeMust;  
59 -  
60 - protected static $dispatch;  
61 - protected static $file = [];  
62 -  
63 - /**  
64 - * 执行应用程序  
65 - * @access public  
66 - * @param Request $request Request对象  
67 - * @return Response  
68 - * @throws Exception  
69 - */  
70 - public static function run(Request $request = null)  
71 - {  
72 - is_null($request) && $request = Request::instance();  
73 -  
74 - try {  
75 - $config = self::initCommon();  
76 - if (defined('BIND_MODULE')) {  
77 - // 模块/控制器绑定  
78 - BIND_MODULE && Route::bind(BIND_MODULE);  
79 - } elseif ($config['auto_bind_module']) {  
80 - // 入口自动绑定  
81 - $name = pathinfo($request->baseFile(), PATHINFO_FILENAME);  
82 - if ($name && 'index' != $name && is_dir(APP_PATH . $name)) {  
83 - Route::bind($name);  
84 - }  
85 - }  
86 -  
87 - $request->filter($config['default_filter']);  
88 -  
89 - // 默认语言  
90 - Lang::range($config['default_lang']);  
91 - if ($config['lang_switch_on']) {  
92 - // 开启多语言机制 检测当前语言  
93 - Lang::detect();  
94 - }  
95 - $request->langset(Lang::range());  
96 -  
97 - // 加载系统语言包  
98 - Lang::load([  
99 - THINK_PATH . 'lang' . DS . $request->langset() . EXT,  
100 - APP_PATH . 'lang' . DS . $request->langset() . EXT,  
101 - ]);  
102 -  
103 - // 获取应用调度信息  
104 - $dispatch = self::$dispatch;  
105 - if (empty($dispatch)) {  
106 - // 进行URL路由检测  
107 - $dispatch = self::routeCheck($request, $config);  
108 - }  
109 - // 记录当前调度信息  
110 - $request->dispatch($dispatch);  
111 -  
112 - // 记录路由和请求信息  
113 - if (self::$debug) {  
114 - Log::record('[ ROUTE ] ' . var_export($dispatch, true), 'info');  
115 - Log::record('[ HEADER ] ' . var_export($request->header(), true), 'info');  
116 - Log::record('[ PARAM ] ' . var_export($request->param(), true), 'info');  
117 - }  
118 -  
119 - // 监听app_begin  
120 - Hook::listen('app_begin', $dispatch);  
121 - // 请求缓存检查  
122 - $request->cache($config['request_cache'], $config['request_cache_expire'], $config['request_cache_except']);  
123 -  
124 - $data = self::exec($dispatch, $config);  
125 - } catch (HttpResponseException $exception) {  
126 - $data = $exception->getResponse();  
127 - }  
128 -  
129 - // 清空类的实例化  
130 - Loader::clearInstance();  
131 -  
132 - // 输出数据到客户端  
133 - if ($data instanceof Response) {  
134 - $response = $data;  
135 - } elseif (!is_null($data)) {  
136 - // 默认自动识别响应输出类型  
137 - $isAjax = $request->isAjax();  
138 - $type = $isAjax ? Config::get('default_ajax_return') : Config::get('default_return_type');  
139 - $response = Response::create($data, $type);  
140 - } else {  
141 - $response = Response::create();  
142 - }  
143 -  
144 - // 监听app_end  
145 - Hook::listen('app_end', $response);  
146 -  
147 - return $response;  
148 - }  
149 -  
150 - /**  
151 - * 设置当前请求的调度信息  
152 - * @access public  
153 - * @param array|string $dispatch 调度信息  
154 - * @param string $type 调度类型  
155 - * @return void  
156 - */  
157 - public static function dispatch($dispatch, $type = 'module')  
158 - {  
159 - self::$dispatch = ['type' => $type, $type => $dispatch];  
160 - }  
161 -  
162 - /**  
163 - * 执行函数或者闭包方法 支持参数调用  
164 - * @access public  
165 - * @param string|array|\Closure $function 函数或者闭包  
166 - * @param array $vars 变量  
167 - * @return mixed  
168 - */  
169 - public static function invokeFunction($function, $vars = [])  
170 - {  
171 - $reflect = new \ReflectionFunction($function);  
172 - $args = self::bindParams($reflect, $vars);  
173 - // 记录执行信息  
174 - self::$debug && Log::record('[ RUN ] ' . $reflect->__toString(), 'info');  
175 - return $reflect->invokeArgs($args);  
176 - }  
177 -  
178 - /**  
179 - * 调用反射执行类的方法 支持参数绑定  
180 - * @access public  
181 - * @param string|array $method 方法  
182 - * @param array $vars 变量  
183 - * @return mixed  
184 - */  
185 - public static function invokeMethod($method, $vars = [])  
186 - {  
187 - if (is_array($method)) {  
188 - $class = is_object($method[0]) ? $method[0] : self::invokeClass($method[0]);  
189 - $reflect = new \ReflectionMethod($class, $method[1]);  
190 - } else {  
191 - // 静态方法  
192 - $reflect = new \ReflectionMethod($method);  
193 - }  
194 - $args = self::bindParams($reflect, $vars);  
195 -  
196 - self::$debug && Log::record('[ RUN ] ' . $reflect->class . '->' . $reflect->name . '[ ' . $reflect->getFileName() . ' ]', 'info');  
197 - return $reflect->invokeArgs(isset($class) ? $class : null, $args);  
198 - }  
199 -  
200 - /**  
201 - * 调用反射执行类的实例化 支持依赖注入  
202 - * @access public  
203 - * @param string $class 类名  
204 - * @param array $vars 变量  
205 - * @return mixed  
206 - */  
207 - public static function invokeClass($class, $vars = [])  
208 - {  
209 - $reflect = new \ReflectionClass($class);  
210 - $constructor = $reflect->getConstructor();  
211 - if ($constructor) {  
212 - $args = self::bindParams($constructor, $vars);  
213 - } else {  
214 - $args = [];  
215 - }  
216 - return $reflect->newInstanceArgs($args);  
217 - }  
218 -  
219 - /**  
220 - * 绑定参数  
221 - * @access private  
222 - * @param \ReflectionMethod|\ReflectionFunction $reflect 反射类  
223 - * @param array $vars 变量  
224 - * @return array  
225 - */  
226 - private static function bindParams($reflect, $vars = [])  
227 - {  
228 - if (empty($vars)) {  
229 - // 自动获取请求变量  
230 - if (Config::get('url_param_type')) {  
231 - $vars = Request::instance()->route();  
232 - } else {  
233 - $vars = Request::instance()->param();  
234 - }  
235 - }  
236 - $args = [];  
237 - if ($reflect->getNumberOfParameters() > 0) {  
238 - // 判断数组类型 数字数组时按顺序绑定参数  
239 - reset($vars);  
240 - $type = key($vars) === 0 ? 1 : 0;  
241 - $params = $reflect->getParameters();  
242 - foreach ($params as $param) {  
243 - $args[] = self::getParamValue($param, $vars, $type);  
244 - }  
245 - }  
246 - return $args;  
247 - }  
248 -  
249 - /**  
250 - * 获取参数值  
251 - * @access private  
252 - * @param \ReflectionParameter $param  
253 - * @param array $vars 变量  
254 - * @param string $type  
255 - * @return array  
256 - */  
257 - private static function getParamValue($param, &$vars, $type)  
258 - {  
259 - $name = $param->getName();  
260 - $class = $param->getClass();  
261 - if ($class) {  
262 - $className = $class->getName();  
263 - $bind = Request::instance()->$name;  
264 - if ($bind instanceof $className) {  
265 - $result = $bind;  
266 - } else {  
267 - if (method_exists($className, 'invoke')) {  
268 - $method = new \ReflectionMethod($className, 'invoke');  
269 - if ($method->isPublic() && $method->isStatic()) {  
270 - return $className::invoke(Request::instance());  
271 - }  
272 - }  
273 - $result = method_exists($className, 'instance') ? $className::instance() : new $className;  
274 - }  
275 - } elseif (1 == $type && !empty($vars)) {  
276 - $result = array_shift($vars);  
277 - } elseif (0 == $type && isset($vars[$name])) {  
278 - $result = $vars[$name];  
279 - } elseif ($param->isDefaultValueAvailable()) {  
280 - $result = $param->getDefaultValue();  
281 - } else {  
282 - throw new \InvalidArgumentException('method param miss:' . $name);  
283 - }  
284 - return $result;  
285 - }  
286 -  
287 - protected static function exec($dispatch, $config)  
288 - {  
289 - switch ($dispatch['type']) {  
290 - case 'redirect':  
291 - // 执行重定向跳转  
292 - $data = Response::create($dispatch['url'], 'redirect')->code($dispatch['status']);  
293 - break;  
294 - case 'module':  
295 - // 模块/控制器/操作  
296 - $data = self::module($dispatch['module'], $config, isset($dispatch['convert']) ? $dispatch['convert'] : null);  
297 - break;  
298 - case 'controller':  
299 - // 执行控制器操作  
300 - $vars = array_merge(Request::instance()->param(), $dispatch['var']);  
301 - $data = Loader::action($dispatch['controller'], $vars, $config['url_controller_layer'], $config['controller_suffix']);  
302 - break;  
303 - case 'method':  
304 - // 执行回调方法  
305 - $vars = array_merge(Request::instance()->param(), $dispatch['var']);  
306 - $data = self::invokeMethod($dispatch['method'], $vars);  
307 - break;  
308 - case 'function':  
309 - // 执行闭包  
310 - $data = self::invokeFunction($dispatch['function']);  
311 - break;  
312 - case 'response':  
313 - $data = $dispatch['response'];  
314 - break;  
315 - default:  
316 - throw new \InvalidArgumentException('dispatch type not support');  
317 - }  
318 - return $data;  
319 - }  
320 -  
321 - /**  
322 - * 执行模块  
323 - * @access public  
324 - * @param array $result 模块/控制器/操作  
325 - * @param array $config 配置参数  
326 - * @param bool $convert 是否自动转换控制器和操作名  
327 - * @return mixed  
328 - */  
329 - public static function module($result, $config, $convert = null)  
330 - {  
331 - if (is_string($result)) {  
332 - $result = explode('/', $result);  
333 - }  
334 - $request = Request::instance();  
335 - if ($config['app_multi_module']) {  
336 - // 多模块部署  
337 - $module = strip_tags(strtolower($result[0] ?: $config['default_module']));  
338 - $bind = Route::getBind('module');  
339 - $available = false;  
340 - if ($bind) {  
341 - // 绑定模块  
342 - list($bindModule) = explode('/', $bind);  
343 - if (empty($result[0])) {  
344 - $module = $bindModule;  
345 - $available = true;  
346 - } elseif ($module == $bindModule) {  
347 - $available = true;  
348 - }  
349 - } elseif (!in_array($module, $config['deny_module_list']) && is_dir(APP_PATH . $module)) {  
350 - $available = true;  
351 - }  
352 -  
353 - // 模块初始化  
354 - if ($module && $available) {  
355 - // 初始化模块  
356 - $request->module($module);  
357 - $config = self::init($module);  
358 - // 模块请求缓存检查  
359 - $request->cache($config['request_cache'], $config['request_cache_expire'], $config['request_cache_except']);  
360 - } else {  
361 - throw new HttpException(404, 'module not exists:' . $module);  
362 - }  
363 - } else {  
364 - // 单一模块部署  
365 - $module = '';  
366 - $request->module($module);  
367 - }  
368 - // 当前模块路径  
369 - App::$modulePath = APP_PATH . ($module ? $module . DS : '');  
370 -  
371 - // 是否自动转换控制器和操作名  
372 - $convert = is_bool($convert) ? $convert : $config['url_convert'];  
373 - // 获取控制器名  
374 - $controller = strip_tags($result[1] ?: $config['default_controller']);  
375 - $controller = $convert ? strtolower($controller) : $controller;  
376 -  
377 - // 获取操作名  
378 - $actionName = strip_tags($result[2] ?: $config['default_action']);  
379 - $actionName = $convert ? strtolower($actionName) : $actionName;  
380 -  
381 - // 设置当前请求的控制器、操作  
382 - $request->controller(Loader::parseName($controller, 1))->action($actionName);  
383 -  
384 - // 监听module_init  
385 - Hook::listen('module_init', $request);  
386 -  
387 - try {  
388 - $instance = Loader::controller($controller, $config['url_controller_layer'], $config['controller_suffix'], $config['empty_controller']);  
389 - } catch (ClassNotFoundException $e) {  
390 - throw new HttpException(404, 'controller not exists:' . $e->getClass());  
391 - }  
392 -  
393 - // 获取当前操作名  
394 - $action = $actionName . $config['action_suffix'];  
395 -  
396 - $vars = [];  
397 - if (is_callable([$instance, $action])) {  
398 - // 执行操作方法  
399 - $call = [$instance, $action];  
400 - } elseif (is_callable([$instance, '_empty'])) {  
401 - // 空操作  
402 - $call = [$instance, '_empty'];  
403 - $vars = [$actionName];  
404 - } else {  
405 - // 操作不存在  
406 - throw new HttpException(404, 'method not exists:' . get_class($instance) . '->' . $action . '()');  
407 - }  
408 -  
409 - Hook::listen('action_begin', $call);  
410 -  
411 - return self::invokeMethod($call, $vars);  
412 - }  
413 -  
414 - /**  
415 - * 初始化应用  
416 - */  
417 - public static function initCommon()  
418 - {  
419 - if (empty(self::$init)) {  
420 - if (defined('APP_NAMESPACE')) {  
421 - self::$namespace = APP_NAMESPACE;  
422 - }  
423 - Loader::addNamespace(self::$namespace, APP_PATH);  
424 -  
425 - // 初始化应用  
426 - $config = self::init();  
427 - self::$suffix = $config['class_suffix'];  
428 -  
429 - // 应用调试模式  
430 - self::$debug = Env::get('app_debug', Config::get('app_debug'));  
431 - if (!self::$debug) {  
432 - ini_set('display_errors', 'Off');  
433 - } elseif (!IS_CLI) {  
434 - //重新申请一块比较大的buffer  
435 - if (ob_get_level() > 0) {  
436 - $output = ob_get_clean();  
437 - }  
438 - ob_start();  
439 - if (!empty($output)) {  
440 - echo $output;  
441 - }  
442 - }  
443 -  
444 - if (!empty($config['root_namespace'])) {  
445 - Loader::addNamespace($config['root_namespace']);  
446 - }  
447 -  
448 - // 加载额外文件  
449 - if (!empty($config['extra_file_list'])) {  
450 - foreach ($config['extra_file_list'] as $file) {  
451 - $file = strpos($file, '.') ? $file : APP_PATH . $file . EXT;  
452 - if (is_file($file) && !isset(self::$file[$file])) {  
453 - include $file;  
454 - self::$file[$file] = true;  
455 - }  
456 - }  
457 - }  
458 -  
459 - // 设置系统时区  
460 - date_default_timezone_set($config['default_timezone']);  
461 -  
462 - // 监听app_init  
463 - Hook::listen('app_init');  
464 -  
465 - self::$init = true;  
466 - }  
467 - return Config::get();  
468 - }  
469 -  
470 - /**  
471 - * 初始化应用或模块  
472 - * @access public  
473 - * @param string $module 模块名  
474 - * @return array  
475 - */  
476 - private static function init($module = '')  
477 - {  
478 - // 定位模块目录  
479 - $module = $module ? $module . DS : '';  
480 -  
481 - // 加载初始化文件  
482 - if (is_file(APP_PATH . $module . 'init' . EXT)) {  
483 - include APP_PATH . $module . 'init' . EXT;  
484 - } elseif (is_file(RUNTIME_PATH . $module . 'init' . EXT)) {  
485 - include RUNTIME_PATH . $module . 'init' . EXT;  
486 - } else {  
487 - $path = APP_PATH . $module;  
488 - // 加载模块配置  
489 - $config = Config::load(CONF_PATH . $module . 'config' . CONF_EXT);  
490 - // 读取数据库配置文件  
491 - $filename = CONF_PATH . $module . 'database' . CONF_EXT;  
492 - Config::load($filename, 'database');  
493 - // 读取扩展配置文件  
494 - if (is_dir(CONF_PATH . $module . 'extra')) {  
495 - $dir = CONF_PATH . $module . 'extra';  
496 - $files = scandir($dir);  
497 - foreach ($files as $file) {  
498 - if ('.' . pathinfo($file, PATHINFO_EXTENSION) === CONF_EXT) {  
499 - $filename = $dir . DS . $file;  
500 - Config::load($filename, pathinfo($file, PATHINFO_FILENAME));  
501 - }  
502 - }  
503 - }  
504 -  
505 - // 加载应用状态配置  
506 - if ($config['app_status']) {  
507 - $config = Config::load(CONF_PATH . $module . $config['app_status'] . CONF_EXT);  
508 - }  
509 -  
510 - // 加载行为扩展文件  
511 - if (is_file(CONF_PATH . $module . 'tags' . EXT)) {  
512 - Hook::import(include CONF_PATH . $module . 'tags' . EXT);  
513 - }  
514 -  
515 - // 加载公共文件  
516 - if (is_file($path . 'common' . EXT)) {  
517 - include $path . 'common' . EXT;  
518 - }  
519 -  
520 - // 加载当前模块语言包  
521 - if ($module) {  
522 - Lang::load($path . 'lang' . DS . Request::instance()->langset() . EXT);  
523 - }  
524 - }  
525 - return Config::get();  
526 - }  
527 -  
528 - /**  
529 - * URL路由检测(根据PATH_INFO)  
530 - * @access public  
531 - * @param \think\Request $request  
532 - * @param array $config  
533 - * @return array  
534 - * @throws \think\Exception  
535 - */  
536 - public static function routeCheck($request, array $config)  
537 - {  
538 - $path = $request->path();  
539 - $depr = $config['pathinfo_depr'];  
540 - $result = false;  
541 - // 路由检测  
542 - $check = !is_null(self::$routeCheck) ? self::$routeCheck : $config['url_route_on'];  
543 - if ($check) {  
544 - // 开启路由  
545 - if (is_file(RUNTIME_PATH . 'route.php')) {  
546 - // 读取路由缓存  
547 - $rules = include RUNTIME_PATH . 'route.php';  
548 - if (is_array($rules)) {  
549 - Route::rules($rules);  
550 - }  
551 - } else {  
552 - $files = $config['route_config_file'];  
553 - foreach ($files as $file) {  
554 - if (is_file(CONF_PATH . $file . CONF_EXT)) {  
555 - // 导入路由配置  
556 - $rules = include CONF_PATH . $file . CONF_EXT;  
557 - if (is_array($rules)) {  
558 - Route::import($rules);  
559 - }  
560 - }  
561 - }  
562 - }  
563 -  
564 - // 路由检测(根据路由定义返回不同的URL调度)  
565 - $result = Route::check($request, $path, $depr, $config['url_domain_deploy']);  
566 - $must = !is_null(self::$routeMust) ? self::$routeMust : $config['url_route_must'];  
567 - if ($must && false === $result) {  
568 - // 路由无效  
569 - throw new RouteNotFoundException();  
570 - }  
571 - }  
572 - if (false === $result) {  
573 - // 路由无效 解析模块/控制器/操作/参数... 支持控制器自动搜索  
574 - $result = Route::parseUrl($path, $depr, $config['controller_auto_search']);  
575 - }  
576 - return $result;  
577 - }  
578 -  
579 - /**  
580 - * 设置应用的路由检测机制  
581 - * @access public  
582 - * @param bool $route 是否需要检测路由  
583 - * @param bool $must 是否强制检测路由  
584 - * @return void  
585 - */  
586 - public static function route($route, $must = false)  
587 - {  
588 - self::$routeCheck = $route;  
589 - self::$routeMust = $must;  
590 - }  
591 -} 1 +<?php
  2 +// +----------------------------------------------------------------------
  3 +// | ThinkPHP [ WE CAN DO IT JUST THINK ]
  4 +// +----------------------------------------------------------------------
  5 +// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
  6 +// +----------------------------------------------------------------------
  7 +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8 +// +----------------------------------------------------------------------
  9 +// | Author: liu21st <liu21st@gmail.com>
  10 +// +----------------------------------------------------------------------
  11 +
  12 +namespace think;
  13 +
  14 +use think\exception\ClassNotFoundException;
  15 +use think\exception\HttpException;
  16 +use think\exception\HttpResponseException;
  17 +use think\exception\RouteNotFoundException;
  18 +
  19 +/**
  20 + * App 应用管理
  21 + * @author liu21st <liu21st@gmail.com>
  22 + */
  23 +class App
  24 +{
  25 + /**
  26 + * @var bool 是否初始化过
  27 + */
  28 + protected static $init = false;
  29 +
  30 + /**
  31 + * @var string 当前模块路径
  32 + */
  33 + public static $modulePath;
  34 +
  35 + /**
  36 + * @var bool 应用调试模式
  37 + */
  38 + public static $debug = true;
  39 +
  40 + /**
  41 + * @var string 应用类库命名空间
  42 + */
  43 + public static $namespace = 'app';
  44 +
  45 + /**
  46 + * @var bool 应用类库后缀
  47 + */
  48 + public static $suffix = false;
  49 +
  50 + /**
  51 + * @var bool 应用路由检测
  52 + */
  53 + protected static $routeCheck;
  54 +
  55 + /**
  56 + * @var bool 严格路由检测
  57 + */
  58 + protected static $routeMust;
  59 +
  60 + protected static $dispatch;
  61 + protected static $file = [];
  62 +
  63 + /**
  64 + * 执行应用程序
  65 + * @access public
  66 + * @param Request $request Request对象
  67 + * @return Response
  68 + * @throws Exception
  69 + */
  70 + public static function run(Request $request = null)
  71 + {
  72 + is_null($request) && $request = Request::instance();
  73 +
  74 + try {
  75 + $config = self::initCommon();
  76 + if (defined('BIND_MODULE')) {
  77 + // 模块/控制器绑定
  78 + BIND_MODULE && Route::bind(BIND_MODULE);
  79 + } elseif ($config['auto_bind_module']) {
  80 + // 入口自动绑定
  81 + $name = pathinfo($request->baseFile(), PATHINFO_FILENAME);
  82 + if ($name && 'index' != $name && is_dir(APP_PATH . $name)) {
  83 + Route::bind($name);
  84 + }
  85 + }
  86 +
  87 + $request->filter($config['default_filter']);
  88 +
  89 + // 默认语言
  90 + Lang::range($config['default_lang']);
  91 + if ($config['lang_switch_on']) {
  92 + // 开启多语言机制 检测当前语言
  93 + Lang::detect();
  94 + }
  95 + $request->langset(Lang::range());
  96 +
  97 + // 加载系统语言包
  98 + Lang::load([
  99 + THINK_PATH . 'lang' . DS . $request->langset() . EXT,
  100 + APP_PATH . 'lang' . DS . $request->langset() . EXT,
  101 + ]);
  102 +
  103 + // 获取应用调度信息
  104 + $dispatch = self::$dispatch;
  105 + if (empty($dispatch)) {
  106 + // 进行URL路由检测
  107 + $dispatch = self::routeCheck($request, $config);
  108 + }
  109 + // 记录当前调度信息
  110 + $request->dispatch($dispatch);
  111 +
  112 + // 记录路由和请求信息
  113 + if (self::$debug) {
  114 + Log::record('[ ROUTE ] ' . var_export($dispatch, true), 'info');
  115 + Log::record('[ HEADER ] ' . var_export($request->header(), true), 'info');
  116 + Log::record('[ PARAM ] ' . var_export($request->param(), true), 'info');
  117 + }
  118 +
  119 + // 监听app_begin
  120 + Hook::listen('app_begin', $dispatch);
  121 + // 请求缓存检查
  122 + $request->cache($config['request_cache'], $config['request_cache_expire'], $config['request_cache_except']);
  123 +
  124 + $data = self::exec($dispatch, $config);
  125 + } catch (HttpResponseException $exception) {
  126 + $data = $exception->getResponse();
  127 + }
  128 +
  129 + // 清空类的实例化
  130 + Loader::clearInstance();
  131 +
  132 + // 输出数据到客户端
  133 + if ($data instanceof Response) {
  134 + $response = $data;
  135 + } elseif (!is_null($data)) {
  136 + // 默认自动识别响应输出类型
  137 + $isAjax = $request->isAjax();
  138 + $type = $isAjax ? Config::get('default_ajax_return') : Config::get('default_return_type');
  139 + $response = Response::create($data, $type);
  140 + } else {
  141 + $response = Response::create();
  142 + }
  143 +
  144 + // 监听app_end
  145 + Hook::listen('app_end', $response);
  146 +
  147 + return $response;
  148 + }
  149 +
  150 + /**
  151 + * 设置当前请求的调度信息
  152 + * @access public
  153 + * @param array|string $dispatch 调度信息
  154 + * @param string $type 调度类型
  155 + * @return void
  156 + */
  157 + public static function dispatch($dispatch, $type = 'module')
  158 + {
  159 + self::$dispatch = ['type' => $type, $type => $dispatch];
  160 + }
  161 +
  162 + /**
  163 + * 执行函数或者闭包方法 支持参数调用
  164 + * @access public
  165 + * @param string|array|\Closure $function 函数或者闭包
  166 + * @param array $vars 变量
  167 + * @return mixed
  168 + */
  169 + public static function invokeFunction($function, $vars = [])
  170 + {
  171 + $reflect = new \ReflectionFunction($function);
  172 + $args = self::bindParams($reflect, $vars);
  173 + // 记录执行信息
  174 + self::$debug && Log::record('[ RUN ] ' . $reflect->__toString(), 'info');
  175 + return $reflect->invokeArgs($args);
  176 + }
  177 +
  178 + /**
  179 + * 调用反射执行类的方法 支持参数绑定
  180 + * @access public
  181 + * @param string|array $method 方法
  182 + * @param array $vars 变量
  183 + * @return mixed
  184 + */
  185 + public static function invokeMethod($method, $vars = [])
  186 + {
  187 + if (is_array($method)) {
  188 + $class = is_object($method[0]) ? $method[0] : self::invokeClass($method[0]);
  189 + $reflect = new \ReflectionMethod($class, $method[1]);
  190 + } else {
  191 + // 静态方法
  192 + $reflect = new \ReflectionMethod($method);
  193 + }
  194 + $args = self::bindParams($reflect, $vars);
  195 +
  196 + self::$debug && Log::record('[ RUN ] ' . $reflect->class . '->' . $reflect->name . '[ ' . $reflect->getFileName() . ' ]', 'info');
  197 + return $reflect->invokeArgs(isset($class) ? $class : null, $args);
  198 + }
  199 +
  200 + /**
  201 + * 调用反射执行类的实例化 支持依赖注入
  202 + * @access public
  203 + * @param string $class 类名
  204 + * @param array $vars 变量
  205 + * @return mixed
  206 + */
  207 + public static function invokeClass($class, $vars = [])
  208 + {
  209 + $reflect = new \ReflectionClass($class);
  210 + $constructor = $reflect->getConstructor();
  211 + if ($constructor) {
  212 + $args = self::bindParams($constructor, $vars);
  213 + } else {
  214 + $args = [];
  215 + }
  216 + return $reflect->newInstanceArgs($args);
  217 + }
  218 +
  219 + /**
  220 + * 绑定参数
  221 + * @access private
  222 + * @param \ReflectionMethod|\ReflectionFunction $reflect 反射类
  223 + * @param array $vars 变量
  224 + * @return array
  225 + */
  226 + private static function bindParams($reflect, $vars = [])
  227 + {
  228 + if (empty($vars)) {
  229 + // 自动获取请求变量
  230 + if (Config::get('url_param_type')) {
  231 + $vars = Request::instance()->route();
  232 + } else {
  233 + $vars = Request::instance()->param();
  234 + }
  235 + }
  236 + $args = [];
  237 + if ($reflect->getNumberOfParameters() > 0) {
  238 + // 判断数组类型 数字数组时按顺序绑定参数
  239 + reset($vars);
  240 + $type = key($vars) === 0 ? 1 : 0;
  241 + $params = $reflect->getParameters();
  242 + foreach ($params as $param) {
  243 + $args[] = self::getParamValue($param, $vars, $type);
  244 + }
  245 + }
  246 + return $args;
  247 + }
  248 +
  249 + /**
  250 + * 获取参数值
  251 + * @access private
  252 + * @param \ReflectionParameter $param
  253 + * @param array $vars 变量
  254 + * @param string $type
  255 + * @return array
  256 + */
  257 + private static function getParamValue($param, &$vars, $type)
  258 + {
  259 + $name = $param->getName();
  260 + $class = $param->getClass();
  261 + if ($class) {
  262 + $className = $class->getName();
  263 + $bind = Request::instance()->$name;
  264 + if ($bind instanceof $className) {
  265 + $result = $bind;
  266 + } else {
  267 + if (method_exists($className, 'invoke')) {
  268 + $method = new \ReflectionMethod($className, 'invoke');
  269 + if ($method->isPublic() && $method->isStatic()) {
  270 + return $className::invoke(Request::instance());
  271 + }
  272 + }
  273 + $result = method_exists($className, 'instance') ? $className::instance() : new $className;
  274 + }
  275 + } elseif (1 == $type && !empty($vars)) {
  276 + $result = array_shift($vars);
  277 + } elseif (0 == $type && isset($vars[$name])) {
  278 + $result = $vars[$name];
  279 + } elseif ($param->isDefaultValueAvailable()) {
  280 + $result = $param->getDefaultValue();
  281 + } else {
  282 + throw new \InvalidArgumentException('method param miss:' . $name);
  283 + }
  284 + return $result;
  285 + }
  286 +
  287 + protected static function exec($dispatch, $config)
  288 + {
  289 + switch ($dispatch['type']) {
  290 + case 'redirect':
  291 + // 执行重定向跳转
  292 + $data = Response::create($dispatch['url'], 'redirect')->code($dispatch['status']);
  293 + break;
  294 + case 'module':
  295 + // 模块/控制器/操作
  296 + $data = self::module($dispatch['module'], $config, isset($dispatch['convert']) ? $dispatch['convert'] : null);
  297 + break;
  298 + case 'controller':
  299 + // 执行控制器操作
  300 + $vars = array_merge(Request::instance()->param(), $dispatch['var']);
  301 + $data = Loader::action($dispatch['controller'], $vars, $config['url_controller_layer'], $config['controller_suffix']);
  302 + break;
  303 + case 'method':
  304 + // 执行回调方法
  305 + $vars = array_merge(Request::instance()->param(), $dispatch['var']);
  306 + $data = self::invokeMethod($dispatch['method'], $vars);
  307 + break;
  308 + case 'function':
  309 + // 执行闭包
  310 + $data = self::invokeFunction($dispatch['function']);
  311 + break;
  312 + case 'response':
  313 + $data = $dispatch['response'];
  314 + break;
  315 + default:
  316 + throw new \InvalidArgumentException('dispatch type not support');
  317 + }
  318 + return $data;
  319 + }
  320 +
  321 + /**
  322 + * 执行模块
  323 + * @access public
  324 + * @param array $result 模块/控制器/操作
  325 + * @param array $config 配置参数
  326 + * @param bool $convert 是否自动转换控制器和操作名
  327 + * @return mixed
  328 + */
  329 + public static function module($result, $config, $convert = null)
  330 + {
  331 + if (is_string($result)) {
  332 + $result = explode('/', $result);
  333 + }
  334 + $request = Request::instance();
  335 + if ($config['app_multi_module']) {
  336 + // 多模块部署
  337 + $module = strip_tags(strtolower($result[0] ?: $config['default_module']));
  338 + $bind = Route::getBind('module');
  339 + $available = false;
  340 + if ($bind) {
  341 + // 绑定模块
  342 + list($bindModule) = explode('/', $bind);
  343 + if (empty($result[0])) {
  344 + $module = $bindModule;
  345 + $available = true;
  346 + } elseif ($module == $bindModule) {
  347 + $available = true;
  348 + }
  349 + } elseif (!in_array($module, $config['deny_module_list']) && is_dir(APP_PATH . $module)) {
  350 + $available = true;
  351 + }
  352 +
  353 + // 模块初始化
  354 + if ($module && $available) {
  355 + // 初始化模块
  356 + $request->module($module);
  357 + $config = self::init($module);
  358 + // 模块请求缓存检查
  359 + $request->cache($config['request_cache'], $config['request_cache_expire'], $config['request_cache_except']);
  360 + } else {
  361 + throw new HttpException(404, 'module not exists:' . $module);
  362 + }
  363 + } else {
  364 + // 单一模块部署
  365 + $module = '';
  366 + $request->module($module);
  367 + }
  368 + // 当前模块路径
  369 + App::$modulePath = APP_PATH . ($module ? $module . DS : '');
  370 +
  371 + // 是否自动转换控制器和操作名
  372 + $convert = is_bool($convert) ? $convert : $config['url_convert'];
  373 + // 获取控制器名
  374 + $controller = strip_tags($result[1] ?: $config['default_controller']);
  375 + $controller = $convert ? strtolower($controller) : $controller;
  376 +
  377 + if (!preg_match('/^[A-Za-z](\w|\.)*$/', $controller)) {
  378 + throw new HttpException(404, 'controller not exists:' . $controller);
  379 + }
  380 +
  381 + // 获取操作名
  382 + $actionName = strip_tags($result[2] ?: $config['default_action']);
  383 + $actionName = $convert ? strtolower($actionName) : $actionName;
  384 +
  385 + // 设置当前请求的控制器、操作
  386 + $request->controller(Loader::parseName($controller, 1))->action($actionName);
  387 +
  388 + // 监听module_init
  389 + Hook::listen('module_init', $request);
  390 +
  391 + try {
  392 + $instance = Loader::controller($controller, $config['url_controller_layer'], $config['controller_suffix'], $config['empty_controller']);
  393 + } catch (ClassNotFoundException $e) {
  394 + throw new HttpException(404, 'controller not exists:' . $e->getClass());
  395 + }
  396 +
  397 + // 获取当前操作名
  398 + $action = $actionName . $config['action_suffix'];
  399 +
  400 + $vars = [];
  401 + if (is_callable([$instance, $action])) {
  402 + // 执行操作方法
  403 + $call = [$instance, $action];
  404 + } elseif (is_callable([$instance, '_empty'])) {
  405 + // 空操作
  406 + $call = [$instance, '_empty'];
  407 + $vars = [$actionName];
  408 + } else {
  409 + // 操作不存在
  410 + throw new HttpException(404, 'method not exists:' . get_class($instance) . '->' . $action . '()');
  411 + }
  412 +
  413 + Hook::listen('action_begin', $call);
  414 +
  415 + return self::invokeMethod($call, $vars);
  416 + }
  417 +
  418 + /**
  419 + * 初始化应用
  420 + */
  421 + public static function initCommon()
  422 + {
  423 + if (empty(self::$init)) {
  424 + if (defined('APP_NAMESPACE')) {
  425 + self::$namespace = APP_NAMESPACE;
  426 + }
  427 + Loader::addNamespace(self::$namespace, APP_PATH);
  428 +
  429 + // 初始化应用
  430 + $config = self::init();
  431 + self::$suffix = $config['class_suffix'];
  432 +
  433 + // 应用调试模式
  434 + self::$debug = Env::get('app_debug', Config::get('app_debug'));
  435 + if (!self::$debug) {
  436 + ini_set('display_errors', 'Off');
  437 + } elseif (!IS_CLI) {
  438 + //重新申请一块比较大的buffer
  439 + if (ob_get_level() > 0) {
  440 + $output = ob_get_clean();
  441 + }
  442 + ob_start();
  443 + if (!empty($output)) {
  444 + echo $output;
  445 + }
  446 + }
  447 +
  448 + if (!empty($config['root_namespace'])) {
  449 + Loader::addNamespace($config['root_namespace']);
  450 + }
  451 +
  452 + // 加载额外文件
  453 + if (!empty($config['extra_file_list'])) {
  454 + foreach ($config['extra_file_list'] as $file) {
  455 + $file = strpos($file, '.') ? $file : APP_PATH . $file . EXT;
  456 + if (is_file($file) && !isset(self::$file[$file])) {
  457 + include $file;
  458 + self::$file[$file] = true;
  459 + }
  460 + }
  461 + }
  462 +
  463 + // 设置系统时区
  464 + date_default_timezone_set($config['default_timezone']);
  465 +
  466 + // 监听app_init
  467 + Hook::listen('app_init');
  468 +
  469 + self::$init = true;
  470 + }
  471 + return Config::get();
  472 + }
  473 +
  474 + /**
  475 + * 初始化应用或模块
  476 + * @access public
  477 + * @param string $module 模块名
  478 + * @return array
  479 + */
  480 + private static function init($module = '')
  481 + {
  482 + // 定位模块目录
  483 + $module = $module ? $module . DS : '';
  484 +
  485 + // 加载初始化文件
  486 + if (is_file(APP_PATH . $module . 'init' . EXT)) {
  487 + include APP_PATH . $module . 'init' . EXT;
  488 + } elseif (is_file(RUNTIME_PATH . $module . 'init' . EXT)) {
  489 + include RUNTIME_PATH . $module . 'init' . EXT;
  490 + } else {
  491 + $path = APP_PATH . $module;
  492 + // 加载模块配置
  493 + $config = Config::load(CONF_PATH . $module . 'config' . CONF_EXT);
  494 + // 读取数据库配置文件
  495 + $filename = CONF_PATH . $module . 'database' . CONF_EXT;
  496 + Config::load($filename, 'database');
  497 + // 读取扩展配置文件
  498 + if (is_dir(CONF_PATH . $module . 'extra')) {
  499 + $dir = CONF_PATH . $module . 'extra';
  500 + $files = scandir($dir);
  501 + foreach ($files as $file) {
  502 + if ('.' . pathinfo($file, PATHINFO_EXTENSION) === CONF_EXT) {
  503 + $filename = $dir . DS . $file;
  504 + Config::load($filename, pathinfo($file, PATHINFO_FILENAME));
  505 + }
  506 + }
  507 + }
  508 +
  509 + // 加载应用状态配置
  510 + if ($config['app_status']) {
  511 + $config = Config::load(CONF_PATH . $module . $config['app_status'] . CONF_EXT);
  512 + }
  513 +
  514 + // 加载行为扩展文件
  515 + if (is_file(CONF_PATH . $module . 'tags' . EXT)) {
  516 + Hook::import(include CONF_PATH . $module . 'tags' . EXT);
  517 + }
  518 +
  519 + // 加载公共文件
  520 + if (is_file($path . 'common' . EXT)) {
  521 + include $path . 'common' . EXT;
  522 + }
  523 +
  524 + // 加载当前模块语言包
  525 + if ($module) {
  526 + Lang::load($path . 'lang' . DS . Request::instance()->langset() . EXT);
  527 + }
  528 + }
  529 + return Config::get();
  530 + }
  531 +
  532 + /**
  533 + * URL路由检测(根据PATH_INFO)
  534 + * @access public
  535 + * @param \think\Request $request
  536 + * @param array $config
  537 + * @return array
  538 + * @throws \think\Exception
  539 + */
  540 + public static function routeCheck($request, array $config)
  541 + {
  542 + $path = $request->path();
  543 + $depr = $config['pathinfo_depr'];
  544 + $result = false;
  545 + // 路由检测
  546 + $check = !is_null(self::$routeCheck) ? self::$routeCheck : $config['url_route_on'];
  547 + if ($check) {
  548 + // 开启路由
  549 + if (is_file(RUNTIME_PATH . 'route.php')) {
  550 + // 读取路由缓存
  551 + $rules = include RUNTIME_PATH . 'route.php';
  552 + if (is_array($rules)) {
  553 + Route::rules($rules);
  554 + }
  555 + } else {
  556 + $files = $config['route_config_file'];
  557 + foreach ($files as $file) {
  558 + if (is_file(CONF_PATH . $file . CONF_EXT)) {
  559 + // 导入路由配置
  560 + $rules = include CONF_PATH . $file . CONF_EXT;
  561 + if (is_array($rules)) {
  562 + Route::import($rules);
  563 + }
  564 + }
  565 + }
  566 + }
  567 +
  568 + // 路由检测(根据路由定义返回不同的URL调度)
  569 + $result = Route::check($request, $path, $depr, $config['url_domain_deploy']);
  570 + $must = !is_null(self::$routeMust) ? self::$routeMust : $config['url_route_must'];
  571 + if ($must && false === $result) {
  572 + // 路由无效
  573 + throw new RouteNotFoundException();
  574 + }
  575 + }
  576 + if (false === $result) {
  577 + // 路由无效 解析模块/控制器/操作/参数... 支持控制器自动搜索
  578 + $result = Route::parseUrl($path, $depr, $config['controller_auto_search']);
  579 + }
  580 + return $result;
  581 + }
  582 +
  583 + /**
  584 + * 设置应用的路由检测机制
  585 + * @access public
  586 + * @param bool $route 是否需要检测路由
  587 + * @param bool $must 是否强制检测路由
  588 + * @return void
  589 + */
  590 + public static function route($route, $must = false)
  591 + {
  592 + self::$routeCheck = $route;
  593 + self::$routeMust = $must;
  594 + }
  595 +}