skip to content

In Laravel, what do url()->current(), url()->full(), url()->previous() and asset() return, and where do their scheme and host come from?

level: juniorimportance: should knowfreq 40%

answer

  1. url() without arguments returns UrlGenerator
  2. current drops the query string
  3. previous: Referer header, then session
  4. ASSET_URL for a CDN root
  5. APP_URL in console; forceScheme overrides

basics

~20 s

url()->current() is the current URL without its query string, url()->full() includes it, url()->previous() uses the Referer header or the session's last URL, and asset() builds a URL to a public file. Scheme and host come from the current request.

solid answer

~40 s

Called without arguments, `url()` returns the `UrlGenerator`. `current()` is the request's URL **without** the query string; `full()` is the same **with** it. `previous($fallback = false)` returns the `Referer` header if present, else the last GET page stored in the session, else the fallback, else the site root. `asset('css/app.css')` builds an absolute URL to a file under `public/`, using `ASSET_URL` as the root when set (a CDN), and adds no cache-busting hash. All of them take scheme and host from the current request; in a console process, such as a queue worker, the request is synthesised from `APP_URL`. `URL::forceScheme('https')` or `URL::forceHttps()` in a service provider forces the scheme of generated URLs.

go deeper

for a junior

Recall which of current() and full() keeps the query string, that previous() gives the last page, and that asset() points at files in public/.

for a middle

Explain the lookup order of previous() and where scheme and host come from, including APP_URL for console processes and ASSET_URL for assets.

for a senior

Anticipate wrong-host links from workers, mixed-content from scheme drift, and the risk of redirecting to a client-supplied Referer.

for a principal

Set a team convention for absolute links — one configured origin, forced scheme in production, CDN for assets — so URL bugs stop depending on where the code runs.

## `url()` as a helper and as an object Laravel's `url()` helper has two faces: - `url('/pricing')` returns a **string**: an absolute URL built from the current request's scheme and host, such as `https://example.com/pricing`. A value that already looks like a full URL is returned unchanged. - `url()` with no arguments returns the **`Illuminate\Routing\UrlGenerator`** instance, the same object behind the `URL` facade. `url()->current()` and `URL::current()` are the same call. ## The current request: `current()` vs `full()` | Call | For a request to `/reports?page=2` | Query string | |---|---|---| | `url()->current()` | `https://example.com/reports` | dropped | | `url()->full()` | `https://example.com/reports?page=2` | kept | | `request()->path()` | `reports` | dropped, and relative | Use `current()` for canonical links and active-menu checks where the query string is noise; use `full()` when you must return the user to exactly the page they were on, filters and page number included. One subtle difference: `full()` delegates to `$request->fullUrl()`, which reads the incoming request directly, while `current()` goes through the generator and therefore honours `forceScheme`. ## `previous()` and `previousPath()` `url()->previous($fallback = false)` resolves in this order: 1. The **`Referer` header** of the current request, if the browser sent one. 2. Otherwise the URL stored in the session. The session middleware records the full URL of each GET request that matched a route and was not AJAX, a prefetch or a precognitive request. 3. Otherwise `$fallback`, if you passed one. 4. Otherwise the site root. `url()->previousPath()` returns just the path of that URL. Two cautions follow from the order. First, the `Referer` header is **client-controlled**: it can be missing, stripped by a referrer policy, or forged, and an absolute URL is passed through unchanged. Do not treat `previous()` as proof of where a user came from, and be careful redirecting to it after sensitive actions. Second, without a session (API routes) only the header and the fallback remain, so always pass a sensible fallback. ## `asset()` for files in `public/` `asset('images/logo.svg')` returns an absolute URL to a file under the `public/` directory: - The root is **`ASSET_URL`** (config key `app.asset_url`) when it is set — typically a CDN origin — otherwise the request's root. - A leading slash is trimmed, and a path that is already a full URL is returned as-is. - `secure_asset()` forces `https`; `asset($path, true)` does the same. - `asset()` does **no fingerprinting**. Cache-busting for compiled CSS and JS is the job of the Vite integration, not of `asset()`. ## Where scheme and host come from The generator reads the root and the scheme from the request it holds: - **In an HTTP request**, from the request itself: its `Host` and its scheme as the app perceives it. Behind a TLS-terminating proxy, that perception depends on whether the app trusts the proxy's forwarded headers — a separate middleware concern. - **In a console process** — Artisan commands, the scheduler and **queue workers** — there is no browser request, so Laravel creates one from `config('app.url')`, i.e. `APP_URL` (the skeleton's `.env.example` sets `http://localhost:8000`). A queued email built with a wrong `APP_URL` links to the wrong place. - **Overrides**, usually in `AppServiceProvider::boot()`: - `URL::forceScheme('https')` or `URL::forceHttps($this->app->isProduction())` rewrite the scheme of every generated URL. - `URL::useOrigin('https://example.com')` forces the whole root, and `URL::useAssetOrigin()` does the same for `asset()` only. ## Related helpers in the same family - `url()->query('/reports', ['page' => 2])` builds a URL with a query string, merging with any query already in the path. - `secure_url('/pricing')` is `url()` with the scheme forced to `https` for that one call. - `url()->previousPath()` returns only the path of the previous URL, handy for comparisons that must ignore the host. - `url()->isValidUrl($value)` tells you whether a string is already absolute (it accepts `http(s)://`, `//`, `#`, `mailto:`, `tel:` and `sms:` prefixes), which is how `url()` and `asset()` decide to pass it through untouched. ## Common mistakes - Expecting `current()` to keep `?page=2` and losing the pagination state on a redirect. - Hard-coding `http://` in templates and getting mixed-content warnings once the site moves to HTTPS. - Using `previous()` in an API route and getting the site root, because there is no session and no `Referer`. - Building absolute links in a queued job and blaming the queue when `APP_URL` is wrong.

  • What does action() generate in Laravel, and what happens when no route points to the given controller method?
    `action([ReportController::class, 'show'], ['report' => 5])` finds the route registered for that controller action and builds its URL, so the path is not hard-coded. If no registered route uses that action, the generator throws an `InvalidArgumentException` reading "Action … not defined."
  • Why do links in emails sent from a Laravel queue worker sometimes point at localhost?
    A worker is a console process with no incoming HTTP request, so Laravel synthesises one from `APP_URL`. If production still carries a development value such as `http://localhost:8000`, every URL the worker generates — `url()`, `route()`, `asset()`, signed links — uses that root. Set `APP_URL` to the public origin.

saying these in an interview costs you the question

  • url()->current() includes the query string
  • url()->previous() only reads the session, never a request header
  • asset() adds a version hash for cache-busting
  • Generated URLs always use APP_URL, even during an HTTP request
  • The Referer header is a trustworthy record of where the user came from