Laravel Monitor DELETE CASCADE
[Finalizado Pelo Aluno]
Gostaria de saber qual é o motivo da decisão de não utilizar a cláusula ON DELETE CASCADE nas chaves estrangeiras. Será que isso é considerado um uso inadequado? Além disso, como é realizado o processo de exclusão em cascata a nível de código, especialmente considerando que temos diversos níveis de relacionamentos filhos? Afinal, essa funcionalidade não foi implementada.
Olá, Wilder!
Tudo bem?
Alguns motivos para não trabalhar com onDelete cascade:
1) Pode levar à perda de dados. Se um registro na tabela pai for excluído acidentalmente, todos os registros relacionados na tabela filha também serão excluídos. Isso pode levar à perda de dados importantes.
2) Pode causar problemas de desempenho. A exclusão de registros em cascata pode ser uma operação demorada, especialmente se houver muitos registros relacionados.
3) Pode ser difícil de reverter. Se você excluir um registro na tabela pai e, em seguida, perceber que cometeu um erro, pode ser difícil reverter a exclusão dos registros relacionados na tabela filha.
Se um dado for exluído acidentalmente, sem o cascade teremos vários registros no banco pesando, isso não é outro problema?
Como é realizado o processo de exclusão em cascata a nível de código, quando temos diversos níveis de relacionamentos filhos?
Se um dado for excluído acidentalmente, sem o cascade teremos vários registros no banco pesando, isso não é outro problema?
Problema mesmo é perder dados!!
Registros órfãos no banco apenas "ocupando espaço" não são interessantes, mas podem ser deletados a nível de código.
--
Como é realizado o processo de exclusão em cascata a nível de código, quando temos diversos níveis de relacionamentos filhos?
Obrigado a deletar primeiramente os registros filhos.
Ou delegando ainda a nível de código os registros filhos + o registro em questão.
Tentei encontrar uma forma automática de identificar todos relacionamentos para deletar em cascada dentro do framework mas não encontrei uma solução.
Testa pra ver se assim funciona:
public function destroy(string $id)
{
$pai = ModelPai::with('filhos')->find($id);
ModelFilho::destroy($pai->filhos->pluck('id'));
$pai->delete();
}
public function destroy(Site $site)
{
$site->endpoints()->delete();
$site->delete();
return redirect()->route('sites.index')->with('message', 'Site deletado com sucesso');
}
Neste caso, o código acima funciona se os endpoints não tiverem nenhum log.
EndPoint::delete($site->endpoints->pluck('id'));
SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails (`laravel_monitor`.`checks`, CONSTRAINT `checks_endpoint_id_foreign` FOREIGN KEY (`endpoint_id`) REFERENCES `endpoints` (`id`))
A lógica que te passei chegou a deletar os endpoints primeiro?
Não consegue deletar os endpoints pois possuem logs relacionados a eles
Ah sim, verdade, precisa fazer um loop:
public function destroy(Site $site)
{
Check::delete($site->endpoints->checks->pluck('id'));
EndPoint::delete($site->endpoints->pluck('id'));
$site->delete();
return redirect()->route('sites.index')->with('message', 'Site deletado com sucesso');
}
Só consegui da seguinte maneira:
public function destroy(Site $site)
{
$site->endpoints->each(function (Endpoint $endpoint) {
Check::destroy($endpoint->checks()->pluck('id'));
$endpoint->delete();
});
$site->delete();
return redirect()->route('sites.index')->with('message', 'Site deletado com sucesso');
}
Ainda assim não me agrada, se houvesse outro relacionamento com checks, talvez teria que fazer outro loop. Existe alguma maneira automática de fazer isso, de modo que identifique os relacionamentos?
@Wilder, Credito que o mais adequado para poder executar esse delete em cascata por meio da aplicação não seja colocando esse tipo de regra no seu controller diretamente. Minimamente seria interessante criar um Job no Laravel para processar isso de maneira assíncrona. E em caso de sucesso ou erro notificar a pessoa responsável por aquele site ou endpoint em questão. Além disso colocar essas regras dentro de uma transação seria interessante. Possibilitando um controle maior do que será, de fato, commitado.
Pensa num cenário onde um determinado endpoint tenha milhares de de logs... Algo desse gênero causaria uma péssima experiência para o usuário final, ou até, ter-se-ía problema de timeout de uma requisição, por conta da demora em executar um loop, ao qual sabemos ser nada performático.
Certamente esta ação, de maneira recursiva, cabe o uso de uma fila para que a processe. Acho que cabe uma errata acerca disso no curso em questão.
Fala Sérgio!
Como vai?
Super concordo com você, seus argumentos estão corretos.
--
Vou anotar aqui para criar uma sobre deletar registros em cascata, de forma assíncrona.
Precisa estar logado para conseguir responder a este ticket!
Clique Aqui Para Entrar!