Una guía sobre los accessors, mutators y los casting en Laravel

  • Publicado el 09 abril, 2025
  • Palabras: 872

Los casting, los mutators y los accessors son elementos con los que trabajamos mucho al crear aplicaciones Laravel. Desempeñan un papel esencial en la interacción con los modelos y sus datos subyacentes.

Una guía sobre los accessors, mutators y los casting en Laravel

Laravel incluye una variedad de conversiones prácticas e integradas que cubren la mayoría de los casos de uso. Sin embargo, puede que en ocasiones necesites crear tus propias conversiones personalizadas para gestionar el almacenamiento y la recuperación de datos de una forma específica. Examinaremos qué son los casting, los mutators y los accessors en Laravel.  

 

# ¿Qué son los mutators y los accessors en Laravel?

Los mutators y los accessors son dos conceptos clave en Laravel que permiten manipular los datos del modelo al almacenarse o recuperarse de la base de datos.

 

Al almacenar o actualizar un modelo en la base de datos, los mutators convierten los datos a un formato que puede almacenarse en la base de datos.

 

Al recuperar un modelo de la base de datos, los accessors convierten los datos a un formato que puede usarse en la aplicación.

 

Es el claro ejemplo de los métodos getters y setters que permiten obtener y modificar los valores de atributos en programación orientada a objetos.

 

Si quieres profundizar más existe una gran documentación  sobre ello.

 

#Accessors en los modelos de Laravel

Imaginemos que tenemos un modelo AppModelsUser con los campos first_name y last_name. En lugar de tener que concatenar estos campos cada vez que queremos obtener el nombre completo, podemos usar un accessor para hacerlo automáticamente.

 

Tomemos este ejemplo del modelo AppModelsUser:

 

declare(strict_types=1);

namespace AppModels;

use IlluminateDatabaseEloquentCastsAttribute;
use IlluminateFoundationAuthUser as Authenticatable;

final class User extends Authenticatable
{
    // ...

    protected function fullName(): Attribute
    {
        return Attribute::get(
            fn(): string => $this->first_name.' '.$this->last_name,
        );
    }
}

 

En el ejemplo, añadimos el método fullName y especificamos que es un accessor mediante el método IlluminateDatabaseEloquentCastsAttribute::get, que devuelve una instancia de IlluminateDatabaseEloquentCastsAttribute. De esta forma, especificamos que, al intentar acceder al atributo full_name del modelo, se devolverá el resultado del clousure.

 

Por ejemplo, imaginemos un usuario con el nombre "Juan" y el apellido "Pérez". Mediante el descriptor de acceso, podemos acceder al atributo full_name de la siguiente manera:

 

use AppModelsUser;

$user = User::find(1);

$fullName = $user->full_name; // "Juan Pérez"

 

#Mutators en los modelos de Laravel

Al igual que los accessors, también podemos definir mutators para nuestros modelos de Laravel. Estos mutators se utilizan para manipular los datos antes de almacenarlos en la base de datos.

 

Son útiles para situaciones como garantizar que los datos se almacenen en un formato consistente. Por ejemplo, podrías querer convertir todas las direcciones de correo electrónico a minúsculas antes de almacenarlas en la base de datos.

 

Veamos cómo podríamos hacer esto en nuestro modelo AppModelsUser:

 

declare(strict_types=1);

namespace AppModels;

use IlluminateDatabaseEloquentCastsAttribute;
use IlluminateFoundationAuthUser as Authenticatable;

final class User extends Authenticatable
{
    // ...

    protected function email(): Attribute
    {
        return Attribute::set(
            fn(string $value): string => strtolower($value),
        );
    }
}

 

En nuestro ejemplo, podemos ver que hemos añadido un método de correo electrónico a nuestro modelo AppModelsUser. A continuación, especificamos que es un mutator mediante el método IlluminateDatabaseEloquentCastsAttribute::set, que devuelve una instancia de IlluminateDatabaseEloquentCastsAttribute. De esta forma, especificamos que, siempre que se intente almacenar un valor en el atributo de correo electrónico del modelo, el resultado del clousure se almacenará en la base de datos.

 

