I have a form that is a system_settings_form. The form is very large and there are a lot of settings. I was wondering if there is a way to create an array (as there is in php) as follows using this form:

function module_admin_form(){
  //...A bunch of settings...
  $first_names = variable_get('first_name');
  foreach($array as $key){
    $form[$key]['first_name[]'] = array(
      '#type'=>'radios',
      '#title'=>t($key.' First Name'),
      '#options' => $options,
      '#default_value'=> $first_names[$key],
      '#description'=>t("Which is the first name for %s?.", array('%s'=>$key))
    );
  }
    //...A bunch of settings...

  return system_settings_form($form);
}

Basically, I want the first_name variable to be stored in the database as a an array. However, when you save the form, it only saves the last value that you created. I also tried to put a key in the first_name array, but it saved each value separate. I know that I could save this form myself, but I would prefer not to because there are so many settings on the form. Is there a way that I could just handle these values myself (the values inside the foreach loop) and let the settings form handle the rest? Or is there a way to get it to save this as an array?

Comments

pembeci’s picture

I didn't completely understand your code and what you want to achieve but you may try using php's serialize function. It basically converts your array (or any other value type) into a string. You can save that string in the database and then use its sister function unserialize to get back the array when you need it.

j_ten_man’s picture

That isn't exactly what I want. The problem is that a system settings form does all the saving for you. I would like to do the saving of just this section of code myself and not everything. I was wondering if there is a way for me to handle just a few pieces of a form in my own submit handler, and let the standard submit function for system settings form do the rest.

pembeci’s picture

I see. I guess then you can try these:

  • Do not use system settings form at all. At your settings page define your own form and duplicate the code at system_settings_form (drop the line involving $form['#base']) and system_settings_form_submit. Then you have the power to save your data however you want.
  • Have two forms at your page. One for submitting and saving your problematic data defined by your own functions and the other one, a ready made system settings form.
  • You can achieve what you described above by registring a validation callback (by the adding the #validate property to your form), saving your data at the validation function and then unsetting the related form elements to handle the rest by system_settings_form_submit. This is the most dirty solution and I don't recommend it if you are not 100% sure what you are doing.

I would go with the first option but it is your call.

j_ten_man’s picture

K - I knew I could do that, but I was seeing if there was another solution. Thanks a lot.

iLLin’s picture

This is crazy old but figured I would post what I did.

function mymodule_settings() {
  $form = array();
  $values = unserialize(variable_get('my_textfield_array', ''));
  $total = 5;
  for ($i=0; $i<$total; $i++) {
    $form['my_textfield_array_'. $i] = array(
      '#type' => 'textfield',
      '#title' => t('Field %i', array('%i' => $i),
      '#default_value' => isset($values['my_textfield_array_'. $i]) ? $values['my_textfield_array_'. $i] : '',
    );
  }
  return system_settings_form($form);
}

function mymodule_settings_validate($form, &$form_state) {
  $values = array();
  foreach ($form_state['values'] as $key => $value) {
    if (strstr($key, 'my_textfield_array')) {
      $values[$key] = $value;
      unset($form_state['values'][$key]);
    }
  }
  // Now lets add in a single value to be saved.
  $form_state['values']['my_textfield_array'] = serialize($values);
}

I changed this from what I actually did so this is untested. But I think the idea is there for anyone else that needs a solution like this.

blairski’s picture

A cleaner way to do this is to do it in a submit function rather than a validate function.

The trick is to make sure your custom submit function fires before system_settings_form_submit(). To do that, add it to your form with array_unshift() like so:

function mymodule_settings() {
....
  $form = system_settings_form($form);
  array_unshift($form['#submit'], 'mymodule_submit');
  return $form;
}

And then put the logic to serialize in the mymodule_submit(). I also simplified what you did to store the values before unseting the form_state key:

function mymodule_submit($form, &$form_state) {
  $field_values = $form_state['values'];
  unset($form_state['values']);
  $form_state['values']['my_textfield_array'] = serialize($field_values);

}
msupko’s picture

IMO the cleanest way to do this is using #tree. The nested values will appear in $form_state as an array, and system_settings_form() will automatically save the variable as an array for you.

For example...


function mymodule_settings() {
  $values = variable_get('my_array');
  $total = 5;

  $form['my_array'] = array(
    '#type' => 'fieldset',
    '#tree' => TRUE,
    '#title' => t('All this stuff is goin\' into an array!'),
  );

  for ($i=0; $i<$total; $i++) {
    $form['my_field_'. $i] = array(
      '#type' => 'textfield',
      '#title' => t('Field %i', array('%i' => $i)),
      '#default_value' => isset($values['my_field_'. $i]) ? $values['my_field_'. $i] : '',
    );
  }

  return system_settings_form($form);
}

Marko B’s picture

On right tracks but a bit wrong. as a Tree, fields needs to have parents as $form['my_array'] ['my_field_'. $i] = array(

  for ($i=0; $i<$total; $i++) {
    $form['my_array'] ['my_field_'. $i] = array(
      '#type' => 'textfield',
      '#title' => t('Field %i', array('%i' => $i)),
      '#default_value' => isset($values['my_field_'. $i]) ? $values['my_field_'. $i] : '',
    );
  }
norman.lol’s picture

#tree is the right answer.