Laravel-Docs/session.md

270 lines
12 KiB
Markdown
Raw Permalink Normal View History

2016-07-13 18:17:22 +02:00
# HTTP Session
2013-01-10 20:08:51 +01:00
2015-05-27 23:18:24 +02:00
- [Introduction](#introduction)
2016-07-13 18:17:22 +02:00
- [Configuration](#configuration)
- [Driver Prerequisites](#driver-prerequisites)
- [Using The Session](#using-the-session)
- [Retrieving Data](#retrieving-data)
- [Storing Data](#storing-data)
2015-07-02 16:54:27 +02:00
- [Flash Data](#flash-data)
2016-07-13 18:17:22 +02:00
- [Deleting Data](#deleting-data)
- [Regenerating The Session ID](#regenerating-the-session-id)
2015-05-04 20:07:50 +02:00
- [Adding Custom Session Drivers](#adding-custom-session-drivers)
2016-07-13 18:17:22 +02:00
- [Implementing The Driver](#implementing-the-driver)
- [Registering The Driver](#registering-the-driver)
2013-01-10 20:08:51 +01:00
2015-05-27 23:18:24 +02:00
<a name="introduction"></a>
## Introduction
2013-01-10 20:08:51 +01:00
2017-10-12 02:59:38 +02:00
Since HTTP driven applications are stateless, sessions provide a way to store information about the user across multiple 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 out of the box.
2013-01-10 20:08:51 +01:00
2016-06-06 14:56:30 +02:00
<a name="configuration"></a>
2015-05-27 23:18:24 +02:00
### Configuration
2016-07-13 18:17:22 +02:00
The 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 `file` session driver, which will work well for many applications. In production applications, you may consider using the `memcached` or `redis` drivers for even faster session performance.
2013-01-10 20:08:51 +01:00
2016-07-13 18:17:22 +02:00
The session `driver` configuration option defines where session data will be stored for each request. Laravel ships with several great drivers out of the box:
2015-05-05 19:02:24 +02:00
2015-05-28 04:46:41 +02:00
<div class="content-list" markdown="1">
- `file` - sessions are stored in `storage/framework/sessions`.
- `cookie` - sessions are stored in secure, encrypted cookies.
2016-07-13 18:17:22 +02:00
- `database` - sessions are stored in a relational database.
2015-07-29 02:49:50 +02:00
- `memcached` / `redis` - sessions are stored in one of these fast, cache based stores.
2016-07-13 18:17:22 +02:00
- `array` - sessions are stored in a PHP array and will not be persisted.
2015-05-28 04:46:41 +02:00
</div>
2015-05-05 19:02:24 +02:00
2016-07-13 18:17:22 +02:00
> {tip} The array driver is used during [testing](/docs/{{version}}/testing) and prevents the data stored in the session from being persisted.
2015-05-05 19:02:24 +02:00
2016-07-13 18:17:22 +02:00
<a name="driver-prerequisites"></a>
2015-05-05 19:02:24 +02:00
### Driver Prerequisites
2015-01-26 17:33:02 +01:00
2015-05-05 19:02:24 +02:00
#### Database
2016-07-13 18:17:22 +02:00
When using the `database` session driver, you will need to create a table to contain the session items. Below is an example `Schema` declaration for the table:
2015-01-23 18:06:38 +01:00
2015-07-02 16:54:27 +02:00
Schema::create('sessions', function ($table) {
$table->string('id')->unique();
$table->unsignedInteger('user_id')->nullable();
2015-12-15 22:52:58 +01:00
$table->string('ip_address', 45)->nullable();
$table->text('user_agent')->nullable();
2015-07-02 16:54:27 +02:00
$table->text('payload');
$table->integer('last_activity');
});
2015-04-23 16:46:39 +02:00
2016-07-13 18:17:22 +02:00
You may use the `session:table` Artisan command to generate this migration:
2015-05-05 19:02:24 +02:00
2015-07-02 16:54:27 +02:00
php artisan session:table
2015-05-05 19:02:24 +02:00
2015-07-02 16:54:27 +02:00
php artisan migrate
2015-05-05 19:02:24 +02:00
#### Redis
Before using Redis sessions with Laravel, you will need to install the `predis/predis` package (~1.0) via Composer. You may configure your Redis connections in the `database` configuration file. In the `session` configuration file, the `connection` option may be used to specify which Redis connection is used by the session.
2016-07-13 18:17:22 +02:00
<a name="using-the-session"></a>
## Using The Session
2015-05-05 19:02:24 +02:00
2016-07-13 18:17:22 +02:00
<a name="retrieving-data"></a>
### Retrieving Data
2015-05-05 19:02:24 +02:00
2016-07-13 18:17:22 +02:00
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 controller method. Remember, controller method dependencies are automatically injected via the Laravel [service container](/docs/{{version}}/container):
2015-02-24 19:21:48 +01:00
2015-07-02 16:54:27 +02:00
<?php
2015-07-02 16:54:27 +02:00
namespace App\Http\Controllers;
2015-05-05 19:02:24 +02:00
2015-07-02 16:54:27 +02:00
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
2015-05-05 19:02:24 +02:00
2015-07-02 16:54:27 +02:00
class UserController extends Controller
{
/**
* Show the profile for the given user.
*
* @param Request $request
* @param int $id
* @return Response
*/
2016-07-13 18:17:22 +02:00
public function show(Request $request, $id)
2015-07-02 16:54:27 +02:00
{
$value = $request->session()->get('key');
2015-05-05 19:02:24 +02:00
2015-07-02 16:54:27 +02:00
//
}
}
2015-05-05 19:02:24 +02:00
2018-02-12 08:48:29 +01:00
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:
2015-02-24 19:21:48 +01:00
2015-07-02 16:54:27 +02:00
$value = $request->session()->get('key', 'default');
2013-01-10 20:08:51 +01:00
2016-11-11 16:35:36 +01:00
$value = $request->session()->get('key', function () {
2015-07-02 16:54:27 +02:00
return 'default';
});
2013-01-10 20:08:51 +01:00
2016-07-13 18:17:22 +02:00
#### The Global Session Helper
2013-08-09 17:49:40 +02:00
2016-07-13 18:17:22 +02:00
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:
2013-08-09 17:49:40 +02:00
2015-07-02 16:54:27 +02:00
Route::get('home', function () {
// Retrieve a piece of data from the session...
$value = session('key');
2013-01-10 20:08:51 +01:00
2016-07-13 18:17:22 +02:00
// Specifying a default value...
$value = session('key', 'default');
2015-07-02 16:54:27 +02:00
// Store a piece of data in the session...
session(['key' => 'value']);
});
2013-01-10 20:08:51 +01:00
2016-07-13 18:17:22 +02:00
> {tip} 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/{{version}}/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:
$data = $request->session()->all();
2018-02-12 08:48:29 +01:00
#### Determining If An Item Exists In The Session
2015-02-24 19:21:48 +01:00
2018-02-12 08:48:29 +01:00
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`:
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
if ($request->session()->has('users')) {
//
}
2013-01-10 20:08:51 +01:00
2018-02-12 08:48:29 +01:00
To determine if an item is present in the session, even if its value is `null`, you may use the `exists` method. The `exists` method returns `true` if the item is present:
if ($request->session()->exists('users')) {
//
}
2016-07-13 18:17:22 +02:00
<a name="storing-data"></a>
### Storing Data
2013-01-10 20:08:51 +01:00
2016-07-13 18:17:22 +02:00
To store data in the session, you will typically use the `put` method or the `session` helper:
2014-04-19 15:39:26 +02:00
2016-07-13 18:17:22 +02:00
// Via a request instance...
2015-07-02 16:54:27 +02:00
$request->session()->put('key', 'value');
2016-07-13 18:17:22 +02:00
// Via the global helper...
session(['key' => 'value']);
2015-05-27 23:18:24 +02:00
#### Pushing To Array Session Values
2013-08-08 05:52:56 +02:00
2015-05-27 23:18:24 +02:00
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:
2013-08-08 05:52:56 +02:00
2015-07-02 16:54:27 +02:00
$request->session()->push('user.teams', 'developers');
2013-01-10 20:08:51 +01:00
2016-07-13 18:17:22 +02:00
#### Retrieving & Deleting An Item
2013-01-10 20:08:51 +01:00
2016-07-13 18:17:22 +02:00
The `pull` method will retrieve and delete an item from the session in a single statement:
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
$value = $request->session()->pull('key', 'default');
2015-05-27 23:18:24 +02:00
2016-07-13 18:17:22 +02:00
<a name="flash-data"></a>
### Flash Data
Sometimes you may wish to store items in the session only for the next request. You may do so using the `flash` method. Data stored in the session using this method will only be available during the subsequent HTTP request, and then will be deleted. Flash data is primarily useful for short-lived status messages:
$request->session()->flash('status', 'Task was successful!');
If you need to keep your flash data around 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:
$request->session()->reflash();
$request->session()->keep(['username', 'email']);
<a name="deleting-data"></a>
### Deleting Data
2013-01-10 20:08:51 +01:00
2015-05-27 23:18:24 +02:00
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:
2015-07-02 16:54:27 +02:00
$request->session()->forget('key');
2013-01-10 20:08:51 +01:00
2015-07-02 16:54:27 +02:00
$request->session()->flush();
2013-01-10 20:08:51 +01:00
2016-07-13 18:17:22 +02:00
<a name="regenerating-the-session-id"></a>
### Regenerating The Session ID
Regenerating the session ID is often done in order to prevent malicious users from exploiting a [session fixation](https://en.wikipedia.org/wiki/Session_fixation) attack on your application.
2013-01-10 20:08:51 +01:00
2016-07-13 18:17:22 +02:00
Laravel automatically regenerates the session ID during authentication if you are using the built-in `LoginController`; however, if you need to manually regenerate the session ID, you may use the `regenerate` method.
2015-05-27 23:18:24 +02:00
2015-07-02 16:54:27 +02:00
$request->session()->regenerate();
2013-01-10 20:08:51 +01:00
2016-07-13 18:17:22 +02:00
<a name="adding-custom-session-drivers"></a>
## Adding Custom Session Drivers
2013-01-10 20:08:51 +01:00
2016-07-13 18:17:22 +02:00
<a name="implementing-the-driver"></a>
#### Implementing The Driver
2013-01-10 20:08:51 +01:00
2016-07-13 18:17:22 +02:00
Your custom session driver should implement the `SessionHandlerInterface`. This interface contains just a few simple methods we need to implement. A stubbed MongoDB implementation looks something like this:
2013-01-10 20:08:51 +01:00
2016-07-13 18:17:22 +02:00
<?php
2013-01-10 20:08:51 +01:00
2016-07-13 18:17:22 +02:00
namespace App\Extensions;
2013-01-10 20:08:51 +01:00
class MongoSessionHandler implements \SessionHandlerInterface
2016-07-13 18:17:22 +02:00
{
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) {}
}
2015-05-04 20:07:50 +02:00
> {tip} Laravel does not ship with a directory to contain your extensions. You are free to place them anywhere you like. In this example, we have created an `Extensions` directory to house the `MongoSessionHandler`.
2016-07-13 18:17:22 +02:00
Since the purpose of these methods is not readily understandable, let's quickly cover what each of the methods do:
<div class="content-list" markdown="1">
2018-01-23 18:48:13 +01:00
- The `open` method would typically be used in file based session store systems. Since Laravel ships with a `file` session driver, you will almost never need to put anything in this method. You can leave it as an empty stub. It is a fact of poor interface design (which we'll discuss later) that PHP requires us to implement this method.
2016-07-13 18:17:22 +02:00
- 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, Dynamo, etc. 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.
</div>
2015-05-04 20:07:50 +02:00
2016-07-13 18:17:22 +02:00
<a name="registering-the-driver"></a>
#### Registering The Driver
Once your driver has been implemented, you are ready to register it with the framework. To add additional drivers to Laravel's session backend, you may use the `extend` method on the `Session` [facade](/docs/{{version}}/facades). You should call the `extend` method from the `boot` method of a [service provider](/docs/{{version}}/providers). You may do this from the existing `AppServiceProvider` or create an entirely new provider:
2015-05-04 20:07:50 +02:00
<?php
namespace App\Providers;
2015-05-04 20:07:50 +02:00
use App\Extensions\MongoSessionHandler;
2016-07-13 18:17:22 +02:00
use Illuminate\Support\Facades\Session;
2015-05-04 20:07:50 +02:00
use Illuminate\Support\ServiceProvider;
class SessionServiceProvider extends ServiceProvider
{
/**
* Perform post-registration booting of services.
*
* @return void
*/
public function boot()
{
2016-11-11 16:35:36 +01:00
Session::extend('mongo', function ($app) {
2015-07-02 16:54:27 +02:00
// Return implementation of SessionHandlerInterface...
return new MongoSessionHandler;
2015-07-02 16:54:27 +02:00
});
2015-05-04 20:07:50 +02:00
}
/**
* Register bindings in the container.
*
* @return void
*/
public function register()
{
//
}
}
Once the session driver has been registered, you may use the `mongo` driver in your `config/session.php` configuration file.