Por ejemplo, supongamos que queremos actualizar la dirección de correo electrónico de un usuario con un ID de 1 a INFO@EJEMPLO.COM:

 

use AppModelsUser;

$user = User::find(1);
$user->update(['email' => 'INFO@EJEMPLO.COM']);

$user->email; // info@ejemplo.com

 

#Usando un accesor y un mutator para el mismo campo

En nuestros ejemplos anteriores, solo definimos un accesor o un mutator para un campo. Sin embargo, puede que en ocasiones desee usar ambos para el mismo campo.

 

namespace AppModels;

use IlluminateDatabaseEloquentCastsAttribute;
use IlluminateDatabaseEloquentModel;

class User extends Model
{
    /**
     * Interact with the user's first name.
     */
    protected function firstName(): Attribute
    {
        return Attribute::make(
            get: fn (string $value) => ucfirst($value),
            set: fn (string $value) => strtolower($value),
        );
    }
}

 

En el ejemplo anterior, podemos ver que el modelo User tiene un accesor y un mutator para el campo first_name. El accesor (definido por el clousure pasado al parámetro get) convertirá la primera letra del nombre en mayúsculas al recuperarlo de la base de datos, y el mutator (definido por el clousure pasada al parámetro set) convertirá el nombre a minúsculas antes de almacenarlo en la base de datos.

 

Nota: El ejemplo anterior es puramente ilustrativo para demostrar cómo usar un accesor y un mutator en el mismo campo. Es recomendable evitar usar esta misma lógica en una aplicación real, ya que podría provocar que nombres como "McDonald" se almacenen como "mcdonald" y luego se recuperen como "Mcdonald".

 

#¿Qué son los casting en Laravel?

Puede haber ocasiones en que la lógica utilizada en tus mutators y accesors sea compleja o esté diseñada para ser reutilizada en múltiples modelos. En estos casos, podrías considerar usar un "casting".

 

Los casting de modelos de Laravel suelen ser clases que definen la lógica sobre cómo se debe almacenar o recuperar un atributo de un modelo de la base de datos. Pueden usarse para gestionar lógica compleja que sería difícil o confusa de gestionar en un mutator o accesor.

 

Al momento de escribir este artículo, Laravel viene con 21 casting que puedes usar de manera inmediata.

 

Para comprender cómo usar los casting de Laravel en tus modelos, veamos un ejemplo de la clase AppModelsUser y luego analicemos su funcionamiento:

 

declare(strict_types=1);

namespace AppModels;

use IlluminateFoundationAuthUser as Authenticatable;

final class User extends Authenticatable
{
    // ...

    /**
     * Get the attributes that should be cast.
     *
     * @return array<string, string>
     */
    protected function casts(): array
    {
        return [
            'email_verified_at' => 'datetime',
            // ...
        ];
    }
}

 

En el ejemplo anterior, utilizamos el método de casts para definir qué atributos del modelo deben convertirse mediante mutators y accessors. En este caso, especificamos que el atributo email_verified_at debe utilizar la conversión de fecha y hora.

 

La conversión de fecha y hora se utiliza para:

 

  • Convierte el campo email_verified_at a un formato que pueda almacenarse en la base de datos.
  • Convierte el campo email_verified_at de nuevo a una instancia de CarbonCarbon al recuperarlo de la base de datos (suponiendo que no hayas cambiado el comportamiento predeterminado de la clase a la que debe resolverse la fecha).

 

Por ejemplo, supongamos que tenemos un modelo AppModelsUser con un valor email_verified_at almacenado en la base de datos como 2025-03-13 12:00:00. Al aplicar la conversión de fecha y hora, el valor se convertirá en una instancia de CarbonCarbon al recuperarse de la base de datos. Esto significa que podemos interactuar con el valor y realizar acciones como $user->email_verified_at->addDays(2), $user->email_verified_at->format('Y-m-d'), etc.

Antonio Jenaro
Antonio Jenaro

Web Developer

Archivado en:

Inicia la conversación

Hazte miembro de Antonio Jenaro para comenzar a comentar.

Regístrate ahora

¿Ya estás registrado? Inicia sesión