0
votes

I'm currently building a form where Permissions are assigned to Roles through a Belongs-To-Many relationship. This is currently on my Add Role view. I managed to get multiple checkboxes and the association working by using:

echo $this->Form->input('Roles.permissions._ids', [
    'label' => false,
    'type' => 'select',
    'multiple' => 'checkbox',
    'options' => $permissions
]);

That worked, but the list of Permissions is growing and needs some sort of organization. So now I have used map/reduce to group these permissions by a Category field, and that works to pass into the view. N

My problem exists when I try to manually loop through each Permission result and assign the entity ID and label to different checkbox inputs throughout the View, but in the same array.

Here is the closest I can get it to actually putting the values in the correct format for the _ids array to save the belongsToMany association:

echo $this->Form->input('Roles.permissions._ids[]', [
    'id' => 'roles-permissions-ids-' . $permission->PermissionId,
    'type' => 'checkbox',
    'label' => $permission->DisplayName,
    'value' => $permission->PermissionId,
    'hiddenField' => false
]);

This allows the selections to end up in the correct array and make it into the merged entity, but it throws the following warning:

Notice (8): Array to string conversion [CORE\src\View\Widget\CheckboxWidget.php, line 80]

The data entered in the form does not make it back into the form inputs, but appears to be correct everywhere else. I've tried manually adding the hidden input, tweaking the input IDs, and just about anything else. This is the best way I could get the data to post right.

After looking at the CakePHP source code (on version 3.1.11) at the CheckboxWidget, I noticed the isChecked function returns return (string)$data['val'] === (string)$data['value']; but somehow it is getting the entire array.

I modified just before the return statement and it technically works, but obviously isn't the right, long-term solution:

if (is_array($data['val'])) {
    // value was right, so just copy it over to val
    $data['val'] = $data['value'];
}

If anyone knows if I'm doing something wrong or if this is a bug in the framework, it would help me out a lot.

1
I reckon the main issue is your form name is incorrect. The name for the form field should be (in the case of BelongsToMany), be <property_name>._ids, so try doing permissions._ids. Your first form input options array is correct, except for the field name. - Dakota
I tried every variation like that but I can't get FormHelper to put the data back into the inputs. I can get it to save correctly, but if there is an error all the options are lost when rendering the view. I made a PasteBin of a simplified version of the code I'm using at pastebin.com/WUPX1QsH - Kyle Weishaupt
Updated pastebin that is posting correctly, but won't populate the form from the data: pastebin.com/SFYWLmeH - Kyle Weishaupt
I took your pastebin, and updated it: gist.github.com/dakota/b38a20e2c319f45445e4 You need to change the field name to be permissions._ids, and remove the 'name' attribute. - Dakota

1 Answers

1
votes

Your input method call needs to look like

echo $this->Form->input('permissions._ids', [
    'label' => false,
    'type' => 'select',
    'multiple' => 'checkbox',
    'options' => $permissions,
    'hiddenField' => false
]);

The Roles need to be removed.