2.1 KiB
2.1 KiB
Routing & Controllers Best Practices
Use Implicit Route Model Binding
Let Laravel resolve models automatically from route parameters.
Incorrect:
public function show(int $id)
{
$post = Post::findOrFail($id);
}
Correct:
public function show(Post $post)
{
return view('posts.show', ['post' => $post]);
}
Use Scoped Bindings for Nested Resources
Enforce parent-child relationships automatically.
Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
// $post is automatically scoped to $user
})->scopeBindings();
Use Resource Controllers
Use Route::resource() or apiResource() for RESTful endpoints.
Route::resource('posts', PostController::class);
Route::apiResource('api/posts', Api\PostController::class);
Keep Controllers Thin
Aim for under 10 lines per method. Extract business logic to action or service classes.
Incorrect:
public function store(Request $request)
{
$validated = $request->validate([...]);
if ($request->hasFile('image')) {
$request->file('image')->move(public_path('images'));
}
$post = Post::create($validated);
$post->tags()->sync($validated['tags']);
event(new PostCreated($post));
return redirect()->route('posts.show', $post);
}
Correct:
public function store(StorePostRequest $request, CreatePostAction $create)
{
$post = $create->execute($request->validated());
return redirect()->route('posts.show', $post);
}
Type-Hint Form Requests
Type-hinting Form Requests triggers automatic validation and authorization before the method executes.
Incorrect:
public function store(Request $request): RedirectResponse
{
$validated = $request->validate([
'title' => ['required', 'max:255'],
'body' => ['required'],
]);
Post::create($validated);
return redirect()->route('posts.index');
}
Correct:
public function store(StorePostRequest $request): RedirectResponse
{
Post::create($request->validated());
return redirect()->route('posts.index');
}