Хуки и drupal_alter

Копался тут с разными целями в коде модулей Organic Groups и вдруг обнаружил неведомую мне раньше функцию drupal_alter. Для примера приведу порезанный фрагмент кода, генерирующего блок информации о группе (из функции og_block_details()):

$links['invite'] = l(t('Invite friend'), "og/invite/$node->nid");
$links['subscribers'] = $txt;
$links['manager'] = t('Manager: !name', array('!name' => theme('username', $node)));
$links['my_membership'] = $subscribe;
$links['must_login'] = t('You must <a href="!login">login</a> in order to post into this group.', array('!login' => url("user/login", array('query' => $dest))));
$links['closed'] = t('This is a <em>closed</em> group. The group administrators add/remove members as needed.');

// Modify these links by reference. If you want control of the whole block, see og_block_details().
drupal_alter('og_links', $links, $node);
Так что же делает функция drupal_alter? Она передает ссылку на $links всем функциям-хукам, поименованным по правилам имямодуля_og_links_alter для изменений. То есть фактически, это механизм быстрого создания произвольных хуков для модификации произвольных данных. И чтобы изменить массив $links мне достаточно написать хук mymodule_og_og_links_alter(&$links, $node) и в нем делать с массивом все что угодно.

Функция drupal_alter в качестве аргументов принимает название хука (часть 'og_links'), массив или объект $data, ссылка на который будет передана хукам, а также любые дополнительные аргументы, которые тоже будут переданы хукам (но не по ссылке).

Есть мнение, очень удобная функция. Взял на вооружение.

xandeadx
Аватар пользователя xandeadx

т.е. это то же самое что module_invoke_all, только параметр передаётся по ссылке?

graker
Аватар пользователя graker

В общем да.
Плюс есть возможность передать по ссылке несколько параметров, запихнув их в $data['__drupal_alter_by_ref'].

Гость (гость)
Аватар пользователя Гость

Еще одно потенциальное открытие — функции *_load и параметры menu callback —
http://significantbits.wordpress.com/2008/06/02/drupal-menu-system-magic

graker
Аватар пользователя graker

Господь с тобой, про вайлдкарды в системе меню известно очень давно :)
А все остальное про меню - вообще азы.

andypost
Аватар пользователя andypost

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

Живой пример node_view() ссылки ноды собираются хуком, и после генерации всего массива модулям дается возможность изменить этот массив.

PS в D7 появился drupal_static(), что тоже является фичей :)

graker
Аватар пользователя graker

Угу, только для ключевого он как-то редко встречается. В 2.5 раза реже, чем module_invoke и в 2 раза реже, чем module_invoke_all - это только по стандартным модулям.

Учитывая предоставляемые возможности по модификации - это досадно.

Гость (гость)
Аватар пользователя Гость

Ну почему редко? Тот самый hook_form_alter по-моему самый распространенный хук который используется. Но мне немного непонятно зачем отдельно использовать drupal_alter и module_invoke? drupal_alter() позволяет модифицировать данные после прогона хуков. Аналогично мне нужно будет что-то изменить после того как была вызвана ф-ия drupal_alter для всех модулей, что тогда использовать?

Гость (гость)
Аватар пользователя Гость

P.S. Переменные по ссылке можно передавать и в хуках которые не вызываются через через drupal_alter. Например hook_nodeapi

graker
Аватар пользователя graker

Гость пишет:
Ну почему редко? Тот самый hook_form_alter по-моему самый распространенный хук который используется.
Речь о частоте использования в коде модулей обсуждаемой функции, а не производных хуков.

Цитата:
Но мне немного непонятно зачем отдельно использовать drupal_alter и module_invoke
Для создания собственных хуков и exposure своих данных для модификации в других модулях. Очевидно же.

Цитата:
Аналогично мне нужно будет что-то изменить после того как была вызвана ф-ия drupal_alter для всех модулей, что тогда использовать?
Манипулировать весом модуля.

Цитата:
P.S. Переменные по ссылке можно передавать и в хуках которые не вызываются через через drupal_alter. Например hook_nodeapi
Это потому что hook_nodeapi создан с помощью собственной инвок-функции, а не с помощью module_invoke.

Гость (гость)
Аватар пользователя Гость

Цитата:
Аналогично мне нужно будет что-то изменить после того как была вызвана ф-ия drupal_alter для всех модулей, что тогда использовать?
Манипулировать весом модуля.
А если мне необходимо чтобы один альтер шел первым(соответственно другие модули могут что-то изменить после обработки алтера), а в другой функции которая реализует альтер нужно чтобы он вызывался последним?

graker
Аватар пользователя graker

А если необходимо реализовать альтер на 0-й позиции, на 31-й, 63-й и 97-й, а потом последние 3? В чем вопрос-то? :)

В первой и последней позициях - реализуется, например, двумя модулями с минимальным и максимальным весом. Но возможно, задача, которая требует подобного подхода, изначально содержит в себе изъян и должна решаться иначе.

Отправить комментарий

CAPTCHA
Пройдите, пожалуйста, проверку. Она нужна, чтобы отличать людей от спам-роботов. А если не хотите проходить эту проверку регулярно — зарегистрируйтесь.
Image CAPTCHA
Введите цифры, изображенные на картинке (без пробелов).