[TOC]
## 介紹
FastAdmin 是一款基于 ThinkPHP5 和 Bootstrap 的極速后臺開發框架。
后端使用 ThinkPHP5(原生 ThinkPHP 框架),前端使用 AdminLTE 模板,做了大量二次開發和整合。
* 支持無限級父子級權限繼承,父級的管理員可任意增刪改子級管理員及權限設置
* 支持單管理員多角色
* 一鍵生成CRUD,包括控制器、模型、視圖、JS、語言包、菜單等
* 一鍵生成控制器菜單和規則
* 一鍵生成API接口文檔
## 插件路由演示
ThinkPHP 的路由就像是整個應用的調度室,讓你的應用 url 更友好,而且讓應用更安全,不會讓真實的地址暴露出去。
了解過 Laravel 的同學都知道,Laravel 一開始就是一堆繁瑣的路由定義,但是 ThinkPHP5 不用,系統默認已經定義了路由規則。
而 FastAdmin 更是將 ThinkPHP5 發揮到了極致,將 ThinkPHP 強大的路由功能帶到了插件中,可以在后臺自定義插件的路由。
這里以 CMS 插件為例[^1],在插件管理的 CMS 插件配置中看到 CMS 的插件偽靜態就是利用了 ThinkPHP5 的路由功能實現,當打開 cms前臺[^2] 時就是自動進入 addons/cms/index/index,下面我們分析一下是如何實現的。

## 插件路由分析
當插件配置提交后通過 `\fastadmin\vendor\karsonzhang\fastadmin-addons\src\addons\Service.php` 中的 ` refresh() ` 將路由規則寫入到 `application\extra\addons.php` 中。
```php
$file = APP_PATH . 'extra' . DS . 'addons.php';
$config = get_addon_autoload_config(true);
if ($config['autoload'])
return;
if (!is_really_writable($file)) {
throw new Exception("addons.php文件沒有寫入權限");
}
if ($handle = fopen($file, 'w')) {
fwrite($handle, "<?php\n\n" . "return " . var_export($config, TRUE) . ";");
fclose($handle);
} else {
throw new Exception("文件沒有寫入權限");
}
return true;
```
在 `addons.php` 我們可以看到真實的路由規則。
```php
array (
'/$' => 'cms/index/index',
'/cms/a/[:diyname]' => 'cms/archives/index',
'/cms/t/[:name]' => 'cms/tags/index',
'/cms/p/[:diyname]' => 'cms/page/index',
'/cms/s' => 'cms/search/index',
'/cms/c/[:diyname]' => 'cms/channel/index',
'/cms/d/[:diyname]' => 'cms/diyform/index',
),
```
當打開前臺時加載 `addons.php` 中的路由配置 [^4] ,通過 `vendor\karsonzhang\fastadmin-addons\src\common.php` 注冊路由。
```php
//注冊路由
$routeArr = (array)Config::get('addons.route');
$domains = [];
$rules = [];
$execute = "\\think\\addons\\Route@execute?addon=%s&controller=%s&action=%s";
```
并通過 `vendor\karsonzhang\fastadmin-addons\src\addons\Route.php` 解析到插件。
```php
/**
* 插件執行
*/
public function execute($addon = null, $controller = null, $action = null)
{
$request = Request::instance();
// 是否自動轉換控制器和操作名
$convert = Config::get('url_convert');
$filter = $convert ? 'strtolower' : 'trim';
$addon = $addon ? trim(call_user_func($filter, $addon)) : '';
$controller = $controller ? trim(call_user_func($filter, $controller)) : 'index';
$action = $action ? trim(call_user_func($filter, $action)) : 'index';
Hook::listen('addon_begin', $request);
if (!empty($addon) && !empty($controller) && !empty($action)) {
$info = get_addon_info($addon);
if (!$info) {
throw new HttpException(404, __('addon %s not found', $addon));
}
if (!$info['state']) {
throw new HttpException(500, __('addon %s is disabled', $addon));
}
$dispatch = $request->dispatch();
if (isset($dispatch['var']) && $dispatch['var']) {
//$request->route($dispatch['var']);
}
// 設置當前請求的控制器、操作
$request->controller($controller)->action($action);
// 監聽addon_module_init
Hook::listen('addon_module_init', $request);
// 兼容舊版本行為,即將移除,不建議使用
Hook::listen('addons_init', $request);
$class = get_addon_class($addon, 'controller', $controller);
if (!$class) {
throw new HttpException(404, __('addon controller %s not found', Loader::parseName($controller, 1)));
}
$instance = new $class($request);
$vars = [];
if (is_callable([$instance, $action])) {
// 執行操作方法
$call = [$instance, $action];
} elseif (is_callable([$instance, '_empty'])) {
// 空操作
$call = [$instance, '_empty'];
$vars = [$action];
} else {
// 操作不存在
throw new HttpException(404, __('addon action %s not found', get_class($instance) . '->' . $action . '()'));
}
Hook::listen('addon_action_begin', $call);
return call_user_func_array($call, $vars);
} else {
abort(500, lang('addon can not be empty'));
}
}
```
從而使用路由功能達到插件偽靜態的效果。
## 總結
* ThinkPHP5 的路由非常強大,不僅支持路由到控制器的方法,還可以路由類或者閉合。
* ThinkPHP5.0 的路由需要在 `application/config.php` 將 `url_route_on` 設置為 `true` 開啟,ThinkPHP5.1 路由默認就是開啟,且不能關閉。 [^3]
* 在使用使用路由時文件不一定是 `route.php`,FastAdmin 的插件路由就是單獨的文件配置。
* 路由執行過程有三個部分:路由注冊、路由檢查和路由解析。
## 文檔版本
記錄文檔版本更新歷史
| Version | Remark | Commits By | Date |
| ------- | -------------------------- | ------------------------------------ | ---------------- |
| V1 | 初版 | [F4NNIU](mailto:sparkamax@gmail.com) | 2018-12-07 09:05 |
| V2 | 加入 TOC 和 文檔和版本說明 | [F4NNIU](mailto:sparkamax@gmail.com) | 2018-12-07 23:31 |
| V3 | 加入文檔版本的提交者 | [F4NNIU](mailto:sparkamax@gmail.com) | 2018-12-08 11:49 |
## 參考
文檔中引用的參考
[^1]: CMS 插件 DEMO 插件管理頁 https://demo.fastadmin.net/admin/addon?ref=addtabs
[^2]: CMS 前臺 DEMO https://demo.fastadmin.net/cms
[^3]: ThinkPHP5路由完全指南 http://www.hmoore.net/thinkphp/route-master/223110
[^4]: 擴展配置文件直接放入`application/extra`目錄會自動加載 http://www.hmoore.net/manual/thinkphp5/118024