hook_node_load($nodes, $types)
Вызывается после загрузки нод из БД или из кэша.
Пример использования:
function hook_node_load($nodes, $types) {
$result = db_query('SELECT nid, foo FROM {mytable} WHERE nid IN(:nids)', array(':nids' => array_keys($nodes)));
foreach ($result as $record) {
$nodes[$record->nid]->foo = $record->foo;
}
}
hook_node_delete($node)
Вызывается перед удалением ноды из БД.
Пример использования:
function hook_node_delete($node) {
db_delete('mytable')
->condition('nid', $node->nid)
->execute();
}
hook_node_presave($node)
Вызывается перед добавлением или обновлением ноды в БД. При добавлении ноды её nid ещё недоступен.
Пример использования:
function hook_node_presave($node) {
if ($node->nid && $node->moderate) {
// Reset votes when node is updated:
$node->score = 0;
$node->users = '';
$node->votes = 0;
}
}
hook_node_insert($node)
Вызывается после добавления ноды в БД.
Пример использования:
function hook_node_insert($node) {
db_insert('mytable')
->fields(array(
'nid' => $node->nid,
'extra' => $node->extra,
))
->execute();
}
hook_node_update($node)
Вызывается после обновления ноды в БД.
Пример использования:
function hook_node_update($node) {
db_update('mytable')
->fields(array('extra' => $node->extra))
->condition('nid', $node->nid)
->execute();
}
hook_node_prepare($node)
Вызывается перед открытием формы добавления/редактирования ноды.
Пример использования:
function hook_node_prepare($node) {
if (!isset($node->comment)) {
$node->comment = variable_get("comment_$node->type", COMMENT_NODE_OPEN);
}
}
hook_node_validate($node, $form, &$form_state)
Вызывается во время валидации ноды перед добавлением/обновлением её в БД. Объект ноды недоступен к изменению.
Пример использования:
function hook_node_validate($node, $form, &$form_state) {
if (isset($node->end) && isset($node->start)) {
if ($node->start > $node->end) {
form_set_error('time', t('An event may not end before it starts.'));
}
}
}
hook_node_search_result($node)
Вызывается перед выводом ноды в результатах поиска.
Пример использования:
function hook_node_search_result($node) {
$comments = db_query('SELECT comment_count FROM {node_comment_statistics} WHERE nid = :nid', array('nid' => $node->nid))->fetchField();
return array('comment' => format_plural($comments, '1 comment', '@count comments'));
}
hook_node_submit($node, $form, &$form_state)
Вызывается после валидации формы создания/редактирования ноды, но до добавления/сохранения ноды в БД.
Пример использования:
function hook_node_submit($node, $form, &$form_state) {
// Decompose the selected menu parent option into 'menu_name' and 'plid', if
// the form used the default parent selection widget.
if (!empty($form_state['values']['menu']['parent'])) {
list($node->menu['menu_name'], $node->menu['plid']) = explode(':', $form_state['values']['menu']['parent']);
}
}
hook_node_view($node, $view_mode, $langcode)
Вызывается перед рендерингом (выводом) ноды. Элементы ноды, отображаемые на странице, доступны в свойстве $node->content
в виде рендер-массива.
Пример использования:
function hook_node_view($node, $view_mode, $langcode) {
$node->content['my_additional_field'] = array(
'#markup' => $additional_field,
'#weight' => 10,
'#theme' => 'mymodule_my_additional_field',
);
}
hook_node_view_alter(&$build)
Вызывается перед рендерингом (выводом) ноды. В отличии от hook_node_view
, используется для изменения частей рендер-массива.
Пример использования:
function hook_node_view_alter(&$build) {
if ($build['#view_mode'] == 'full' && isset($build['an_additional_field'])) {
// Change its weight.
$build['an_additional_field']['#weight'] = -10;
}
// Add a #post_render callback to act on the rendered HTML of the node.
$build['#post_render'][] = 'my_module_node_post_render';
}
hook_node_access($node, $op, $account)
Вызывается во время проверки прав доступа к ноде (создание, удаление, просмотр, обновление). Хук не вызывается для главного администратора.
В официальной документации можно посмотреть порядок выполнения хуков при различных событиях.
- Тонкая настройка прав материалов с помощью hook_node_access()
- Добавить своё действие над сущностью в bulk operations
- Добавить своё действие над сущностью в contextual links
- Добавить своё действие над сущностью в operations links
- Добавляем на страницу управления отображением материала поля "Заголовок" и "Дата создания"
Комментарии
Спасибо за полезную справку.
Интересно, а в чем логика разделения задачи обработки ноды перед её отображением на два хука - hook_node_view и hook_node_view_alter ?
Почему бы их не объединить в один хук, где можно было бы как добавлять новые элементы ноды, так и редактировать уже существующие ?
чтобы можно было изменять данные, добавленные модулями с бОльшим весом.
на самом деле есть ещё два "хука" — hook_preprocess_node и hook_process_node :)
То есть, получается, что сначала выполняются все хуки hook_node_view, а потом уже все хуки hook_node_view_alter ?
да
Вопрос, при использовании hook_node_view
Добавленый мною контент будеть отображаться в Manage display ноды?
нет
Не совсем корректно говорить о хуке node_insert как "Вызывается после добавления ноды в БД.". Есть небольшой, но важный нюанс - он высывается внутри транзакции создании ноды, что влечёт за собой во-первых возможный её откат, а во-вторых - отсутствие данных в БД о ноде. Было у меня пару случаев, когда это было сложно разрешимой проблемой.
Вообще не понимаю почему нельзя вызывать хук node_insert реально после создании ноды.
мне кажется логичным, что если транзакция откатится, то и изменения сделанные в hook_node_insert откатятся
Да, так сейчас и сделано. Это логично для текущей реализации. Но я говорю про другое - если транзакция откатилась и нода не создалась, то тогда и не надо вызывать hook_node_insert. Если же всё ок - то вызываем hook_node_insert.
тоже разумно
А по-моему всё как раз логично: есть _presave() в котором подготовливаются данные, далее _insert()/_update() в котором уже есть NID и пытаемся добавить/изменить свою запись в базе.
Транзакция откатывается целиком, если любой из модулей не смог сохранить свои данные - иначе это уже не транзакция!
Если нода не создалась/сохранилась (drupal_write_record() ...) то и хук не вызовется - внимательно смотрим код node_save()
hook_entity_presave($entity, $type)
Это реализация не только для ноды, но и для любой сущности?
да
Я так понимаю что хуки
hook_node_view
hook_node_view_alter
hook_preprocess_node
hook_process_node
Делают одно и тоже,причем можно использовать и в теме и в модуле...а как выбирать нужный хук,по какому признаку?
hook_node_view[_alter] не доступны в темах. выбирать исходя из задачи
Пример: разбил содержание ноды на вкладки с помощью field_group , хочу перенести комментарии в одну из вкладок. какой из хуков использовать в template.php ? Точее больше интересует исходя из чего я должен выбрать хук
http://xandeadx.ru/blog/drupal/390
http://xandeadx.ru/blog/drupal/615
Подскажите, пожалуйста, как отменить проверку на заполнение обязательных полей при удалении ноды?
Т.е., например, фото - обязательное поле, пользователь удаляет сначала фото, потом пытается удалить саму ноду и ему выдает ошибку, что обязательные поля не заполнены. Хочется отменить все проверки CCK на тапе удаления.
Drupal 6.
Спасибо!
Доброго времени суток!
У меня такая проблемка - нужно чтобы при сохранении ноды, image перезаписывался, а не добавлялся счетчик (_n), так как фотки одинаковые. Что делать при удалении это потом...
Либо в hook_node_presave - удалить перезаписанный файл и записать со своими настройками или хочется посмотреть в сторону - https://api.drupal.org/api/drupal/modules!field!field.attach.inc/functi…
особенно вот это - _field_invoke_default('extract_form_values', $entity_type, $entity, $form, $form_state);
Как это работает?
Заранее спасибо за ответ.
я снова тебя не понимаю)
Попробую по подробней. Вообще то это для commerce_product, но для ноды это как то привычней. Вообщем есть тип материала, у него поля разные и поле field_image.
штук по 20 нод - одна и та же картинка прикрепляется, ну и вместо 1Гб - 20 Гб всяких дублей. Вот как при сохранении перехватить вызов функции file_save_data($data, $destination = NULL, $replace = FILE_EXISTS_RENAME) (видимо она там вызывается) то есть файл.jpg второй такой же станет файл_0.jpg потом _1 и т.д. Но это один и тот же файл. И мне хотелось бы чтобы $replace = FILE_EXISTS_REPLACE. Можно тупо влезть в ядро и там перезаписать, но мне это надо только для одного типа.
Единственное, как потом при удалении ноды не удалять файл.jpg, если есть ссылка(id - fid) на этот же файл в другой ноде, но это потом...
сравнение файлов идёт только по имени? это как-то не очень разумно
А может здесь подойти по-другому ?
Например, сделать, чтобы при работе с картинкой использовался соответствующий менеджер картинок (типа IMCE или ElFinder), где пользователь сам смог бы при необходимости выбрать одну и ту же картинку для разных товаров ?
Сделал так(работает!):
Мне нужно загрузить данные к ноде, но они нужны только при просмотре одной ноды. Где мне их загружать?
(в моём случае это множество "атрибутов")
В блоке
только на страницах
node/id
Игорь, меня интересуют hook_node_load() и hook_node_view().
Вообщем то понятно что hook_node_load() используется и для множества и для одной ноды.
Но непонятно зачем загружать для множества нод то, что будет показано только для одной? т.е. где там что-то вроде $view_mode?
Если обновить значение поля внутри hook_node_update($node) следующим образом:
$node->field_height['und'][0]['value'] = $new_value;
, то значение field_height_value в таблице field_data_field_height базе данных не обновится.
С другой стороны, если внутри hook_node_update($node) изменить значение поля field_height_value прямо в базе данных, например средствами API баз данных или каким-либо другим образом, то новое значение сохранится.
Это говорит о том, что событие node_update возникает не перед обновлением БД, а после. Если бы этот хук был перед обновлением, то должно быть наоборот.
(хотя могу и ошибаться, для подобного поведения могут быть какие-то другие причины, но обновить поле внутри этого хука получилось только напрямую в базе).
я ошибся, hook_node_update вызывается после обновления.
значения полей можно менять в hook_node_presave
Встала такая задача:создал тип материала - "товар на складе" с полями ID товара, название товара, дата добавления товара, место хранения товара (предполагается, что будет веб-интерфейс учета товара на складе). Нужно, что бы при заведении ID товара, из отдельной таблицы с каталогом товара подтягивалось название товара (заводить будет кладовщик сканируя штрих-код, потому и надо подтягивать название). Таблица, из которой должно подтягиваться название товара простая (id товара, название товара, артикул и количество товара). hook_node_insert тут может подойти? Если можно, то киньте пример на русском.
Mihon_kri - не проще ли комерц поставить, там всё есть и даже больше, правда потом пол года его понимать и настраивать, но это уже издержки ;-)
Ребят, нужно после обновления ноды проверять одно из полей, если оно не изменилось то ничего не делать, если изменилось то отправлять письмо.
Используя hook_node_update я могу отправить письмо, но не могу проверить каким было это поле до сохранения.
Есть hook_node_presave, но теперь встает вопрос, как передать значение моего поля из одного хука в другой?
hook_node_presave -> hook_node_update
Спасибо
Как вариант можно создать класс со статическим свойством и использовать это свойство как аналог некой глобальной переменной.
В hook_node_presave это свойство устанавливать, а в hook_node_update - считывать.
Класс можно описать прямо в файле вашего модуля.
И еще есть вариант - возможно будет работать - в druapl'е есть пара функций: что-то типа variable_set и variable_get (в синтаксисе могу ошибаться). Ими можно просто глобальные переменные устанавливать-считывать.
Но я на практике не пробовал - всегда использовал статические свойства, но может этот вариант где-то будет даже правильнее.
@Али в hook_node_presave можно вычислить разницу массива с $node->original. И если в массиве поле присутствует - отправлять письмо.
Здравствуйте!
В своем модуле добавляю сабмит который выполняется после основного и программно создает термин из поля ноды title. Стоит задача прицепить ссылку на этот термин к создаваемой ноде. Получить TID из объекта созданного термина нет проблем, а вот как вытянуть NID из создаваемой ноды ... .
Я не профи в РНР (хотя кое какие понятия имею), а вдобавок и в доках к hook_node_insert все как то туманно описано.
$node->nid
Пробовал. Нет значения. Код вставлял в свой сабмит, который выполнялся после основного.
Ставил метку из drupal_set_message до и после кода. Метки есть, значения нет. А после всех меток сообщение "Материал "Вася Пупкин" создан".
Разобрался. Вытаскивать nid нужно было не в сабмите, а в самом хуке hook_node_insert.
Протупил, что впрочем и неудивительно. Благодарю за помощь.
Приветствую
А как выполнить код после удаления ноды, до не катит?
Не понял вопроса.
>hook_node_delete($node)
>Вызывается перед удалением ноды из БД.
А нужно после удаления выполнить некий код
Добавить комментарий