CakePHP4的中间件机制允许开发者在HTTP请求的处理流程中插入自定义逻辑,无需修改控制器或路由的核心代码,就能实现请求校验、日志记录、跨域处理等通用功能,让代码结构更清晰,复用性更强。

CakePHP4中间件的基本概念
中间件是处于应用和请求处理流程之间的组件,每个中间件都会接收请求对象,处理完成后可以选择将请求传递给下一个中间件,或者直接返回响应。在CakePHP4中,中间件的执行顺序和注册顺序一致,先注册的中间件会先处理请求,后注册的中间件会先处理响应。
创建自定义中间件
首先需要在应用的中间件目录下创建自定义中间件类,该类需要实现PsrHttpServerMiddlewareInterface接口,实现process方法。以下是一个简单的请求日志中间件示例:
<?php
declare(strict_types=1);
namespace AppMiddleware;
use PsrHttpMessageResponseInterface;
use PsrHttpMessageServerRequestInterface;
use PsrHttpServerMiddlewareInterface;
use PsrHttpServerRequestHandlerInterface;
class RequestLogMiddleware implements MiddlewareInterface
{
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
// 请求到达时记录请求路径
$path = $request->getUri()->getPath();
error_log('请求路径:' . $path);
// 将请求传递给下一个中间件或控制器处理
$response = $handler->handle($request);
// 响应返回前记录响应状态码
$statusCode = $response->getStatusCode();
error_log('响应状态码:' . $statusCode);
return $response;
}
}
注册中间件到请求流程
创建好中间件后,需要将其注册到应用的请求处理流程中,CakePHP4的中间件注册在src/Application.php文件的middleware方法中完成。以下是注册上述日志中间件的示例:
<?php
declare(strict_types=1);
namespace App;
use AppMiddlewareRequestLogMiddleware;
use CakeHttpBaseApplication;
use CakeHttpMiddlewareQueue;
class Application extends BaseApplication
{
public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
{
// 添加自定义中间件到队列中
$middlewareQueue
->add(new RequestLogMiddleware());
return $middlewareQueue;
}
}
中间件的执行顺序说明
中间件的执行顺序和注册顺序直接相关,假设我们注册了三个中间件A、B、C,执行流程如下:
- 请求阶段:A的process方法先执行,然后调用handler->handle将请求传递给B,B再传递给C,C将请求传递给控制器处理
- 响应阶段:控制器返回响应后,C的process方法继续执行后续逻辑,然后返回响应给B,B执行后续逻辑后返回给A,最终返回给客户端
如果需要调整中间件的执行顺序,只需要调整middleware方法中的注册顺序即可。
中间件中处理请求和响应的注意事项
在中间件中可以直接修改请求对象,比如添加自定义参数,供后续控制器使用:
<?php
// 在中间件中给请求添加自定义属性
$request = $request->withAttribute('user_id', 1001);
return $handler->handle($request);
也可以在中间件中直接返回响应,中断后续的请求处理流程,比如实现未登录拦截:
<?php
declare(strict_types=1);
namespace AppMiddleware;
use PsrHttpMessageResponseInterface;
use PsrHttpMessageServerRequestInterface;
use PsrHttpServerMiddlewareInterface;
use PsrHttpServerRequestHandlerInterface;
use CakeHttpResponse;
class AuthCheckMiddleware implements MiddlewareInterface
{
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$session = $request->getAttribute('session');
if (!$session || !$session->read('user')) {
// 未登录直接返回跳转响应,中断后续流程
$response = new Response();
return $response->withHeader('Location', '/login')->withStatus(302);
}
return $handler->handle($request);
}
}
常见问题解答
中间件和控制器的区别是什么
中间件作用于整个请求流程,适合处理通用逻辑,比如日志、鉴权、跨域等;控制器只处理特定路由的业务逻辑,职责更单一。中间件可以在请求到达控制器前就完成处理,甚至直接返回响应,不需要进入控制器。
中间件可以依赖注入吗
可以,CakePHP4的中间件支持依赖注入,只需要在中间件的构造函数中声明依赖,框架会自动解析并注入对应的实例,方便中间件复用其他服务的功能。