laravel-routes-best-practices
Keep routes clean and focused on mapping requests to controllers; avoid business logic, validation, or database operations in route files
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Keep routes clean and focused on mapping requests to controllers; avoid business logic, validation, or database operations in route files
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.
Enforces an opinionated UI baseline to prevent AI-generated interface slop.
Build apps with the Claude API or Anthropic SDK. TRIGGER when: code imports `anthropic`/`@anthropic-ai/sdk`/`claude_agent_sdk`, or user asks to use Claude API, Anthropic SDKs, or Agent SDK. DO NOT TRIGGER when: code imports `openai`/other AI SDK, general programming, or ML/data-science tasks.
React composition patterns that scale. Use when refactoring components with boolean prop proliferation, building flexible component libraries, or designing reusable APIs. Triggers on tasks involving compound components, render props, context providers, or component architecture. Includes React 19 API changes.
Deploy applications and websites to Vercel. Use when the user requests deployment actions like "deploy my app", "deploy and give me the link", "push this live", or "create a preview deployment".
Use when writing blog posts or documentation markdown files - provides writing style guide (active voice, present tense), content structure patterns, and MDC component usage. Overrides brevity rules for proper grammar. Use nuxt-content for MDC syntax, nuxt-ui for component props.
| name | laravel-routes-best-practices |
| description | Keep routes clean and focused on mapping requests to controllers; avoid business logic, validation, or database operations in route files |
Keep your route files clean and focused on mapping requests to controllers. Routes should never contain business logic, validation, or database operations.
// BAD: Business logic directly in routes
Route::post('/order/{order}/cancel', function (Order $order) {
if ($order->status !== 'pending') {
return response()->json(['error' => 'Cannot cancel'], 400);
}
$order->status = 'cancelled';
$order->cancelled_at = now();
$order->save();
Mail::to($order->user)->send(new OrderCancelled($order));
return response()->json(['message' => 'Order cancelled']);
});
// BAD: Validation in routes
Route::post('/users', function (Request $request) {
$validated = $request->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users',
]);
return User::create($validated);
});
// GOOD: Routes only map to controllers
Route::post('/order/{order}/cancel', [OrderController::class, 'cancel']);
Route::post('/users', [UserController::class, 'store']);
// GOOD: Use route groups for organization
Route::prefix('api/v1')->group(function () {
Route::apiResource('orders', OrderController::class);
Route::post('orders/{order}/cancel', [OrderController::class, 'cancel']);
});
// GOOD: Named routes for maintainability
Route::post('/order/{order}/cancel', [OrderController::class, 'cancel'])
->name('orders.cancel');
// GOOD: Middleware in routes, logic in controllers
Route::middleware(['auth', 'verified'])->group(function () {
Route::resource('admin/users', AdminUserController::class);
});
// app/Http/Controllers/OrderController.php
class OrderController extends Controller
{
public function __construct(
private readonly OrderCancellationService $cancellationService
) {}
public function cancel(CancelOrderRequest $request, Order $order)
{
$this->cancellationService->cancel($order);
return response()->json([
'message' => 'Order cancelled successfully'
]);
}
}
// app/Http/Requests/CancelOrderRequest.php
class CancelOrderRequest extends FormRequest
{
public function authorize(): bool
{
return $this->user()->can('cancel', $this->route('order'));
}
public function rules(): array
{
return [
'reason' => 'nullable|string|max:500',
];
}
}
// routes/web.php - Keep it minimal
Route::get('/', [HomeController::class, 'index']);
Route::get('/about', [PageController::class, 'about']);
require __DIR__ . '/auth.php';
require __DIR__ . '/admin.php';
// routes/admin.php - Separate concerns
Route::prefix('admin')
->middleware(['auth', 'admin'])
->name('admin.')
->group(function () {
Route::get('/dashboard', [AdminDashboardController::class, 'index'])
->name('dashboard');
Route::resource('users', AdminUserController::class);
});
// routes/api.php - API routes
Route::prefix('v1')->group(function () {
Route::apiResource('products', Api\ProductController::class);
Route::post('products/{product}/reviews', [Api\ReviewController::class, 'store']);
});
Routes are declarations, not implementations
Use route model binding
// Laravel automatically resolves the Order model
Route::put('/orders/{order}', [OrderController::class, 'update']);
Group related routes
Route::controller(OrderController::class)->group(function () {
Route::get('/orders', 'index');
Route::get('/orders/{order}', 'show');
Route::post('/orders', 'store');
});
Use resource controllers when appropriate
Route::resource('photos', PhotoController::class)
->only(['index', 'show'])
->names('gallery.photos');
Leverage route caching in production
sail artisan route:cache
Route closures are acceptable only for:
// Acceptable for simple static views
Route::view('/terms', 'legal.terms');
Route::view('/privacy', 'legal.privacy');
// Or simple redirects
Route::redirect('/home', '/dashboard');
Route::permanentRedirect('/old-about', '/about');
test('order cancellation route requires authentication', function () {
$order = Order::factory()->create();
$response = $this->postJson("/orders/{$order->id}/cancel");
$response->assertUnauthorized();
});
test('route names are properly defined', function () {
expect(route('orders.cancel', ['order' => 1]))
->toBe('http://localhost/orders/1/cancel');
});
Remember: If you're writing more than one line of code in a route definition, it belongs in a controller!