• Час читання ~1 хв
  • 25.11.2023

Якщо у вас є події Watcher для оновлення або видалення записів, важливо знати, що вони запускаються лише під час оновлення окремих записів, а не під час їх масового оновлення

.Код спостерігача:Цей спостерігач зареєстрований у постачальника послуг:А тепер уявіть собі три різні промовисті запити:

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();// Это также НЕ БУДЕТ запускать Наблюдателя!

Причина в тому, що події Спостерігача походять від Моделі красномовства. У випадку delete() з конструктором запитів запит виконується безпосередньо до бази даних, минаючи окрему модель та її події.

Навіть якщо результатом запиту буде одна модель Eloquent, Watchers не запуститься.

Post::where('id', 4)->delete();

Це справедливо для будь-якого методу Observer: updated() або , delete() або updating()deleting().

Це не менш важливо у випадку з деякими пакетами, які автоматично реєструють спостерігачів.

Наприклад, у випадку Spatie Media Library вона реєструє методdeleted(), який не видалятиме пов'язані медіафайли, якщо ви видаляєте записи моделі масово, а не одну модель.

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());        });    }

Comments

No comments yet
Yurij Finiv

Yurij Finiv

Full stack

Про мене

Professional Fullstack Developer with extensive experience in website and desktop application development. Proficient in a wide range of tools and technologies, including Bootstrap, Tailwind, HTML5, CSS3, PUG, JavaScript, Alpine.js, jQuery, PHP, MODX, and Node.js. Skilled in website development using Symfony, MODX, and Laravel. Experience: Contributed to the development and translation of MODX3 i...

Про автора CrazyBoy49z
WORK EXPERIENCE
Контакти
Ukraine, Lutsk
+380979856297