一切的不能突破閾值,都是因爲輪子造得不夠。所以最好的情況大致是這樣的 - 工作中出於成本和進度的考慮要,儘量少造輪子,但是業餘一定要多造輪子。不造出自己的輪子,永遠在表層遊走,沒法擊穿。
個人當前階段,最感興趣是高效的研發管理體系和工具打造,所以研究了市面上衆多產品後,還是會選擇以禪道的功能體系爲藍本進行學習。因此標題所表達的內容不屬於研究的主題範圍,純粹因爲個人在企業級應用開發領域所涉及的一些問題的額外探索。
禪道中的僞靜態路由格式是這樣的:
/product-browse-27.html
/product-browse-27-0-allstory-0-story.html
即除了控制器和動作,後面的參數部分,是不帶參數名的,框架需要將這些參數按順序賦值給參數。看起來會比較簡潔,有一定的吸引力。因此針對這一項特性解構出來獨立實現。
PHP這個玩意雖然一直在快速發展,但是似乎關注的人和應用的空間越來越少。支持國產,因此嘗試在 ThinkPHP 上來研究這個問題。
tp的路由機制當前有了比較大的靈活度,由於這項特性需要使用反射機制讀取方法的參數定義,因此使用 路由到調度對象(V6.0.3+)這些特性。
// 路由到自定義調度對象
Route::get('blog/:id',\app\route\BlogDispatch::class);
路由調度類 app\route\ZentaoDispatch
<?php
namespace app\route;
use ReflectionMethod;
use think\facade\Route;
class ZentaoDispatch extends \think\route\dispatch\Url
{
const CTRL_KEY = '_control';
const ACT_KEY = '_action';
const PARAM_KEY = '_params';
const SEPR_KEY = '_sepr';
const SEPR = '-';
public static function rule()
{
$rule = vsprintf("<%s>-<%s><%s?><%s?>", [
self::CTRL_KEY,
self::ACT_KEY,
self::SEPR_KEY,
self::PARAM_KEY
]);
return $rule;
}
public static function addRouteRule()
{
Route::rule(ZentaoDispatch::rule(), ZentaoDispatch::class)->pattern([
self::SEPR_KEY => self::SEPR,
self::PARAM_KEY => '[\w|-]+',
])->ext('html|json');
}
/**
* 解析URL地址,看該方法的主要目的是解析出控制器和動作 將第一截參數的-換爲/應該就可以
* @access protected
* @param string $url URL app\route\ZentaoDispatch 沒有意義了
* @return array
*/
protected function parseUrl(string $url): array
{
$pathinfo = $this->buildPathinfo();
$this->request->setPathinfo($pathinfo);
$route = parent::parseUrl($pathinfo);
return $route;
}
protected function buildPathinfo()
{
$pathinfo_depr = $this->rule->config('pathinfo_depr');
$vars = $this->rule->getVars();
$paths = [
$vars[self::CTRL_KEY] => $vars[self::ACT_KEY],
self::SEPR_KEY => $vars[self::SEPR_KEY],
self::PARAM_KEY => $vars[self::PARAM_KEY],
];
$pathinfo = '';
foreach ($paths as $key => $path) {
$pathinfo .= $pathinfo_depr . $key . $pathinfo_depr . $path;
}
$pathinfo = trim($pathinfo, '/');
return $pathinfo;
}
/**
* 似乎這裏是最佳時機,不必重複初始化控制器對象造成性能損失
*
* @param string $name
* @return mixed|object
*/
public function controller(string $name)
{
$instance = parent::controller($name);
// 獲取當前操作名
$suffix = $this->rule->config('action_suffix');
$action = $this->actionName . $suffix;
$paramValue = $this->request->param(self::PARAM_KEY);
$items = explode(self::SEPR, $paramValue);
$reflect = new ReflectionMethod($instance, $action);
$i = 0;
$params = [];
foreach($reflect->getParameters() as $param) {
if (isset($items[$i])) {
$params[$param->getName()] = $items[$i];
}
$i ++;
}
$requestReflect = new \ReflectionClass($this->request);
$paramProperty = $requestReflect->getProperty('param');
$paramProperty->setAccessible(true);
$params = array_merge($this->request->param(), $params);
$paramProperty->setValue($this->request, $params);
return $instance;
}
}
註冊路由
route/app.php
use app\route\ZentaoDispatch;
ZentaoDispatch::addRouteRule();
測試
路由:/index.php/Abc-do1-27-0-allstory-0-story.json
文件:app/controller/AbcController.php
<?php
namespace app\controller;
class AbcController
{
public function do1($p1, $p2, $p3, $p4, $p5, $p6 = '')
{
var_dump(func_get_args());
echo 'here do1';
}
}