Создание нескольких одинаковых форм на одной странице

Недавно возникла нужда написать функцию, создающую несколько одинаковых форм на одной странице. Формы небольшие, состоят из одного текстового поля и кнопки, а также (что важно) двух переменных для внутреннего использования:

function _my_form(&$form_state,$id1,$id2) {
  $form = array();
  $form['mytext'] = array(
    '#type'  => 'textarea',
    '#title' => t("Enter text"),
    '#required'  => 'true',
  );
  $form['#id1'] = $id1;
  $form['#id2'] = $id2;
  $form['submit'] = array(
    '#type'  => 'submit',
    '#value' => t('Save'),
  );
  return $form;
}

По нажатию кнопки содержимое текстового поля записывается в БД вместе с $id1 и $id2, которые меняются от одной формы к другой.

Сделать хотелось примерно вот что:

  //...
  $id2 = x;
  foreach ($ids as $id1) {
    $output .= drupal_get_form('_my_form',$id1,$id2);
  }
  //...
  return $output;

Однако очевидно, что данный код работать не будет. Загвоздка в том, что все формы генерируются с одинаковым form_ID и при сохранении любой формы Друпал будет считать, что сохраняется самая первая. Поэтому $id1 и $id2 всегда будут равны указанным при создании первой формы на странице. Значит, нужно сделать, чтобы, с одной стороны, у всех форм при создании был разный ID, а с другой - чтобы создавались и обрабатывались они одной функцией.

Порывшись изрядно по Drupal.org было найдено решение в виде хука hook_forms. Собственно, будь на странице в Drupal API правильное описание хука, искать изрядно и не пришлось бы. А так - несколько раз натыкался, и каждый раз думал, что это не выход.

Дело все в том, что в описании hook_forms функция для Drupal 6 указана без аргументов, тогда как на деле она принимает и $form_id, и $args. Все сразу встало на свои места. Вот так для всех форм, начинающихся с _my_form, задается единый конструктор:

/**
 * Реализует hook_forms
 *
 * @param string $form_id - ID формы
 * @param array $args - дополнительные параметры, полученные от drupal_get_form
 * @return array
 */
function mymodule_forms($form_id,$args) {
  $forms = array();
  if (strpos($form_id,'_my_form') === 0) {
    $forms[$form_id] = array(
      'callback' => '_my_form',
      'callback arguments' => $args,
    );
  }
  return $forms;
} //function mymodule_forms

Но поскольку формы у нас стали с разными ID, Друпал при сохранении формы будет искать разные функции-обработчики. Так что нужно указать единый валидатор и обработчик при создании формы:

function _my_form(&$form_state,$id1,$id2) {
  //...
  //валидатор и обработчик
  $form['#submit'] = array('_my_form_submit');
  $form['#validate'] = array('_my_form_validate');
  return $form;
}

Дело сделано. Теперь остается только немного изменить генерацию данных на странице, чтобы формы создавались с разными ID:

  //...
  $id2 = x;
  foreach ($ids as $id1) {
    //$id1, естественно, должен быть уникальным
    $output .= drupal_get_form('_my_form'.$id1,$id1,$id2);
  }
  //...
  return $output;

Комментарии