When building applications in Laravel, you’ll often work with related data. A common example is:
- A Book has many Reviews
- A Review belongs to a Book
Now the question is:
How should we structure routes when one resource depends on another?
This is where nested routes come in.
📌 The Problem
Let’s say you want to create a review.
A review cannot exist without a book, right?
So this kind of route feels incomplete:
POST /reviewsBecause:
- Which book does this review belong to?
- You’ll have to manually pass
book_id - It’s easier to make mistakes
✅ The Solution: Nested Routes
Laravel allows you to define routes like this:
Route::resource('books.reviews', ReviewController::class)->only(['create', 'store']);This creates routes like:
GET /books/{book}/reviews/create
POST /books/{book}/reviewsNow every review is clearly tied to a specific book.
🧠 Why This Is Better
1. Clear and meaningful URLs
Instead of:
/reviews/createYou get:
/books/1/reviews/createMuch clearer — you’re creating a review for Book #1.
2. No need to pass book_id manually
Laravel automatically gives you the Book model:
public function store(Request $request, Book $book)
{
$book->reviews()->create($request->all());
}No need to do:
Book::find($request->book_id);3. Safer and cleaner code
Since you’re using:
$book->reviews()->create(...)- The
book_idis automatically set - Users can’t fake or change it
4. Matches real-world relationships
Think of it like this:
A review always belongs to a book.
So your routes should reflect that relationship.
📝 Example Form
<form action="{{ route('books.reviews.store', $book) }}" method="POST">
@csrf
<textarea name="content"></textarea>
<input type="number" name="rating" min="1" max="5">
<button type="submit">Submit Review</button>
</form>Notice how we pass $book in the route.
⚠️ When NOT to Use Nested Routes
Nested routes are great, but not always needed.
Avoid them if:
- The resource can exist independently
- You need very deep nesting (it becomes messy)
🎯 Benefits of Nested Routes
Here are some simple reasons why nested routes are useful:
🔹 1. Enforces the relationship in the URL
With nested routes:
/books/{book}/reviews
you’re making it impossible (by design) to create a review without a book.
Compare that to a flat route:
/reviews
Now you must pass book_id manually and trust validation. That’s more error-prone.
🔹 2. Cleaner, more meaningful URLs
Nested routes naturally describe the relationship:
/books/10/reviews→ reviews of book 10/books/10/reviews/create→ create review for that book
This follows REST principles and makes your app easier to understand (for you and others).
🔹 3. Automatic model binding (less boilerplate)
With:
Route::resource('books.reviews', ReviewController::class);
Laravel injects the parent model automatically:
public function store(Request $request, Book $book)
So instead of:
$book = Book::findOrFail($request->book_id);
you just get $book directly. Less code, fewer mistakes.
🔹 4. Safer data handling
When you do:
$book->reviews()->create($data);
you guarantee:
- the
book_idis correct - users can’t tamper with it (e.g., sending a different
book_idin the request)
With flat routes, that risk is higher unless you guard against it.
🔹 5. Easier authorization logic
It becomes straightforward to apply rules like:
- “User can review this book only once”
- “Only logged-in users can review a book”
- “Only reviews of this specific book can be accessed”
Because you always have the parent $book available in the controller.
🔹 6. Scoped queries (optional but powerful)
Laravel supports scoped bindings, meaning:
/books/{book}/reviews/{review}
can ensure the review actually belongs to that book.
So this won’t happen:
- Accessing a review of Book A through Book B’s URL ❌
🔹 7. Better organization as your app grows
If later you add more child resources:
/books/{book}/reviews/books/{book}/chapters/books/{book}/authors
Your routing stays consistent and predictable.
⚖️ When NOT to use nested routes
Nested routes aren’t always ideal:
- If the child resource can exist independently
(e.g., users and posts where posts might be globally browsable) - If nesting becomes too deep (
/a/{a}/b/{b}/c/{c}/d/{d}→ messy fast)
In short:
- Clear relationship
The URL itself shows the connection:/books/1/reviews→ reviews of a specific book - No confusion about data
You always know which book the review belongs to - Less code to write
Laravel automatically gives you theBookmodel, so no need to manually find it - More secure
Users can’t change thebook_idbecause it’s handled by the route - Cleaner structure
Your app stays organized as it grows
In short, nested routes make your code simpler, safer, and easier to understand.
🏁 Conclusion
Nested routes in Laravel help you:
- Keep your URLs clean and meaningful
- Enforce relationships between models
- Write safer and simpler code
For cases like Books and Reviews, they are the perfect fit.
