Laravel 13 API 开发最佳实践
API 是现代应用程序的核心组件。本文将介绍 Laravel 13 API 开发的最佳实践,帮助你构建高质量的 RESTful API。
路由设计
RESTful 路由
1 2 3 4 5 6 7 8 9 10 11
| use Illuminate\Support\Facades\Route; use App\Http\Controllers\Api\UserController; use App\Http\Controllers\Api\PostController;
Route::prefix('api/v1')->group(function () { Route::apiResource('users', UserController::class); Route::apiResource('posts', PostController::class); Route::get('users/{user}/posts', [UserController::class, 'posts']); Route::post('posts/{post}/comments', [PostController::class, 'addComment']); });
|
路由版本控制
1 2 3 4 5 6 7
| Route::prefix('api/v1')->group(function () { Route::apiResource('users', UserController::class); });
Route::prefix('api/v2')->group(function () { Route::apiResource('users', V2\UserController::class); });
|
控制器设计
API 控制器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| <?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller; use App\Models\User; use App\Http\Resources\UserResource; use App\Http\Requests\StoreUserRequest; use App\Http\Requests\UpdateUserRequest;
class UserController extends Controller { public function index() { $users = User::paginate(15); return UserResource::collection($users); }
public function store(StoreUserRequest $request) { $user = User::create($request->validated()); return new UserResource($user); }
public function show(User $user) { return new UserResource($user); }
public function update(UpdateUserRequest $request, User $user) { $user->update($request->validated()); return new UserResource($user); }
public function destroy(User $user) { $user->delete(); return response()->json(null, 204); } }
|
资源转换
API 资源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <?php
namespace App\Http\Resources;
use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\JsonResource;
class UserResource extends JsonResource { public function toArray(Request $request): array { return [ 'id' => $this->id, 'name' => $this->name, 'email' => $this->email, 'role' => $this->role, 'created_at' => $this->created_at->toIso8601String(), 'updated_at' => $this->updated_at->toIso8601String(), ]; } }
|
资源集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <?php
namespace App\Http\Resources;
use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\ResourceCollection;
class UserCollection extends ResourceCollection { public function toArray(Request $request): array { return [ 'data' => $this->collection, 'meta' => [ 'total' => $this->total(), 'per_page' => $this->perPage(), 'current_page' => $this->currentPage(), 'last_page' => $this->lastPage(), ], 'links' => [ 'first' => $this->url(1), 'last' => $this->url($this->lastPage()), 'prev' => $this->previousPageUrl(), 'next' => $this->nextPageUrl(), ], ]; } }
|
条件属性
1 2 3 4 5 6 7 8 9 10 11 12 13
| public function toArray(Request $request): array { return [ 'id' => $this->id, 'name' => $this->name, 'email' => $this->when($request->user()->isAdmin(), $this->email), 'posts' => PostResource::collection($this->whenLoaded('posts')), 'posts_count' => $this->whenCounted('posts'), 'secret' => $this->when($request->user()->isAdmin(), function () { return $this->secret; }), ]; }
|
表单请求验证
API 表单请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| <?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Contracts\Validation\Validator; use Illuminate\Http\Exceptions\HttpResponseException;
class StoreUserRequest extends FormRequest { public function authorize(): bool { return true; }
public function rules(): array { return [ 'name' => ['required', 'string', 'max:255'], 'email' => ['required', 'email', 'unique:users,email'], 'password' => ['required', 'string', 'min:8', 'confirmed'], ]; }
protected function failedValidation(Validator $validator) { throw new HttpResponseException( response()->json([ 'message' => 'Validation failed', 'errors' => $validator->errors(), ], 422) ); } }
|
认证授权
Sanctum API 认证
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable { use HasApiTokens; }
public function login(Request $request) { $credentials = $request->validate([ 'email' => 'required|email', 'password' => 'required', ]);
if (!Auth::attempt($credentials)) { return response()->json([ 'message' => 'Invalid credentials', ], 401); }
$token = $request->user()->createToken('api-token')->plainTextToken;
return response()->json([ 'token' => $token, 'user' => new UserResource($request->user()), ]); }
public function logout(Request $request) { $request->user()->currentAccessToken()->delete(); return response()->json(null, 204); }
|
路由保护
1 2 3 4 5 6
| Route::middleware('auth:sanctum')->group(function () { Route::apiResource('users', UserController::class); Route::get('/user', function (Request $request) { return new UserResource($request->user()); }); });
|
错误处理
统一错误响应
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| public function render($request, Throwable $exception) { if ($request->expectsJson()) { if ($exception instanceof ModelNotFoundException) { return response()->json([ 'message' => 'Resource not found', ], 404); }
if ($exception instanceof AuthenticationException) { return response()->json([ 'message' => 'Unauthenticated', ], 401); }
if ($exception instanceof AuthorizationException) { return response()->json([ 'message' => 'Unauthorized', ], 403); }
if ($exception instanceof ValidationException) { return response()->json([ 'message' => 'Validation failed', 'errors' => $exception->errors(), ], 422); } }
return parent::render($request, $exception); }
|
分页
分页响应
1 2 3 4 5 6 7 8 9 10 11 12 13
| public function index() { $users = User::paginate(15); return UserResource::collection($users); }
$users = User::paginate( $perPage = request('per_page', 15), $columns = ['*'], $pageName = 'page', $page = request('page', 1) );
|
速率限制
API 速率限制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| use Illuminate\Cache\RateLimiting\Limit; use Illuminate\Http\Request; use Illuminate\Support\Facades\RateLimiter;
public function boot(): void { RateLimiter::for('api', function (Request $request) { return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip()); }); }
Route::middleware('throttle:api')->group(function () { Route::apiResource('users', UserController::class); });
|
API 文档
注释文档
1 2 3 4 5 6 7 8 9 10 11
|
public function index() { return UserResource::collection(User::paginate()); }
|
缓存
API 缓存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public function index() { $users = Cache::remember('users.list', 3600, function () { return User::paginate(15); });
return UserResource::collection($users); }
public function show(User $user) { $user = Cache::remember("users.{$user->id}", 3600, function () use ($user) { return $user->load('posts'); });
return new UserResource($user); }
|
最佳实践总结
1. 使用资源转换
1 2 3 4 5
| return new UserResource($user);
return response()->json($user->toArray());
|
2. 使用表单请求验证
1 2 3 4 5 6 7 8 9 10 11
| public function store(StoreUserRequest $request) { $user = User::create($request->validated()); }
public function store(Request $request) { $validated = $request->validate([...]); }
|
3. 使用 HTTP 状态码
1 2 3 4 5 6 7 8
| return new UserResource($user)->response()->setStatusCode(201);
return response()->json(null, 204);
return response()->json(['errors' => $errors], 422);
|
4. 使用路由模型绑定
1 2 3 4 5 6 7 8 9 10 11 12
| public function show(User $user) { return new UserResource($user); }
public function show($id) { $user = User::findOrFail($id); return new UserResource($user); }
|
总结
Laravel 13 提供了完善的 API 开发支持。通过合理使用资源转换、表单请求验证、认证授权和错误处理,可以构建出高质量的 RESTful API。记住使用资源转换来控制响应格式、使用表单请求来验证输入、使用 Sanctum 来保护 API、并遵循 RESTful 设计原则。API 是现代应用的核心,良好的 API 设计可以提升开发效率和用户体验。