Skip to content

Commit 11508cd

Browse files
authored
Support ObservedBy on parent model classes (#53579)
* Support ObservedBy on parent model classes * Traverse entire ancestry * Prepend parent observers instead of append * add test * remove unused includes
1 parent 3c672db commit 11508cd

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

src/Illuminate/Database/Eloquent/Concerns/HasEvents.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44

55
use Illuminate\Contracts\Events\Dispatcher;
66
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
7+
use Illuminate\Database\Eloquent\Model;
78
use Illuminate\Events\NullDispatcher;
89
use Illuminate\Support\Arr;
10+
use Illuminate\Support\Collection;
911
use InvalidArgumentException;
1012
use ReflectionClass;
1113

@@ -48,9 +50,16 @@ public static function resolveObserveAttributes()
4850
{
4951
$reflectionClass = new ReflectionClass(static::class);
5052

53+
$isEloquentGrandchild = is_subclass_of(static::class, Model::class)
54+
&& get_parent_class(static::class) !== Model::class;
55+
5156
return collect($reflectionClass->getAttributes(ObservedBy::class))
5257
->map(fn ($attribute) => $attribute->getArguments())
5358
->flatten()
59+
->when($isEloquentGrandchild, function (Collection $attributes) {
60+
return collect(get_parent_class(static::class)::resolveObserveAttributes())
61+
->merge($attributes);
62+
})
5463
->all();
5564
}
5665

tests/Database/DatabaseEloquentModelTest.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2106,6 +2106,20 @@ public function testModelObserversCanBeAttachedToModelsThroughAnArrayUsingAttrib
21062106
EloquentModelWithObserveAttributeUsingArrayStub::flushEventListeners();
21072107
}
21082108

2109+
public function testModelObserversCanBeAttachedToModelsThroughAttributesOnParentClasses()
2110+
{
2111+
EloquentModelWithObserveAttributeGrandchildStub::setEventDispatcher($events = m::mock(Dispatcher::class));
2112+
$events->shouldReceive('dispatch');
2113+
$events->shouldReceive('listen')->once()->with('eloquent.creating: Illuminate\Tests\Database\EloquentModelWithObserveAttributeGrandchildStub', EloquentTestObserverStub::class.'@creating');
2114+
$events->shouldReceive('listen')->once()->with('eloquent.saved: Illuminate\Tests\Database\EloquentModelWithObserveAttributeGrandchildStub', EloquentTestObserverStub::class.'@saved');
2115+
$events->shouldReceive('listen')->once()->with('eloquent.creating: Illuminate\Tests\Database\EloquentModelWithObserveAttributeGrandchildStub', EloquentTestAnotherObserverStub::class.'@creating');
2116+
$events->shouldReceive('listen')->once()->with('eloquent.saved: Illuminate\Tests\Database\EloquentModelWithObserveAttributeGrandchildStub', EloquentTestAnotherObserverStub::class.'@saved');
2117+
$events->shouldReceive('listen')->once()->with('eloquent.creating: Illuminate\Tests\Database\EloquentModelWithObserveAttributeGrandchildStub', EloquentTestThirdObserverStub::class.'@creating');
2118+
$events->shouldReceive('listen')->once()->with('eloquent.saved: Illuminate\Tests\Database\EloquentModelWithObserveAttributeGrandchildStub', EloquentTestThirdObserverStub::class.'@saved');
2119+
$events->shouldReceive('forget');
2120+
EloquentModelWithObserveAttributeGrandchildStub::flushEventListeners();
2121+
}
2122+
21092123
public function testThrowExceptionOnAttachingNotExistsModelObserverWithString()
21102124
{
21112125
$this->expectException(InvalidArgumentException::class);
@@ -3206,6 +3220,19 @@ public function saved()
32063220
}
32073221
}
32083222

3223+
class EloquentTestThirdObserverStub
3224+
{
3225+
public function creating()
3226+
{
3227+
//
3228+
}
3229+
3230+
public function saved()
3231+
{
3232+
//
3233+
}
3234+
}
3235+
32093236
class EloquentModelStub extends Model
32103237
{
32113238
public $connection;
@@ -3699,6 +3726,24 @@ class EloquentModelWithObserveAttributeUsingArrayStub extends EloquentModelStub
36993726
//
37003727
}
37013728

3729+
#[ObservedBy([EloquentTestObserverStub::class])]
3730+
class EloquentModelWithObserveAttributeGrandparentStub extends EloquentModelStub
3731+
{
3732+
//
3733+
}
3734+
3735+
#[ObservedBy([EloquentTestAnotherObserverStub::class])]
3736+
class EloquentModelWithObserveAttributeParentStub extends EloquentModelWithObserveAttributeGrandparentStub
3737+
{
3738+
//
3739+
}
3740+
3741+
#[ObservedBy([EloquentTestThirdObserverStub::class])]
3742+
class EloquentModelWithObserveAttributeGrandchildStub extends EloquentModelWithObserveAttributeParentStub
3743+
{
3744+
//
3745+
}
3746+
37023747
class EloquentModelSavingEventStub
37033748
{
37043749
//

0 commit comments

Comments
 (0)