这段代码还是 walkor
的auto-route代码,主要是因为,没有默认应用自己使用上不是很方便;
但是,我又不想因为一个小功能就去安装一个composer包;
默认不使用这个代码,你前端访问一样是需要手动增加路由URL地址的,否则就需要/app/controller/action的这种方式去访问!直接把这段代码粘贴复制到config/route
文件中即可
代码的流程还是很简单的,如何实现默认应用?其实就是写路由,如果你已经习惯TP Laravel等框架,可忽略
1、首先你需要在config/app.php
文件中配置 default_app
=> index
2、遍历app下的这个应用文件夹,通过PHP反射类拿到他的函数
3、如果路由没有被设置过,则增加
注意:默认会把继承的函数都获取到,所以父类的某些功能性函数,请设置为protected function action();
代码里面我还加了注释,方便刚接触webman的同学!
$ignoreList = [];
$routes = Route::getRoutes();
// 获取已存在路由
foreach ($routes as $tmp_route) {
$ignoreList[] = $tmp_route->getPath();
}
// 遍历默认应用文件夹
$default_app = config('app.default_app', 'index');
$files = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator(root_path('app/' . $default_app), \FilesystemIterator::SKIP_DOTS),
\RecursiveIteratorIterator::CHILD_FIRST
);
// 循环处理每一个
foreach ($files as $file) {
if ($file->isDir()) {
continue;
}
// 获取文件名
$filePath = str_replace('\\', '/', $file->getPathname());
$fileExt = pathinfo($filePath, PATHINFO_EXTENSION);
// 只处理PHP文件
if (strpos(strtolower($filePath), '/controller/') === false || strtolower($fileExt) !== 'php') {
continue;
}
// 获取路由URL路径
$urlPath = str_replace(['/controller/', '/Controller/'], '/', substr(substr($filePath, strlen(app_path())), 0, -4));
$urlPath = str_replace($default_app . '/', '', $urlPath);
$className = str_replace('/', '\\', substr(substr($filePath, strlen(base_path())), 0, -4));
if (!class_exists($className)) {
continue;
}
/**
* 反射获取类的方法
* 注意:继承类会将所有父类方法也获取到
* 所以非路由方法,请设置为protected属性
*/
$refClass = new \ReflectionClass($className);
$className = $refClass->name;
$methods = $refClass->getMethods(\ReflectionMethod::IS_PUBLIC);
// 添加路由函数
$route = function ($uri, $action) use ($ignoreList) {
if (in_array($uri, $ignoreList) || empty($uri)) {
return;
}
Route::any($uri, $action);
Route::any($uri . '/', $action);
};
// 循环处理每一个路由方法
foreach ($methods as $item) {
$action = $item->name;
$magic = [
'__construct', '__destruct', '__call', '__callStatic', '__get', '__set','__isset', '__unset', '__sleep', '__wakeup', '__toString',
'__invoke', '__set_state', '__clone', '__autoload', '__debugInfo', 'initialize',
];
// 过滤魔术方法
if (in_array($action,$magic)) {
continue;
}
// 执行路由代码
if ($action === 'index') {
if (strtolower(substr($urlPath, -6)) === '/index') {
// 默认路由
$route('/', [$className, $action]);
$route(substr($urlPath, 0, -6), [$className, $action]);
}
$route($urlPath, [$className, $action]);
}
$route($urlPath . '/' . $action, [$className, $action]);
}
}
默认的路由我没有转换小写,是为了我自己项目的风格统一,这个功能融合进内核也挺好的,还是期望 walkor
能考虑下!
如果你有默认应用,应该用这样的目录结构。
内核里加一坨这样路由逻辑实在不合适。内核里不应该设置任何路由,很容易和用户的路由冲突。
由于我之前的项目写的代码太多了,所以只能用这种方式来兼容下!如果使用上述的目录结构建立一个新项目,那应用中间件要如何写?
看了下代码流程,可以判断app为空则为默认应用,但感觉这种会有一些不规范的感觉,我还是用自己的这种方式兼容下吧!
app/controller 下的控制器不属于任何应用,没有应用中间件,全局中间件对它有效。
那要给前端应用写一个鉴权中间件,如果不做判断就访问每个应用都会执行,这样写有点耦合
你可以弄个全局中间件,通过$request->app 判断是哪个应用,根据应用鉴权。