Sunday, February 27, 2022

[FIXED] Associate/Dissociate related entity on (new) entity

Issue

Is there a way to associate/dissociate one entity to another in CakePHP4.x? Similar to Laravel's? https://laravel.com/docs/8.x/eloquent-relationships#updating-belongs-to-relationships

For instance, if i create a new entity and assign a related entity like this:

    #in a controller
    $entity = $this->Entity->newEmptyEntity();
    $related = $this->Related->get(1);
    $entity->set('related', $related);

This will bind $related to $entity->related but it wont set $entity->relation_id = 1. I suspect that $this->Entity->save($entity) will set $entity->relation_id, but i don't want to save it.

One way to fix it would be:

    $entity->set(['related_id' => $related->id ,'related', $related]);

That doesn't look very elegant?


Solution

There is no equivalent shorthand method for that in CakePHP.

While belongsToMany and hasMany associations have the link() and unlink() methods to associate and save entities, there is nothing similar (yet) for belongsTo or hasOne.

So for now you'd have to manually set the entity on the correct property, and then save the source entity, for example:

$entity = $this->Table->newEmptyEntity(); // or $this->Table->get(1); to update
$entity->set('related', $this->Related->get(1));
$this->Table->save($entity);

After saving, the source entity will hold the foreign key(s) of the newly associated record. If you do not actually want to save it (for whatever reason), then you have no choice but to manually set the foreign key(s) on the entity, or to implement your own helper method that is aware of the association configuration, so that it would know which properties to populate.

Just to get you started with something, in a custom \Cake\ORM\Association\BelongsTo based association class this could look something like this:

public function associate(EntityInterface $source, EntityInterface $target)
{
    $source->set($this->getProperty(), $target);

    $foreignKeys = (array)$this->getForeignKey();
    $bindingKeys = (array)$this->getBindingKey();
    foreach ($foreignKeys as $index => $foreignKey) {
        $source->set($foreignKey, $target->get($bindingKeys[$index]));
    }
}

and could then be used like:

$entity = $this->Table->newEmptyEntity();
$this->Table->Related->associate($entity, $this->Related->get(1));


Answered By - ndm

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.