Hey everyone! Are you using Laravel?
I'm currently working mainly with TypeScript, but I also touch Laravel from time to time.
Checking if data exists after receiving a request is a pretty common scenario. I recently discovered something new (to me at least!), so I wanted to share it with you all.
Traditional Implementation Patterns
Let's say you have a feature that retrieves post information using a post_id and displays the details on the screen.
class PostController extends Controller
{
public function edit(PostEditRequest $request)
{
$detail = Post::where('id', $request->post_id)->first();
return view('post', ['data' => $detail]);
}
}
And in the FormRequest:
class PostEditRequest extends FormRequest
{
public function rules()
{
return [
'post_id' => 'required|exists:posts,id'
];
}
}
Alternatively, you might set up routing like this:
Route::get('/post/{id}', [PostController::class, 'edit']);
And handle it in the controller:
class PostController extends Controller
{
public function edit(int $id)
{
$detail = Post::where('id', $id)->first();
if (is_null($detail)) {
// Handle error
}
return view('post', ['data' => $detail]);
}
}
These are pretty standard patterns, right?
What is Route Model Binding?
What I recently learned about is "Route Model Binding" - apparently it's been around for quite a while. (Please don't judge me for not knowing about it! 😅)
With Route Model Binding, you can do this:
Route::get('/post/{post}', [PostController::class, 'edit']);
And in your controller:
class PostController extends Controller
{
public function edit(Post $post)
{
return view('post', ['data' => $post]);
}
}
By the time your code reaches the controller, you already have an Eloquent Model instance!
Plus, if the ID doesn't exist, Laravel automatically returns a 404 error. How convenient!
Searching by Non-Primary Key Columns
You can also do this:
Route::get('/post/{post:post_uuid}', [PostController::class, 'edit']);
This searches by a different column. If found, the controller processes it; if not, you get a 404.
If you need ID validation but implementing a FormRequest feels like overkill, this approach might be perfect for your use case.
Binding Related Models
Here's a bonus: you can also use Route Model Binding with related data.
For example, let's say you want to retrieve Employee data that belongs to a specific Company:
Route::get('/company/{company}/employee/{employee}', [EmployeeController::class, 'detail'])->scopeBindings();
This ensures you have the employee model that's associated with the company when the controller processes the request.
In your controller:
class EmployeeController extends Controller
{
public function detail(Company $company, Employee $employee)
{
// Do something
}
}
For this to work, Laravel's Eloquent ORM needs to understand the parent-child relationship. You'll need to define the relationship in your Company model:
class Company extends Model
{
public function employees(): HasMany
{
return $this->hasMany(Employee::class);
}
}
(There are other ways to establish these relationships, but I'll skip those for now.)
Summary
- Route Model Binding gives you a Model instance by the time you reach the controller
- Great for simple implementations where you don't need complex validation
- Automatically returns a 404 error for non-existent data
- You can search by columns other than the primary key
- Parent-child relationships can be bound using
scopeBindings()- This automatically verifies that the specified employee actually belongs to that company
Choosing Your Approach for Resource Existence Checks
Note: This comparison focuses on how to fetch the resource from the database. Of course, you can still use FormRequest for other validation rules (like validating request parameters) even when using Route Model Binding for fetching the model.
- Use FormRequest when: You have complex validation rules or need custom error messages
- Use Route Model Binding when: Simple existence checks are sufficient and you want simple code
Wrapping Up
Route Model Binding is simple and incredibly convenient! Laravel still has so many features I haven't discovered yet. I'll share more as I find them!
Top comments (3)
I'm glad you discovered route model binding.
You can use route model binding and
FormRequesttogether, they are not mutually exclusive. The model binding can handle the path parameters, while theFormRequestcan handle the form input.Wow — I wasn’t expecting a comment, so getting yours genuinely made my day! 🙌
You’re absolutely right: route model binding and
FormRequestserve different purposes and can absolutely be used together.Calling it “When to Use What” was misleading — thanks for pointing that out. I’ve added a note in the article to clarify it.
Thanks again for your insight!
No problem, that is why we post things here. Learning from each other.