Framework: [7.x] Bug: BelongsTo relation returns old relation when associate() is called with model ID

Created on 26 Nov 2019  路  5Comments  路  Source: laravel/framework

  • Laravel Version: 6.6
  • PHP Version: 7.3

Description:

This issue is almost the same as previously submitted #26401 (@joostbaptist), but reports incomplete bug fixes.

The argument can be checked with isDirty() when the relation corresponding to the synced key is loaded, but it will fail if the relation corresponding to the dirty key is loaded.

Steps To Reproduce:

$user = User::find(1);

$post = new Post();
$post->user()->associate(2);
$post->save();

$post->user()->associate($user); // dirty
$post->user()->associate(2); // clean

assert($user !== $post->user); // fails

Patch Proposal:

     /**
      * Associate the model instance to the given parent.
      *
      * @param  \Illuminate\Database\Eloquent\Model|int|string  $model
      * @return \Illuminate\Database\Eloquent\Model
      */
     public function associate($model)
     {
         $ownerKey = $model instanceof Model ? $model->getAttribute($this->ownerKey) : $model;

         $this->child->setAttribute($this->foreignKey, $ownerKey);

         if ($model instanceof Model) {
             $this->child->setRelation($this->relationName, $model);
-        } elseif ($this->child->isDirty($this->foreignKey)) {
+        } elseif (
+            $this->child->relationLoaded($this->relationName)
+            && optional($this->child->getRelationValue($this->relationName))->getKey() !== $ownerKey
+        ) {
             $this->child->unsetRelation($this->relationName);
         }

         return $this->child;
     }
bug

Most helpful comment

I think it would be easier to remove the key comparison and just always unset the relation when associate() is called with an ID.

All 5 comments

Thanks for reporting. Feel free to send in a PR with a test.

@driesvints

optional($this->child->getRelationValue($this->relationName))->getKey()

I'm pretty anxious whether the statement is really appropriate. How do you think?

(CC: @taylorotwell @joostbaptist @staudenmeir)

I think it would be easier to remove the key comparison and just always unset the relation when associate() is called with an ID.

@staudenmeir Good idea

@driesvints Should we target 7.x?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

SachinAgarwal1337 picture SachinAgarwal1337  路  3Comments

progmars picture progmars  路  3Comments

kerbylav picture kerbylav  路  3Comments

ghost picture ghost  路  3Comments

PhiloNL picture PhiloNL  路  3Comments