Stop rewriting your API responses in Laravel (Use this Trait instead)
Stop rewriting your API responses in Laravel (Use this Trait instead)
别再重复编写 Laravel API 响应了(改用这个 Trait 吧)
If you are building API-driven applications, nothing clutters up your controllers faster than manually typing out response()->json(...) arrays every single time you need to return data or throw an error.
如果你正在构建 API 驱动的应用程序,没有什么比每次需要返回数据或抛出错误时手动编写 response()->json(...) 数组更能让控制器变得臃肿了。
When you have inconsistent response structures, your frontend (and the developers consuming your API) will constantly have to guess whether the data is nested under ['data'], ['payload'], or just at the root of the object.
当响应结构不一致时,你的前端(以及调用你 API 的开发者)将不得不不断猜测数据是嵌套在 ['data']、['payload'] 下,还是直接位于对象的根目录下。
The cleanest way I’ve found to standardize this across an entire application is by creating a dedicated ApiResponse trait. Instead of rewriting your JSON structure in every controller method, create this trait in your app/Traits directory:
我发现实现全应用标准化的最简洁方法是创建一个专门的 ApiResponse trait。与其在每个控制器方法中重写 JSON 结构,不如在 app/Traits 目录下创建这个 trait:
namespace App\Traits;
use Illuminate\Http\JsonResponse;
trait ApiResponse {
protected function success(mixed $data, ?string $message = null, int $code = 200): JsonResponse {
return response()->json([
'status' => 'success',
'message' => $message,
'data' => $data
], $code);
}
protected function error(string $message, int $code = 400, array|string $errors = []): JsonResponse {
// Force errors into an array format for consistent frontend parsing
$formattedErrors = is_string($errors) ? [$errors] : $errors;
return response()->json([
'status' => 'error',
'message' => $message,
'errors' => $formattedErrors
], $code);
}
}
Next, simply use this trait inside your base Controller.php. Now, your actual endpoints become incredibly readable and strictly standardized:
接下来,只需在你的基础 Controller.php 中使用这个 trait。现在,你的实际端点代码将变得非常易读且严格标准化:
namespace App\Http\Controllers;
use App\Models\Task;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Throwable;
class TaskController extends Controller {
use ApiResponse; // 使用 trait
public function store(Request $request): JsonResponse {
$validated = $request->validate([
'title' => 'required|string|max:255',
'description' => 'nullable|string'
]);
try {
$task = Task::create($validated);
return $this->success($task, 'Task successfully generated', 201);
} catch (Throwable $e) {
// Note: Exposing raw exception messages is fine for local dev,
// but should be sanitized or logged in production environments.
return $this->error('Failed to generate task', 500, [$e->getMessage()]);
}
}
}
This guarantees that every single endpoint in your application returns the exact same JSON signature. Your frontend will thank you. 这保证了你应用程序中的每一个端点都返回完全相同的 JSON 签名。你的前端开发人员会感谢你的。
How are you handling global API responses in your current stack? Do you use traits, or do you prefer wrapping everything in dedicated Resource classes? Let me know below. 你在当前的开发栈中是如何处理全局 API 响应的?你是使用 trait,还是更喜欢将所有内容封装在专门的 Resource 类中?请在下方告诉我。