skip to content

Named Routes & Groups

Named routes decouple links from paths, and prefix, name, middleware, controller and domain groups share attributes across many routes. Interviewers probe how nested groups merge.

on this pageshow

explore

questions

5

In Laravel, how do you name a route with ->name() and build its URL with route(), including parameters and extra query keys?

level: juniorimportance: must knowfreq 70%

answer

  1. chain ->name() on the definition
  2. route(name, parameters, absolute)
  3. named keys fill placeholders, list fills in order
  4. leftover keys become the query string
  5. unknown name: RouteNotFoundException

basics

~10 s

Chain ->name('franchise.orders.show') on the route, then call route('franchise.orders.show', ['order' => 42]); matching keys fill the placeholders, leftover keys become the query string, and the URL is absolute unless the third argument is false.

solid answer

~30 s

`->name()` gives a route a name, and `route($name, $parameters = [], $absolute = true)` builds its URL. Keys that match placeholders fill them (`['order' => 42]` fills `{order}`), unnamed values fill the remaining placeholders in order, and any other string keys are appended as a query string, so `route('franchise.orders.show', ['order' => 42, 'tab' => 'items'])` gives `https://.../orders/42?tab=items`. Passing `false` as the third argument returns just the path. An unknown name throws `RouteNotFoundException` (`Route [x] not defined.`), and a missing required value throws `UrlGenerationException` listing the missing parameter. `Route::has('name')` checks whether a name exists, and names should be unique.

code

php · 13 lines
php
<?php

use App\Http\Controllers\OrderController;
use Illuminate\Support\Facades\Route;

Route::get('/orders/{order}', [OrderController::class, 'show'])
    ->name('franchise.orders.show');

$absolute = route('franchise.orders.show', ['order' => 42, 'tab' => 'items']);
// https://example.com/orders/42?tab=items

$path = route('franchise.orders.show', ['order' => 42], false);
// /orders/42

go deeper

for a junior

Know how to chain ->name() and call route() with a parameters array, and that extra keys become the query string.

for a middle

Explain how named and positional values fill placeholders, the absolute flag, and the two exceptions for unknown names and missing parameters.

for a senior

Use Route::has for optional links, choose relative URLs where hosts vary, and treat name typos as failures caught by rendering tests.

for a principal

Set a naming scheme that scales across teams and packages so names stay unique and predictable for years.

