直接返回 JSON 时应使用 response()->json() 默认状态码,避免手动设 200;CSRF 错误需检查 meta token 和 Axios 配置;验证失败自动返回 JSON 错误,无需手动处理;Resource 类中禁止 N+1 查询,应预加载关联。

直接返回 JSON 时,别用 response()->json() 包裹数组再手动加状态码
很多人写 AJAX 响应时习惯先构造数组,再塞进 response()->json(),还额外调用 ->withStatus(200) 或拼 ['status' => 'success']。这既冗余又容易出错——Laravel 的 response()->json() 本身已默认返回 200,且自动设置 Content-Type: application/json。手动覆盖状态码反而可能掩盖真实错误(比如本该是 422 却强行写成 200)。
实操建议:
- 成功响应直接用
return response()->json(['data' => $user, 'message' => 'OK']); - 需要非 200 状态码时,明确传参:
return response()->json(['error' => 'Not found'], 404); - 避免在控制器里先
$arr = ['status' => 'ok'];再json($arr)——语义重复,且后续中间件或异常处理器难统一拦截
前端发来 CSRF token 缺失或过期,TokenMismatchException 怎么快速定位
Laravel 默认对所有非 GET/HEAD 请求校验 _token,AJAX 请求若没带或带错,直接 500 或空响应,不报具体错误。常见原因是前端没读取 meta 标签里的 token,或 JS 框架(如 Axios)没配置全局 header。
实操建议:
- 检查页面是否包含
<meta name="csrf-token" content="{{ csrf_token() }}"> - Axios 场景下,在 JS 初始化处加:
axios.defaults.headers.common['X-CSRF-TOKEN'] = document.querySelector('meta[name="csrf-token"]').getAttribute('content'); - 临时调试可注释掉
App\Http\Middleware\VerifyCsrfToken中的except数组,但上线前必须删掉——不能靠排除法绕过防护 - 注意:API 路由(
routes/api.php)默认不校验 CSRF,但如果你把 AJAX 接口写在web.php里,就必须处理 token
validate() 失败时返回 JSON 格式错误,而不是跳转或白屏
表单验证失败默认重定向回上一页,这对 AJAX 完全不适用。如果没显式告诉 Laravel “这是 API 请求”,$request->validate() 会抛出 Illuminate\Validation\ValidationException,最终渲染成 HTML 页面,前端拿到一堆 HTML 字符串,解析失败。
Laravel Cloud(cloud.laravel.com)。此技能用于处理所有 Laravel Cloud 请求,包括搜索和读取数据。只要任务涉及 Laravel Cloud,即使用此技能。
实操建议:
- 确保请求头含
Accept: application/json(Axios 默认带,fetch 需手动设) - 控制器方法开头加
if ($request->expectsJson()) { ... }判断不是必须,Laravel 5.5+ 会自动识别 JSON 请求并返回 JSON 错误 - 自定义错误格式?重写
failedValidation()方法,但只在必要时——默认的{"message":"The given data was invalid.","errors":{"email":["The email field is required."]}}已足够前端消费 - 别在验证失败后写
return response()->json(..., 422)——重复造轮子,Laravel 已内置处理逻辑
用 Resource 类封装数据时,别在 toArray() 里做 N+1 查询
写 UserResource::collection($users) 很优雅,但如果 toArray() 里写了 $this->posts->count() 或 $this->profile->avatar,每次实例化都会触发新查询,100 个用户就是 100 次额外 DB 请求。
实操建议:
- 提前加载关联:控制器里用
User::with('posts', 'profile')->get() - 资源类中只做字段映射,不做计算或懒加载:
'post_count' => $this->whenLoaded('posts', $this->posts->count()) - 复杂计算逻辑提到控制器或服务类,资源类保持“纯数据转换”职责
- 开发期打开
DB::enableQueryLog()+dd(DB::getQueryLog())快速确认是否 N+1
真正麻烦的从来不是怎么返回 JSON,而是前后端对“错误边界”的理解不一致:前端以为 200 就代表成功,后端却在 200 里塞了业务错误码;或者后端用 422 表示验证失败,前端却只监听 400 和 500。这类问题不会报错,但会让联调卡半天。

















