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.
Curso Laravel - Eloquent ORM Avançado
Conhecer o cursoRelacionando 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,
];
Curso Doctrine ORM - Fundamentos
Conhecer o cursoVia 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! :)