Files
laravelDocScrappy/output/12.x/session.md
2025-09-02 15:19:23 +02:00

752 lines
21 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# HTTP Session
* Introduction
* Configuration
* Driver Prerequisites
* Interacting With the Session
* Retrieving Data
* Storing Data
* Flash Data
* Deleting Data
* Regenerating the Session ID
* Session Blocking
* Adding Custom Session Drivers
* Implementing the Driver
* Registering the Driver
## Introduction
Since HTTP driven applications are stateless, sessions provide a way to store
information about the user across multiple requests. That user information is
typically placed in a persistent store / backend that can be accessed from
subsequent requests.
Laravel ships with a variety of session backends that are accessed through an
expressive, unified API. Support for popular backends such as
[Memcached](https://memcached.org), [Redis](https://redis.io), and databases
is included.
### Configuration
Your application's session configuration file is stored at
`config/session.php`. Be sure to review the options available to you in this
file. By default, Laravel is configured to use the `database` session driver.
The session `driver` configuration option defines where session data will be
stored for each request. Laravel includes a variety of drivers:
* `file` \- sessions are stored in `storage/framework/sessions`.
* `cookie` \- sessions are stored in secure, encrypted cookies.
* `database` \- sessions are stored in a relational database.
* `memcached` / `redis` \- sessions are stored in one of these fast, cache-based stores.
* `dynamodb` \- sessions are stored in AWS DynamoDB.
* `array` \- sessions are stored in a PHP array and will not be persisted.
The array driver is primarily used during [testing](/docs/12.x/testing) and
prevents the data stored in the session from being persisted.
### Driver Prerequisites
#### Database
When using the `database` session driver, you will need to ensure that you
have a database table to contain the session data. Typically, this is included
in Laravel's default `0001_01_01_000000_create_users_table.php` [database
migration](/docs/12.x/migrations); however, if for any reason you do not have
a `sessions` table, you may use the `make:session-table` Artisan command to
generate this migration:
1php artisan make:session-table
2 
3php artisan migrate
php artisan make:session-table
php artisan migrate
#### Redis
Before using Redis sessions with Laravel, you will need to either install the
PhpRedis PHP extension via PECL or install the `predis/predis` package (~1.0)
via Composer. For more information on configuring Redis, consult Laravel's
[Redis documentation](/docs/12.x/redis#configuration).
The `SESSION_CONNECTION` environment variable, or the `connection` option in
the `session.php` configuration file, may be used to specify which Redis
connection is used for session storage.
## Interacting With the Session
### Retrieving Data
There are two primary ways of working with session data in Laravel: the global
`session` helper and via a `Request` instance. First, let's look at accessing
the session via a `Request` instance, which can be type-hinted on a route
closure or controller method. Remember, controller method dependencies are
automatically injected via the Laravel [service
container](/docs/12.x/container):
1<?php
2 
3namespace App\Http\Controllers;
4 
5use Illuminate\Http\Request;
6use Illuminate\View\View;
7 
8class UserController extends Controller
9{
10 /**
11 * Show the profile for the given user.
12 */
13 public function show(Request $request, string $id): View
14 {
15 $value = $request->session()->get('key');
16 
17 // ...
18 
19 $user = $this->users->find($id);
20 
21 return view('user.profile', ['user' => $user]);
22 }
23}
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\View\View;
class UserController extends Controller
{
/**
* Show the profile for the given user.
*/
public function show(Request $request, string $id): View
{
$value = $request->session()->get('key');
// ...
$user = $this->users->find($id);
return view('user.profile', ['user' => $user]);
}
}
When you retrieve an item from the session, you may also pass a default value
as the second argument to the `get` method. This default value will be
returned if the specified key does not exist in the session. If you pass a
closure as the default value to the `get` method and the requested key does
not exist, the closure will be executed and its result returned:
1$value = $request->session()->get('key', 'default');
2 
3$value = $request->session()->get('key', function () {
4 return 'default';
5});
$value = $request->session()->get('key', 'default');
$value = $request->session()->get('key', function () {
return 'default';
});
#### The Global Session Helper
You may also use the global `session` PHP function to retrieve and store data
in the session. When the `session` helper is called with a single, string
argument, it will return the value of that session key. When the helper is
called with an array of key / value pairs, those values will be stored in the
session:
1Route::get('/home', function () {
2 // Retrieve a piece of data from the session...
3 $value = session('key');
4 
5 // Specifying a default value...
6 $value = session('key', 'default');
7 
8 // Store a piece of data in the session...
9 session(['key' => 'value']);
10});
Route::get('/home', function () {
// Retrieve a piece of data from the session...
$value = session('key');
// Specifying a default value...
$value = session('key', 'default');
// Store a piece of data in the session...
session(['key' => 'value']);
});
There is little practical difference between using the session via an HTTP
request instance versus using the global `session` helper. Both methods are
[testable](/docs/12.x/testing) via the `assertSessionHas` method which is
available in all of your test cases.
#### Retrieving All Session Data
If you would like to retrieve all the data in the session, you may use the
`all` method:
1$data = $request->session()->all();
$data = $request->session()->all();
#### Retrieving a Portion of the Session Data
The `only` and `except` methods may be used to retrieve a subset of the
session data:
1$data = $request->session()->only(['username', 'email']);
2 
3$data = $request->session()->except(['username', 'email']);
$data = $request->session()->only(['username', 'email']);
$data = $request->session()->except(['username', 'email']);
#### Determining if an Item Exists in the Session
To determine if an item is present in the session, you may use the `has`
method. The `has` method returns `true` if the item is present and is not
`null`:
1if ($request->session()->has('users')) {
2 // ...
3}
if ($request->session()->has('users')) {
// ...
}
To determine if an item is present in the session, even if its value is
`null`, you may use the `exists` method:
1if ($request->session()->exists('users')) {
2 // ...
3}
if ($request->session()->exists('users')) {
// ...
}
To determine if an item is not present in the session, you may use the
`missing` method. The `missing` method returns `true` if the item is not
present:
1if ($request->session()->missing('users')) {
2 // ...
3}
if ($request->session()->missing('users')) {
// ...
}
### Storing Data
To store data in the session, you will typically use the request instance's
`put` method or the global `session` helper:
1// Via a request instance...
2$request->session()->put('key', 'value');
3 
4// Via the global "session" helper...
5session(['key' => 'value']);
// Via a request instance...
$request->session()->put('key', 'value');
// Via the global "session" helper...
session(['key' => 'value']);
#### Pushing to Array Session Values
The `push` method may be used to push a new value onto a session value that is
an array. For example, if the `user.teams` key contains an array of team
names, you may push a new value onto the array like so:
1$request->session()->push('user.teams', 'developers');
$request->session()->push('user.teams', 'developers');
#### Retrieving and Deleting an Item
The `pull` method will retrieve and delete an item from the session in a
single statement:
1$value = $request->session()->pull('key', 'default');
$value = $request->session()->pull('key', 'default');
#### Incrementing and Decrementing Session Values
If your session data contains an integer you wish to increment or decrement,
you may use the `increment` and `decrement` methods:
1$request->session()->increment('count');
2 
3$request->session()->increment('count', $incrementBy = 2);
4 
5$request->session()->decrement('count');
6 
7$request->session()->decrement('count', $decrementBy = 2);
$request->session()->increment('count');
$request->session()->increment('count', $incrementBy = 2);
$request->session()->decrement('count');
$request->session()->decrement('count', $decrementBy = 2);
### Flash Data
Sometimes you may wish to store items in the session for the next request. You
may do so using the `flash` method. Data stored in the session using this
method will be available immediately and during the subsequent HTTP request.
After the subsequent HTTP request, the flashed data will be deleted. Flash
data is primarily useful for short-lived status messages:
1$request->session()->flash('status', 'Task was successful!');
$request->session()->flash('status', 'Task was successful!');
If you need to persist your flash data for several requests, you may use the
`reflash` method, which will keep all of the flash data for an additional
request. If you only need to keep specific flash data, you may use the `keep`
method:
1$request->session()->reflash();
2 
3$request->session()->keep(['username', 'email']);
$request->session()->reflash();
$request->session()->keep(['username', 'email']);
To persist your flash data only for the current request, you may use the `now`
method:
1$request->session()->now('status', 'Task was successful!');
$request->session()->now('status', 'Task was successful!');
### Deleting Data
The `forget` method will remove a piece of data from the session. If you would
like to remove all data from the session, you may use the `flush` method:
1// Forget a single key...
2$request->session()->forget('name');
3 
4// Forget multiple keys...
5$request->session()->forget(['name', 'status']);
6 
7$request->session()->flush();
// Forget a single key...
$request->session()->forget('name');
// Forget multiple keys...
$request->session()->forget(['name', 'status']);
$request->session()->flush();
### Regenerating the Session ID
Regenerating the session ID is often done in order to prevent malicious users
from exploiting a [session fixation](https://owasp.org/www-
community/attacks/Session_fixation) attack on your application.
Laravel automatically regenerates the session ID during authentication if you
are using one of the Laravel [application starter kits](/docs/12.x/starter-
kits) or [Laravel Fortify](/docs/12.x/fortify); however, if you need to
manually regenerate the session ID, you may use the `regenerate` method:
1$request->session()->regenerate();
$request->session()->regenerate();
If you need to regenerate the session ID and remove all data from the session
in a single statement, you may use the `invalidate` method:
1$request->session()->invalidate();
$request->session()->invalidate();
## Session Blocking
To utilize session blocking, your application must be using a cache driver
that supports [atomic locks](/docs/12.x/cache#atomic-locks). Currently, those
cache drivers include the `memcached`, `dynamodb`, `redis`, `mongodb`
(included in the official `mongodb/laravel-mongodb` package), `database`,
`file`, and `array` drivers. In addition, you may not use the `cookie` session
driver.
By default, Laravel allows requests using the same session to execute
concurrently. So, for example, if you use a JavaScript HTTP library to make
two HTTP requests to your application, they will both execute at the same
time. For many applications, this is not a problem; however, session data loss
can occur in a small subset of applications that make concurrent requests to
two different application endpoints which both write data to the session.
To mitigate this, Laravel provides functionality that allows you to limit
concurrent requests for a given session. To get started, you may simply chain
the `block` method onto your route definition. In this example, an incoming
request to the `/profile` endpoint would acquire a session lock. While this
lock is being held, any incoming requests to the `/profile` or `/order`
endpoints which share the same session ID will wait for the first request to
finish executing before continuing their execution:
1Route::post('/profile', function () {
2 // ...
3})->block($lockSeconds = 10, $waitSeconds = 10);
4 
5Route::post('/order', function () {
6 // ...
7})->block($lockSeconds = 10, $waitSeconds = 10);
Route::post('/profile', function () {
// ...
})->block($lockSeconds = 10, $waitSeconds = 10);
Route::post('/order', function () {
// ...
})->block($lockSeconds = 10, $waitSeconds = 10);
The `block` method accepts two optional arguments. The first argument accepted
by the `block` method is the maximum number of seconds the session lock should
be held for before it is released. Of course, if the request finishes
executing before this time the lock will be released earlier.
The second argument accepted by the `block` method is the number of seconds a
request should wait while attempting to obtain a session lock. An
`Illuminate\Contracts\Cache\LockTimeoutException` will be thrown if the
request is unable to obtain a session lock within the given number of seconds.
If neither of these arguments is passed, the lock will be obtained for a
maximum of 10 seconds and requests will wait a maximum of 10 seconds while
attempting to obtain a lock:
1Route::post('/profile', function () {
2 // ...
3})->block();
Route::post('/profile', function () {
// ...
})->block();
## Adding Custom Session Drivers
### Implementing the Driver
If none of the existing session drivers fit your application's needs, Laravel
makes it possible to write your own session handler. Your custom session
driver should implement PHP's built-in `SessionHandlerInterface`. This
interface contains just a few simple methods. A stubbed MongoDB implementation
looks like the following:
1<?php
2 
3namespace App\Extensions;
4 
5class MongoSessionHandler implements \SessionHandlerInterface
6{
7 public function open($savePath, $sessionName) {}
8 public function close() {}
9 public function read($sessionId) {}
10 public function write($sessionId, $data) {}
11 public function destroy($sessionId) {}
12 public function gc($lifetime) {}
13}
<?php
namespace App\Extensions;
class MongoSessionHandler implements \SessionHandlerInterface
{
public function open($savePath, $sessionName) {}
public function close() {}
public function read($sessionId) {}
public function write($sessionId, $data) {}
public function destroy($sessionId) {}
public function gc($lifetime) {}
}
Since Laravel does not include a default directory to house your extensions.
You are free to place them anywhere you like. In this example, we have created
an `Extensions` directory to house the `MongoSessionHandler`.
Since the purpose of these methods is not readily understandable, here is an
overview of the purpose of each method:
* The `open` method would typically be used in file based session store systems. Since Laravel ships with a `file` session driver, you will rarely need to put anything in this method. You can simply leave this method empty.
* The `close` method, like the `open` method, can also usually be disregarded. For most drivers, it is not needed.
* The `read` method should return the string version of the session data associated with the given `$sessionId`. There is no need to do any serialization or other encoding when retrieving or storing session data in your driver, as Laravel will perform the serialization for you.
* The `write` method should write the given `$data` string associated with the `$sessionId` to some persistent storage system, such as MongoDB or another storage system of your choice. Again, you should not perform any serialization - Laravel will have already handled that for you.
* The `destroy` method should remove the data associated with the `$sessionId` from persistent storage.
* The `gc` method should destroy all session data that is older than the given `$lifetime`, which is a UNIX timestamp. For self-expiring systems like Memcached and Redis, this method may be left empty.
### Registering the Driver
Once your driver has been implemented, you are ready to register it with
Laravel. To add additional drivers to Laravel's session backend, you may use
the `extend` method provided by the `Session` [facade](/docs/12.x/facades).
You should call the `extend` method from the `boot` method of a [service
provider](/docs/12.x/providers). You may do this from the existing
`App\Providers\AppServiceProvider` or create an entirely new provider:
1<?php
2 
3namespace App\Providers;
4 
5use App\Extensions\MongoSessionHandler;
6use Illuminate\Contracts\Foundation\Application;
7use Illuminate\Support\Facades\Session;
8use Illuminate\Support\ServiceProvider;
9 
10class SessionServiceProvider extends ServiceProvider
11{
12 /**
13 * Register any application services.
14 */
15 public function register(): void
16 {
17 // ...
18 }
19 
20 /**
21 * Bootstrap any application services.
22 */
23 public function boot(): void
24 {
25 Session::extend('mongo', function (Application $app) {
26 // Return an implementation of SessionHandlerInterface...
27 return new MongoSessionHandler;
28 });
29 }
30}
<?php
namespace App\Providers;
use App\Extensions\MongoSessionHandler;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\ServiceProvider;
class SessionServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
// ...
}
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Session::extend('mongo', function (Application $app) {
// Return an implementation of SessionHandlerInterface...
return new MongoSessionHandler;
});
}
}
Once the session driver has been registered, you may specify the `mongo`
driver as your application's session driver using the `SESSION_DRIVER`
environment variable or within the application's `config/session.php`
configuration file.