這段代碼還是 walkor
的auto-route代碼,主要是因?yàn)?,沒(méi)有默認(rèn)應(yīng)用自己使用上不是很方便;
但是,我又不想因?yàn)橐粋€(gè)小功能就去安裝一個(gè)composer包;
默認(rèn)不使用這個(gè)代碼,你前端訪問(wèn)一樣是需要手動(dòng)增加路由URL地址的,否則就需要/app/controller/action的這種方式去訪問(wèn)!直接把這段代碼粘貼復(fù)制到config/route
文件中即可
代碼的流程還是很簡(jiǎn)單的,如何實(shí)現(xiàn)默認(rèn)應(yīng)用?其實(shí)就是寫路由,如果你已經(jīng)習(xí)慣TP Laravel等框架,可忽略
1、首先你需要在config/app.php
文件中配置 default_app
=> index
2、遍歷app下的這個(gè)應(yīng)用文件夾,通過(guò)PHP反射類拿到他的函數(shù)
3、如果路由沒(méi)有被設(shè)置過(guò),則增加
注意:默認(rèn)會(huì)把繼承的函數(shù)都獲取到,所以父類的某些功能性函數(shù),請(qǐng)?jiān)O(shè)置為protected function action();
代碼里面我還加了注釋,方便剛接觸webman的同學(xué)!
$ignoreList = [];
$routes = Route::getRoutes();
// 獲取已存在路由
foreach ($routes as $tmp_route) {
$ignoreList[] = $tmp_route->getPath();
}
// 遍歷默認(rèn)應(yīng)用文件夾
$default_app = config('app.default_app', 'index');
$files = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator(root_path('app/' . $default_app), \FilesystemIterator::SKIP_DOTS),
\RecursiveIteratorIterator::CHILD_FIRST
);
// 循環(huán)處理每一個(gè)
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;
}
/**
* 反射獲取類的方法
* 注意:繼承類會(huì)將所有父類方法也獲取到
* 所以非路由方法,請(qǐng)?jiān)O(shè)置為protected屬性
*/
$refClass = new \ReflectionClass($className);
$className = $refClass->name;
$methods = $refClass->getMethods(\ReflectionMethod::IS_PUBLIC);
// 添加路由函數(shù)
$route = function ($uri, $action) use ($ignoreList) {
if (in_array($uri, $ignoreList) || empty($uri)) {
return;
}
Route::any($uri, $action);
Route::any($uri . '/', $action);
};
// 循環(huán)處理每一個(gè)路由方法
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',
];
// 過(guò)濾魔術(shù)方法
if (in_array($action,$magic)) {
continue;
}
// 執(zhí)行路由代碼
if ($action === 'index') {
if (strtolower(substr($urlPath, -6)) === '/index') {
// 默認(rèn)路由
$route('/', [$className, $action]);
$route(substr($urlPath, 0, -6), [$className, $action]);
}
$route($urlPath, [$className, $action]);
}
$route($urlPath . '/' . $action, [$className, $action]);
}
}
默認(rèn)的路由我沒(méi)有轉(zhuǎn)換小寫,是為了我自己項(xiàng)目的風(fēng)格統(tǒng)一,這個(gè)功能融合進(jìn)內(nèi)核也挺好的,還是期望 walkor
能考慮下!
如果你有默認(rèn)應(yīng)用,應(yīng)該用這樣的目錄結(jié)構(gòu)。
內(nèi)核里加一坨這樣路由邏輯實(shí)在不合適。內(nèi)核里不應(yīng)該設(shè)置任何路由,很容易和用戶的路由沖突。
由于我之前的項(xiàng)目寫的代碼太多了,所以只能用這種方式來(lái)兼容下!如果使用上述的目錄結(jié)構(gòu)建立一個(gè)新項(xiàng)目,那應(yīng)用中間件要如何寫?
看了下代碼流程,可以判斷app為空則為默認(rèn)應(yīng)用,但感覺(jué)這種會(huì)有一些不規(guī)范的感覺(jué),我還是用自己的這種方式兼容下吧!
那要給前端應(yīng)用寫一個(gè)鑒權(quán)中間件,如果不做判斷就訪問(wèn)每個(gè)應(yīng)用都會(huì)執(zhí)行,這樣寫有點(diǎn)耦合