Accessors y Mutators en Laravel

Desarrollo Web

Los Accessors y Mutators son una forma de acceso a los datos de un modelo en Laravel Ambos son definidos dentro de los modelos creado en Laravel 5.

Los Accessors son métodos que cambian la forma en la que se devuelven los datos al momento de ser consultados al modelo, mientras que los Mutators son aquellos los cuales modifican el dato antes de ser almacenado en la base de datos.

Instalación y configuración Laravel 5.5

Instalamos Laravel con composer

composer create-project --prefer-dist laravel/laravel blog "5.5.*"

Creamos un modelo y una migración

php artisan make:model Product -m

Modificamos la migración de la siguiente con el fin de almacenar productos con su nombre, marca y descripción, además de sus ya conocidos created_at y updated_at definiéndolo en nuestro método up.

public function up()
{
    Schema::create('products', function(Blueprint $table){
        $table->increments('id');
        $table->string('name');
        $table->string('brand');
        $table->string('description');
        $table->timestamps();
    });
}

Creamos las migraciones

php artisan migrate

Ahora, vamos a hacer las pruebas usando Tinker, por lo que no hace falta definir las rutas ni controladores, ya que los cambios los vamos a ver dentro directamente desde la terminal.

Finalmente, solo vamos a modificar nuestro modelo para permitir la asignación masiva

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    protected $fillable = ['name', 'brand', 'description'];
}

Accessors

Como dijimos anteriormente, los Accessors son con los que transformamos nuestros atributos antes de ser enviados a quien consulta los datos. Para definir un Accessor solo tenemos que crear una función dentro de nuestro modelo con el nombre de nuestra columna en formato Camel case, anteponiéndole la palabra get y agregando al final la palabra Attribute, del modo que, si nuestra columna se llama name nuestro método se llamará getNameAttribute, si nuestra columna se llamara last_name, nuestro método será getLastNameAttribute.

Supongamos que queremos que siempre que la marca de nuestro modelo siempre se devuelva en mayúsculas, por lo que agregamos el método getBrandAttribute y lo hacemos de la siguiente manera

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    protected $fillable = ['name', 'brand', 'description'];
    
    public function getBrandAttribute($value)
    {
        return strtoupper($value);
    }
}

Vemos que la función recibe un parámetro, el cual usamos para transformar y después regresar un valor.

Mutators

Los Mutators o Mutadores son aquellos métodos que cambian antes de ser guardados a la base de datos. Se definen de la misma manera que los accessors pero con una diferencia, la palabra get se reemplaza por set. Por lo que si queremos que antes de que la descripción de un producto sea guardado o actualizada agregue un texto antes de la description, debemos crear un método con le nombre setDescriptionAttribute.

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    protected $fillable = ['name', 'brand', 'description'];
    
    public function getBrandAttribute($value)
    {
        return strtoupper($value);
    }

    public function setDescriptionAttribute($value)
    {
        $this->attributes['description'] = trim("Descripción: $value");
    }
}

Con esto hacemos que al momento de consultar la marca de algún producto primero la convierta a mayúsculas antes de ser entregada al usuario quien la consulta y que se modifique la descripción antes de ser guardada anteponiendo la palabra Descripción.

Pruebas con tinker

Ahora, vayamos a nuestra consola, naveguemos dentro de la carpeta del proyecto y entramos a la consola interactiva de Laravel llamada Tinker

php artisan tinker

Veremos algo como esto

Psy Shell v0.9.4 (PHP 7.0.26 cli) by Justin Hileman
>>>

Primero definimos el nombre de espacio

Psy Shell v0.9.4 (PHP 7.0.26 cli) by Justin Hileman
>>> namespace App
>>>

Ahora vamos a crear un modelo usando la asignación masiva

Psy Shell v0.9.4 (PHP 7.0.26 cli) by Justin Hileman
>>> $product = Product::create(['name' => 'T-shirt 1', 'brand' => 'Aeroposole', 'description' => 'T-shirt XL'])
=> App\Product {#1234
        id: 1,
        name: "T-shirt 1",
        brand: "Aeroposole",
        description: "Descripción: T-shirt XL",
        created_at: ..,
        updated_at: ..,
    }
>>>

Como vemos en el ejemplo anterior, Laravel automáticamente nos modificó el campo description por el que definimos en el Mutator, pero estarás pensando, ¿por qué no mostro la marca en mayúsculas?, esto es porque el método setDescriptionAttribute se llama al momento de crear o editar el campo description, cuando consulto los datos claro que aparecen, pero para el caso de marca, el método se llama solo cuando llamo particularmente al atributo brand, más no cuando llamo a todo el conjunto de atributos o bien a todo el conjunto de datos.

En nuestro caso, si imprimimos la variable $product podremos ver que no muestra la marca en mayúsculas

Psy Shell v0.9.4 (PHP 7.0.26 cli) by Justin Hileman
>>> $product
=> App\Product {#1234
        id: 1,
        name: "T-shirt 1",
        brand: "Aeroposole",
        description: "Descripción: T-shirt XL",
        created_at: ..,
        updated_at: ..,
    }
>>>

Pero si llamamos únicamente al método $product->brand podremos ver la diferencia

Psy Shell v0.9.4 (PHP 7.0.26 cli) by Justin Hileman
>>> $product->brand
=> "AEROPOSOLE"
>>>

Conclusión

Ya sabemos el uso de Mutator y Accessors, son ideales para manipular modelos de una manera transparente al programador, de esta manera, no debemos preocuparnos de estar llamando funciones cada vez que modifiquemos o consultemos las propiedades de los modelos