PHP

Como aliviar seus controllers com os eventos do Eloquent no Laravel

Aprenda como os eventos do Eloquent podem te ajudar a diminuir a quantidade de lógica nos controllers de suas aplicações Laravel.

há 6 anos 2 meses

Formação Desenvolvedor PHP
Conheça a formação em detalhes

O sonho de todo programador é desenvolver código limpo, organizado, legível, manutenível e muitos outros adjetivos que poderia colocar em uma lista enorme. O Laravel possui vários recursos que nos ajuda a organizar nosso código para conseguir alcançar alguns desses atributos que descrevi acima, se usados de maneira correta. Um desses recursos são os eventos do Eloquent.

Esses eventos são executados sempre que uma ação acontece no model. Isso possibilita removermos responsabilidade dos controllers e executar quando o evento for acionado, com isso, conseguimos um controller mais simples e organizado.

O Eloquent disponibiliza os eventos:

  • Retrieved
  • Creating e Created
  • Updating e Updated
  • Saving e Saved
  • Deleting e Deleted
  • Restoring e Restored

Os eventos com final ing são executados antes da ação no banco de dados e os eventos com final ed são executados após a ação no banco de dados.

Laravel - Eloquent ORM Avançado
Curso Laravel - Eloquent ORM Avançado
Conhecer o curso

Relacionando os eventos no Model

É possível relacionar um evento do Eloquent a um método que fará a ação de três modos diferentes.

Via o método boot

O primeiro modo que podemos adicionar uma ação em um evento do model é através do método estático boot. Por exemplo, para executar uma ação antes da criação podemos fazer:

protected static function boot()
{
    parent::boot();

    static::creating(function ($nomeDoModel) {
        //Ação a ser executada 
    });

}

O Eloquent sempre injeta uma instância do model automaticamente no evento. Nos eventos executados antes da ação no banco é possível alterar os valores do model que serão persistidos.

A utilização dos eventos dentro do próprio model pode não ser a mais aconselhável, pois dependendo da quantidade de eventos pode sobrecarregar, tirando a complexidade dos controllers e transferindo para o models, o que não é bom, pois a solução de um problema criaria outro.

Via classe de evento

Um modo mais limpo de executar os eventos do Eloquent é através de classes específicas para cada um dos eventos. Para isso, basta declarar no model uma propriedade chamada dispatchesEvents com um array contendo o nome do evento e a respectiva classe que será responsável por executar a ação:

protected $dispatchesEvents = [
        'creating' => NomeDoModelCreating::class,
        'deleting' => NomeDoModelDeleting::class,
    ];

Doctrine ORM - Fundamentos
Curso Doctrine ORM - Fundamentos
Conhecer o curso

Via Observer

Na minha opinião, esse é o modo mais prático de executar ações quando precisamos executar ações em vários eventos do mesmo model.

Essa abordagem consiste basicamente em criar uma classe e declarar métodos públicos com o mesmo nome dos eventos, com isso, o próprio Eloquent verifica se o método existe, se sim, ele executa.

<?php

namespace AppObservers;

use AppNomeDoModel;

class NomeDoModelObserver
{

    public function creating(NomeDoModel $nomeDoModel)
    {
        //Executa antes de criar no banco
    }

    public function deleting(NomeDoModel $nomeDoModel)
    {
        //Executa antes de deletar no banco
    }
}

Único detalhe é que para o Eloquent fazer a referência entre a classe do model e a classe do Observer precisamos declarar dentro do método boot do AppServiceProvider essa relação:

NomeDoModel::observe(NomeDoModelObserver::class);

Note que usamos o método observe() do próprio model que recebe o caminho da classe do observer.

Exemplo prático

Vamos supor que temos uma relação 1 para 1 entre festa e cliente. Baseado nisso, a cada evento do model festa precisamos executar uma ação:

  • Quanto uma festa for criada para um cliente precisamos alterar o status do cliente para com-proposta;
  • Quando uma festa for atualizada, se o atributo valor for maior que zero precisamos alterar o status do cliente para festa-agendada;
  • Por fim, se a festa for excluída, alteramos o status do cliente para sem-proposta;

Nesse caso, podemos criar um observer com os eventos created, updated e deleted para realizar essas ações:

<?php

namespace AppObservers;

use AppFesta;

class FestaObserver
{

    /**
     * Evento executado após a festa ser criada
     *
     * @param Festa $festa
     */
    public function created(Festa $festa)
    {
        $festa->cliente->update(['status' => 'com-proposta']);
    }


    /**
     * Evento executado após a festa ser atualizada
     *
     * @param Festa $festa
     */
    public function updated(Festa $festa)
    {
        if ($festa->valor > 0) {
            $festa->cliente->update(['status' => 'festa-agendada']);
        }
    }

    /**
     * Evento executado após a festa ser deletada
     *
     * @param Festa $festa
     */
    public function deleted(Festa $festa)
    {
        $festa->cliente->update(['status' => 'sem-proposta']);
    }

}

Conclusão

Esse é apenas um dos recursos que podemos usar no Laravel para manter a organização do código. Podemos usar outros como View Composer, Route Model Bind, Policies para permissões, Presenters para remover lógica das views e muito mais.

Quais dos recursos você tem utilizado em seus projetos para melhorar a qualidade do seu código? Fique à vontade para nos contar aqui nos comentários.

Ah, temos uma formação completa aqui na TreinaWeb. Dê uma espiadinha? :)

Já leu nossos artigos sobre Laravel e Eloquent? Veja como usar escopos do Eloquent para construir consultas mais limpas no Laravel e como remover a lógica das views com presenters no Laravel, tudo aqui no blog da Treina Web.

Até a próxima! :)

Autor(a) do artigo

Elton Fonseca
Elton Fonseca

Professor e desenvolvedor. Formado em análise e desenvolvimento de sistema, pós graduado em engenharia e arquitetura de software. É autor de cursos em diversos temas, como, desenvolvimento back-end, cloud computing e CMSs. Nas horas vagas adora estudar sobre o mercado financeiro, cozinhar e brincar com pequeno Daniel. @eltonfonsecadev

Todos os artigos

Artigos relacionados Ver todos