0

I am building something which uses a form element with '#type' => 'checkboxes'.

I want this to be reusable, so it should accept anything as option values that works as a PHP array key (integers and non-integer strings).

$form['checkboxes'] = [
  '#type' => 'checkboxes',
  '#options' => [
    0 => 'zero',
    '' => 'empty string',
    ' ' => 'space',
    'other' => 'Other',
  ],
];

However there seems to be a problem with values 0 (zero) and '' (empty string).

Even when the checkboxes for '' or 0 are checked, the values are gone in the $element['#value'] array, e.g. when checking with a custom '#element_validate' callback.

$element['#value'] === [
  # '' and 0 are gone, even if they were checked.
  ' ' => ' ',
  'other' => 'other',
];

Interestingly, the $_POST still contains the values, with an interesting twist, where space and empty string behave like array insertion via []. I suppose this is due to the way POST data is sent.

$_POST['checkboxes'] === [
  0 => '0',
  1 => '',
  2 => ' ',
  'other' => 'other',
];

I can imagine why all of this happens, but is there a workaround or solution?

EDIT: The previous version of the code snippet was misleading, sorry. I had mixed up $_POST and the original '#options' array.

  • Why would you put an empty string in the first place? Try putting zero without quotes 0 => 0, – No Sssweat Feb 22 at 1:31
  • Sorry, my code snippet was misleading. I fixed it. – donquixote Feb 22 at 9:22
  • "Why would you put an empty string in the first place?" - I want this component to be usable by others, and I assume that empty string would be a valid option value. – donquixote Feb 22 at 9:24
  • 1
    Ah, after Drupal gets its dirty mitts on it you mean. Yeah that makes sense. Have a look at api.drupal.org/api/drupal/includes%21form.inc/function/… and api.drupal.org/api/drupal/includes%21form.inc/function/…, I don't have time to look at the moment but the comments specifically talk about '0' and '' as return values for checkboxes, so you might be able to get a start point to debug in there – Clive Feb 22 at 11:37
  • 1
    You could always 'preprocess' your options by concatenating a prefix (e.g., '_') to it when creating the form elements and remove that prefix in the submit handler. Thus, a key like 0 would become '_0', '' becomes '_', ' ' becomes '_ ', and so on. – Mario Steinitz Feb 25 at 12:51
0

I managed to prevent this problem by adding an '#element_validate' handler on the checkboxes element.

The code below is a simplified version of what I did, up to you to fine-tune.

$element['#element_validate'][] = '_MYMODULE_checkboxes_validate';

function _MYMODULE_checkboxes_validate(array &$element, array &$form_state) {

  // The form value already has the format $[$id] = $id, mostly.
  // However, if trim($id) === '', the array key will be an integer increment.
  $value = $element['#value'];

  // Make sure it has the expected format.
  if (!is_array($value) || [] === $value) {
    $ids = [];
  }
  else {
    // Get rid of integer keys for empty-ish string ids.
    $ids = array_combine($value, $value);
  }

  // Remove dangling * => 0 entries.
  form_set_value($element, $ids, $form_state);
}

Note: If you have the value_is module installed, empty-ish values will always be unset, thanks to _value_is_disabled_options_value_callback().

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.