## Naming a route A **route name** is a stable identifier you can use instead of the URI. You add it by chaining `name()` onto the definition: ```php use App\Http\Controllers\OrderController; use Illuminate\Support\Facades\Route; Route::get('/orders/{order}', [OrderController::class, 'show']) ->name('franchise.orders.show'); ``` Points worth knowing: - Names are plain strings; the dotted `area.resource.action` style is a convention, not a rule. - `name()` **appends** to any name prefix inherited from a group, so inside `Route::name('franchise.')` you write only `->name('orders.show')`. - A string-backed enum case is accepted as the name as well. - Names should be **unique**; the docs say so explicitly, and duplicates cause subtle bugs. ## Building a URL with route() The global `route()` helper calls the URL generator's `route()` method. Its signature is `route($name, $parameters = [], $absolute = true)`. The generator fills the route's URI in a fixed order: 1. **Named keys first**: `['order' => 42]` replaces `{order}`. 2. **Unnamed values next**: a list such as `[42]`, or a single scalar `route('franchise.orders.show', 42)`, fills the remaining placeholders left to right. 3. **Absent optional placeholders** (`{status?}` with no value) are dropped from the URI. 4. **Leftover string keys** become the query string. 5. The result is **absolute** (scheme and host of the current request or configured root) unless `$absolute` is `false`. | Call | Result | |---|---| | `route('franchise.orders.show', ['order' => 42])` | `https://example.com/orders/42` | | `route('franchise.orders.show', 42)` | `https://example.com/orders/42` | | `route('franchise.orders.show', ['order' => 42, 'tab' => 'items'])` | `https://example.com/orders/42?tab=items` | | `route('franchise.orders.show', ['order' => 42], false)` | `/orders/42` | Values are encoded as needed, so a `?` or `#` inside a parameter does not break the URL. ## When generation fails Two exceptions cover the common mistakes: - **Unknown name**: `Symfony\Component\Routing\Exception\RouteNotFoundException` with the message `Route [franchise.order.show] not defined.` Typos in names surface here, at the call site, instead of as broken links. - **Missing required value**: `Illuminate\Routing\Exceptions\UrlGenerationException`, for example `Missing required parameter for [Route: franchise.orders.show] [URI: orders/{order}] [Missing parameter: order].` Both are thrown while rendering, so a Blade view with a bad `route()` call fails loudly in development and in tests. ## Checking that a name exists `Route::has('franchise.orders.show')` returns `true` when a route with that name is registered, and accepts several names, returning `true` only if all exist. Packages and shared layouts use it to render a link only when the host app defines the route. ## Naming conventions that scale A consistent scheme keeps names unique without anyone keeping a list: 1. **Area first**: `franchise.`, `admin.`, `api.`, applied once with a group name prefix. 2. **Resource next**: `orders.`, `stores.`. 3. **Action last**: `index`, `show`, `create`, `store`, `edit`, `update`, `destroy`, matching the controller method where there is one. The result, `franchise.orders.show`, reads like a path through the app and lets wildcard checks such as `routeIs('franchise.orders.*')` select a whole area. Teams that prefer typed names can use a string-backed enum case, since both `->name()` and `route()` accept one and read its value. ## A franchise dashboard example In a Blade view for the franchise dashboard: ```html <a href="{{ route('franchise.orders.show', ['order' => $order->id, 'tab' => 'items']) }}"> Order #{{ $order->id }} </a> ``` If the URI later moves from `/orders/{order}` to `/dashboard/orders/{order}`, every link built with `route()` follows automatically; only hardcoded paths would break. ## Pitfalls interviewers probe - **Expecting relative URLs by default.** `route()` is absolute unless the third argument is `false`; relative paths matter when the same markup is served on several hosts. - **Misspelling a key**: `['id' => 42]` for `{order}` leaves `{order}` unfilled, and the unused `id` would have become a query key, so the call throws for the missing `order` instead. - **Duplicate names**: `route()` silently resolves to only one of the routes. - **Assuming `route()` returns `null` for an unknown name.** It throws.

  • What does Laravel's route() do when you pass ['id' => 42] for a route whose URI is /orders/{order}?
    The generator fills placeholders by key first, finds no `order` key, and has no unnamed value left to fill `{order}` by position. The placeholder stays in the URI, so it throws `UrlGenerationException` with `[Missing parameter: order]`. Rename the key to `order`, or pass the value unnamed as `[42]`.
  • When would you ask route() for a relative path instead of an absolute URL?
    When the same markup is served under several hosts or behind a proxy that rewrites the host, or when a value is stored and later rendered elsewhere. `route('franchise.orders.show', ['order' => 42], false)` returns `/orders/42`, which the browser resolves against whatever host served the page.

saying these in an interview costs you the question

  • route() returns a relative path by default
  • Extra keys passed to route() are silently discarded
  • route() returns null when the name does not exist
  • Route names are automatically unique, so duplicates cannot happen
  • Parameters must always be passed as an associative array
open as a page

In Laravel, how do nested route groups combine their prefix, name, middleware, where, controller and domain attributes?

level: middleimportance: must knowfreq 55%

basics

~20 s

Nested Laravel groups append prefixes with a slash and concatenate name prefixes exactly as written, merge middleware (outer first) and where constraints (inner wins on a clash), and let an inner controller or domain replace the outer one.

open as a page

In Laravel, how do you check which named route handled the current request, for example to highlight the active admin menu item?

level: juniorimportance: should knowfreq 45%

basics

~10 s

Use request()->routeIs('admin.orders.'), which matches the current route's name with * wildcards, or Route::currentRouteName() for the name itself; request()->is('admin/') checks the path instead, and both name checks are false or null when no route matched.

open as a page

How does Laravel's Route::domain() serve a franchise subdomain such as {franchise}.example.com, and what changed about domain routes in Laravel 13?

level: seniorimportance: should knowfreq 30%

basics

~10 s

Route::domain('{franchise}.example.com')->group(...) matches the host and captures franchise, which reaches the handler before path parameters; route() needs it to build URLs, and since Laravel 13 domain routes are matched before routes without a domain.

open as a page

In Laravel, what happens when two routes share a name, and how does that surface differently with and without route caching?

level: seniorimportance: should knowfreq 25%

basics

~20 s

Without caching, Laravel's name lookup keeps just one of the routes, so route() silently points at it while the other stays reachable only by URL; route:cache refuses the duplicate with a LogicException naming the URI and the name.

open as a page