Skip to content

Commit

Permalink
PHPORM-175: Use foreign key name for MorphTo relationships
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jmikola committed Jun 19, 2024
1 parent e79b0ae commit 647abf7
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/Eloquent/HybridRelations.php
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ public function morphTo($name = null, $type = null, $id = null, $ownerKey = null
$this->newQuery(),
$this,
$id,
$ownerKey ?: $this->getKeyName(),
$ownerKey,
$type,
$name,
);
Expand Down
2 changes: 1 addition & 1 deletion src/Relations/MorphTo.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public function addConstraints()
// or has many relationships, we need to actually query on the primary key
// of the related models matching on the foreign key that's on a parent.
$this->query->where(
$this->ownerKey,
$this->ownerKey ?? $this->getForeignKeyName(),
'=',
$this->getForeignKeyFrom($this->parent),
);
Expand Down
74 changes: 74 additions & 0 deletions tests/Ticket/GH2783Test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php

declare(strict_types=1);

namespace MongoDB\Laravel\Tests\Ticket;

use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Relations\MorphTo;
use Illuminate\Database\Eloquent\Relations\MorphOne;

/**
* @see https://github.com/mongodb/laravel-mongodb/issues/2783
* @see https://jira.mongodb.org/browse/PHPORM-175
*/
class GH2783Test extends TestCase
{
public function testMorphToInfersCustomOwnerKey()
{
GH2783Image::truncate();
GH2783Post::truncate();
GH2783User::truncate();

$post = GH2783Post::create(['text' => 'Lorem ipsum']);
$user = GH2783User::create(['username' => 'jsmith']);

$imageWithPost = GH2783Image::create(['uri' => 'http://example.com/post.png']);
$imageWithPost->imageable()->associate($post)->save();

$imageWithUser = GH2783Image::create(['uri' => 'http://example.com/user.png']);
$imageWithUser->imageable()->associate($user)->save();

$queriedImageWithPost = GH2783Image::with('imageable')->find($imageWithPost->getKey());
$this->assertInstanceOf(GH2783Post::class, $queriedImageWithPost->imageable);
$this->assertEquals($post->_id, $queriedImageWithPost->imageable->getKey());

$queriedImageWithUser = GH2783Image::with('imageable')->find($imageWithUser->getKey());
$this->assertInstanceOf(GH2783User::class, $queriedImageWithUser->imageable);
$this->assertEquals($user->username, $queriedImageWithUser->imageable->getKey());
}
}

class GH2783Image extends Model

Check failure on line 42 in tests/Ticket/GH2783Test.php

View workflow job for this annotation

GitHub Actions / phpcs

Each class must be in a file by itself
{
protected $connection = 'mongodb';
protected $fillable = ['uri'];

public function imageable(): MorphTo
{
return $this->morphTo(__FUNCTION__, 'imageable_type', 'imageable_id');
}
}

class GH2783Post extends Model

Check failure on line 53 in tests/Ticket/GH2783Test.php

View workflow job for this annotation

GitHub Actions / phpcs

Each class must be in a file by itself
{
protected $connection = 'mongodb';
protected $fillable = ['text'];

public function image(): MorphOne
{
return $this->morphOne(GH2783Image::class, 'imageable');
}
}

class GH2783User extends Model

Check failure on line 64 in tests/Ticket/GH2783Test.php

View workflow job for this annotation

GitHub Actions / phpcs

Each class must be in a file by itself
{
protected $connection = 'mongodb';
protected $fillable = ['username'];
protected $primaryKey = 'username';

public function image(): MorphOne
{
return $this->morphOne(GH2783Image::class, 'imageable');
}
}

0 comments on commit 647abf7

Please sign in to comment.