Mutators e Accessors, como tratar dados no Eloquent.
Olá, mundo.
Já falamos aqui sobre padrões de projeto aplicados à persistência dos dados, na figura do ORM (Object Relational Mapper). Hoje pegando mais fundo nos conceitos de tratamento de dados, aplicado ao Framework Laravel, mais precisamente do Eloquent. Vamos falar sobre Accessors e Mutators.
Bom, para começarmos o que são e para que servem? No Laravel estas funções aplicadas às classes de Model, nos permite alterar a propriedade para serem devidamente inseridas no banco de dados (Mutator), e acessar e alterar a propriedade em tempo de execução, buscando o registro do banco.
Para que este conceito fique bem claro, vamos começar um novo projeto no Laravel.
composer create-project laravel/laravel meublog
Após o Composer baixar o framework, crie o banco de dados para nossa aplicação.
CREATE DATABASE meublog;
Com o banco criado, altere o nome o arquivo de ambiente do Laravel o .env
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=meublog DB_USERNAME=<nome do usuário> DB_PASSWORD=<senha do banco de dados>
Próximo passo será a criação de uma tabela de produtos, para exemplificar a manipulação dos Accessors e Mutators.
php artisan make:migration criar_tabela_produtos
Este comando irá criar o arquivo na pasta /database/migrations/2022_06_20_225049_criar_tabela_produtos.php, vamos alterar e deixar nesta conformidade.
<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('produtos', function (Blueprint $table) { $table->id(); $table->string('nome'); $table->integer('quantidade'); $table->text('descricao'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('produtos'); } };
agora vamos rodar a migração para criação da estrutura de nossa tabela para nosso banco de dados.
php artisan migrate
Vejamos a estrutura de nossa tabela:
Pronto, acabou?
Claro que não!Iremos agora começar pelo Mutators, este que tem a premissa de alterar o objeto antes mesmo de ser registrado no banco de dados. Para tanto iremos criar nossa classe Model para manipular a tabela Produtos.
Mutators
php artisan make:model Produto
Vamos alterar o Model que está na pasta /app/Models/Produto.php.
<?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Produto extends Model { use HasFactory; protected $fillable = [ 'nome', 'quantidade', 'descricao' ]; /** * Mutator para a Coluna Nome * quando o nome será salvo, ele será convertido em caixa alta. */ public function setNomeAttribute($value) { $this->attributes['nome'] = strtoupper($value); } }
Aqui que entra em ação o Mutator, ele vem na forma de uma função em que possui em seu prefixo set seguido pelo campo que queremos alterar, no caso Nome, e o sufixo Attribute, na função é injetada a variável $value para que seja encapsulada. Após ela é instanciada pela palavra reservada $this, referenciando um array attributes, indicando o campo da tabela e posteriormente, a função strtoupper($value), com a finalidade de deixar em caixa alta, todos os caracteres que inserimos no nome do produto.
Nosso próximo passo será a criação de nosso Controller.
php artisan make:controller ProdutoController
Será criado o arquivo ProdutoController.php em /app/Http/Controllers.
Façamos a seguinte alteração:
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Models\Produto; class ProdutoController extends Controller { public function index() { $produto = new Produto(); $produto->nome = "produto exemplo 1"; $produto->quantidade = 10; $produto->descricao = "exemplo de criação de produto com Mutators"; $produto->save(); } }
Note que a propriedade nome está com o valor em caixa baixa, o Mutator atuará na camada Model, antes do método save(), colocando o nome do produto em caixa alta. Tudo isso em tempo de execução.
Façamos isso alterando nosso arquivo de rotas disponível em /routes/web.php
<?php use App\Http\Controllers\ProdutoController; use Illuminate\Support\Facades\Route; /* |-------------------------------------------------------------------------- | Web Routes |-------------------------------------------------------------------------- | | Here is where you can register web routes for your application. These | routes are loaded by the RouteServiceProvider within a group which | contains the "web" middleware group. Now create something great! | */ /* *Rota que aciona o método Index do Controller para realizar a inserção no banco de dados, *utilizando o Mutator *em tempo de execução *com o Active Record no Eloquent */ Route::get('/', [ProdutoController::class, 'index']);
agora vamos iniciar a aplicação:
php artisan serve
Digitamos na URL localhost:8000 e façamos a consulta no banco de dados:
Voilà, funcionou nosso Mutator!Esta é a finalidade desta função no Eloquent.
Accessors
Do contrário que fizemos em nosso Mutator, no Accessors iremos fazer com o que o nome de nosso produto seja mostrado em caixa baixa, vamos lá?
Faremos alteração na Model Produto, em que como o Mutator, o Accessor terá o prefixo set – Produto e o sufixo Attribute.
<?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Produto extends Model { use HasFactory; protected $fillable = [ 'nome', 'quantidade', 'descricao' ]; /** * Mutator para a Coluna Nome * quando o nome será salvo, ele será convertido em caixa alta. */ public function setNomeAttribute($value) { $this->attributes['nome'] = strtoupper($value); } /** * Accessor para a Coluna Nome * quando o nome será exibido, ele será convertido em caixa baixa. */ public function getNomeAttribute($value) { return strtolower($value); } }
Por fim, façamos a alteração do nosso Controller para exibição:
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Models\Produto; class ProdutoController extends Controller { public function index() { $produto = new Produto(); $produto->nome = "produto exemplo 1"; $produto->quantidade = 10; $produto->descricao = "exemplo de criação de produto com Mutators"; $produto->save(); } public function getProdutos() { $produtos = Produto::get(); foreach ($produtos as $produto) { echo $produto->nome . "<br/>"; } } }
E incluímos a rota /produtos no arquivo de rotas /routes/web.php
Route::get('/produtos', [ProdutoController::class, 'getProdutos']);
Executamos a url localhost:8000/produtos:
O produto, na base de dados persiste em caixa alta, no entanto o Accessor alterou sua propriedade para exibição.
Espero que tenha ficado claro os conceitos de Accessors e Mutators no Laravel.
Boa viagem.
Código fonte do artigo disponível aqui.
Não ajunteis tesouros na terra, onde a traça e a ferrugem tudo consomem, e onde os ladrões minam e roubam. Mas ajuntai tesouros no céu, onde nem a traça nem a ferrugem consomem, e onde os ladrões não minam, nem roubam. Porque onde estiver o vosso tesouro, aí estará também o vosso coração.
Mateus 6:19-21