Criando o próprio cast no Laravel

Já criei um artigo falando o que é o cast no Laravel, e você pode ver ele clicando aqui, e te aconselho muito a ler esse artigo antes de continuar com esse.

Utilizando os casts padrões do Laravel, a “única coisa” que você vai fazer é transformar o tipo de dados, por exemplo de integer para boolean, mas com o nosso próprio cast podemos brincar um pouco mais com esses dados.

Primeiro tenho que te falar como crio o próprio cast, que é bem simples, é só uma classe, isso mesmo, o nosso cast será uma classe, e essas classes ficarão dentro de App/Casts.

Essa classe tem a seguinte estrutura.

namespace App\Casts;

use Illuminate\Contracts\Database\Eloquent\CastsAttributes;

class Name implements CastsAttributes
{
    public function get($model, string $key, $value, array $attributes)
    {
        //
    }

    public function set($model, string $key, $value, array $attributes)
    {
        //
    }
}

Veja que criei uma classe chamada Name dentro da pasta Casts que está dentro da pasta App, e essa classe obrigatoriamente tem que implementar a interface CastsAttributes e com isso utilizar os métodos get e set.

Você tem que ter em mente que o cast serve tanto para ler como gravar, o set e get são para isso, o set é para gravar e o get para ler.

Agora vou “brincar” um pouco com o campo name da tabela users, e vou fazer isso no get, para listar, mas antes preciso te mostrar como faz para chamar esse cast lá na propriedade $casts dentro do Model.

    protected $casts = [
        'name' => Name::class
    ];

Viu como é simples ?Para chamar o nosso cast é somente colocar NomeCast::class.

Agora voltando para o cast vou trabalhar em cima do método get, que é para listar, mas antes de fazer alguma coisa você precisa saber o que significam cada um dos parâmetros desse método, então vamos a eles.

O primeiro parâmetro é o model, que acho que não precisa de maiores explicações, que é o próprio model onde está a propriedade $casts.

O segundo é o $key, que é o índice no array $casts no qual estou colocando essa classe, no exemplo abaixo o $key é o name.

 protected $casts = [
    'name' => Name::class
 ];

O terceiro é o $value, que é o valor desse campo name, o valor que está la no banco de dados nesse campo.

E por último tem o $attributes, que são todos os campos da tabela.

Perceba o tanto de coisas que podemos usar para “brincar” como o retorno, eu por exemplo vou colocar um prefixo antes do valor, ficando assim:

namespace App\Casts;

use Illuminate\Contracts\Database\Eloquent\CastsAttributes;

class User implements CastsAttributes
{
    public function get($model, string $key, $value, array $attributes)
    {
        return "CFS_{$value}";
    }

    public function set($model, string $key, $value, array $attributes)
    {
        //
    }
}

O resultado vai ser CFS_Nome_da_pessoa em todos os registros, agora imagine o número de possibilidades.

O outro método é o set, que é usado para quando eu for gravar no banco de dados, e para isso vou utilizar o campo tags do tabela users que é um campo do tipo text, e vou gravar um json.

Mas antes de gravar eu preciso validar, por exemplo, o número de elementos do array que será gravado não pode ser maior que um determinado número.

namespace App\Casts;

use Illuminate\Contracts\Database\Eloquent\CastsAttributes;

class Tag implements CastsAttributes
{
    public function get($model, string $key, $value, array $attributes)
    {
        return json_decode($value);
    }

    public function set($model, string $key, $value, array $attributes)
    {
        $countElements = count($value);
        if($countElements > 5){
            throw new \Exception("Podem ter somente 5 tags");
        }

        return json_encode($value);
    }
}

Se o número de elementos for maior que 5 lança uma exceção, caso não, retorno o json com json_encode, assim posso gravar o array no banco de dados a representação desse array, e veja que no set estou dando um json_decode que é para listar esse array como um array.

Mas e se eu quiser alterar o limite de elementos aceitos no array eu preciso entrar na classe e mudar, e eu não quero isso, eu quero mudar direto na propriedade $casts, fazendo isso:

  protected $casts = [
      'tags' => \App\Casts\Tag::class.':3'
  ];

Eu concatenei ‘:3’ depois da classe, e para resgatar esse valor na classe eu pego no método mágico construtor, assim:

namespace App\Casts;

use Illuminate\Contracts\Database\Eloquent\CastsAttributes;

class Tag implements CastsAttributes
{
    public function __construct($countLimit)
    {
        $this->countLimit = (int)$countLimit;
    }

    public function get($model, string $key, $value, array $attributes)
    {
        return json_decode($value);
    }

    public function set($model, string $key, $value, array $attributes)
    {
        $countElements = count($value);
        if($countElements > $this->countLimit){
            throw new \Exception("Podem ter somente {$this->countLimit} tags");
        }

        return json_encode($value);
    }
}


Espero que tenha gostado desse segundo artigo sobre como trabalhar com casts no Laravel, e realmente tenha entendido, e para ver o primeiro artigo sobre o assunto clique aqui.


Se quiser conhecer meu trabalho mais a fundo, visite meu canal no YouTube e se quiser um curso completo de Laravel 8 veja meu curso para iniciantes.

🔥 Canal no YouTube: Ir para o canal no YouTube
🔥 Curso de Laravel 8 para iniciantes: Ir para o curso
🔥 Veja meus cursos disponíveis: Ir para a lista de cursos

About the Author

Alexandre Eduardo Cardoso
Alexandre Eduardo Cardoso

Meu nome é Alexandre Cardoso e tenho 41 anos. Sou programador desde 2008, quando comecei a estudar e me especializar em PHP e Javascript. Já em 2011, dei minhas primeiras aulas de programação, e não consegui mais parar desde então. Ensinar é minha missão neste mundo!

0 Comments

Leave a comment

O seu endereço de email não será publicado. Campos obrigatórios marcados com *