

Друпал содержит множество всевозможных форм. Иногда, не все они выглядят так, как бы вам хотелось. Изменение друпаловских форм это тема, которую многие разработчики встречают дружными стонами неудовольствия и непонимания. Между тем, достаточно уяснить всего два метода их изменения и все становится намного яснее и проще.
Итак, существует два способа модификации форм в Друпале. Один из них реализуется через написание модуля. Второй — посредством темизации. Оба способа, в конечном счете, допускают изменения HTML представления формы, поэтому вы вольны выбирать какой из них использовать, исходя из конкретной задачи или личных пристрастий.
Однако, существуют два случая, когда придется реализовать изменения через модуль:
$_POST. А удаление поля в модуле, удаляет поле везде и насовсем. В большинстве случаев это не является серьезной проблемой, но все же, вы должны знать о такой возможности, прежде чем отдать предпочтение методу темизации.В данном примере не будет никаких изменений функциональности, поэтому будет показано применение обоих методов изменения формы. На самом деле, код в обоих случаях очень похож, и опирается на две важные вещи: 1) ID формы 2) некоторые знания Forms API Друпала.
Наш пример покажет, как изменить в форме, расположенной на странице Мои учетные данные > Изменить (http://example.com/user/123/edit), скажем, заголовка "Имя пользователя" на "Логин ID".
Все формы в Друпале имеют уникальные идентификаторы (ID). Вы можете без особого труда найти ID формы в HTML коде формы. На вашем сайте, зайдите на страницу с формой и загляните в ее исходный код (Firebug или Dragonfly идеально подходят для этой задачи) и посмотрите на скрытые поля, ближе к верху формы.

Там должно быть одно, имеющее name="form_id":
<input id="edit-user-edit" type="hidden" value="user_edit" name="form_id"/>В дальнейшем, вам понадобится значение (value) этого поля. В нашем случае, это "user_edit". В шестом Друпале, ID этой формы будет равен "user_profile_form".
Примечание: Возможно вы заметили, что сама форма имеет HTML аттрибут id="user-edit". Важно помнить, что это не тот ID, что нам нужен. Наш идентификатор почти всегда имеет нижнее подчеркивание (_) вместо черточек (-).
Теперь приступим к созданию функций. Конечно же, названия и размещение функций для тем и модулей кардинально отличаются. Также, не забудьте подставить во все эти примеры названия настоящих тем или модулей. Итак, поехали.
Для этого, вставьте вашу функцию в файл template.php вашей темы. Вам нужно будет создавать новую функцию для каждой формы, которую вы захотите изменить.
<?php
/**
* Темизация формы редактирования пользователя.
*
* Функцию следует называть по типу названиетемы_formid.
*/
function названиетемы_user_edit($form) {
// Тут совершаем наши мега-изменения
}
?>В шестом Друпале все становится чуть интереснее. Многие формы в шестерке теперь имеют свои шаблоны или "зарегистрированные" функции. Для них, вы можете просто отредактировать шаблон или перекрыть соответствующую функцию.
Для форм, которые не имеют шаблонов или зарегистрированных функций, нам нужно не только перекрыть функцию темизации, но и зарегистрировать ее в системе темизации, чтобы Друпал о ней знал. Больше информации о регистре темизации можно найти на страницах документации. Наша форма как раз такой и является. Как только добавите следующие функции в ваш template.php, обновите регистр темизации, сбросив кеш на странице "Администрация" > "Производительность".
Вот функция регистрации, которая нам нужна:
<?php
/**
* Реализация hook_theme.
*
* Регистрирует пользовательские функции темизации
*/
function названиетемы_theme() {
return array(
// ID формы
'user_profile_form' => array(
// Формы всегда имеют аргумент form
'arguments' => array('form' => NULL),
),
);
}
?>А вот и сама функция темизации. Она очень походит на функцию из пятерки, за исключением ID формы:
<?php
/**
* Темизация формы редактирования пользователя.
*
* Функцию следует называть по типу названиетемы_formid.
*/
function названиетемы_user_profile_form($form) {
// Тут совершаем наши мега-изменения
}
?>
Используя этот способ, нам потребуется реализовать хук hook_form_alter() и поместить его в .module-файле нашего модуля. Еще одной особенностью данного способа является то, что вы можете изменить сколько угодно форм внутри лишь одной функции, используя условие на ID формы.
<?php
/**
* Реализация hook_form_alter().
*
* Функцию следует называть по типу названиемодуля_form_alter.
*/
function названиемодуля_form_alter($form_id, &$form) {
// лучше использовать конструкцию switch, потому что редко когда
// дело ограничивается одной формой, а в switch довольно просто
// добавлять новые условия
switch ($form_id) {
// Наш ID формы
case 'user_edit':
// Наши мега-изменения
break;
}
?><?php
/**
* Реализация hook_form_alter().
*
* Функцию следует называть по типу названиемодуля_form_alter.
*/
function названиемодуля_form_alter(&$form, $form_state, $form_id) {
// лучше использовать конструкцию switch, потому что редко когда
// дело ограничивается одной формой, а в switch довольно просто
// добавлять новые условия
switch ($form_id) {
// Наш ID формы
case 'user_profile_form':
// Наши мега-изменения
break;
}
?>Итак, вы достали нужный ID формы, создали необходимые функции, осталось только узнать, какие элементы содержит формы и с чем вам придется работать. Самый простой способ узнать содержание массива формы — это вывести его на экран функцией print_r() и глянуть в исходный код страницы. Например, так:
<?php
function themename_user_edit($form) {
return print_r($form);
}
?>Нам нужно отыскать в массиве формы то, что следует поменять, а потом превратить это в PHP код наших функций, используя небольшую магию Forms Api. Итак, что представляет собой массив $form для нашей формы:
Array
(
[account] => Array
(
[#type] => fieldset
[#title] => Информация об учетной записи
[name] => Array
(
[#type] => textfield
[#title] => Имя пользователя
[#weight] => 0
[#maxlength] => 60
[#description] => Например, "VasyaPupkin". Должен состоять из латинских символов (a-z), цифр, дефиса начинаться и заканчиваться буквой или цифрой и содержать не более 20 символов.
)
)
[pass] => Array
(
[#type] => password_confirm
// ...
)
// ...
[comment_settings] => Array
(
[#type] => fieldset
[#title] => Настройка комментариев
[#collapsible] => 1
[#collapsed] =>
// ...
)
)
Итак, нам нужно просто пройтись по этому массиву и найти то, что нужно поменять. Как вы помните, мы хотим поменять заголовок поля "Имя пользователя". Исходя из массива формы, нам нужно взяться за [account][name][#title]:
$form['account']['name']['#title'] = t('Login ID');Более того, если у нас разыграется аппетит, мы можем, к примеру, сделать "Настройку комментариев" закрытой по-умолчанию:
$form['comment_settings']['#collapsed'] = TRUE;Или же вообще удалить ее с формы:
unset($form['comment_settings']);Вы можете делать с формой абсолютно все, главное не забывать подсматривать в шпаргалку по Forms API ;)
Итак, теперь вы имеете необходимые знания для того, чтобы справиться с любой друпаловской формой.
<?php
/**
* Темизация формы редактирования пользователя.
*
* Функцию следует называть по типу названиетемы_formid.
*/
function названиетемы_user_edit($form) {
$output = '';
// Выводим на экран массив формы, чтобы узнать с чем работать
// print_r($form)
// Используя структуру Forms API, совершаем изменения
$form['account']['name']['#title'] = t('Login ID');
// Вызов drupal_render() для всего массива $form, чтобы убедится, что
// все элементы формы выведены на экран
$output .= drupal_render($form);
return $output;
}
?>Функция регистрации:
<?php
/**
* Реализация hook_theme.
*
* Регистрирует пользовательские функции темизации
*/
function themename_theme() {
return array(
// ID формы
'user_profile_form' => array(
// Формы всегда имеют аргумент form
'arguments' => array('form' => NULL),
),
);
}
?>Функция темизации:
<?php
/**
* Темизация формы редактирования пользователя.
*
* Функцию следует называть по типу названиетемы_formid.
*/
function названиетемы_user_profile_form($form) {
$output = '';
// Выводим на экран массив формы, чтобы узнать с чем работать
// print_r($form)
// Используя структуру Forms API, совершаем изменения
$form['account']['name']['#title'] = t('Login ID');
// Вызов drupal_render() для всего массива $form, чтобы убедится, что
// все элементы формы выведены на экран
$output .= drupal_render($form);
return $output;
}
?><?php
/**
* Реализация hook_form_alter().
*
* Позволяет изменять любую форму сайта. Вы можете не только менять,
* удалять или добавлять элементы к форме, но и добавлять дополнительные
* валидаторы или обработчики для формы. Функцию следует называть
* по типу названиемодуля_form_alter.
*/
function modulename_form_alter($form_id, &$form) {
// лучше использовать конструкцию switch, потому что редко когда
// дело ограничивается одной формой, а в switch довольно просто
// добавлять новые условия
switch ($form_id) {
// Наш ID формы
case 'user_edit':
// Выводим на экран массив формы, чтобы узнать с чем работать
// print_r($form)
// Используя структуру Forms API, совершаем изменения
$form['account']['name']['#title'] = t('Login ID');
break;
}
}
?><?php
/**
* Реализация hook_form_alter().
*
* Позволяет изменять любую форму сайта. Вы можете не только менять,
* удалять или добавлять элементы к форме, но и добавлять дополнительные
* валидаторы или обработчики для формы. Функцию следует называть
* по типу названиемодуля_form_alter.
*/
function modulename_form_alter(&$form, $form_state, $form_id) {
// лучше использовать конструкцию switch, потому что редко когда
// дело ограничивается одной формой, а в switch довольно просто
// добавлять новые условия
switch ($form_id) {
// Наш ID формы
case 'user_profile_form':
// Выводим на экран массив формы, чтобы узнать с чем работать
// print_r($form)
// Используя структуру Forms API, совершаем изменения
$form['account']['name']['#title'] = t('Login ID');
break;
}
}
?>Для укрепления знаний, можете взглянуть еще раз на статью Человеческая форма комментирования. Там использовалась темизация.
14 комментариев
# | andypost
Стоит еще освятить hook_alter и вытекающие hook_formname_alter
# | neochief
hook_alter? К сожалению, мне известен только один альтер для форм, он же hook_form_alter(). Поиск тоже не дал результатов. Мы, часом, не говорим об одном и том же?
# | andypost
Я говорю про http://drupal.org/node/144132#form-id-alter и http://drupal.org/node/114774#drupal-alter
# | neochief
Да уж, и в прямь :) Век живи — век учись.
# | vebdiver
Спасибо за статью. Будет полезна многим.
Попутно есть вопрос. А как насчет темизации форм которые размещены в блоках а не на в контенте?
Крутил вертел с формой авторизации - ничего. Все что нужно сделать - добавить яваскрипт для подстановки текста "Логин" и "Пароль" при пустом значении поля и удаление этого текста при получении фокуса полем. Может кто уже делал?
# | DesTincT
аналогично...
# | sadmin
В примерах к "hook_form_alter() в Друпал5" закрывающие фигурные скобки пропущены, к 6й версии тоже
# | Николай
гм. позновательно. А эта система, Друпал, она вообще для чего то конкретно предназначена? Ну типа как ВП для блогов.
# | neochief
На друпале можно делать очень много вещей — начиная с блогов и галерей, и заканчивая социальными сетями и интернет магазинами.
# | DesTincT
user_login() таким образом не перехватывается + print_r($form) выводит саму форму и не ее параметры О_о
# | neochief
user_login_form()
# | appolo
а можно ли как-нибудь поместить форму (список+кнопка) на страницу профиля пользователя, чтобы,например, отсылать определенное сообщение пользователю?
поначалу думал что в case можно прописать user_view....ан нет, нет такой формы..
# | Ingumsky
Спасибо!
Очень полезный материал.
# | анонимус
присоединяюсь
Оставить комментарий