在 Laravel 中,路由或控制器最终需要返回一个响应对象,将内容发送给客户端。框架提供了丰富的响应类型和灵活的定制方式,让你能够轻松构建各种 HTTP 响应。 本章将系统介绍常见的响应类型以及如何自定义响应行为。
在 Laravel 中,最简单的响应是返回字符串或数组,框架会自动转换为合适的响应对象:
Route::get('/', function () {
return 'Hello, World!'; // 返回字符串,响应类型为 text/html
});
Route::get('/data', function () {
return ['name' => 'John', 'age' => 30]; // 返回数组,自动转为 JSON
});
Content-Type 设置为 application/json 并返回 JSON 格式。
通过 view() 辅助函数返回 Blade 视图:
return view('welcome', ['name' => 'Taylor']);
使用 response()->json() 可以更精确地控制 JSON 响应:
return response()->json([
'name' => 'Abigail',
'state' => 'CA'
], 201, ['X-Header' => 'value']);
也可以设置 JSON 响应选项,如 JSON_PRETTY_PRINT:
return response()->json($data, 200, [], JSON_PRETTY_PRINT);
重定向响应有多种生成方式:
// 重定向到指定 URL
return redirect('/dashboard');
// 重定向到路由名称
return redirect()->route('profile');
// 重定向到带有参数的命名路由
return redirect()->route('profile', ['id' => 1]);
// 重定向回上一页
return redirect()->back();
// 重定向并携带闪存数据
return redirect()->route('login')->with('error', '登录失败');
// 重定向到控制器动作
return redirect()->action([UserController::class, 'index']);
使用 download 方法让浏览器下载文件:
return response()->download($pathToFile); // 使用原文件名
return response()->download($pathToFile, 'custom_name.pdf'); // 自定义文件名
return response()->download($pathToFile, 'custom.pdf', ['Content-Type' => 'application/pdf']);
使用 file 方法在浏览器中直接显示文件(如图片、PDF):
return response()->file($pathToFile);
return response()->file($pathToFile, ['Content-Type' => 'image/jpeg']);
返回一个没有内容的响应,常用于删除等操作:
return response()->noContent(); // 状态码 204
对于大文件或流式数据,可以使用 stream 方法:
return response()->stream(function () {
echo 'Hello, ';
echo 'World!';
}, 200, ['Content-Type' => 'text/plain']);
所有响应类型都可以通过 response() 辅助函数获得响应工厂实例,然后调用对应方法:
response()->view('view.name', $data) → 视图响应response()->json($data, $status, $headers) → JSON 响应response()->redirectTo($url) → 重定向响应response()->download($path, $name, $headers) → 下载响应response()->file($path, $headers) → 文件响应response()->noContent($status) → 无内容响应Illuminate\Http\Response 或 Illuminate\Http\JsonResponse 实例,但使用工厂方法更为简洁。
如果某些响应模式在项目中频繁使用,可以通过响应宏扩展响应工厂。在服务提供者(如 AppServiceProvider)的 boot 方法中注册:
use Illuminate\Support\Facades\Response;
public function boot(): void
{
Response::macro('success', function ($message, $data = null, $status = 200) {
return response()->json([
'success' => true,
'message' => $message,
'data' => $data,
], $status);
});
Response::macro('error', function ($message, $code = 400, $errors = []) {
return response()->json([
'success' => false,
'message' => $message,
'errors' => $errors,
], $code);
});
}
之后可以在控制器中直接使用:
return response()->success('用户创建成功', $user, 201);
return response()->error('参数错误', 422, ['email' => '邮箱格式不正确']);
对于更复杂的响应逻辑,可以创建自定义响应类,继承 Illuminate\Http\Response 或 Illuminate\Http\JsonResponse:
namespace App\Http\Responses;
use Illuminate\Http\JsonResponse;
class ApiResponse extends JsonResponse
{
public function __construct($data = null, $message = 'Success', $status = 200, $headers = [], $options = 0)
{
$payload = [
'status' => $status,
'message' => $message,
'data' => $data,
];
parent::__construct($payload, $status, $headers, $options);
}
public static function error($message, $status = 400, $errors = [])
{
$payload = [
'status' => $status,
'message' => $message,
'errors' => $errors,
];
return new static($payload, $status);
}
}
使用时:
return new ApiResponse($user, '获取成功');
return ApiResponse::error('未找到资源', 404);
以下是一个完整的示例,展示如何使用响应宏实现统一的 API 响应格式:
服务提供者注册(AppServiceProvider):
use Illuminate\Support\Facades\Response;
public function boot(): void
{
Response::macro('api', function ($data = null, $message = null, $code = 200) {
return response()->json([
'code' => $code,
'message' => $message ?? ($code === 200 ? 'Success' : 'Error'),
'data' => $data,
], $code);
});
}
控制器中使用:
public function index()
{
$users = User::all();
return response()->api($users, '用户列表获取成功');
}
public function store(Request $request)
{
// 验证...
$user = User::create($request->all());
return response()->api($user, '用户创建成功', 201);
}
public function show($id)
{
$user = User::find($id);
if (!$user) {
return response()->api(null, '用户不存在', 404);
}
return response()->api($user);
}
可以在响应中添加自定义头部和 Cookies:
return response($content)
->header('X-Custom-Header', 'Value')
->withCookie(cookie('name', 'value', 60)); // 有效期 60 分钟
response() 工厂时,可以传递状态码作为第二个参数:response()->json($data, 201)。对于字符串响应,可以:response('Not Found', 404)。
with() 方法:return redirect()->route('profile')->with('status', '操作成功');,然后在视图中通过 session('status') 获取。
掌握 Laravel 的响应类型和自定义技巧,能够让你灵活应对各种前端需求,并保持代码的统一性和可维护性。 无论是简单的字符串、复杂的 JSON 还是文件下载,Laravel 都提供了优雅的解决方案。 结合响应宏和自定义响应类,可以进一步提升开发效率。 下一章我们将学习表单验证,为应用筑牢数据安全的第一道防线。