Для создания пользовательских форм очень удобно использовать встроенные в Drupal механизмы. Это гораздо удобнее, чем писать html код вручную с нуля.
Сразу даю ссылку на документацию, к которой мы будем обращаться http://api.drupal.org/api/drupal/developer!topics!forms_api_reference.html/7
Это очень удобная таблица, а также пример использования каждого элемента.
Для использования формы нужно создать функцию, которая будет возвращать массив элементов формы. Давайте сделаем несложную форму с одним полем ввода и переключателем. Каждый элемент массива $form – это элемент html формы. Каждый элемент также является массивом. Значение его ключей определяют, каким будет тот или иной элемент, как будет сформирован html код формы.
Ключ #type – это тип элемента (поле ввода, область ввода, выпадающий список, скрытое поле и т.д.).
#title –отвечает за заголовок поля
#description – описание поля
#default_value – значение по умолчанию
И так далее. Для разных типов элементов доступны свои аргументы. Смотрите документацию.
//первая простая форма function my_first_form($form, &$form_state){ '#type' => 'textfield', '#title' => t('Название поля'), '#default_value' => t('Текст по умолчанию'), ); '#type' => 'radios', '#title' => t('Состояние статуса'), '#description' => t('Описание данного элемента.'), ); '#type' => 'submit', '#value' => t('Submit'), ); return $form; }
Чтобы отобразить эту форму – к ней нужно обратиться и отрендерить её. Для получения формы используем функцию drupal_get_form(), которой в качестве аргумента передадим id формы. Id формы совпадает с названием функции, которая возвращает массив её элементов. В нашем случае это my_first_form.
Вернемся к функции отрисовки страницы test_url - main_function.
Создадим переменную $form , которая будет содержать в себе нашу форму.
function main_function(){ $form = drupal_get_form('my_first_form'); //получаем поля формы $form = drupal_render($form); //рендерим форму return $form.'Содержимое тестовой страницы.'; }
В 17-й строке в переменную form был помещен массив элементов формы и в 18-й этот массив отрендерен в html код. И в 19-й мы выводим эту форму.
Если всё сделано верно-то в браузере мы увидим нашу форму.
Все три поля успешно отрисованы.
Теперь обработчик формы. Для обработчика формы не требуется создавать отдельный файл, как это было с привычными html формами. Обработчиком также будет функция.
По умолчанию имя этой функции будет <id формы>_submit . Но при желании в функции формы можно задать любое другое имя.
Создадим функцию my_first_form_submit. Она будет запускаться при сабмите нашей формы. Чтобы принять данные, отправленные формой - следует обратиться к её второму аргументу - $form_state , передаваемому ей по ссылке. Но также можно использовать и стандартный массив $_POST.
Проверим работу функции, выведя на экран значение всех элементов формы.
function my_first_form_submit($form, &$form_state){ debug($form_state['values']); }
Обратите внимание - выводим только значение элемента с ключом values. Так как в массиве form_state очень много ненужной нам служебной информации. Проверяем работу формы.
Заполняем форму.
И отправляем её.
Нужные нам переменные - это name и settings. Теперь мы можем записать их в файл, в БД или использовать по своему усмотрению.
Ещё у форм есть замечательный аргумент - #states. Он позволяет создавать динамические формы, без написания JavaScript кода. Например, есть следующее задание на создание формы: в форме должен быть переключатель для выбора пола (М и Ж). Если выбран Ж – то показать поле для ввода девичьей фамилии. Если выбран М – то дать возможность отметить чекбокс «Служил в армии», и если отмечен-то показать поле для ввода воинского звания.
Сейчас мы сделаем это всё тем же Form API.
Создадим новую форму с именем my_next_form. Вначале просто создадим все элементы, а потом настроим их отображение.
function my_next_form($form, &$form_state){ '#type' => 'textfield', '#title' => t('Ваше имя'), '#required' => true ); '#type' => 'radios', '#title' => t('Ваш пол'), '#required' => true ); '#type' => 'textfield', '#title' => t('Ваша девичья фамилия') ); '#type' => 'checkbox', '#title' => 'Служил в армии' ); '#type' => 'textfield', '#title' => t('Ваше воинское звание'), '#default_value' =>t('Рядовой') ); '#type' => 'submit', '#value' => t('Submit'), ); return $form; }
Также создадим новую страницу для работы с этой формой. Дадим ей адрес next_form.
function test_module_menu(){ 'title' => 'Заголовок страницы',//заголовок страницы 'page callback' => 'main_function',//имя функции 'type' => MENU_NORMAL_ITEM, //тип страницы 'access callback' => TRUE, //доступ к странице ); 'title' => 'Сложная форма',//заголовок страницы 'page callback' => 'form_function',//имя функции 'type' => MENU_NORMAL_ITEM, //тип страницы 'access callback' => TRUE, //доступ к странице ); return $items; }
Задаем ей новый title и главной функцией назначим функцию form_function, которую создадим далее.
function form_function(){ $form = drupal_get_form('my_next_form'); //получаем поля формы $form = drupal_render($form); //рендерим форму return $form; }
Очистим кэш Друпала и перейдем на URL next_form. Если не было допущено ошибок – то увидим всю форму.
Я намеренно сделал поля для имени и пола обязательными к заполнению. Как вы заметили – Drupal автоматически присвоил им нужные стили, поставил звёздочки.
Если попробовать отправить форму прямо сейчас – система выдаст сообщение о том, что поле для имени не заполнено и форма не будет отправлена. Все остальные поля сохранят свои значения (если вы их изменили).
Теперь сделаем поля зависимыми. Вначале настроим отображение поля для ввода девичьей фамилии. Дополним поле maiden_name.
'#type' => 'radios', '#title' => t('Ваш пол'), '#required' => true ); '#type' => 'textfield', '#title' => t('Ваша девичья фамилия'), ), ), );
Аргумент states у поля maiden_name представляет собой массив. В нем может быть элемент с ключом visible или invisible, отвечающем за показ или скрытие элемента. Значением этого элемента также будет массив. Его ключ – это проверяемое значение формы, а значение этого ключа – это значение этого проверяемого значения.
Наше условие сделает элемент maiden_name видимым при условии, что значение элемента с именем sex будет равно 1.
Данного условия будет достаточно. Проверьте работу формы. Поле для ввода девичьей фамилии будет видно, только если выбран пол Ж.
Аналогично поступаем с элементом served. Только значение элемента sex должно быть равно 0.
'#type' => 'checkbox', '#title' => 'Служил в армии', ), ), );
Теперь зададим условия для поля rank. Оно должно быть видно при условии что выбран пол М и поставлена отметка о службе в армии. Для этого в массив visible помещаем 2 элемента – 2 условия.
'#type' => 'textfield', '#title' => t('Ваше воинское звание'), '#default_value' =>t('Рядовой'), ), ), );
Проверяем форму. Выбираем женский пол и видим только поле ввода девичьей фамилии, о службе в армии и воинском звании ничего нет.
Таким образом можно создавать сложные интерактивные формы.
Также помимо обработчика форм в Drupal есть система валидации форм. Например, можно проверить – была ли введена девичья фамилия. И если не была введена – то подставить какое-то дефолтное значение. Данный функционал можно описать и в обработчике, но мы рассмотрим его в валидаторе в качестве примера.
Валидатор формы – это функция с именем <id формы> _ validate.
Создадим функцию my_next_form_validate и проверим в ней поле maiden_name. Если оно будет пустым – присвоим ему значение «Отсутствует».
function my_next_form_validate($form, &$form_state){ if($form_state['values']['maiden_name']==''){ $form_state['values']['maiden_name']='Отсутствует'; } }
Обратите внимание, что переменная form_state передаётся по ссылке.
Для проверки нашей функции валидации выведем значения полей формы в обработчике формы.
function my_next_form_submit($form, &$form_state){ debug($form_state['values']); }
Введем в форму только имя и нажмём Submit.
Как видите – переменная maiden_name приняла значение «Отсутствует».
Давайте ещё сделаем проверку на длину имени. Выведем ошибку, если длинна имени менее трёх символов.
function my_next_form_validate($form, &$form_state){ if($form_state['values']['maiden_name']==''){ $form_state['values']['maiden_name']='Отсутствует'; } form_set_error('name', t('Слишком короткое имя.')); } }
Функцией mb_strlen определим длину строки. Если она меньше трёх – то функцией form_set_error создадим ошибку. Первый аргумент этой функции – это имя поля, которое должно быть подсвечено. И второй – текст ошибки. Проверяем, пробуем ввести поле имени 1 символ.
Функция валидации успешно сработала. Форма не была отправлена.
А теперь давайте напишем простой обработчик – поместим имя, пол, девичью фамилию и воинское звание в файл.
Напишем обработчик.
function my_next_form_submit($form, &$form_state){ $name = $form_state['values']['name']; $sex = $form_state['values']['sex']; $maiden_name = $form_state['values']['maiden_name']; $rank = $form_state['values']['rank']; $str = $name."\r\n".$sex."\r\n".$maiden_name."\r\n".$rank; drupal_set_message('Данные успешно отправлены'); }
Вначале создадим 4 переменные из полученных данных. Далее объединяем их в одну переменную. Потом определим - по какому адресу будет располагаться создаваемый файл.
Строка public:// будет означать путь sites/default/files . В дальнейшем используйте её. Далее стандартными функциями PHP осуществляем запись в файл.
Теперь при каждой отправке формы будет создан файл с уникальным именем и в него будут записаны данные. И в последней строке функции выведем сообщение пользователю о том, что форма успешно отправлена. Используем для этого функцию drupal_set_message.
Проверяем.
И открываем sites/default/files.
Файл успешно создан.
Данный пример показывает, как использовать Drupal Form API при написании кода. В реальных проектах обязательно осуществляйте проверку создания файла и записи в него. В нашем случае эти проверки не делаются, в целях минимизации кода.
3){>