Documentación de Laravel 10.x
Aquí encontrarás fragmentos de código de Laravel y consejos útiles sobre desarrollo web.
Dado que las aplicaciones impulsadas por HTTP son sin estado, las sesiones proporcionan una manera de almacenar información sobre el usuario en varias solicitudes. Esa información del usuario se coloca típicamente en una tienda / backend persistente que se puede acceder desde solicitudes posteriores.
Laravel incluye una variedad de backends de sesión a los que se accede a través de una API expresiva y unificada. Se incluye soporte para backends populares como Memcached, Redis y bases de datos.
El archivo de configuración de sesión de su aplicación se encuentra en config/session.php
. Asegúrese de revisar las opciones disponibles en este archivo. De forma predeterminada, Laravel está configurado para usar el controlador de sesión file
, que funcionará bien para muchas aplicaciones. Si su aplicación se equilibrará entre varios servidores web, debe elegir una tienda centralizada a la que todos los servidores puedan acceder, como Redis o una base de datos.
La opción de configuración driver
de la sesión define dónde se almacenarán los datos de la sesión para cada solicitud. Laravel incluye varios excelentes controladores de forma predeterminada:
file
- las sesiones se almacenan en storage/framework/sessions
.cookie
- las sesiones se almacenan en cookies seguras y cifradas.database
- las sesiones se almacenan en una base de datos relacional.memcached
/ redis
- las sesiones se almacenan en una de estas tiendas rápidas basadas en caché.dynamodb
- las sesiones se almacenan en AWS DynamoDB.array
- las sesiones se almacenan en una matriz de PHP y no se persistirán.Nota El controlador de matriz se utiliza principalmente durante las pruebas y evita que los datos almacenados en la sesión se persistan.
Cuando utilice el controlador de sesión database
, deberá crear una tabla para contener los registros de sesión. Se puede encontrar un ejemplo de declaración de Schema
para la tabla a continuación:
use Illuminate\Database\Schema\Blueprint;use Illuminate\Support\Facades\Schema; Schema::create('sessions', function (Blueprint $table) { $table->string('id')->primary(); $table->foreignId('user_id')->nullable()->index(); $table->string('ip_address', 45)->nullable(); $table->text('user_agent')->nullable(); $table->text('payload'); $table->integer('last_activity')->index();});
Puede utilizar el comando Artisan session:table
para generar esta migración. Para obtener más información sobre las migraciones de base de datos, puede consultar la documentación completa de migraciones:
php artisan session:table php artisan migrate
Antes de utilizar sesiones Redis con Laravel, deberá instalar la extensión de PHP PhpRedis a través de PECL o instalar el paquete predis/predis
(~1.0) a través de Composer. Para obtener más información sobre la configuración de Redis, consulte la documentación de Redis de Laravel.
Nota En el archivo de configuración
session
, la opciónconnection
se puede usar para especificar qué conexión de Redis se utiliza para la sesión.
Hay dos formas principales de trabajar con datos de sesión en Laravel: el ayudante global session
y mediante una instancia de Request
. Primero, veamos cómo acceder a la sesión a través de una instancia de Request
, que puede ser tipo-hinted en un cierre de ruta o en un método del controlador. Recuerde, las dependencias del método del controlador se inyectan automáticamente a través del contenedor de servicios de Laravel:
<?php namespace App\Http\Controllers; use Illuminate\Http\Request;use Illuminate\View\View; class UserController extends Controller{ /** * Mostrar el perfil del usuario dado. */ public function show(Request $request, string $id): View { $value = $request->session()->get('key'); // ... $user = $this->users->find($id); return view('user.profile', ['user' => $user]); }}
Cuando recupera un elemento de la sesión, también puede pasar un valor predeterminado como segundo argumento al método get
. Este valor predeterminado se devolverá si la clave especificada no existe en la sesión. Si pasa un cierre como valor predeterminado al método get
y la clave solicitada no existe, se ejecutará el cierre y se devolverá su resultado:
$value = $request->session()->get('key', 'default'); $value = $request->session()->get('key', function () { return 'default';});
También puede utilizar la función global de PHP session
para recuperar y almacenar datos en la sesión. Cuando se llama al ayudante session
con un solo argumento de cadena, devolverá el valor de esa clave de sesión. Cuando el ayudante se llama con una matriz de pares clave/valor, esos valores se almacenarán en la sesión:
Route::get('/home', function () { // Obtener un dato de la sesión... $value = session('key'); // Especificar un valor predeterminado... $value = session('key', 'default'); // Almacenar un dato en la sesión... session(['key' => 'value']);});
Nota Hay poca diferencia práctica entre usar la sesión a través de una instancia de solicitud HTTP y utilizar el ayudante global
session
. Ambos métodos son testables mediante el métodoassertSessionHas
que está disponible en todos sus casos de prueba.
Si desea recuperar todos los datos de la sesión, puede utilizar el método all
:
$data = $request->session()->all();
Para determinar si un elemento está presente en la sesión, puede utilizar el método has
. El método has
devuelve true
si el elemento está presente y no es null
:
if ($request->session()->has('users')) { // ...}
Para determinar si un elemento está presente en la sesión, incluso si su valor es null
, puede utilizar el método exists
:
if ($request->session()->exists('users')) { // ...}
Para determinar si un elemento no está presente en la sesión, puede utilizar el método missing
. El método missing
devuelve true
si el elemento no está presente:
if ($request->session()->missing('users')) { // ...}
Para almacenar datos en la sesión, normalmente utilizará el método put
de la instancia de solicitud o el ayudante global session
:
// A través de una instancia de solicitud...$request->session()->put('key', 'value'); // A través del ayudante global "session"...session(['key' => 'value']);
El método push
se puede utilizar para agregar un nuevo valor a un valor de sesión que es una matriz. Por ejemplo, si la clave user.teams
contiene una matriz de nombres de equipos, puede agregar un nuevo valor a la matriz de la siguiente manera:
$request->session()->push('user.teams', 'developers');
El método pull
recuperará y eliminará un elemento de la sesión en una sola declaración:
$value = $request->session()->pull('key', 'default');
Si los datos de su sesión contienen un número entero que desea incrementar o decrementar, puede utilizar los métodos increment
y decrement
:
$request->session()->increment('count'); $request->session()->increment('count', $incrementBy = 2); $request->session()->decrement('count'); $request->session()->decrement('count', $decrementBy = 2);
A veces puede desear almacenar elementos en la sesión para la próxima solicitud. Puede hacerlo utilizando el método flash
. Los datos almacenados en la sesión utilizando este método estarán disponibles inmediatamente y durante la siguiente solicitud HTTP. Después de la siguiente solicitud HTTP, los datos destellados se eliminarán. Los datos de destello son principalmente útiles para mensajes de estado de corta duración:
$request->session()->flash('status', 'Task was successful!');
Si necesita persistir sus datos de destello durante varias solicitudes, puede utilizar el método reflash
, que mantendrá todos los datos de destello durante una solicitud adicional. Si solo necesita mantener datos de destello específicos, puede utilizar el método keep
:
$request->session()->reflash(); $request->session()->keep(['username', 'email']);
Para persistir sus datos de destello solo durante la solicitud actual, puede utilizar el método now
:
$request->session()->now('status', 'Task was successful!');
El método forget
eliminará un dato de la sesión. Si desea eliminar todos los datos de la sesión, puede utilizar el método flush
:
// Olvidar una clave única...$request->session()->forget('name'); // Olvidar varias claves...$request->session()->forget(['name', 'status']); $request->session()->flush();
Regenerar el ID de sesión se hace a menudo para evitar que los usuarios malintencionados aprovechen un ataque de fijación de sesión en su aplicación.
Laravel regenera automáticamente el ID de sesión durante la autenticación si está utilizando uno de los kits de inicio de la aplicación Laravel o Laravel Fortify; sin embargo, si necesita regenerar manualmente el ID de sesión, puede utilizar el método regenerate
:
$request->session()->regenerate();
Si necesita regenerar el ID de sesión y eliminar todos los datos de la sesión en una sola declaración, puede utilizar el método invalidate
:
$request->session()->invalidate();
Advertencia Para utilizar el bloqueo de sesiones, su aplicación debe estar utilizando un controlador de caché que admita bloqueos atómicos. Actualmente, esos controladores de caché incluyen los controladores
memcached
,dynamodb
,redis
ydatabase
. Además, no puede utilizar el controlador de sesióncookie
.
De forma predeterminada, Laravel permite que las solicitudes que utilizan la misma sesión se ejecuten de manera concurrente. Así que, por ejemplo, si utiliza una biblioteca HTTP de JavaScript para hacer dos solicitudes HTTP a su aplicación, ambas se ejecutarán al mismo tiempo. Para muchas aplicaciones, esto no es un problema; sin embargo, la pérdida de datos de sesión puede ocurrir en un pequeño conjunto de aplicaciones que realizan solicitudes concurrentes a dos puntos finales de la aplicación diferentes que escriben datos en la sesión.
Para mitigar esto, Laravel proporciona funcionalidad que le permite limitar las solicitudes concurrentes para una sesión dada. Para empezar, simplemente puede encadenar el método block
en la definición de su ruta. En este ejemplo, una solicitud entrante al endpoint /profile
adquiriría un bloqueo de sesión. Mientras se mantiene este bloqueo, cualquier solicitud entrante a los endpoints /profile
o /order
que compartan el mismo ID de sesión esperarán a que la primera solicitud termine de ejecutarse antes de continuar su ejecución:
Route::post('/profile', function () { // ...})->block($lockSeconds = 10, $waitSeconds = 10) Route::post('/order', function () { // ...})->block($lockSeconds = 10, $waitSeconds = 10)
El método block
acepta dos argumentos opcionales. El primer argumento aceptado por el método block
es el tiempo máximo en segundos que se debe mantener el bloqueo de sesión antes de que se libere. Por supuesto, si la solicitud termina de ejecutarse antes de este tiempo, el bloqueo se liberará antes.
El segundo argumento aceptado por el método block
es el tiempo máximo en segundos que una solicitud debe esperar al intentar obtener un bloqueo de sesión. Se lanzará una excepción Illuminate\Contracts\Cache\LockTimeoutException
si la solicitud no puede obtener un bloqueo de sesión dentro del número dado de segundos.
Si no se pasa ninguno de estos argumentos, el bloqueo se obtendrá durante un máximo de 10 segundos y las solicitudes esperarán un máximo de 10 segundos al intentar obtener un bloqueo:
Route::post('/profile', function () { // ...})->block()
Si ninguno de los controladores de sesión existentes satisface las necesidades de su aplicación, Laravel le permite escribir su propio controlador de sesión. Su controlador de sesión personalizado debe implementar SessionHandlerInterface
incorporado en PHP. Esta interfaz contiene solo algunos métodos simples. Una implementación ficticia de MongoDB se ve así:
<?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) {}}
Nota Laravel no incluye un directorio para contener sus extensiones. Puede colocarlas donde desee. En este ejemplo, hemos creado un directorio
Extensions
para alojar elMongoSessionHandler
.
Dado que el propósito de estos métodos no es fácilmente comprensible, cubramos rápidamente qué hace cada uno de los métodos:
open
se utilizaría típicamente en sistemas de almacenamiento de sesión basados en archivos. Dado que Laravel incluye un controlador de sesión file
, rara vez necesitará poner algo en este método. Simplemente puede dejar este método vacío.close
, al igual que el método open
, generalmente también se puede pasar por alto. Para la mayoría de los controladores, no es necesario.read
debe devolver la versión de cadena de los datos de la sesión asociados con el $sessionId
dado. No es necesario realizar ninguna serialización u otro tipo de codificación al recuperar o almacenar datos de sesión en su controlador, ya que Laravel realizará la serialización por usted.write
debe escribir la cadena $data
dada asociada con el $sessionId
en algún sistema de almacenamiento persistente, como MongoDB u otro sistema de almacenamiento de su elección. Nuevamente, no debe realizar ninguna serialización, ya que Laravel ya habrá manejado eso por usted.destroy
debe eliminar los datos asociados con el $sessionId
del almacenamiento persistente.gc
debe destruir todos los datos de sesión que sean más antiguos que el $lifetime
dado, que es una marca de tiempo UNIX. Para sistemas de autodestrucción como Memcached y Redis, este método puede dejarse vacío.Una vez que su controlador haya sido implementado, está listo para registrarlo con Laravel. Para agregar controladores adicionales al backend de sesión de Laravel, puede utilizar el método extend
proporcionado por el facade Session
. Debería llamar al método extend
desde el método boot
de un proveedor de servicios. Puede hacer esto desde el proveedor existente App\Providers\AppServiceProvider
o crear un proveedor completamente nuevo:
<?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{ /** * Registrar cualquier servicio de la aplicación. */ public function register(): void { // ... } /** * Inicializar cualquier servicio de la aplicación. */ public function boot(): void { Session::extend('mongo', function (Application $app) { // Devolver una implementación de SessionHandlerInterface... return new MongoSessionHandler; }); }}
Una vez que se haya registrado el controlador de sesión, puede usar el controlador mongo
en su archivo de configuración config/session.php
.