Skip to content
Advertisement

Checkbox HTML array syntax doesn’t work in CakePHP 4

I have an application in CakePHP 4 where I’m doing the equivalent of what’s described in Make array from checkbox form

The markup I have is simple:

<input type="checkbox" name="services[]" value="Service 1" id="service1">
<input type="checkbox" name="services[]" value="Service 2" id="service2">
<input type="checkbox" name="services[]" value="Service 3" id="service3">

So somebody could for example check “Service 1” and “Service 3” and omit “Service 2”, e.g.

enter image description here

I’ve used the Form Helper in CakePHP to generate the HTML above. The code looks like this and is in my template file for that page:

<?= $this->Form->checkbox('services[]', ['value' => 'Service 1', 'id' => 'service1', 'hiddenField' => false]); ?>
<?= $this->Form->checkbox('services[]', ['value' => 'Service 2', 'id' => 'service2', 'hiddenField' => false]); ?>
<?= $this->Form->checkbox('services[]', ['value' => 'Service 3', 'id' => 'service3', 'hiddenField' => false]); ?>

When I submit the form and debug the output:

// in my Controller
if ($this->request->is('post')) {
    debug($this->request->getData());
}

I get:

'services' => [
    (int) 0 => 'Service 1',
    (int) 1 => 'Service 3',
],

This is fine, because it has the selected services which is all I need in terms of data submitted from the user on this part of the form.

But when the form is rendered following submit it errors with:

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

None of the checkboxes are checked (whereas the remainder of fields on the form are populated with the request data, albeit they are all text inputs as opposed to checkboxes). It looks like this:

enter image description here

Why does this happen? The markup which is being generated uses the array syntax for checkbox names (e.g. services[]) which from what I can see is perfectly valid HTML and also something which was used on the linked post without anyone saying it’s a problem.

Is this a CakePHP specific problem (e.g. wrong syntax used somewhere in the Form Helper) or a general issue with the way the HTML or PHP is being interpreted?

Advertisement

Answer

Your field name is the same as the data name, eg services, and thus the form helper will pick up an array for the current value of each individual control, and that will fail, as the “should be checked” logic needs to compare two flat values.

If you want to create individual checkboxes like this, then you either need to take care of passing the possible POST data for the individual controls too, which is what mark’s example does, or you need to test the data manually and mark the boxes checked accordingly, here’s one example:

$values = (array)$this->Form->getSourceValue('services');

echo $this->Form->checkbox('services[]', [
    'value' => 'first',
    'checked' => in_array('first', $values),
    // ...
]);
echo $this->Form->checkbox('services[]', [
    'value' => 'second',
    'checked' => in_array('second', $values),
    'hiddenField' => false,
    // ...
]);
echo $this->Form->checkbox('services[]', [
    'value' => 'third',
    'checked' => in_array('third', $values),
    'hiddenField' => false,
    // ...
]);

That being said, for your specific case you should be able to simply use a multi-checkbox control, which will handle looking up data and marking the boxes checked automatically:

echo $this->Form->select(
    'services',
    $options,
    ['multiple' => 'checkbox', /* ... */]
);

If you want to use names as the option values, $options would need to be an array like:

[
    'Service 1' => 'Service 1',
    'Service 2' => 'Service 2',
    // ...
]

as the array index is used for the checkbox value, and the array value is used for the checkbox label.

See also

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement