0

I have the following code in my Drupal’s template.php file. What it does is to embed every element of my site's contact form (created with the Webform module) in a li element (the form itself is already embedded in a ul element).

function MYTHEME_form_alter(&$form, &$form_state, $form_id) {

  if ($form_id == 'webform_client_form_MYFORMID') {
    foreach($form['submitted'] as &$field) {
      $field['#prefix'] = '<li>';
      $field['#suffix'] = '</li>';
    }
  }

This works, but I get 'Warning: Cannot use a scalar value as an array in MYTHEME_form_alter()' when accessing a page that contains such a form. The warning shows twice, once for each of the two lines where I add the prefix and suffix, respectively.

I have searched far and wide, but I do not know what to do. To the best of my knowledge, this is how Drupal wants me to handle this. And like I said, it does work, but it would be nice to get rid of the warnings and do everything 100 % correct.

(I'm using Drupal 7 and PHP 5.6.24.)

Does anybody know a better / the correct way to do this? Thank you.

1
  • Just add condition to check is_array($field) before adding #prefix and #suffix
    – Jimmy Ko
    Commented Aug 12, 2016 at 10:23

3 Answers 3

1

Not everything in a render array is an element to be rendered. The field contains other data in the form of properties, and some of those values will be scalar types, which causes the errors you see.

To fix, use element_children:

foreach (element_children($form['submitted']) as $key) {
  $form['submitted'][$key]['#prefix'] = '<li>';
  $form['submitted'][$key]['#suffix'] = '</li>';
}
1
  • This works, too! Thank you so much for the explanation; now everything finally makes sense, and I can see why both your and Jimmy Ko’s solution work. I've switched to marking your solution as the answer because it seems much cleaner. Commented Aug 12, 2016 at 10:57
0

if you change it to

 foreach($form['submitted'] as $key => $field) {
  $form['submitted'][$key]['#prefix'] = '<li>';
  $form['submitted'][$key]['#suffix'] = '</li>';
}

i think that will solve your problem

1
  • There is no difference from the code. He is using &$field which means passing the value of $form['submitted'][$key] as reference.
    – Jimmy Ko
    Commented Aug 12, 2016 at 10:36
0

Warning: Cannot use a scalar value as an array in MYTHEME_form_alter()

It is a common PHP error which means you are treating a scalar value (eg: int, string) as an array.

You can fix it by checking if it is an array before using it.

function MYTHEME_form_alter(&$form, &$form_state, $form_id) {

  if ($form_id == 'webform_client_form_MYFORMID') {
    foreach($form['submitted'] as &$field) {
      if (is_array($field)) {
        $field['#prefix'] = '<li>';
        $field['#suffix'] = '</li>';
      }
    }
  }

As mentioned by @Clive

Since you are adding #prefix and #suffix, you are obviously trying to change for the render element. So it would be better to limit the change occurred on render element only.

element_children is the API provided by Drupal for that purpose.

function MYTHEME_form_alter(&$form, &$form_state, $form_id) {

  if ($form_id == 'webform_client_form_MYFORMID') {
    foreach($element_children($form['submitted']) as $key) {
      $field = &$form['submitted'][$key];
      $field['#prefix'] = '<li>';
      $field['#suffix'] = '</li>';
    }
  }
7
  • This seems to be the right answer. I was worried that adding the if statement might mean that the code that adds the prefix and suffix will simply get ignored altogether, but it works, and the warning messages are gone. I don’t quite understand why – did the foreach access something that wasn't an array that I am not aware of? – but I'm happy it works. Thank you so much! :) Commented Aug 12, 2016 at 10:53
  • 1
    This is a hacky workaround, the proper way to handle it is to use element_children to extract only keys of sub-elements in the render array, ignoring properties with scalar values. Doing it this way you can still get the same, even bigger, problems. All you'd need is for one of the properties to be an array and this could cause any number of unwanted side-effects
    – Clive
    Commented Aug 12, 2016 at 10:56
  • @SimilarToACoolPerson did the foreach access something that wasn't an array that I am not aware of? You can simply check it by adding dpm($field) in the else case. :)
    – Jimmy Ko
    Commented Aug 12, 2016 at 10:57
  • @Clive I agree, but it is good to know the what the message means as well.
    – Jimmy Ko
    Commented Aug 12, 2016 at 10:58
  • Thanks to both of you, Jimmy Ko and Clive. I’ve marked Clive’s solution as the answer now because it seems ‘cleaner’. And now I also understand what the issue was in the first place. I’m very grateful to both of you, and so happy it works! :) Commented Aug 12, 2016 at 11:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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