标签:方式 安全性 行修改 model eve 配置参数 修改 actor contract
laravel已经有很多项目在使用,但是路由配置却是一个不可缺少的工作,很多时候路由配置工作不仅增加重复工作量而且还会增加代码开销,当项目到一定的级别时路由配置数量将是惊人的。很多时候不得不认为laravel路由配置虽然灵活但很臃肿,反而使用其它可以自动匹配的路由的框架更方便。当项目中路由是按 命名空间\类名+方法名 时就可以使用通用的配置方式来简化路由配置。
如果laravel使用自动匹配路由是否会折损框架本身的功能或特性么?这是由使用人或决策人来判定的,如果认为路由过多是可以接受的那么则不需要这么操作。
当如果需要这么配置时,可以直接使用下面的代码块。
路由配置代码如下:(这块代码需要配置到其它路由后面,否则可能会影响其它路由匹配)
//所有其它路由不可在这条之后添加
Route::any(‘/{controller}.{action}/{one?}/{two?}/{three?}/{four?}/{five?}‘, [
‘as‘ => ‘mvc‘,
‘uses‘ => function() {
return abort(404);
}])
->where(‘controller‘, ‘(.*)‘);
//匹配mvc成功后事件处理
Route::matched(function(\Illuminate\Routing\Events\RouteMatched $matched) {
if ($matched->route->getName() == ‘mvc‘) {
$controllerParam = $matched->route->parameter(‘controller‘);
$actionParam = $matched->route->parameter(‘action‘);
//必需合法
if (!preg_match(‘#[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)+#‘, $controllerParam . ‘/‘ . $actionParam)) {
return;
}
//控制器与方法解析匹配
$space = explode(‘/‘, $controllerParam);
$namecpase = $matched->route->getAction(‘namespace‘) ?: ‘App\\Http\\Controllers‘;
$controller = rtrim($namecpase, ‘\\‘) . ‘\\‘ . implode(‘\\‘, array_map(‘studly_case‘, array_filter($space))) . ‘Controller‘;
$action = studly_case($actionParam);
if (!method_exists($controller, $action)) {
return;
}
$method = new ReflectionMethod($controller, $action);
$comment = $method->getDocComment();
if(!$method->isPublic() || !preg_match(‘/@methods\(\s*([a-z]+)(\s*,\s*[a-z]+)\s*\)/i‘, $comment, $matches)){
return;
}
$methods = array_map(function($item) {
return trim(ltrim($item, ‘,‘));
}, array_slice($matches, 1));
if(!in_array(request()->method(), $methods)){
return;
}
//路由参数处理
$parameters = array_keys($matched->route->parameters());
$parameters = array_slice($parameters, array_search(‘one‘, $parameters));
$setParameters = [];
foreach ($method->getParameters() as $num => $parameter) {
$class = $parameter->getClass();
if ($class && is_subclass_of($class->name, Illuminate\Database\Eloquent\Model::class) && !is_null($matched->route->parameters[$parameters[$num]])) {
$setParameters[$parameter->name] = $matched->route->parameters[$parameters[$num]];
}
}
$matched->route->parameters = array_merge($setParameters, $matched->route->parameters);
$actions = $matched->route->getAction();
$actions[‘uses‘] = $controller . ‘@‘ . $action;
$actions[‘controller‘] = $actions[‘uses‘];
$matched->route->setAction($actions);
}
});
控制器配置代码:
namespace App\Http\Controllers\IndexController;
class IndexController extends Controller {
/**
* 初始化,配置中间件
*/
public function __construct() {
$this->middleware([‘auth‘], [‘only‘ => [‘modify‘], ‘except‘ => [‘add‘]]);
}
/**
* 列表
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
* @methods(POST, GET)
*/
public function lists() {
return view(‘index.lists‘, [‘lists‘ => Model::paginate()]);
}
/**
* 列表
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
* @methods(GET)
*/
public function add() {
return view(‘index.add‘, []);
}
/**
* 列表
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
* @methods(GET)
*/
public function modify(Model $model){
return view(‘index.modify‘, [‘model‘ => $model]);
}
访问地址分别是:
http://localhost/index.lists
http://localhost/index.add
http://localhost/index.modify/{model_id}
需要注意的是,这种配置方式优化了路由性能,减少了路由配置工作,但会直接暴露控制器的相对路径(对此有偏见的不建议使用),同时也会影响通过路由获取URL的功能,比如route()函数,需要通过控制器的相对路径,不好再指定其它别名(当然这块影响还好)。
使用注意事项:
1、非通用的中间件配置需要放到控制器的构造函数来配置,也可以指定使用或排除的函数名,如上面的代码中
2、控制器方法可以支持到5个路由参数,参数是以{action}之后开始,可以自由配置参数类型
3、控制器方法允许的请求类型通过注释来配置@methods(POST, GET) 可以配置想要的对应请求类型,不配置不能访问,并且方法是共有方法
4、如果需要通过route()函数生成路由地址,需要指定对应的路径参数,如:route(‘mvc‘,[‘controller‘=>‘index‘,‘action‘=>‘lists‘]) 或者另外封装
5、控制器与方法是严格匹配合法标识符,匹配不到的直接404,安全性好,有偏见的可以自行修改
6、这种配置可以与标准配置同时存在,只是规则不重叠即可,理论上这种配置放到最后会更好
7、这种配置可以派生到域名参数,或其它参数上,看项目的需求
标签:方式 安全性 行修改 model eve 配置参数 修改 actor contract
原文地址:https://blog.51cto.com/php2012web/2494235