Limit for a relation

I would like to set a limit for a relation, so my $belongsToMany relation can have 4 selected entries at max.

I thought there was something like this:

    public $belongsToMany = [
        'myRelation' => [
            My::class,
            'table' => '...',
            'limit' => 4
        ]
    ];

but it doesnt work and I cant find it in the docu, too.

So I made this workaround within the model:

    public function beforeSave()
    {
        if ($this->myRelation->count() > 4) {
            throw new ValidationException([
                'myRelation' => 'My Error MEssage...'
            ]);
        }
    }

But now I wonder: Am I remembering this wrong and the “limit => 4” never worked or did I miss something?

Hi @LordRazen

You should be able to use a validation rule to enforce this. Specifically the between or size rules should be used. Give it a try!

1 Like

Hm, have to edit my last post, cause this solution did not work as I stated in my first post:

    public $rules = [
        'exampleCreations' => 'between:0,6',
    ];

    public $belongsToMany = [
        'exampleCreations' => [
            Creation::class,
            'table' => 'myplugin_rel_tags_examples',
            'key' => 'tag_id',
            'otherKey' => 'creation_id',
        ]
    ];

(Rules array on the model which have this relation).

As soon as I select one example, the following message appears:
“The example creations field must be between 0 and 6 characters.”

So I wonder why it tells about characters here, the validation rule seem to apply in a strange way.

The second thing: The message should not appear if there’s just one model.

And the third thing: Even if the saving process on the Tag model throws this message, the new relation is already saved. So directly after I selected the entries from the form, configured within the config_relation, the new relation is created.

So… still not sure if I did something wrong or if this is still the wrong spot.

Thanks for your help already. ^^

Hmm, this looks a bug introduced in v3.3. Update october/rain to v3.3.10 and try it again.

1 Like

Thx for having a detailed look.

Just tested it again. I dont see any changes. What’s the expected outcome?

Here is the fix: Fixes countable validation (between, size, etc) · octobercms/library@6e16389 · GitHub

Here is a test confirming it works: Testing validation of relation size · octobercms/test-plugin@ff6a9be · GitHub

1 Like

Ah I think I found our missunderstanding:

I can confirm the rule works if there’s no relation manager configured within config_relation.

I removed my config for the relation manager within the config_relation file and the applied rules worked. Since the relations are created on save of the model this seems reasonable.

If I applied the config_relation again and used the relation manager, the rule still worked on the save of the model and I got the expected error message if two many examples were attached.

But since the relation was created after clicking “Add Selected” within the relation manager modal, the example was already saved.

Do the rules have to be applied differently if a relation manager is used?

This likely occurs because the relation manager uses deferred binding. We will fix it in v3.4 since it involves a bit of internal refactoring.

1 Like

Temporary workaround:

public function beforeValidate()
{
    if ($this->exampleCreations()->withDeferred($this->sessionKey)->count() > 6) {
        throw new ValidationException(['exampleCreations' => 'Too many']);
    }
}
1 Like

Ah ok so there is indeed an issue. I really worried that I did something wrong and now get on your nerves with a bug :smiley:

Thanks for having a second look, the workaround and fixing it ^^

Since 3.4 is out (I run on 3.4.7) I had another look into this but didnt see any changes. Is this really fixed with the 3.4 or is the issue still open? I’m ready to test if there’s something to test :wink:

It should be fixed, yes. Take a look at the Test plugin:

If you can reproduce a problem here, we can fix it quickly and easily.

Ok I worked with the Posts and Tags within the test plugin.

  1. Added a four tags for testing
  2. Added this validation rule to Post.php
    public $rules = [
        'tags' => 'between:0,2',
        'name' => 'required',
    ];
  1. Test 1:
    Added two tags to a post and saved => all good
    Added three tags to a post and saved => validation message appears
    Checked the database: Only the two relations were created in the table october_test_posts_tags

  2. Now I created a relation config:
    Changes within post > fields.yaml

        tags:
            label: Tags by Relation
            commentAbove: Enter some tags here first, select them below
            type: relation
            mode: relation
            useController: true
            nameFrom: name
            tab: Tags

Changes within posts > config_relation.yaml


tags:
    label: Tags
    view:
        form: $/october/test/models/tag/fields.yaml
        list: $/october/test/models/tag/columns.yaml
        toolbarButtons: link|unlink
    manage:
        showSearch: true
        recordsPerPage: 8

Now the tag selection is not a taglist, it’s the relation widget where you can select.

  1. Added a third tag to the opened post:
    => Tag was added to the tag form AND to the database already

  2. Saved the post with three tags
    => an error message appears, but the tag is already added on the database level
    => the error should probably appear earlier, when the tag is submitted.

1 Like