webman_ad/config/plugin/webman/auto-route/route.php

110 lines
3.5 KiB
PHP

<?php
/**
* This file is part of webman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
use Webman\Route;
// 已经设置过路由的uri则忽略
$routes = Route::getRoutes();
$ignore_list = [];
foreach ($routes as $tmp_route) {
$ignore_list[$tmp_route->getPath()] = 0;
}
$default_app = config('plugin.webman.auto-route.app.default_app');
$suffix = config('app.controller_suffix', '');
$suffix_length = strlen($suffix);
// 递归遍历目录查找控制器自动设置路由
$dir_iterator = new \RecursiveDirectoryIterator(app_path());
$iterator = new \RecursiveIteratorIterator($dir_iterator);
foreach ($iterator as $file) {
// 忽略目录和非php文件
if (is_dir($file) || $file->getExtension() != 'php') {
continue;
}
$file_path = str_replace('\\', '/',$file->getPathname());
// 文件路径里不带controller的文件忽略
if (strpos(strtolower($file_path), '/controller/') === false) {
continue;
}
// 只处理带 controller_suffix 后缀的
if ($suffix_length && substr($file->getBaseName('.php'), -$suffix_length) !== $suffix) {
continue;
}
// 根据文件路径计算uri
$uri_path = str_replace(['/controller/', '/Controller/'], '/', substr(substr($file_path, strlen(app_path())), 0, - (4 + $suffix_length)));
// 默认应用
$is_default_app = false;
if (is_string($default_app) && !empty($default_app)) {
$seg = explode('/', $uri_path);
if ($seg[1] == $default_app) {
$uri_path = str_replace($default_app . '/', '', $uri_path);
$is_default_app = true;
}
}
// 根据文件路径是被类名
$class_name = str_replace('/', '\\',substr(substr($file_path, strlen(base_path())), 0, -4));
if (!class_exists($class_name)) {
echo "Class $class_name not found, skip route for it\n";
continue;
}
// 通过反射找到这个类的所有共有方法作为action
$class = new ReflectionClass($class_name);
$class_name = $class->name;
$methods = $class->getMethods(ReflectionMethod::IS_PUBLIC);
$route = function ($uri, $cb) use ($ignore_list) {
if (isset($ignore_list[strtolower($uri)])) {
return;
}
Route::any($uri, $cb);
if ($uri !== '') {
Route::any($uri . '/', $cb);
}
$lower_uri = strtolower($uri);
if ($lower_uri !== $uri) {
Route::any($lower_uri, $cb);
Route::any($lower_uri . '/', $cb);
}
};
// 设置路由
foreach ($methods as $item) {
$action = $item->name;
if (in_array($action, ['__construct', '__destruct'])) {
continue;
}
// action为index时uri里末尾/index可以省略
if ($action === 'index') {
// controller也为index时uri里可以省略/index/index
if (strtolower(substr($uri_path, -6)) === '/index') {
if ($is_default_app) {
$route('/', [$class_name, $action]);
}
$route(substr($uri_path, 0, -6), [$class_name, $action]);
}
$route($uri_path, [$class_name, $action]);
}
$route($uri_path.'/'.$action, [$class_name, $action]);
}
}