在Laravel项目开发中,当我们处理某些接口请求时,比如删除资源、更新操作不需要返回具体数据,或者查询不到对应数据时,经常会遇到返回空响应的情况。默认情况下Laravel会返回200状态码,但是按照RESTful API的规范,无返回内容的成功请求应该返回204 No Content状态码,手动在每个控制器中处理这样的逻辑会非常繁琐,通过自定义中间件可以统一解决这个问题。

实现思路
核心思路是创建一个中间件,在响应返回给客户端之前,检查响应内容是否为空,如果为空且请求方法是符合返回204的场景,就将状态码修改为204。需要处理的响应场景包括响应体为空字符串、空的JSON对象、空的数组等情况。
创建中间件
首先使用Artisan命令创建中间件:
php artisan make:middleware HandleEmptyResponse
然后打开生成的app/Http/Middleware/HandleEmptyResponse.php文件,编写处理逻辑:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class HandleEmptyResponse
{
/**
* 处理传入的请求
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return \Symfony\Component\HttpFoundation\Response
*/
public function handle(Request $request, Closure $next): Response
{
// 先执行后续逻辑获取响应
$response = $next($request);
// 只处理成功状态的响应
if (!$response->isSuccessful()) {
return $response;
}
// 获取响应内容
$content = $response->getContent();
$isEmpty = false;
// 判断响应内容是否为空
if (empty($content)) {
$isEmpty = true;
} else {
// 尝试解析JSON内容
$decoded = json_decode($content, true);
if (json_last_error() === JSON_ERROR_NONE) {
// 空的JSON对象或空数组视为空响应
if ($decoded === [] || $decoded === null || $decoded === new \stdClass()) {
$isEmpty = true;
}
}
}
// 如果是空响应,设置为204状态码
if ($isEmpty) {
$response->setStatusCode(204);
// 204状态码不应该有响应体,清空内容
$response->setContent('');
}
return $response;
}
}注册中间件
打开app/Http/Kernel.php文件,将中间件注册到全局中间件或者需要的路由中间件组中,这里以注册到api中间件组为例:
<?php
namespace App\Http;
use App\Http\Middleware\HandleEmptyResponse;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
// ... 其他代码
protected $middlewareGroups = [
'web' => [
// ... 其他中间件
],
'api' => [
// ... 其他中间件
HandleEmptyResponse::class,
],
];
// ... 其他代码
}测试验证
我们可以创建一个测试路由来验证效果,首先在routes/api.php中添加测试路由:
<?php
use App\Http\Controllers\TestController;
use Illuminate\Support\Facades\Route;
Route::get('/test-empty', [TestController::class, 'testEmpty']);
Route::post('/test-empty-json', [TestController::class, 'testEmptyJson']);然后创建对应的控制器方法:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class TestController extends Controller
{
// 返回空字符串的测试
public function testEmpty()
{
return response('');
}
// 返回空JSON的测试
public function testEmptyJson()
{
return response()->json([]);
}
}使用Postman或者curl请求这两个接口,会发现返回的状态码都是204,符合我们的预期。如果返回的内容不为空,比如返回response->json(['id' => 1]),状态码仍然是200,不会受到影响。
注意事项
- 204状态码的响应不应该包含响应体,所以中间件中如果发现是空响应,需要清空响应内容,避免返回多余的内容。
- 如果某些接口需要返回空响应但不需要204状态码,可以在中间件中添加排除逻辑,比如通过路由名称或者请求路径判断是否需要跳过处理。
- 该方法只处理成功状态的响应,错误响应不会被修改,不会影响正常的错误处理逻辑。