skip to content

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