Understanding Nested Routes in Laravel

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 /reviews

Because:

  • 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}/reviews

Now every review is clearly tied to a specific book.


🧠 Why This Is Better

1. Clear and meaningful URLs

Instead of:

/reviews/create

You get:

/books/1/reviews/create

Much 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_id is 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_id is correct
  • users can’t tamper with it (e.g., sending a different book_id in 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 the Book model, so no need to manually find it
  • More secure
    Users can’t change the book_id because 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.