Route::get
Registers a route that answers GET and HEAD requests at the given URI.
get(string $uri, array|string|callable $action = null): Illuminate\Routing\RouteParameters
| Parameter | Type | Description |
|---|---|---|
$$uri | string | The URI pattern to match. Segments wrapped in braces such as {post} become route parameters; add ? for an optional parameter. |
$$actionoptional | array|string|callable= null | What 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/populardeclared 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:cacherefuses to serialize a closure, so production route files should point at controllers. - Slashes. A parameter cannot contain
/unless you allow it withwhere('search', '.*'), and only in the last segment.
Example
<?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/12When 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.
<?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/AdaGrouped 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.
<?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