Você ainda faz json_decode na mão, né?
Confessa. Tem um lugar no seu projeto onde você lê uma coluna do banco, dá um json_decode, mexe no array, dá json_encode de volta e salva. E toda vez você reza pra não esquecer o true no json_decode.
Ou pior: aquela coluna que guarda uma lista separada por vírgula e vive num vai-e-vem de explode e implode.
O Eloquent resolve isso há anos com casts. Só que a maioria dos devs conhece uns quatro (array, boolean, datetime, integer) e para por aí. O problema é que a lista é bem maior — e tem uns casts que são pura mão na roda esperando você descobrir.
Relembrando rapidinho: o que é um cast
Cast é uma tradução automática entre o formato que fica no banco e o formato que você quer usar no PHP. Você declara no model e o Eloquent faz a ponte sozinho, nos dois sentidos:
class Produto extends Model
{
protected function casts(): array
{
return [
'ativo' => 'boolean',
'preco' => 'decimal:2',
'publicado_em' => 'datetime',
];
}
}
Até aqui, nada de novo. A graça começa nos casts que ninguém mostra.
AsArrayObject: array de verdade, mexível
O cast array clássico tem uma pegadinha chata: você não consegue mutar um item direto. Isso aqui não funciona como você espera:
$produto->options['cor'] = 'azul'; // ignorado silenciosamente 😑
Com AsArrayObject, funciona:
use Illuminate\Database\Eloquent\Casts\AsArrayObject;
protected function casts(): array
{
return [
'options' => AsArrayObject::class,
];
}
$produto->options['cor'] = 'azul';
$produto->options['tamanho'] = 'M';
$produto->save(); // salva certinho
Coluna JSON que você mexe direto, sem cerimônia.
AsCollection: sua coluna JSON vira Collection
Se você ama as Collections do Laravel (e você ama), por que trabalhar com aquele JSON como array cru? O AsCollection te devolve uma Collection completa, com map, filter, where, o pacote inteiro:
use Illuminate\Database\Eloquent\Casts\AsCollection;
protected function casts(): array
{
return [
'tags' => AsCollection::class,
];
}
$produto->tags->filter(fn ($tag) => $tag['ativo'])->pluck('nome');
E tem um detalhe pouco conhecido: dá pra apontar uma Collection customizada sua, com métodos próprios de negócio:
'options' => AsCollection::using(OptionCollection::class),
AsEnumCollection: lembra dos Enums? Agora um array deles
Já falei aqui sobre castar uma coluna pra Enum. Mas e quando a coluna guarda vários enums? Tipo as permissões de um usuário, os status pelos quais um pedido passou?
use App\Enums\Permissao;
use Illuminate\Database\Eloquent\Casts\AsEnumCollection;
protected function casts(): array
{
return [
'permissoes' => AsEnumCollection::of(Permissao::class),
];
}
Salva como JSON no banco, volta como uma Collection de enums tipados. Type-safety num array inteiro, de graça.
AsStringable: string com superpoderes
Toda vez que você faz Str::of($model->titulo)->slug(), tá tratando na mão o que o cast já faz. Com AsStringable, a coluna já sai como um objeto Stringable, pronto pra encadear:
use Illuminate\Database\Eloquent\Casts\AsStringable;
protected function casts(): array
{
return [
'titulo' => AsStringable::class,
];
}
$post->titulo->slug(); // já é fluente
$post->titulo->limit(50)->upper();
encrypted e hashed: segurança sem boilerplate
Precisa guardar um dado sensível criptografado no banco? Tem cast pra isso, e ele criptografa na gravação e descriptografa na leitura sozinho:
protected function casts(): array
{
return [
'token_api' => 'encrypted',
'dados_bancarios' => 'encrypted:array', // criptografa E serializa
];
}
E pra senha, o hashed aplica o hash automático quando você atribui — chega de Hash::make() espalhado:
'password' => 'hashed',
$user->password = 'senha123'; // já vai hasheada pro banco
Como usar na prática
Configurações de usuário. Uma coluna preferencias JSON com AsArrayObject deixa você fazer $user->preferencias['tema'] = 'dark' e salvar, sem decode nenhum.
Roles/permissões. AsEnumCollection::of(Permissao::class) guarda a lista tipada e você compara com contains() sem medo de string errada.
Metadados de qualquer coisa. Pedido, produto, post — aquela coluna meta JSON com AsCollection te dá map, filter e amigos direto no model.
Pegadinha: quer o seu? Cria um custom cast
Nenhum dos prontos serve? Você cria o seu implementando CastsAttributes (leitura e gravação) ou CastsInboundAttributes (só na gravação, tipo um hash). Exemplo real de um cast que hasheia antes de salvar:
<?php
namespace App\Casts;
use Illuminate\Contracts\Database\Eloquent\CastsInboundAttributes;
use Illuminate\Database\Eloquent\Model;
class AsHash implements CastsInboundAttributes
{
public function set(Model $model, string $key, mixed $value, array $attributes): string
{
return bcrypt($value);
}
}
'codigo_secreto' => AsHash::class,
A regra de bolso: se você percebe que fica transformando o mesmo atributo do mesmo jeito toda vez, isso é um cast pedindo pra nascer.
Bônus: e agora?
Abre o model mais gordo do seu projeto e procura por json_decode, explode, Str::of($this-> ou Hash::make dentro dele. Cada um desses é forte candidato a virar cast e sumir do controller.
A doc oficial lista uns quantos que nem citei aqui — AsUri, AsFluent, immutable_datetime, decimal. Vale um passeio de 10 minutos.
Antes de você fechar a aba
Qual desses casts você não conhecia? Aposto que pelo menos um vai entrar no seu próximo commit. 😄
Me conta aí embaixo qual coluna JSON do seu projeto tá implorando por um AsArrayObject. E se o post te economizou uns json_decode, salva ele e manda pro colega que ainda trata dado na unha.
Top comments (0)