Init
This commit is contained in:
708
output/12.x/urls.md
Normal file
708
output/12.x/urls.md
Normal file
@@ -0,0 +1,708 @@
|
||||
# URL Generation
|
||||
|
||||
* Introduction
|
||||
* The Basics
|
||||
* Generating URLs
|
||||
* Accessing the Current URL
|
||||
* URLs for Named Routes
|
||||
* Signed URLs
|
||||
* URLs for Controller Actions
|
||||
* Fluent URI Objects
|
||||
* Default Values
|
||||
|
||||
## Introduction
|
||||
|
||||
Laravel provides several helpers to assist you in generating URLs for your
|
||||
application. These helpers are primarily helpful when building links in your
|
||||
templates and API responses, or when generating redirect responses to another
|
||||
part of your application.
|
||||
|
||||
## The Basics
|
||||
|
||||
### Generating URLs
|
||||
|
||||
The `url` helper may be used to generate arbitrary URLs for your application.
|
||||
The generated URL will automatically use the scheme (HTTP or HTTPS) and host
|
||||
from the current request being handled by the application:
|
||||
|
||||
|
||||
|
||||
1$post = App\Models\Post::find(1);
|
||||
|
||||
2
|
||||
|
||||
3echo url("/posts/{$post->id}");
|
||||
|
||||
4
|
||||
|
||||
5// http://example.com/posts/1
|
||||
|
||||
|
||||
$post = App\Models\Post::find(1);
|
||||
|
||||
echo url("/posts/{$post->id}");
|
||||
|
||||
// http://example.com/posts/1
|
||||
|
||||
To generate a URL with query string parameters, you may use the `query`
|
||||
method:
|
||||
|
||||
|
||||
|
||||
1echo url()->query('/posts', ['search' => 'Laravel']);
|
||||
|
||||
2
|
||||
|
||||
3// https://example.com/posts?search=Laravel
|
||||
|
||||
4
|
||||
|
||||
5echo url()->query('/posts?sort=latest', ['search' => 'Laravel']);
|
||||
|
||||
6
|
||||
|
||||
7// http://example.com/posts?sort=latest&search=Laravel
|
||||
|
||||
|
||||
echo url()->query('/posts', ['search' => 'Laravel']);
|
||||
|
||||
// https://example.com/posts?search=Laravel
|
||||
|
||||
echo url()->query('/posts?sort=latest', ['search' => 'Laravel']);
|
||||
|
||||
// http://example.com/posts?sort=latest&search=Laravel
|
||||
|
||||
Providing query string parameters that already exist in the path will
|
||||
overwrite their existing value:
|
||||
|
||||
|
||||
|
||||
1echo url()->query('/posts?sort=latest', ['sort' => 'oldest']);
|
||||
|
||||
2
|
||||
|
||||
3// http://example.com/posts?sort=oldest
|
||||
|
||||
|
||||
echo url()->query('/posts?sort=latest', ['sort' => 'oldest']);
|
||||
|
||||
// http://example.com/posts?sort=oldest
|
||||
|
||||
Arrays of values may also be passed as query parameters. These values will be
|
||||
properly keyed and encoded in the generated URL:
|
||||
|
||||
|
||||
|
||||
1echo $url = url()->query('/posts', ['columns' => ['title', 'body']]);
|
||||
|
||||
2
|
||||
|
||||
3// http://example.com/posts?columns%5B0%5D=title&columns%5B1%5D=body
|
||||
|
||||
4
|
||||
|
||||
5echo urldecode($url);
|
||||
|
||||
6
|
||||
|
||||
7// http://example.com/posts?columns[0]=title&columns[1]=body
|
||||
|
||||
|
||||
echo $url = url()->query('/posts', ['columns' => ['title', 'body']]);
|
||||
|
||||
// http://example.com/posts?columns%5B0%5D=title&columns%5B1%5D=body
|
||||
|
||||
echo urldecode($url);
|
||||
|
||||
// http://example.com/posts?columns[0]=title&columns[1]=body
|
||||
|
||||
### Accessing the Current URL
|
||||
|
||||
If no path is provided to the `url` helper, an
|
||||
`Illuminate\Routing\UrlGenerator` instance is returned, allowing you to access
|
||||
information about the current URL:
|
||||
|
||||
|
||||
|
||||
1// Get the current URL without the query string...
|
||||
|
||||
2echo url()->current();
|
||||
|
||||
3
|
||||
|
||||
4// Get the current URL including the query string...
|
||||
|
||||
5echo url()->full();
|
||||
|
||||
6
|
||||
|
||||
7// Get the full URL for the previous request...
|
||||
|
||||
8echo url()->previous();
|
||||
|
||||
9
|
||||
|
||||
10// Get the path for the previous request...
|
||||
|
||||
11echo url()->previousPath();
|
||||
|
||||
|
||||
// Get the current URL without the query string...
|
||||
echo url()->current();
|
||||
|
||||
// Get the current URL including the query string...
|
||||
echo url()->full();
|
||||
|
||||
// Get the full URL for the previous request...
|
||||
echo url()->previous();
|
||||
|
||||
// Get the path for the previous request...
|
||||
echo url()->previousPath();
|
||||
|
||||
Each of these methods may also be accessed via the `URL`
|
||||
[facade](/docs/12.x/facades):
|
||||
|
||||
|
||||
|
||||
1use Illuminate\Support\Facades\URL;
|
||||
|
||||
2
|
||||
|
||||
3echo URL::current();
|
||||
|
||||
|
||||
use Illuminate\Support\Facades\URL;
|
||||
|
||||
echo URL::current();
|
||||
|
||||
## URLs for Named Routes
|
||||
|
||||
The `route` helper may be used to generate URLs to [named
|
||||
routes](/docs/12.x/routing#named-routes). Named routes allow you to generate
|
||||
URLs without being coupled to the actual URL defined on the route. Therefore,
|
||||
if the route's URL changes, no changes need to be made to your calls to the
|
||||
`route` function. For example, imagine your application contains a route
|
||||
defined like the following:
|
||||
|
||||
|
||||
|
||||
1Route::get('/post/{post}', function (Post $post) {
|
||||
|
||||
2 // ...
|
||||
|
||||
3})->name('post.show');
|
||||
|
||||
|
||||
Route::get('/post/{post}', function (Post $post) {
|
||||
// ...
|
||||
})->name('post.show');
|
||||
|
||||
To generate a URL to this route, you may use the `route` helper like so:
|
||||
|
||||
|
||||
|
||||
1echo route('post.show', ['post' => 1]);
|
||||
|
||||
2
|
||||
|
||||
3// http://example.com/post/1
|
||||
|
||||
|
||||
echo route('post.show', ['post' => 1]);
|
||||
|
||||
// http://example.com/post/1
|
||||
|
||||
Of course, the `route` helper may also be used to generate URLs for routes
|
||||
with multiple parameters:
|
||||
|
||||
|
||||
|
||||
1Route::get('/post/{post}/comment/{comment}', function (Post $post, Comment $comment) {
|
||||
|
||||
2 // ...
|
||||
|
||||
3})->name('comment.show');
|
||||
|
||||
4
|
||||
|
||||
5echo route('comment.show', ['post' => 1, 'comment' => 3]);
|
||||
|
||||
6
|
||||
|
||||
7// http://example.com/post/1/comment/3
|
||||
|
||||
|
||||
Route::get('/post/{post}/comment/{comment}', function (Post $post, Comment $comment) {
|
||||
// ...
|
||||
})->name('comment.show');
|
||||
|
||||
echo route('comment.show', ['post' => 1, 'comment' => 3]);
|
||||
|
||||
// http://example.com/post/1/comment/3
|
||||
|
||||
Any additional array elements that do not correspond to the route's definition
|
||||
parameters will be added to the URL's query string:
|
||||
|
||||
|
||||
|
||||
1echo route('post.show', ['post' => 1, 'search' => 'rocket']);
|
||||
|
||||
2
|
||||
|
||||
3// http://example.com/post/1?search=rocket
|
||||
|
||||
|
||||
echo route('post.show', ['post' => 1, 'search' => 'rocket']);
|
||||
|
||||
// http://example.com/post/1?search=rocket
|
||||
|
||||
#### Eloquent Models
|
||||
|
||||
You will often be generating URLs using the route key (typically the primary
|
||||
key) of [Eloquent models](/docs/12.x/eloquent). For this reason, you may pass
|
||||
Eloquent models as parameter values. The `route` helper will automatically
|
||||
extract the model's route key:
|
||||
|
||||
|
||||
|
||||
1echo route('post.show', ['post' => $post]);
|
||||
|
||||
|
||||
echo route('post.show', ['post' => $post]);
|
||||
|
||||
### Signed URLs
|
||||
|
||||
Laravel allows you to easily create "signed" URLs to named routes. These URLs
|
||||
have a "signature" hash appended to the query string which allows Laravel to
|
||||
verify that the URL has not been modified since it was created. Signed URLs
|
||||
are especially useful for routes that are publicly accessible yet need a layer
|
||||
of protection against URL manipulation.
|
||||
|
||||
For example, you might use signed URLs to implement a public "unsubscribe"
|
||||
link that is emailed to your customers. To create a signed URL to a named
|
||||
route, use the `signedRoute` method of the `URL` facade:
|
||||
|
||||
|
||||
|
||||
1use Illuminate\Support\Facades\URL;
|
||||
|
||||
2
|
||||
|
||||
3return URL::signedRoute('unsubscribe', ['user' => 1]);
|
||||
|
||||
|
||||
use Illuminate\Support\Facades\URL;
|
||||
|
||||
return URL::signedRoute('unsubscribe', ['user' => 1]);
|
||||
|
||||
You may exclude the domain from the signed URL hash by providing the
|
||||
`absolute` argument to the `signedRoute` method:
|
||||
|
||||
|
||||
|
||||
1return URL::signedRoute('unsubscribe', ['user' => 1], absolute: false);
|
||||
|
||||
|
||||
return URL::signedRoute('unsubscribe', ['user' => 1], absolute: false);
|
||||
|
||||
If you would like to generate a temporary signed route URL that expires after
|
||||
a specified amount of time, you may use the `temporarySignedRoute` method.
|
||||
When Laravel validates a temporary signed route URL, it will ensure that the
|
||||
expiration timestamp that is encoded into the signed URL has not elapsed:
|
||||
|
||||
|
||||
|
||||
1use Illuminate\Support\Facades\URL;
|
||||
|
||||
2
|
||||
|
||||
3return URL::temporarySignedRoute(
|
||||
|
||||
4 'unsubscribe', now()->addMinutes(30), ['user' => 1]
|
||||
|
||||
5);
|
||||
|
||||
|
||||
use Illuminate\Support\Facades\URL;
|
||||
|
||||
return URL::temporarySignedRoute(
|
||||
'unsubscribe', now()->addMinutes(30), ['user' => 1]
|
||||
);
|
||||
|
||||
#### Validating Signed Route Requests
|
||||
|
||||
To verify that an incoming request has a valid signature, you should call the
|
||||
`hasValidSignature` method on the incoming `Illuminate\Http\Request` instance:
|
||||
|
||||
|
||||
|
||||
1use Illuminate\Http\Request;
|
||||
|
||||
2
|
||||
|
||||
3Route::get('/unsubscribe/{user}', function (Request $request) {
|
||||
|
||||
4 if (! $request->hasValidSignature()) {
|
||||
|
||||
5 abort(401);
|
||||
|
||||
6 }
|
||||
|
||||
7
|
||||
|
||||
8 // ...
|
||||
|
||||
9})->name('unsubscribe');
|
||||
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
Route::get('/unsubscribe/{user}', function (Request $request) {
|
||||
if (! $request->hasValidSignature()) {
|
||||
abort(401);
|
||||
}
|
||||
|
||||
// ...
|
||||
})->name('unsubscribe');
|
||||
|
||||
Sometimes, you may need to allow your application's frontend to append data to
|
||||
a signed URL, such as when performing client-side pagination. Therefore, you
|
||||
can specify request query parameters that should be ignored when validating a
|
||||
signed URL using the `hasValidSignatureWhileIgnoring` method. Remember,
|
||||
ignoring parameters allows anyone to modify those parameters on the request:
|
||||
|
||||
|
||||
|
||||
1if (! $request->hasValidSignatureWhileIgnoring(['page', 'order'])) {
|
||||
|
||||
2 abort(401);
|
||||
|
||||
3}
|
||||
|
||||
|
||||
if (! $request->hasValidSignatureWhileIgnoring(['page', 'order'])) {
|
||||
abort(401);
|
||||
}
|
||||
|
||||
Instead of validating signed URLs using the incoming request instance, you may
|
||||
assign the `signed` (`Illuminate\Routing\Middleware\ValidateSignature`)
|
||||
[middleware](/docs/12.x/middleware) to the route. If the incoming request does
|
||||
not have a valid signature, the middleware will automatically return a `403`
|
||||
HTTP response:
|
||||
|
||||
|
||||
|
||||
1Route::post('/unsubscribe/{user}', function (Request $request) {
|
||||
|
||||
2 // ...
|
||||
|
||||
3})->name('unsubscribe')->middleware('signed');
|
||||
|
||||
|
||||
Route::post('/unsubscribe/{user}', function (Request $request) {
|
||||
// ...
|
||||
})->name('unsubscribe')->middleware('signed');
|
||||
|
||||
If your signed URLs do not include the domain in the URL hash, you should
|
||||
provide the `relative` argument to the middleware:
|
||||
|
||||
|
||||
|
||||
1Route::post('/unsubscribe/{user}', function (Request $request) {
|
||||
|
||||
2 // ...
|
||||
|
||||
3})->name('unsubscribe')->middleware('signed:relative');
|
||||
|
||||
|
||||
Route::post('/unsubscribe/{user}', function (Request $request) {
|
||||
// ...
|
||||
})->name('unsubscribe')->middleware('signed:relative');
|
||||
|
||||
#### Responding to Invalid Signed Routes
|
||||
|
||||
When someone visits a signed URL that has expired, they will receive a generic
|
||||
error page for the `403` HTTP status code. However, you can customize this
|
||||
behavior by defining a custom "render" closure for the
|
||||
`InvalidSignatureException` exception in your application's
|
||||
`bootstrap/app.php` file:
|
||||
|
||||
|
||||
|
||||
1use Illuminate\Routing\Exceptions\InvalidSignatureException;
|
||||
|
||||
2
|
||||
|
||||
3->withExceptions(function (Exceptions $exceptions) {
|
||||
|
||||
4 $exceptions->render(function (InvalidSignatureException $e) {
|
||||
|
||||
5 return response()->view('errors.link-expired', status: 403);
|
||||
|
||||
6 });
|
||||
|
||||
7})
|
||||
|
||||
|
||||
use Illuminate\Routing\Exceptions\InvalidSignatureException;
|
||||
|
||||
->withExceptions(function (Exceptions $exceptions) {
|
||||
$exceptions->render(function (InvalidSignatureException $e) {
|
||||
return response()->view('errors.link-expired', status: 403);
|
||||
});
|
||||
})
|
||||
|
||||
## URLs for Controller Actions
|
||||
|
||||
The `action` function generates a URL for the given controller action:
|
||||
|
||||
|
||||
|
||||
1use App\Http\Controllers\HomeController;
|
||||
|
||||
2
|
||||
|
||||
3$url = action([HomeController::class, 'index']);
|
||||
|
||||
|
||||
use App\Http\Controllers\HomeController;
|
||||
|
||||
$url = action([HomeController::class, 'index']);
|
||||
|
||||
If the controller method accepts route parameters, you may pass an associative
|
||||
array of route parameters as the second argument to the function:
|
||||
|
||||
|
||||
|
||||
1$url = action([UserController::class, 'profile'], ['id' => 1]);
|
||||
|
||||
|
||||
$url = action([UserController::class, 'profile'], ['id' => 1]);
|
||||
|
||||
## Fluent URI Objects
|
||||
|
||||
Laravel's `Uri` class provides a convenient and fluent interface for creating
|
||||
and manipulating URIs via objects. This class wraps the functionality provided
|
||||
by the underlying League URI package and integrates seamlessly with Laravel's
|
||||
routing system.
|
||||
|
||||
You can create a `Uri` instance easily using static methods:
|
||||
|
||||
|
||||
|
||||
1use App\Http\Controllers\UserController;
|
||||
|
||||
2use App\Http\Controllers\InvokableController;
|
||||
|
||||
3use Illuminate\Support\Uri;
|
||||
|
||||
4
|
||||
|
||||
5// Generate a URI instance from the given string...
|
||||
|
||||
6$uri = Uri::of('https://example.com/path');
|
||||
|
||||
7
|
||||
|
||||
8// Generate URI instances to paths, named routes, or controller actions...
|
||||
|
||||
9$uri = Uri::to('/dashboard');
|
||||
|
||||
10$uri = Uri::route('users.show', ['user' => 1]);
|
||||
|
||||
11$uri = Uri::signedRoute('users.show', ['user' => 1]);
|
||||
|
||||
12$uri = Uri::temporarySignedRoute('user.index', now()->addMinutes(5));
|
||||
|
||||
13$uri = Uri::action([UserController::class, 'index']);
|
||||
|
||||
14$uri = Uri::action(InvokableController::class);
|
||||
|
||||
15
|
||||
|
||||
16// Generate a URI instance from the current request URL...
|
||||
|
||||
17$uri = $request->uri();
|
||||
|
||||
|
||||
use App\Http\Controllers\UserController;
|
||||
use App\Http\Controllers\InvokableController;
|
||||
use Illuminate\Support\Uri;
|
||||
|
||||
// Generate a URI instance from the given string...
|
||||
$uri = Uri::of('https://example.com/path');
|
||||
|
||||
// Generate URI instances to paths, named routes, or controller actions...
|
||||
$uri = Uri::to('/dashboard');
|
||||
$uri = Uri::route('users.show', ['user' => 1]);
|
||||
$uri = Uri::signedRoute('users.show', ['user' => 1]);
|
||||
$uri = Uri::temporarySignedRoute('user.index', now()->addMinutes(5));
|
||||
$uri = Uri::action([UserController::class, 'index']);
|
||||
$uri = Uri::action(InvokableController::class);
|
||||
|
||||
// Generate a URI instance from the current request URL...
|
||||
$uri = $request->uri();
|
||||
|
||||
Once you have a URI instance, you can fluently modify it:
|
||||
|
||||
|
||||
|
||||
1$uri = Uri::of('https://example.com')
|
||||
|
||||
2 ->withScheme('http')
|
||||
|
||||
3 ->withHost('test.com')
|
||||
|
||||
4 ->withPort(8000)
|
||||
|
||||
5 ->withPath('/users')
|
||||
|
||||
6 ->withQuery(['page' => 2])
|
||||
|
||||
7 ->withFragment('section-1');
|
||||
|
||||
|
||||
$uri = Uri::of('https://example.com')
|
||||
->withScheme('http')
|
||||
->withHost('test.com')
|
||||
->withPort(8000)
|
||||
->withPath('/users')
|
||||
->withQuery(['page' => 2])
|
||||
->withFragment('section-1');
|
||||
|
||||
For more information on working with fluent URI objects, consult the [URI
|
||||
documentation](/docs/12.x/helpers#uri).
|
||||
|
||||
## Default Values
|
||||
|
||||
For some applications, you may wish to specify request-wide default values for
|
||||
certain URL parameters. For example, imagine many of your routes define a
|
||||
`{locale}` parameter:
|
||||
|
||||
|
||||
|
||||
1Route::get('/{locale}/posts', function () {
|
||||
|
||||
2 // ...
|
||||
|
||||
3})->name('post.index');
|
||||
|
||||
|
||||
Route::get('/{locale}/posts', function () {
|
||||
// ...
|
||||
})->name('post.index');
|
||||
|
||||
It is cumbersome to always pass the `locale` every time you call the `route`
|
||||
helper. So, you may use the `URL::defaults` method to define a default value
|
||||
for this parameter that will always be applied during the current request. You
|
||||
may wish to call this method from a [route
|
||||
middleware](/docs/12.x/middleware#assigning-middleware-to-routes) so that you
|
||||
have access to the current request:
|
||||
|
||||
|
||||
|
||||
1<?php
|
||||
|
||||
2
|
||||
|
||||
3namespace App\Http\Middleware;
|
||||
|
||||
4
|
||||
|
||||
5use Closure;
|
||||
|
||||
6use Illuminate\Http\Request;
|
||||
|
||||
7use Illuminate\Support\Facades\URL;
|
||||
|
||||
8use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
9
|
||||
|
||||
10class SetDefaultLocaleForUrls
|
||||
|
||||
11{
|
||||
|
||||
12 /**
|
||||
|
||||
13 * Handle an incoming request.
|
||||
|
||||
14 *
|
||||
|
||||
15 * @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
|
||||
|
||||
16 */
|
||||
|
||||
17 public function handle(Request $request, Closure $next): Response
|
||||
|
||||
18 {
|
||||
|
||||
19 URL::defaults(['locale' => $request->user()->locale]);
|
||||
|
||||
20
|
||||
|
||||
21 return $next($request);
|
||||
|
||||
22 }
|
||||
|
||||
23}
|
||||
|
||||
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class SetDefaultLocaleForUrls
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
|
||||
*/
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
{
|
||||
URL::defaults(['locale' => $request->user()->locale]);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
|
||||
Once the default value for the `locale` parameter has been set, you are no
|
||||
longer required to pass its value when generating URLs via the `route` helper.
|
||||
|
||||
#### URL Defaults and Middleware Priority
|
||||
|
||||
Setting URL default values can interfere with Laravel's handling of implicit
|
||||
model bindings. Therefore, you should [prioritize your
|
||||
middleware](/docs/12.x/middleware#sorting-middleware) that set URL defaults to
|
||||
be executed before Laravel's own `SubstituteBindings` middleware. You can
|
||||
accomplish this using the `priority` middleware method in your application's
|
||||
`bootstrap/app.php` file:
|
||||
|
||||
|
||||
|
||||
1->withMiddleware(function (Middleware $middleware) {
|
||||
|
||||
2 $middleware->prependToPriorityList(
|
||||
|
||||
3 before: \Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
|
||||
4 prepend: \App\Http\Middleware\SetDefaultLocaleForUrls::class,
|
||||
|
||||
5 );
|
||||
|
||||
6})
|
||||
|
||||
|
||||
->withMiddleware(function (Middleware $middleware) {
|
||||
$middleware->prependToPriorityList(
|
||||
before: \Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
prepend: \App\Http\Middleware\SetDefaultLocaleForUrls::class,
|
||||
);
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user