akeeba / fof

Rapid Application Development framework for Joomla!™ 3 and 4
0 stars 0 forks source link

N-N relation isn't saved #654

Closed vphat28 closed 7 years ago

vphat28 commented 7 years ago

Hi I'm using FOF 3

I would like to do a N-N relation to just one model, mean relate to itself. My model named Champions and this is the constructor

public function __construct(Container $container, array $config = array())
    {
        $config['idFieldName'] = 'id';
        parent::__construct($container, $config);
        $this->belongsToMany(
            'strongers',
            'Champions',
            'id',
            'id',
            '#__lol_champions_strongers',
            'stronger_champion_id',
            'weaker_champion_id'
        );
    }

As you can see the champions can be weaker than some champions and can be stronger than some champions. So i created a glue table #__lol_champions_strongers.

Then i created a form.form.xml

<form validate="true">
  <fieldset name="scaffolding" label="COM_LOL_CHAMPIONS_GROUP_BASIC">
    <field name="title" type="Text" label="COM_LOL_CHAMPIONS_TITLE_LABEL" description="COM_LOL_CHAMPIONS_TITLE_DESC"/>
    <field name="strongers" multiple="true" model="Champions" type="relation" label="COM_LOL_CHAMPIONS_STRONGER_THAN_LABEL" description="COM_LOL_CHAMPIONS_STRONGER_THAN_DESC"/>
    <field name="slug" type="Text" label="COM_LOL_CHAMPIONS_SLUG_LABEL" description="COM_LOL_CHAMPIONS_SLUG_DESC"/>
    <field name="image" type="Media" label="COM_LOL_CHAMPIONS_IMAGE_LABEL" description="COM_LOL_CHAMPIONS_IMAGE_DESC"/>
    <field name="description" type="Editor" label="COM_LOL_CHAMPIONS_DESCRIPTION_LABEL" description="COM_LOL_CHAMPIONS_DESCRIPTION_DESC"/>
    <field name="enabled" type="Published" label="COM_LOL_CHAMPIONS_ENABLED_LABEL" description="COM_LOL_CHAMPIONS_ENABLED_DESC"/>
  </fieldset>
</form>

The form can display the list of champions as a multi select but when I save the record the relation field doesn't save.

Can you please give some advises? Hope you can help

nikosdion commented 7 years ago

This will not work automatically. Many to many relations are not managed by FOF on save and delete. You need to override the onAfterSave and onAfterDelete methods of your model to handle them. These relationships don't touch any fields in the local model, so FOF doesn't know if they have been changed.

That said, I'm not sure the model you're using makes a lot of sense. Stronger/weaker comes down to checking the current record's strength to the other records' strength. If you use an integer field and add an index in the database you can easily find the stronger and weaker champions in relation to your champion with a cheap, fast query. Bonus points for not having to update a massive glue table every time someone's strength changes.

If you're arbitrarily choosing weaker / stronger champions... you are doing something weird. It makes no sense having a situation where A is stronger than B who is weaker than C who is stronger than A, the inference being that C is weaker than B who's weaker than A, ergo C is weaker -not stronger- than A. Yet your model allows it. That sounds like a bad model to me.

vphat28 commented 7 years ago

thank you for your help that make sense. I will try to override afterSave.

yeah it may sounds weird but it is like a "rock -scissor - paper" game. A can be stronger than B and B can be stronger than C but C is stronger than A