XF 2.0 Create relation entity if not exists

CMTV

Well-known member
Hi!

I want for Trophy entity to have default relation with TrophyData entity.

PHP:
$structure->relations = array_merge($structure->relations, [
    'UP' => [
        'entity' => 'UserProgression:TrophyData',
        'type' => self::TO_ONE,
        'conditions' => 'trophy_id',
        'primary' => true
    ]
]);
$structure->defaultWith = array_merge($structure->defaultWith, ['UP']);

But somethimes there is no row in xf_UP_trophy_data table for needed TrophyData entity and relation returns null.

How to create a default row every time the relation returns null?

I tired this but it is not working:
PHP:
$structure->getters = array_merge($structure->getters, [
    'UP' => ['getter' => 'getUP']
]);

public function getUP()
{
    if(!$this->UP)
    {
        $trophyData = $this->em->create('UserProgression:TrophyData');
        $trophyData->setTrusted('trophy_id', $this->trophy_id);
        $trophyData->save();
    }

    return $this->UP;
}

But I get an error:
error.png
 

CMTV

Well-known member
This code is working fine:
PHP:
public function getUP()
{
    if(!$this->getRelation('UP'))
    {
        $trophyData = $this->em()->create('UserProgression:TrophyData');
        $trophyData->setTrusted('trophy_id', $this->trophy_id);
        $trophyData->save();
    }

    return $this->getRelationFinder('UP')->fetchOne();
}

But I can't get rid of the feeling that it is a dirty workaround... Maybe there is a better way to create relation entity?
 

Xon

Well-known member
Hi!

I want for Trophy entity to have default relation with TrophyData entity.

PHP:
$structure->relations = array_merge($structure->relations, [
    'UP' => [
        'entity' => 'UserProgression:TrophyData',
        'type' => self::TO_ONE,
        'conditions' => 'trophy_id',
        'primary' => true
    ]
]);
$structure->defaultWith = array_merge($structure->defaultWith, ['UP']);
Why not do this:

PHP:
$structure->relations['UP'] = [
        'entity' => 'UserProgression:TrophyData',
        'type' => self::TO_ONE,
        'conditions' => 'trophy_id',
        'primary' => true
    ];
$structure->defaultWith[] = 'UP';
You avoid multiple array merges and just extend the current one without a pile of clutter.

But somethimes there is no row in xf_UP_trophy_data table for needed TrophyData entity and relation returns null.

How to create a default row every time the relation returns null?

I tired this but it is not working:
PHP:
$structure->getters = array_merge($structure->getters, [
    'UP' => ['getter' => 'getUP']
]);

public function getUP()
{
    if(!$this->UP)
    {
        $trophyData = $this->em->create('UserProgression:TrophyData');
        $trophyData->setTrusted('trophy_id', $this->trophy_id);
        $trophyData->save();
    }

    return $this->UP;
}

But I get an error:
View attachment 168747
Use;
PHP:
public function getUP()
{
    $trophyData = $this->getRelationOrDefault('UP');
    if($trophyData->isInsert())
    {
        $trophyData->set('trophy_id', $this->trophy_id);
        $trophyData->save();
    }

    return   $trophyData ;
}

Look at hydrateRelation rather than re-fetching the entity you just saved.


Fillip
Nah, use an easier solution; getRelationOrDefault
 

DragonByte Tech

Well-known member
Nah, use an easier solution; getRelationOrDefault
Just to clarify for anyone else looking, getRelationOrDefault only works for TO_ONE relations. hydrateRelation may still be useful if you're attempting to check TO_MANY relations.


Fillip
 
  • Like
Reactions: Xon

giffenk

Member
I have a somewhat related issue so I thought I would tack onto this existing thread.

I am able to create a related entity when my base entity is added, but then the related entity does not get found on an edit and an additional related entity gets created on save after edit. I am failing to locate the existing related entity at edit time.

Background:
I have created an entity that will track additional information for a forum. This information is to be displayed/captured via the normal add/edit forum process using the same form by adding more fields at the bottom of the form.

What Works:
- fields added to the form
- data entered into the fields is captured
- data is written to a new record of the related entity

What doesn't work properly:
- on edit of an existing forum, the data values from the related entity are not displayed
- on save of an existing forum, the data values on the form are saved into an additional related entity
So basically I am failing to obtain the existing related entity which results in a fresh one getting created every edit.

My Design involves:
- a new entity Pforum (which has a TO_ONE relationship to XF:Forum, but this is not really needed yet)
- a template_modification to add additional fields to the forum_edit template
- a code_event_listener on entity_structure that adds a Pforum TO_ONE relationship to the XF:Forum entity
- a saveDataType function in a new Forum Controller that extracts the new form fields and loads them into the Pforum entity obtained via a getRelationOrDefault on the forum entity, setting the cascade save to TRUE
- a nodeAddEdit function in a new Forum Controller that attempts to obtain the related Pforum entity via a getReleationOrDefault call on the forum entity

It is this last item that does not appear to be working correctly...
 

giffenk

Member
I have a somewhat related issue so I thought I would tack onto this existing thread.

I am able to create a related entity when my base entity is added, but then the related entity does not get found on an edit and an additional related entity gets created on save after edit. I am failing to locate the existing related entity at edit time.

Background:
I have created an entity that will track additional information for a forum. This information is to be displayed/captured via the normal add/edit forum process using the same form by adding more fields at the bottom of the form.

What Works:
- fields added to the form
- data entered into the fields is captured
- data is written to a new record of the related entity

What doesn't work properly:
- on edit of an existing forum, the data values from the related entity are not displayed
- on save of an existing forum, the data values on the form are saved into an additional related entity
So basically I am failing to obtain the existing related entity which results in a fresh one getting created every edit.

My Design involves:
- a new entity Pforum (which has a TO_ONE relationship to XF:Forum, but this is not really needed yet)
- a template_modification to add additional fields to the forum_edit template
- a code_event_listener on entity_structure that adds a Pforum TO_ONE relationship to the XF:Forum entity
- a saveDataType function in a new Forum Controller that extracts the new form fields and loads them into the Pforum entity obtained via a getRelationOrDefault on the forum entity, setting the cascade save to TRUE
- a nodeAddEdit function in a new Forum Controller that attempts to obtain the related Pforum entity via a getReleationOrDefault call on the forum entity

It is this last item that does not appear to be working correctly...
Maybe I found my problem? (Scanning my code to create the above description was a good exercise).

I detected that my Pforum to XF:Forum relationship has 'primary' => true but the related field node_id is not the primary key for my new entity. During my search on this forum for help on this topic I vaguely remember a post indicating that this is bad and may cause problems finding the related entity. This could explain the behaviour I am seeing.

I will test later today...

If anyone else has other ideas, please feel free to add them.
 

giffenk

Member
Maybe I found my problem? (Scanning my code to create the above description was a good exercise).

I detected that my Pforum to XF:Forum relationship has 'primary' => true but the related field node_id is not the primary key for my new entity. During my search on this forum for help on this topic I vaguely remember a post indicating that this is bad and may cause problems finding the related entity. This could explain the behaviour I am seeing.

I will test later today...

If anyone else has other ideas, please feel free to add them.
I can confirm that the 'primary' => true was the problem.

Here is a link to the post that provided the solution: https://xenforo.com/community/threads/do-i-have-to-create-relations-on-the-key.136307/post-1186671
 
Top