Skip to content

Commit ff59559

Browse files
authored
[6.x] Fix edge case causing a BadMethodCallExceptions to be thrown when using loadMissing() (#37871)
* Add breaking test * Fix instanceof check to use first non-null value in Eloquent Collection loadMissingRelation()
1 parent 09feffb commit ff59559

File tree

2 files changed

+76
-1
lines changed

2 files changed

+76
-1
lines changed

src/Illuminate/Database/Eloquent/Collection.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ protected function loadMissingRelation(self $models, array $path)
159159
return;
160160
}
161161

162-
$models = $models->pluck($name);
162+
$models = $models->pluck($name)->whereNotNull();
163163

164164
if ($models->first() instanceof BaseCollection) {
165165
$models = $models->collapse();

tests/Integration/Database/EloquentCollectionLoadMissingTest.php

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,21 @@ protected function setUp(): void
3737
$table->unsignedInteger('comment_id');
3838
});
3939

40+
Schema::create('post_relations', function (Blueprint $table) {
41+
$table->increments('id');
42+
$table->unsignedInteger('post_id');
43+
});
44+
45+
Schema::create('post_sub_relations', function (Blueprint $table) {
46+
$table->increments('id');
47+
$table->unsignedInteger('post_relation_id');
48+
});
49+
50+
Schema::create('post_sub_sub_relations', function (Blueprint $table) {
51+
$table->increments('id');
52+
$table->unsignedInteger('post_sub_relation_id');
53+
});
54+
4055
User::create();
4156

4257
Post::create(['user_id' => 1]);
@@ -46,6 +61,11 @@ protected function setUp(): void
4661
Comment::create(['parent_id' => 2, 'post_id' => 1]);
4762

4863
Revision::create(['comment_id' => 1]);
64+
65+
Post::create(['user_id' => 1]);
66+
PostRelation::create(['post_id' => 2]);
67+
PostSubRelation::create(['post_relation_id' => 1]);
68+
PostSubSubRelation::create(['post_sub_relation_id' => 1]);
4969
}
5070

5171
public function testLoadMissing()
@@ -89,6 +109,20 @@ public function testLoadMissingWithDuplicateRelationName()
89109
$this->assertTrue($posts[0]->comments[0]->relationLoaded('parent'));
90110
$this->assertTrue($posts[0]->comments[1]->parent->relationLoaded('parent'));
91111
}
112+
113+
public function testLoadMissingWithoutInitialLoad()
114+
{
115+
$user = User::first();
116+
$user->loadMissing('posts.postRelation.postSubRelations.postSubSubRelations');
117+
118+
$this->assertEquals(2, $user->posts->count());
119+
$this->assertNull($user->posts[0]->postRelation);
120+
$this->assertInstanceOf(PostRelation::class, $user->posts[1]->postRelation);
121+
$this->assertEquals(1, $user->posts[1]->postRelation->postSubRelations->count());
122+
$this->assertInstanceOf(PostSubRelation::class, $user->posts[1]->postRelation->postSubRelations[0]);
123+
$this->assertEquals(1, $user->posts[1]->postRelation->postSubRelations[0]->postSubSubRelations->count());
124+
$this->assertInstanceOf(PostSubSubRelation::class, $user->posts[1]->postRelation->postSubRelations[0]->postSubSubRelations[0]);
125+
}
92126
}
93127

94128
class Comment extends Model
@@ -123,6 +157,42 @@ public function user()
123157
{
124158
return $this->belongsTo(User::class);
125159
}
160+
161+
public function postRelation()
162+
{
163+
return $this->hasOne(PostRelation::class);
164+
}
165+
}
166+
167+
class PostRelation extends Model
168+
{
169+
public $timestamps = false;
170+
171+
protected $guarded = [];
172+
173+
public function postSubRelations()
174+
{
175+
return $this->hasMany(PostSubRelation::class);
176+
}
177+
}
178+
179+
class PostSubRelation extends Model
180+
{
181+
public $timestamps = false;
182+
183+
protected $guarded = [];
184+
185+
public function postSubSubRelations()
186+
{
187+
return $this->hasMany(PostSubSubRelation::class);
188+
}
189+
}
190+
191+
class PostSubSubRelation extends Model
192+
{
193+
public $timestamps = false;
194+
195+
protected $guarded = [];
126196
}
127197

128198
class Revision extends Model
@@ -135,4 +205,9 @@ class Revision extends Model
135205
class User extends Model
136206
{
137207
public $timestamps = false;
208+
209+
public function posts()
210+
{
211+
return $this->hasMany(Post::class);
212+
}
138213
}

0 commit comments

Comments
 (0)