No estoy seguro si estoy malinterpretando cómo funcionan los observadores en Laravel o si estoy haciendo algo incorrectamente. Actualmente estoy ejecutando Laravel 6, aunque esta aplicación está actualmente en proceso de actualización por parte de otro equipo.
Lo que tengo:
class Parent extends Model { public function children() { return $this->hasMany( Child::class ); } } class Child extends Model { public function grandchild() { return $this->hasOne( Grandchild::class ); } }Mis dos observadores están declarados en un proveedor de servicios y ambos se llaman con éxito. Mi pregunta, o posiblemente un malentendido, es sobre cómo interactúan los observadores.
Mis dos observadores tienen una funcionalidad que se ejecuta cuando se recibe un comando de eliminación.
class ParentObserver { public function delete( Parent $parent ) { $parent->children()->delete(); } } class ChildObserver { public function delete( Child $child ) { $child->grandchild()->delete(); } }La función de eliminación de ChildObserver funciona al 100% como se esperaba. Cuando elimino un hijo, el nieto también se elimina. Lo que me confunde es cuando elimino un padre. El padre se elimina y los hijos se eliminan, pero los nietos no. No estoy llamando directamente para eliminar a los nietos en ParentObserver, esperaba que la funcionalidad ChildObserver se activara por las acciones realizadas en ParentObserver.
¿Me perdí algo al configurar los observadores? ¿O las acciones realizadas en un observador no desencadenan otros observadores que normalmente participarían en esas acciones si estuvieran en otra parte del código?
Esto está haciendo una consulta de eliminación masiva. No emite un evento deleted para cada uno de los elementos secundarios de Parent .
class ParentObserver { public function deleted( Parent $parent ) { $parent->children()->delete(); } }Debería funcionar si cambias a esto:
class ParentObserver { public function deleted( Parent $parent ) { $parent->children()->get()->each(function (Child $child) { $child->delete(); }); } }Posibles mejoras:
cursor se implementó en laravel 6, por lo que get usarlo en lugar de reducir el uso de memoriaeach método para simplificar el código. class ParentObserver { public function deleted( Parent $parent ) { $parent->children()->cursor()->each->delete(); } }De la documentación de Laravel:
Al emitir una consulta de actualización o eliminación masiva a través de Eloquent, los eventos de modelos guardados, actualizados, eliminados y eliminados no se enviarán para los modelos afectados. Esto se debe a que los modelos nunca se recuperan cuando se realizan actualizaciones o eliminaciones masivas.
Por lo tanto, si está realizando una eliminación masiva o una actualización masiva, no se activará.