Overview
Esta guía te muestra cómo usar Laravel MongoDB para definir y personalizar los modelos de Laravel Eloquent. Puedes utilizar estos modelos para trabajar con datos de MongoDB utilizando el mapeador objeto-relacional (ORM) Eloquent de Laravel.
Las siguientes secciones explican cómo agregar comportamientos ORM de Laravel Eloquent a los modelos de Laravel MongoDB:
Definir una clase de modelo Eloquent demuestra cómo crear una clase de modelo.
Extiende el modelo autenticable muestra cómo definir MongoDB como el proveedor de usuarios de autenticación.
Personalizar una clase de modelo Eloquent explica varias personalizaciones de clases de modelo.
Ampliar clases de modelos de terceros explica cómo hacer que las clases de modelos de terceros sean compatibles con MongoDB.
Especificar el comportamiento de poda muestra cómo remover periódicamente los modelos que ya no necesitas.
Crear un esquema de modelo versionado muestra cómo implementar la versionado del esquema del modelo.
Define una clase de modelo en Eloquent
Los modelos Eloquent son clases que representan tus datos. Incluyen métodos que realizan operaciones en la base de datos, como inserciones, actualizaciones y eliminaciones.
Para declarar un modelo Laravel MongoDB, cree una clase en el app/Models
directorio de tu aplicación Laravel que extiende MongoDB\Laravel\Eloquent\Model como se muestra en el siguiente ejemplo de código:
namespace App\Models; use MongoDB\Laravel\Eloquent\Model; class Planet extends Model { }
Por defecto, el modelo utiliza el nombre de base de datos de MongoDB establecido en la configuración config/database.php de tu aplicación Laravel y la forma plural en snake_case del nombre de la clase de tu modelo para la colección.
Este modelo se almacena en la colección de MongoDB planets.
Tip
Alternativamente, utiliza la consola artisan para generar la clase de modelo y cambiar la importación Illuminate\Database\Eloquent\Model a MongoDB\Laravel\Eloquent\Model. Para saber más sobre la consola artisan, consulta Consola Artisan en la documentación de Laravel.
Para aprender a especificar el nombre de la base de datos que utiliza su aplicación Laravel, Configura tu conexión a MongoDB.
Nota
MongoDB siempre guarda un valor de clave primaria en el campo _id. Este campo se accede como $id en el modelo. Cuando utiliza el generador de consultas, la integración de Laravel convierte id en _id en la consulta. Esto permite la compatibilidad con otros componentes de Laravel que usan un campo id. Puede personalizar el tipo de identificador configurando la propiedad $keyType del modelo y asignando un valor antes de guardar el modelo.
Extiende el Modelo Autenticable
Para configurar MongoDB como proveedor de usuarios de Laravel, puede extender la clase MongoDB\Laravel\Auth\User de Integración de Laravel. El siguiente ejemplo de código muestra cómo extender esta clase:
namespace App\Models; use MongoDB\Laravel\Auth\User as Authenticatable; class User extends Authenticatable { }
Para obtener más información sobre cómo personalizar un proveedor de usuarios de autenticación de Laravel, consulte Agregar proveedores de usuarios personalizados en la documentación de Laravel.
Personaliza una clase de modelo Eloquent
Esta sección muestra cómo realizar la siguientes personalizaciones de comportamiento del modelo Eloquent:
Cambiar el nombre de la Colección de modelos
Por defecto, el modelo utiliza el nombre de la clase de tu modelo en forma plural con snake case. Para cambiar el nombre de la colección que utiliza el modelo para recuperar y guardar datos en MongoDB, sobreescribe la propiedad $table de la clase del modelo.
Nota
Recomendamos usar el comportamiento por defecto de asignación de nombres de colecciones para mantener las asociaciones entre modelos y colecciones sencillas.
El siguiente ejemplo especifica el nombre personalizado de la colección de MongoDB, celestial_body, para la clase Planet:
namespace App\Models; use MongoDB\Laravel\Eloquent\Model; class Planet extends Model { protected $table = 'celestial_body'; }
Sin sobreescribir la propiedad $table, este modelo se asigna a la colección planets. Con la propiedad anulada, la clase de ejemplo almacena el modelo en la colección celestial_body.
Habilitar eliminaciones lógicas
Eloquent incluye una funcionalidad de borrado lógico que cambia el comportamiento del método delete() en un modelo. Cuando la eliminación suave está habilitada en un modelo, el método delete() marca un documento como borrado en lugar de removerlo de la base de datos. Establece una marca temporal en el campo deleted_at para excluirlo automáticamente de las operaciones de recuperación.
Para habilitar borrados suaves en una clase, agrega el trait Illuminate\Database\Eloquent\SoftDeletes como se muestra en el siguiente ejemplo de código:
namespace App\Models; use Illuminate\Database\Eloquent\SoftDeletes; use MongoDB\Laravel\Eloquent\Model; class Planet extends Model { use SoftDeletes; }
Para aprender sobre los métodos que puedes realizar en modelos con eliminados suaves habilitados, consulta Eliminación suave en Eloquent en los Docs de Laravel.
Cast Tipos de datos
Eloquent permite convertir los tipos de datos de los atributos del modelo antes de almacenar o recuperar datos mediante el uso de un asistente de conversión. Este asistente es una alternativa conveniente a definir métodos equivalentes de acceso y mutación en tu modelo.
En el siguiente ejemplo, el asistente de conversión convierte el atributo del modelo discovery_dt, almacenado en MongoDB como un tipo MongoDB\\BSON\\UTCDateTime, al tipo datetime de Laravel.
namespace App\Models; use MongoDB\Laravel\Eloquent\Model; class Planet extends Model { protected $casts = [ 'discovery_dt' => 'datetime', ]; }
Tip
Conversiones en Laravel 11
A partir de Laravel 11, puedes definir un método casts() para especificar conversiones de tipos de datos en lugar de usar el atributo $casts. El siguiente código realiza la misma conversión que el ejemplo anterior utilizando un método casts():
protected function casts(): array { return [ 'discovery_dt' => 'datetime', ]; }
Para obtener más información, consulta Conversión de atributos en la documentación de Laravel.
Esta conversión te permite usar la clase PHP DateTime para trabajar con fechas en este campo. El siguiente ejemplo muestra una query de Laravel que utiliza el asistente de conversión en el modelo para consultar planetas con un discovery_dt de menos de tres años atrás:
Planet::where( 'discovery_dt', '>', new DateTime('-3 years'))->get();
Nota
Clase de fecha de Carbono
Comenzando en Laravel MongoDB v5.0, Los valores BSON UTCDateTime en MongoDB se devuelven como clases de fecha Carbon en los resultados de las queries. La integración de Laravel aplica la zona horaria por defecto al realizar esta conversión.
Para aprender más sobre los tipos de datos de MongoDB, consulta BSON Types en el manual del Servidor.
Para obtener más información sobre el asistente de conversión de Laravel y los tipos admitidos, consulte Conversión de atributos en la documentación de Laravel.
Personalizar la asignación masiva
Eloquent permite crear varios modelos y sus datos de atributos pasando una matriz de datos al método de modelo create(). Este proceso de inserción de múltiples modelos se denomina asignación masiva.
La asignación masiva puede ser una forma eficiente de crear múltiples modelos. Sin embargo, puede exponer una vulnerabilidad de seguridad explotable. Los datos de los campos podrían contener actualizaciones que otorguen permisos o accesos no autorizados.
Eloquent proporciona los siguientes traits para proteger tus datos de vulnerabilidades de asignación masiva:
$fillableContiene los campos que se pueden escribir en una asignación masiva$guardedcontiene los campos que se ignoran en una asignación masiva
Importante
Recomendamos usar $fillable en lugar de $guarded para protegerse de vulnerabilidades. Para aprender más sobre esta recomendación, consulta el seguridad Release: Laravel 6.18.35, 7.24.0 artículo en el sitio de Laravel.
En el siguiente ejemplo, el modelo permite una asignación masiva de los campos mediante el uso del atributo $fillable:
namespace App\Models; use MongoDB\Laravel\Eloquent\Model; class Planet extends Model { protected $fillable = [ 'name', 'gravitational_force', 'diameter', 'moons', ]; }
El siguiente ejemplo de código muestra la asignación masiva del modelo Planet:
$planets = [ [ 'name' => 'Earth', 'gravitational_force' => 9.8, 'day_length' => '24 hours' ], [ 'name' => 'Mars', 'gravitational_force' => 3.7, 'day_length' => '25 hours' ], ]; Planet::create($planets);
Los modelos guardados en la base de datos contienen únicamente los campos name y gravity ya que day_length está omitido del atributo $fillable.
Para aprender cómo cambiar el comportamiento al intentar llenar un campo omitido del arreglo de $fillable, consulta Excepciones de Asignación Masiva en la Laravel docs.
Ampliar clases de modelos de terceros
Puedes usar la Integración de Laravel para extender una clase de modelo de terceros incluyando el rasgo DocumentModel al definir tu clase de modelo. Al incluir este rasgo, puedes hacer la clase de terceros compatible con MongoDB.
Cuando aplicas el atributo DocumentModel a una clase de modelo, debes establecer la propiedad $keyType en 'string' ya que la integración de Laravel convierte los valores de MongoDB ObjectId al tipo string.
Ejemplo de clase extendida
Este ejemplo crea una clase de modelo Planet que extiende la clase CelestialBody de un paquete llamado ThirdPartyPackage. La clase Post incluye el atributo DocumentModel y define propiedades como $primaryKey y $keyType:
namespace App\Models; use MongoDB\Laravel\Eloquent\DocumentModel; use ThirdPartyPackage\CelestialBody; class Planet extends CelestialBody { use DocumentModel; protected $fillable = ['name', 'diameter']; protected $keyType = 'string'; }
Después de definir tu clase, puedes realizar operaciones de MongoDB como de costumbre.
Tip
Para ver otro ejemplo que utiliza el atributo DocumentModel, consulte la sección Laravel Sanctum de la guía de Autenticación de Usuarios.
Especificar el comportamiento de poda
Eloquent te permite especificar criterios para borrar periódicamente datos de modelos que ya no necesitas. Cuando programas o ejecutas el comando model:prune, Laravel llama al método prunable() en todos los modelos que importan los traits Prunable y MassPrunable para seleccionar los modelos que se eliminarán.
Para usar esta funcionalidad con modelos que utilizan MongoDB como base de datos, añade la importación apropiada a tu modelo:
Illuminate\Database\Eloquent\Prunableopcionalmente realiza un paso de limpieza antes de borrar un modelo que cumpla con los criteriosMongoDB\Laravel\Eloquent\MassPrunableElimina los modelos que coinciden con los criterios sin obtener los datos del modelo.
Nota
Al habilitar eliminaciones suaves en un modelo podable en masa, debe importar los siguientes paquetes Laravel MongoDB:
Illuminate\Database\Eloquent\SoftDeletesMongoDB\Laravel\Eloquent\MassPrunable
Para obtener más información sobre la funcionalidad de eliminación, consulta Eliminación de modelos en los docs de Laravel.
Ejemplo PRUNABLE
La siguiente clase prunable incluye un método prunable() que coincide con los modelos que borra la acción de poda y un método pruning() que se ejecuta antes de borrar un modelo coincidente:
namespace App\Models; use MongoDB\Laravel\Eloquent\Model; use Illuminate\Database\Eloquent\Prunable; class Planet extends Model { use Prunable; public function prunable() { // matches models in which the solar_system field contains a null value return static::whereNull('solar_system'); } protected function pruning() { // Add cleanup actions, such as logging the Planet 'name' attribute } }
Ejemplo "Mass Prunable"
La siguiente clase podable en masa incluye un método prunable() que coincide con los modelos que la acción de poda elimina:
namespace App\Models; use MongoDB\Laravel\Eloquent\MassPrunable; use MongoDB\Laravel\Eloquent\Model; class Planet extends Model { use MassPrunable; public function prunable() { // matches models in which the gravitational_force field contains // a value greater than 0.5 return static::where('gravitational_force', '>', 0.5); } }
Crear un esquema de modelo versionado
Puedes implementar un patrón de control de versiones de esquema en tu aplicación usando el trait HasSchemaVersion en un modelo Eloquent. Puedes optar por implementar una versión de esquema para organizar o estandarizar una colección que contiene datos con distintos esquemas.
Tip
Para obtener más información sobre versionado de esquemas, consulta el tutorial Modelar datos para versionado de esquemas en el Manual de servidor.
Para usar esta funcionalidad con modelos que utilizan MongoDB como base de datos, agrega la importación MongoDB\Laravel\Eloquent\HasSchemaVersion a tu modelo. Luego, ajusta la constante SCHEMA_VERSION a 1 para establecer la primera versión del esquema en tu colección. Si tu colección evoluciona y contiene varios esquemas, puedes actualizar el valor de la constante SCHEMA_VERSION en las clases de modelo siguientes.
Al crear el modelo, puedes definir el método migrateSchema() para especificar una migración a la versión actual del esquema al recuperar un modelo. En este método, puedes especificar los cambios que se deben realizar a un modelo anterior para actualizarlo y que coincida con la versión actual del esquema.
Cuando se guarda un modelo que no tiene una versión de esquema especificada, el rasgo HasSchemaVersion asume que sigue la última versión del esquema. Cuando recuperas un modelo que no contiene el campo schema_version, el trait asume que su versión de esquema es 0 y realiza la migración.
Ejemplo de control de versiones del esquema
En esta situación de muestra, estás trabajando con una colección que fue modelada por primera vez por la siguiente clase:
namespace App\Models; use MongoDB\Laravel\Eloquent\Model; class Planet extends Model { protected $fillable = ['name', 'type']; }
Ahora, quieres implementar una nueva versión de esquema en la colección. Puedes definir la nueva clase del modelo con el siguiente comportamiento:
Implementa el
HasSchemaVersionrasgo y establece elSCHEMA_VERSIONactual en2Define el método
migrateSchema()para migrar modelos en los que la versión del esquema es menor que2, de modo que tengan un campogalaxycon un valor de'Milky Way'
namespace App\Models; use MongoDB\Laravel\Eloquent\HasSchemaVersion; use MongoDB\Laravel\Eloquent\Model; class Planet extends Model { use HasSchemaVersion; public const SCHEMA_VERSION = 2; protected $fillable = ['name', 'type', 'galaxy']; /** * Migrate documents with a lower schema version to the most current * schema when inserting new data or retrieving from the database. */ public function migrateSchema(int $fromVersion): void { if ($fromVersion < 2) { $this->galaxy = 'Milky Way'; } } }
En el documento "WASP-39 b" en el siguiente código, el valor del campo schema_version es menor que 2. Cuando se recupera el documento, la Integración de Laravel agrega el campo galaxy y actualiza la versión del esquema a la versión actual, 2.
El documento "Saturn" no contiene el campo schema_version, por lo que la integración de Laravel le asigna la versión del esquema actual al guardarlo.
Finalmente, el código recupera los modelos de la colección para demostrar los cambios:
// Simulates a document in the collection with schema version 1 Planet::insert([ [ 'name' => 'WASP-39 b', 'type' => 'gas', 'schema_version' => 1, ], ]); // Saves a document with no specified schema version $saturn = Planet::create([ 'name' => 'Saturn', 'type' => 'gas', ]); // Retrieves both models from the collection $planets = Planet::where('type', 'gas') ->get();
[ { "_id": ..., "name": "WASP-39 b", "type": "gas", "galaxy": "Milky Way", "schema_version": 2, }, { "_id": ..., "name": "Saturn", "type": "gas", "schema_version": 2, } ]