Route::get

Registers a route that answers GET and HEAD requests at the given URI.

Signature
get(string $uri, array|string|callable $action = null): Illuminate\Routing\Route

Parameters

ParameterTypeDescription
$$uristringThe URI pattern to match. Segments wrapped in braces such as {post} become route parameters; add ? for an optional parameter.
$$actionoptionalarray|string|callable= nullWhat handles the request: a closure, a [Controller::class, 'method'] array, an invokable controller class name, or a 'Controller@method' string.

Return value

Illuminate\Routing\RouteThe registered Route instance, so you can chain name(), middleware(), where() and the other route-level modifiers onto it.

Errors

Nothing at registration time. A request that matches the URI but fails a where() constraint or an implicit model binding produces a 404 response instead.

Route::get is the entry point for every readable endpoint in an application: pages, listings, detail views, JSON reads. It registers a handler for GET and HEAD — a HEAD request runs the same action and Laravel discards the body — so a GET route must never have side effects.

When to reach for it

Any URI a browser can be pointed at, and any API endpoint that only reads. If the same URI needs to answer several verbs, register each verb separately rather than reaching for Route::any; the docs are explicit that get, post, put, patch, delete and options routes should be defined before any any, match or redirect routes sharing a URI.

What trips people up

  • Registration order wins. A literal /photos/popular declared after /photos/{photo} never runs, because the parameter route matches first.
  • Argument order, not argument names. Route parameters are injected positionally; container dependencies must be listed first, parameters after.
  • Closures block route caching. route:cache refuses to serialize a closure, so production route files should point at controllers.
  • Slashes. A parameter cannot contain / unless you allow it with where('search', '.*'), and only in the last segment.

Example

Example · php
<?php

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

Route::get('/', function () {
    return view('welcome');
});

// A static segment must be registered before the parameter route.
Route::get('/posts/popular', [PostController::class, 'popular']);

Route::get('/posts/{post}', [PostController::class, 'show'])
    ->whereNumber('post')
    ->name('posts.show');

echo route('posts.show', ['post' => 12]);
// http://example.com/posts/12

When to use it

  • Serve a public landing page from a closure that returns a view.
  • Point a product detail URL at a controller method and constrain the id to digits.
  • Expose a read-only JSON endpoint in routes/api.php behind auth:sanctum.
  • Give a route a name so route() and redirect()->route() can build its URL.

Frequently asked questions

Does Route::get also handle HEAD requests?

Yes — a GET route answers HEAD as well, running the same action while the response body is discarded. That is another reason a GET handler should never mutate state.

Why does my route return 404 when the URL looks right?

Most often a where() or whereNumber() constraint failed, or an earlier route with a parameter matched the URI first. Run php artisan route:list --path=... to see which route actually owns the URI, and remember that a failed constraint yields a 404 rather than an error.

Can I put a slash inside a route parameter?

Only if you explicitly allow it with ->where('search', '.*'), and only in the final URI segment. By default a route parameter matches every character except /.

More examples

Optional parameters and dependency injection

The first route shows the injection rule: Illuminate\Http\Request is resolved by the container and listed first, while {id} arrives positionally afterwards. The second shows that an optional parameter simply drops out of the generated URL when route() is called without it, and is appended when a value is supplied.

Example · php
<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

// Container dependencies first, route parameters after.
Route::get('/user/{id}', function (Request $request, string $id) {
    return 'User '.$id;
});

// The ? marks the segment optional; the variable needs a default.
Route::get('/greet/{name?}', function (?string $name = 'John') {
    return 'Hello '.$name;
})->name('greet');

echo route('greet');
echo PHP_EOL;
echo route('greet', ['name' => 'Ada']);
// http://example.com/greet
// http://example.com/greet/Ada

Grouped GET routes sharing a controller and prefix

The output shows how the group attributes compose: prefix('orders') builds the URI, name('orders.') is prepended to each route name so the short name('index') resolves to orders.index, and both routes inherit the auth middleware without repeating it.

Example · php
<?php

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

Route::controller(OrderController::class)
    ->prefix('orders')
    ->name('orders.')
    ->middleware('auth')
    ->group(function () {
        Route::get('/', 'index')->name('index');
        Route::get('/{id}', 'show')->name('show')->whereNumber('id');
    });

echo route('orders.index');
echo PHP_EOL;
echo route('orders.show', ['id' => 7]);
// http://example.com/orders
// http://example.com/orders/7

Discussion

  • Be the first to comment on this lesson.