/** * 查找控制器文件 * * @param string $path_info * @param string $dir 指定控制器目录,命令行下默认为shell,网站运行为controllers * @return array 返回控制器后的参数数组 */ protected static function find_controller($uri, $dir = null, $is_internal = false) { # 包含目录 if (isset(Core::$file_list[Core::$project])) { $includepath = array(DIR_BULIDER . DS . Core::$project . DS); } else { $includepath = Core::$include_path; } $ext = '.controller' . EXT; if (IS_SYSTEM_MODE) { # 系统调用目录 $confolder = 'controllers' . DS . '[system]'; } elseif ($dir && preg_match('#^[a-zA-Z0-9_]+$#', $dir)) { $confolder = 'controllers' . DS . '[' . $dir . ']'; } else { if (IS_CLI) { $confolder = 'controllers' . DS . '[shell]'; } else { if (Core::$is_admin_url) { $confolder = 'controllers' . DS . '[admin]'; } else { $confolder = 'controllers'; } } } # 处理掉2边可能有/的URI $new_uri = '/' . trim($uri, '/'); # 分割参数 $arguments = explode('/', $new_uri); # 默认控制器 $default_controller = strtolower(Core::$project_config['default_controller']); # 记录存在的目录 $pathArr = array(); # 控制器目录 $controller_path = ''; # 临时包含文件 $tmp_includepath = $includepath; # 寻找可能存在的文件夹 foreach ($arguments as $argument) { $controller_path .= $argument . '/'; foreach ($tmp_includepath as $k => $path) { # 获取完整路径 $tmppath = rtrim($path . $confolder . DS . str_replace('/', DS, ltrim($controller_path, '/')), DS) . DS; if (is_dir($tmppath)) { $pathArr['/' . trim($controller_path, '/')][] = $tmppath; } else { # 没有目录则排除 unset($tmp_includepath[$k]); } } } if (!$pathArr) { return false; } # 倒序,因为最深目录优先级最高 $pathArr = array_reverse($pathArr); // $pathArr 格式类似: // Array // ( // [/test/] => Array // ( // [0] => D:\php\myqee_v2\projects\myqee\controllers\test\ // ) // [/] => Array // ( // [0] => D:\php\myqee_v2\projects\myqee\controllers\ // [1] => D:\php\myqee_v2\libraries\MyQEE\Core\controllers\ // ) // ) // // 例1 // URI:/test/abc 筛选控制器优先级排列如下: // [no] [file] [action] // ---------------------------------------------------------------------------------------- // 1 test/abc/index.controller.php default -> 此时若url结尾没有/且为GET方式则跳转到:/test/abc/ // ↓ // 2 test/abc.controller.php index -> 此时若url结尾没有/且为GET方式则跳转到:/test/abc/ // ↓ // 3 test/index.controller.php abc // ↓ // 4 test.controller.php abc // 5 index.controller.php test // ↓ // 6 test/abc.controller.php default // 7 test.controler.php default // // // 例2 // URL:/test/abc/def 筛选控制器优先级排列如下: // [file] [action] // ---------------------------------------------------------------------------------------- // test/abc/def/index.controller.php default -> 此时若url结尾没有/且为GET方式则跳转到:/test/abc/def/ // ↓ // test/abc/def.controller.php index -> 此时若url结尾没有/且为GET方式则跳转到:/test/abc/def/ // ↓ // test/abc/index.controller.php def // ↓ // test/abc.controller.php def // test/index.controller.php abc // ↓ // test.controller.php abc // index.controller.php test // ↓ // test/abc/def.controller.php default // test/abc.controller.php default // test.controller.php default # 处理根目录下index.controller.php文件的default控制器,即例1中no=1部分 if (key($pathArr) === $new_uri) { # 当前的URI存在最深的根目录 $uripaths = current($pathArr); foreach ($uripaths as $item) { $tmp_file = $item . $default_controller . $ext; if (is_file($tmp_file)) { $data = array('file' => $tmp_file, 'controller' => trim(str_replace('/', '__', trim($new_uri, '/')) . '__' . $default_controller, '_'), 'function' => 'default'); if (HttpIO::check_controller_method($data, $is_internal)) { return array('controller' => $data['controller'], 'action' => '', 'arguments' => array(), 'uri' => $new_uri, 'need_redirect' => substr($uri, -1) == '/' ? false : true); } } } } # 处理例1中no=2部分 $new_uri_sub2 = substr($new_uri, 0, strrpos($new_uri, '/')); if ($new_uri_sub2 == '') { $new_uri_sub2 = '/'; } if (key($pathArr) === $new_uri_sub2) { $con_name = substr($new_uri, strrpos($new_uri, '/') + 1); # 当前的URI存在最深的根目录 $uripaths = current($pathArr); foreach ($uripaths as $item) { $tmp_file = $item . $con_name . $ext; if (is_file($tmp_file)) { $data = array('file' => $tmp_file, 'controller' => trim(str_replace('/', '__', trim($new_uri_sub2, '/')) . '__' . $con_name, '_'), 'function' => 'index'); if (HttpIO::check_controller_method($data, $is_internal)) { return array('controller' => $data['controller'], 'action' => 'index', 'arguments' => array(), 'uri' => $new_uri, 'need_redirect' => substr($uri, -1) == '/' ? false : true); } } } } # 处理例1中3-5部分,寻找可能存在的控制器文件 if ($pathArr) { foreach ($pathArr as $left_uri => $all_path) { $tmpuri = trim(substr($new_uri, strlen($left_uri)), '/'); $arguments_arr = explode('/', $tmpuri); $ar_1 = array_shift($arguments_arr); foreach ($all_path as $path) { if ($arguments_arr) { $arguments_arr2 = $arguments_arr; $ar_2 = array_shift($arguments_arr2); $tmp_file = $path . $ar_1 . $ext; if (is_file($tmp_file)) { $data = array('file' => $tmp_file, 'controller' => str_replace('/', '__', ltrim($left_uri . '/', '/') . $ar_1), 'function' => $ar_2); if (HttpIO::check_controller_method($data, $is_internal)) { return array('controller' => $data['controller'], 'action' => $ar_2, 'arguments' => $arguments_arr2, 'uri' => rtrim($left_uri, '/') . '/' . $ar_1 . '/' . $ar_2); } } } $tmp_file = $path . $default_controller . $ext; if (is_file($tmp_file)) { $data = array('file' => $tmp_file, 'controller' => str_replace('/', '__', ltrim($left_uri . '/', '/') . $default_controller), 'function' => $ar_1); if (HttpIO::check_controller_method($data, $is_internal)) { return array('controller' => $data['controller'], 'action' => $ar_1, 'arguments' => $arguments_arr, 'uri' => rtrim($left_uri, '/') . '/' . $ar_1 . '/'); } } } } } # 处理例1中6-7部分,寻找是否含有默认控制 if ($pathArr) { foreach ($pathArr as $left_uri => $all_path) { $tmpuri = trim(substr($new_uri, strlen($left_uri)), '/'); $arguments_arr = explode('/', $tmpuri); $ar_1 = array_shift($arguments_arr); foreach ($all_path as $path) { $tmp_file = $path . $ar_1 . $ext; if (is_file($tmp_file)) { $data = array('file' => $tmp_file, 'controller' => str_replace('/', '__', ltrim($left_uri . '/', '/') . $ar_1), 'function' => 'default'); if (HttpIO::check_controller_method($data, $is_internal)) { return array('controller' => $data['controller'], 'action' => '', 'arguments' => $arguments_arr, 'uri' => rtrim($left_uri, '/') . '/' . $ar_1 . '/'); } break; } } } } return false; }