Skip to content

Commit 647abf7

Browse files
committed
PHPORM-175: Use foreign key name for MorphTo relationships
Incorporates the proposed solution in #2783 to not default $ownerKey to the current model's key name when constructing a MorphTo in HybridRelations::morphTo(). That change alone caused RelationsTest::testMorph() to fail, since MorphTo::addConstraints() would attempt to use a null ownerKey value. This required an additional change to fall back to the foreign key name when building the constraint.
1 parent e79b0ae commit 647abf7

File tree

3 files changed

+76
-2
lines changed

3 files changed

+76
-2
lines changed

src/Eloquent/HybridRelations.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ public function morphTo($name = null, $type = null, $id = null, $ownerKey = null
226226
$this->newQuery(),
227227
$this,
228228
$id,
229-
$ownerKey ?: $this->getKeyName(),
229+
$ownerKey,
230230
$type,
231231
$name,
232232
);

src/Relations/MorphTo.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public function addConstraints()
1717
// or has many relationships, we need to actually query on the primary key
1818
// of the related models matching on the foreign key that's on a parent.
1919
$this->query->where(
20-
$this->ownerKey,
20+
$this->ownerKey ?? $this->getForeignKeyName(),
2121
'=',
2222
$this->getForeignKeyFrom($this->parent),
2323
);

tests/Ticket/GH2783Test.php

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace MongoDB\Laravel\Tests\Ticket;
6+
7+
use MongoDB\Laravel\Eloquent\Model;
8+
use MongoDB\Laravel\Relations\MorphTo;
9+
use Illuminate\Database\Eloquent\Relations\MorphOne;
10+
11+
/**
12+
* @see https://github.com/mongodb/laravel-mongodb/issues/2783
13+
* @see https://jira.mongodb.org/browse/PHPORM-175
14+
*/
15+
class GH2783Test extends TestCase
16+
{
17+
public function testMorphToInfersCustomOwnerKey()
18+
{
19+
GH2783Image::truncate();
20+
GH2783Post::truncate();
21+
GH2783User::truncate();
22+
23+
$post = GH2783Post::create(['text' => 'Lorem ipsum']);
24+
$user = GH2783User::create(['username' => 'jsmith']);
25+
26+
$imageWithPost = GH2783Image::create(['uri' => 'http://example.com/post.png']);
27+
$imageWithPost->imageable()->associate($post)->save();
28+
29+
$imageWithUser = GH2783Image::create(['uri' => 'http://example.com/user.png']);
30+
$imageWithUser->imageable()->associate($user)->save();
31+
32+
$queriedImageWithPost = GH2783Image::with('imageable')->find($imageWithPost->getKey());
33+
$this->assertInstanceOf(GH2783Post::class, $queriedImageWithPost->imageable);
34+
$this->assertEquals($post->_id, $queriedImageWithPost->imageable->getKey());
35+
36+
$queriedImageWithUser = GH2783Image::with('imageable')->find($imageWithUser->getKey());
37+
$this->assertInstanceOf(GH2783User::class, $queriedImageWithUser->imageable);
38+
$this->assertEquals($user->username, $queriedImageWithUser->imageable->getKey());
39+
}
40+
}
41+
42+
class GH2783Image extends Model
43+
{
44+
protected $connection = 'mongodb';
45+
protected $fillable = ['uri'];
46+
47+
public function imageable(): MorphTo
48+
{
49+
return $this->morphTo(__FUNCTION__, 'imageable_type', 'imageable_id');
50+
}
51+
}
52+
53+
class GH2783Post extends Model
54+
{
55+
protected $connection = 'mongodb';
56+
protected $fillable = ['text'];
57+
58+
public function image(): MorphOne
59+
{
60+
return $this->morphOne(GH2783Image::class, 'imageable');
61+
}
62+
}
63+
64+
class GH2783User extends Model
65+
{
66+
protected $connection = 'mongodb';
67+
protected $fillable = ['username'];
68+
protected $primaryKey = 'username';
69+
70+
public function image(): MorphOne
71+
{
72+
return $this->morphOne(GH2783Image::class, 'imageable');
73+
}
74+
}

0 commit comments

Comments
 (0)