Jeśli masz zdarzenia obserwatora do aktualizowania lub usuwania rekordów, ważne jest, aby wiedzieć, że są one uruchamiane tylko wtedy, gdy poszczególne rekordy są aktualizowane, a nie gdy są aktualizowane zbiorczo
.Kod obserwatora:Ten obserwator jest zarejestrowany u Usługodawcy:Teraz wyobraźmy sobie trzy różne zapytania elokwentne:
app/Observers/PostObserver.php
:
class PostObserver{ public function deleted(Post $post) { // Например, удаляет связанные файлы изображений }}
app/Providers/AppServiceProvider.php
:
use App\Models\Post;use App\Observers\PostObserver;class AppServiceProvider extends ServiceProvider{ public function boot() { Post::observe(PostObserver::class); }}
$post = Post::first();$post->delete();// Это БУДЕТ запускать НаблюдателяPost::find(2)->delete();// Это также БУДЕТ запускать НаблюдателяPost::where('id', '>', 3)->delete();// Но это НЕ БУДЕТ запускать Наблюдателя!$user->posts()->delete();// Это также НЕ БУДЕТ запускать Наблюдателя!
Powodem jest to, że zdarzenia obserwatora pochodzą z modelu elokwentnego. W przypadku delete()
Query Builder zapytanie jest wykonywane bezpośrednio do bazy danych, z pominięciem pojedynczego modelu i jego zdarzeń.
Nawet jeśli wynik zapytania jest pojedynczym modelem Eloquent, obserwatorzy nie będą uruchamiani.
Post::where('id', 4)->delete();
Dotyczy to każdej metody Observer: updated()
albo updating()
, delete()
albo deleting()
.
Jest to równie ważne w przypadku niektórych pakietów, które automatycznie rejestrują Observerów.
Na przykład w przypadku Biblioteki multimediów Spatie rejestruje metodędeleted()
, która nie usunie skojarzonych plików multimedialnych, jeśli wpisy modelu zostaną usunięte zbiorczo zamiast pojedynczego modelu.
laravel-medialibrary/src/InteractsWithMedia.php
:
trait InteractsWithMedia{ public static function bootInteractsWithMedia() { static::deleting(function (HasMedia $model) { if ($model->shouldDeletePreservingMedia()) { return; } if (in_array(SoftDeletes::class, class_uses_recursive($model))) { if (! $model->forceDeleting) { return; } } $model->media()->cursor()->each(fn (Media $media) => $media->delete()); }); }