重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
laravel%3Aroutes-best-practices by jpcaparas/superpowers-laravel
npx skills add https://github.com/jpcaparas/superpowers-laravel --skill laravel:routes-best-practices保持路由文件简洁,专注于将请求映射到控制器。路由中绝不应包含业务逻辑、验证或数据库操作。
// 错误:业务逻辑直接写在路由中
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']);
});
// 错误:在路由中进行验证
Route::post('/users', function (Request $request) {
$validated = $request->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users',
]);
return User::create($validated);
});
// 良好:路由仅映射到控制器
Route::post('/order/{order}/cancel', [OrderController::class, 'cancel']);
Route::post('/users', [UserController::class, 'store']);
// 良好:使用路由组进行组织
Route::prefix('api/v1')->group(function () {
Route::apiResource('orders', OrderController::class);
Route::post('orders/{order}/cancel', [OrderController::class, 'cancel']);
});
// 良好:使用命名路由提高可维护性
Route::post('/order/{order}/cancel', [OrderController::class, 'cancel'])
->name('orders.cancel');
// 良好:中间件放在路由中,逻辑放在控制器中
Route::middleware(['auth', 'verified'])->group(function () {
Route::resource('admin/users', AdminUserController::class);
});
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
// 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 - 保持最小化
Route::get('/', [HomeController::class, 'index']);
Route::get('/about', [PageController::class, 'about']);
require __DIR__ . '/auth.php';
require __DIR__ . '/admin.php';
// routes/admin.php - 分离关注点
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 路由
Route::prefix('v1')->group(function () {
Route::apiResource('products', Api\ProductController::class);
Route::post('products/{product}/reviews', [Api\ReviewController::class, 'store']);
});
路由是声明,而非实现
使用路由模型绑定
// Laravel 自动解析 Order 模型
Route::put('/orders/{order}', [OrderController::class, 'update']);
分组相关路由
Route::controller(OrderController::class)->group(function () {
Route::get('/orders', 'index');
Route::get('/orders/{order}', 'show');
Route::post('/orders', 'store');
});
在适当情况下使用资源控制器
Route::resource('photos', PhotoController::class)
->only(['index', 'show'])
->names('gallery.photos');
在生产环境中利用路由缓存
sail artisan route:cache
路由闭包仅适用于以下情况:
// 适用于简单的静态视图
Route::view('/terms', 'legal.terms');
Route::view('/privacy', 'legal.privacy');
// 或简单的重定向
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');
});
请记住:如果在路由定义中编写的代码超过一行,那么它应该属于控制器!
每周安装量
68
代码仓库
GitHub 星标数
122
首次出现
2026年1月21日
已安装于
opencode45
claude-code44
gemini-cli41
codex41
github-copilot40
cursor39
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:
Simple static page renders
Temporary debugging/testing (remove before committing)
Quick prototypes (refactor to controllers before production)
// 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!
Weekly Installs
68
Repository
GitHub Stars
122
First Seen
Jan 21, 2026
Installed on
opencode45
claude-code44
gemini-cli41
codex41
github-copilot40
cursor39
Laravel TDD 测试驱动开发指南:PHPUnit 与 Pest 实现 80% 以上测试覆盖率
1,100 周安装