Models extensos no Laravel? Veja como resolver!
Resumo: Está tendo problemas com models extensos no Laravel? Vou te mostrar como resolver esse problema comum e manter seu código mais organizado e eficiente. Models grandes podem dificultar a manutenção do código, impactar na performance do seu projeto e até aumentar as chances de erros. Aqui, você vai aprender técnicas práticas para dividir a lógica […]
Está tendo problemas com models extensos no Laravel? Vou te mostrar como resolver esse problema comum e manter seu código mais organizado e eficiente. Models grandes podem dificultar a manutenção do código, impactar na performance do seu projeto e até aumentar as chances de erros. Aqui, você vai aprender técnicas práticas para dividir a lógica de seus models e dicas para aplicar boas práticas no desenvolvimento com Laravel. Não perca essas soluções valiosas que vão melhorar significativamente o fluxo do seu projeto! Se você trabalha com Laravel e quer otimizar seu código, tutorial é para você.
Models extensos no Laravel
É comum em sistemas grandes no Laravel e aplicações complexas termos muitos relacionamentos nos Models e regras, e com o passar do tempo, podemos ter outra regra de negócio que envolve a mesma tabela porém com regras de escopo diferentes. Como podemos fazer essas regras sem complicar o código e atrapalhar o já existente?
Para esse artigo, iremos exemplificar que temos um agendamento definido no Model Schedule para a tabela schedules e agora precisamos definir:
- Pré-agendamento.
- Agendamento.
- Pós-agendamento.
E nossa tabela terá exatamente as mesmas colunas. Como resolver esse problema no Laravel?
Solucionando Models extensos
Alguns programadores podem pensar em apenas colocar uma coluna a mais chamada type e uma condicional no método estático booted ou criar vários escopos locais colocando where’s para especificar o registro. O problema é que isso suja o nosso código e faz com que a manutenção dele seja muito extensa e complicada, veja o mal exemplo:
class Schedule extends Model
{
protected $fillable = [
'date',
'time',
'order_id',
'completed',
'type'
];
protected static function booted()
{
static::addGlobalScope(new FilterByUserScope);
}
public function scopePreSchedule(object $query)
{
return $query->where('type','1');
}
public function scopeSchedule(object $query)
{
return $query->where('type','0');
}
public function scopeSchedule(object $query)
{
return $query->where('type','2');
}
}
O código acima no Model do Laravel possui dois problemas:
- O Laravel sempre irá ler o escopo global levando em consideração o método “booted”.
- Os escopos locais irão funcionar apenas quando forem chamados. (métodos iniciados com a palavra scope)
- Não resolve nosso problema.
Com isso podemos colocar uma condicional no escopo global “booted” criando uma constante em nosso código.
const TYPE = '1'; // 1 para agendamentos
protected static function booted()
{
if(self::TYPE == 1){
static::addGlobalScope(new FilterByUserScope);
}
}
Assim, conseguimos separar o escopo global com uma condicional.
Porém, isso ainda não resolve de fato o nosso problema, pois, teríamos os relacionamentos de todas entidades (models) juntas, ou seja, não queremos o relacionamento da entidade Schedule quando for PreSchedule e nem as regras dele.
Logo para resolver o problema de entidades diferentes na mesma tabela, devemos pensar em entidades separadas e dar a responsabilidade única para cada uma.
Models e entidades separados usando a mesma tabela
Criamos um model para cada entidade que iremos usar mas setamos (configuramos) a mesma tabela nele:
Sendo assim, fazemos as seguintes regras:
- No model Schedule usamos a tabela schedules
- No model Preschedule usamos a tabela schedules
Dessa maneira, podemos criar as regras necessárias de forma separada usando a mesma tabela em nossa base de dados, pois, ao separar as entidades e isolarmos as responsabilidades de cada uma, podemos criar os relacionamentos específicos e trabalhar com essa nova entidade de forma isolada, ou seja, sem precisar ficar lembrando que de certa forma é a mesma tabela “schedules“.
Como definir a diferença nos registros dos Models
Depois de termos criado os Models Laravel diferentes, precisamos definir neles os escopos globais que justificam a separação, logo:
No Model Preschedule, iremos adicionar um escopo global informando o que define ele em nossa base de dados:
class Preschedule extends Model
{
//TYPE = 2 é pre-agendamento
const TYPE = '2';
protected static function booted()
{
static::addGlobalScope(function($query){
return $query->where('type',self::TYPE);
});
}
E em Schedule a mesma ação
class Schedule extends Model
{
//TYPE = 1 é agendamento
const TYPE = '1';
protected static function booted()
{
static::addGlobalScope(function($query){
return $query->where('type',self::TYPE);
});
}
Pronto, definimos as diferença de dados.
Agora sempre que fizemos uma consulta ao Model Schedule ele irá retornar todos os registros com type = 1, o que representa agendamentos feitos, e quando consultarmos o model Preschedule iremos buscar todos os registros com type = 2, o que representa todos os pré-agendamentos.
Vantagens e conclusão
As vantagens é que você poderá trabalhar com duas entidades em seu código com nomes diferentes sem precisar ficar se preocupando se colocou alguma condicional ou algum método errôneo, pois, as entidades agora representam dois mundo diferentes, ou seja, você literalmente separou o escopo de responsabilidade.
Gostou do artigo? Deixe sua dúvida ou comentário