From 2dce14aa101bddb273f7a5ad7a6ea47f0d74326c Mon Sep 17 00:00:00 2001 From: Istiak Tridip <13367189+istiak-tridip@users.noreply.github.com> Date: Mon, 18 Nov 2024 22:24:48 +0600 Subject: [PATCH 1/2] feat: ability to listen to multiple eloquent events --- .../Database/Eloquent/Concerns/HasEvents.php | 20 ++++++ ...loquentModelListenToMultipleEventsTest.php | 61 +++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 tests/Integration/Database/EloquentModelListenToMultipleEventsTest.php diff --git a/src/Illuminate/Database/Eloquent/Concerns/HasEvents.php b/src/Illuminate/Database/Eloquent/Concerns/HasEvents.php index 42b16c43a7da..258c981e7974 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/HasEvents.php +++ b/src/Illuminate/Database/Eloquent/Concerns/HasEvents.php @@ -254,6 +254,26 @@ protected function filterModelEventResults($result) return $result; } + /** + * @param \Illuminate\Events\QueuedClosure|\Closure|string|array $events + * @param \Illuminate\Events\QueuedClosure|\Closure|string|array|null $callback + * @return void + */ + public static function listen($events, $callback = null) + { + if (! is_string($events) && ! is_array($events)) { + $callback = $events; + $events = '*'; + } + + if (isset(static::$dispatcher)) { + $name = static::class; + $events = Arr::map((array) $events, fn ($event) => "eloquent.{$event}: {$name}"); + + static::$dispatcher->listen($events, $callback); + } + } + /** * Register a retrieved model event with the dispatcher. * diff --git a/tests/Integration/Database/EloquentModelListenToMultipleEventsTest.php b/tests/Integration/Database/EloquentModelListenToMultipleEventsTest.php new file mode 100644 index 000000000000..f545e582f396 --- /dev/null +++ b/tests/Integration/Database/EloquentModelListenToMultipleEventsTest.php @@ -0,0 +1,61 @@ +increments('id'); + $table->string('title'); + $table->timestamps(); + }); + } + + public function testEloquentModelCanListenToMultipleEvents() + { + Event::fake(); + + Post::listen(['saved', 'deleted'], function () { + // do something + }); + + $post = Post::query()->create(['title' => 'Third post']); + $post->delete(); + + Event::assertListening('eloquent.saved: '.Post::class, Closure::class); + Event::assertListening('eloquent.deleted: '.Post::class, Closure::class); + } + + public function testEloquentModelCanListenToWildcardEvents() + { + Event::fake(); + + Post::listen(function () { + // do something + }); + + Post::query()->create(['title' => 'First post']); + + Event::assertListening('eloquent.booting: '.Post::class, Closure::class); + Event::assertListening('eloquent.booted: '.Post::class, Closure::class); + Event::assertListening('eloquent.saving: '.Post::class, Closure::class); + Event::assertListening('eloquent.creating: '.Post::class, Closure::class); + Event::assertListening('eloquent.created: '.Post::class, Closure::class); + Event::assertListening('eloquent.saved: '.Post::class, Closure::class); + } +} From c1f996742fbd484dc4a2cf53404fb9ff9f89c3ac Mon Sep 17 00:00:00 2001 From: Istiak Tridip <13367189+istiak-tridip@users.noreply.github.com> Date: Tue, 19 Nov 2024 10:14:34 +0600 Subject: [PATCH 2/2] refactor --- src/Illuminate/Database/Eloquent/Concerns/HasEvents.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Illuminate/Database/Eloquent/Concerns/HasEvents.php b/src/Illuminate/Database/Eloquent/Concerns/HasEvents.php index 258c981e7974..b6fcaa368e28 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/HasEvents.php +++ b/src/Illuminate/Database/Eloquent/Concerns/HasEvents.php @@ -2,9 +2,11 @@ namespace Illuminate\Database\Eloquent\Concerns; +use Closure; use Illuminate\Contracts\Events\Dispatcher; use Illuminate\Database\Eloquent\Attributes\ObservedBy; use Illuminate\Events\NullDispatcher; +use Illuminate\Events\QueuedClosure; use Illuminate\Support\Arr; use InvalidArgumentException; use ReflectionClass; @@ -261,7 +263,7 @@ protected function filterModelEventResults($result) */ public static function listen($events, $callback = null) { - if (! is_string($events) && ! is_array($events)) { + if ($events instanceof Closure || $events instanceof QueuedClosure) { $callback = $events; $events = '*'; }