Skip to content

Commit 8333880

Browse files
authored
PHPORM-175: Use foreign key name for MorphTo relationships (#3011)
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. * Allow multiple classes in ticket tests
1 parent d82ab46 commit 8333880

File tree

4 files changed

+81
-2
lines changed

4 files changed

+81
-2
lines changed

phpcs.xml.dist

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,8 @@
4949
<exclude-pattern>docs/**/*.php</exclude-pattern>
5050
</exclude>
5151
</rule>
52+
53+
<rule ref="PSR1.Classes.ClassDeclaration.MultipleClasses">
54+
<exclude-pattern>tests/Ticket/*.php</exclude-pattern>
55+
</rule>
5256
</ruleset>

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

0 commit comments

Comments
 (0)