注意
webman版本>=1.2时请使用 webman/action-hook插件 实现beforeAction()
afterAction()
。
否则请参考以下教程手动配置注意
webman版本>=1.4.6 时,webman默认关闭了控制器复用,可以直接使用控制器__construct()
为每个请求初始化工作
在传统框架中,每个请求都会实例化一次控制器,所以很多开发者__construct()
方法中做一些请求前的准备工作。
而webman由于控制器常驻内存,无法在__construct()
里做这些工作,不过webman提供了更好的解决方案beforeAction()
afterAction()
,它不仅让开发者可以介入到请求前的流程中,而且还可以介入到请求后的处理流程中。
为了介入请求流程,我们需要使用中间件
1、创建文件 app/middleware/ActionHook.php
(middleware目录不存在请自行创建)
<?php
namespace app\middleware;
use support\Container;
use Webman\MiddlewareInterface;
use Webman\Http\Response;
use Webman\Http\Request;
use Webman\Route;
class ActionHook implements MiddlewareInterface
{
public function process(Request $request, callable $next) : Response
{
if ($request->controller) {
// 禁止直接访问beforeAction afterAction
if ($request->action === 'beforeAction' || $request->action === 'afterAction') {
$callback = Route::getFallback() ?? function () {
return new Response(404, [], \file_get_contents(public_path() . '/404.html'));
};
$reponse = $callback($request);
return $reponse instanceof Response ? $reponse : \response($reponse);
}
$controller = Container::get($request->controller);
if (method_exists($controller, 'beforeAction')) {
$before_response = call_user_func([$controller, 'beforeAction'], $request);
if ($before_response instanceof Response) {
return $before_response;
}
}
$response = $next($request);
if (method_exists($controller, 'afterAction')) {
$after_response = call_user_func([$controller, 'afterAction'], $request, $response);
if ($after_response instanceof Response) {
return $after_response;
}
}
return $response;
}
return $next($request);
}
}
2、在 config/middleware.php 中添加如下配置
return [
'' => [
// .... 这里省略了其它配置 ....
app\middleware\ActionHook::class,
]
];
3、这样如果 controller包含了 beforeAction
或者 afterAction
方法会在请求发生时自动被调用。
例如:
<?php
namespace app\controller;
use support\Request;
class Index
{
/**
* 该方法会在请求前调用
*/
public function beforeAction(Request $request)
{
echo 'beforeAction';
// 若果想终止执行Action就直接返回Response对象,不想终止则无需return
// return response('终止执行Action');
}
/**
* 该方法会在请求后调用
*/
public function afterAction(Request $request, $response)
{
echo 'afterAction';
// 如果想串改请求结果,可以直接返回一个新的Response对象
// return response('afterAction');
}
public function index(Request $request)
{
return response('index');
}
}
Request
对象给beforeAction
,开发者可以从中获得用户输入beforeAction
里返回一个Response
对象,比如return redirect('/user/login');
Request
对象以及Response
对象给afterAction
,开发者可以从中获得用户输入以及控制器执行后返回的响应结果$response->rawBody()
获得响应内容$response->getHeader()
获得响应的header头$response->getStatusCode()
获得响应的http状态码$response->withBody()
$response->header()
$response->withStatus()
串改响应,也可以创建并返回一个新的Response
对象替代原响应
404感觉没必要抛异常吧,这样会记录很多无用的异常日志,尤其外网有很多探测请求
前后端分离需要告诉前端统一的数据结构,通过异常就可以解决这个问题
路由404你是怎么触发异常的?
路由配置文件
route.php
增加以下选项假设访问以下接口地址(不存在的路由)
接口响应输出
异常处理
ActionHook 同样抛出404异常
composer require webman/action-hook ^v1.0.1
更新到 1.0.1或者后续更高版本,404统一使用Route::fallback设定的回调返回值。
nice
这个跟
__construct()
功用一样的?在BeforeAction中无法改变Controller中的属性值。
例如在ArticleController定义一个public 属性 $pageInfo, 在beforeAction中赋值$this->pageInfo, 在Action中发现并未写入。
执行 composer info 看下webman-framework 版本
v1.5.1 , 我昨天才create project创建的~~
这边文章是给 1.0 1.1版本写的,1.5直接用__construct就行
好的~ 感谢~~