Какова основная концепция за крючками?


120

Я промежуточный в PHP. Чтобы отточить свои навыки, я начинаю изучать Drupal 7. Во время изучения концепций архитектуры Drupal термины « крючки» и « самозагрузка» меня сильно озадачили. Я прочитал книгу "Pro Pro Drupal development" и некоторую документацию на drupal.org, но я настолько продвинут, что узнал, как в Drupal работают хуки для отображения веб-страницы.

Может кто-нибудь сказать мне, что за крючки в простых словах?

Ответы:


107

Другие ответы отличные, точные, подробные, но я не уверен, что это «простые слова», объясняющие суть концепции, которую искал просящий.

Я думаю о хуках как о точке, в которой код останавливается и выкрикивает: «У кого-нибудь еще есть что добавить? ». Любой модуль может иметь функцию, которая отвечает на это и запускается с соответствующими данными, передаваемыми ему в этот момент кода.

Хороший простой пример - hook_node_delete () . Любой модуль может использовать его, чтобы все происходило каждый раз при удалении узла. Документы сообщают вам, что этот хук передает модулю объект этого удаленного узла для работы и выделяет другую полезную информацию, например, о точном времени, когда он вызывается (например, это происходит до того, как данные узла фактически удаляются из базы данных). и где в коде Drupal вызывается хук (который может быть в нескольких местах).

Вы можете изучить, какие существуют хуки, и узнать, какие данные им передаются, исследуя вещи, начинающиеся с "hook_" в API Drupal .

Хуки работают по соглашениям об именах: используя в hook_node_deleteкачестве нашего примера, когда процесс удаления узла достигает точки, где вызывается хук, для каждого модуля с такой функцией, [modulename]_node_delete()где слово хук в имени хука заменяется именем модуля (например, my_amazing_module_node_delete()) эти функции вызываются.

Почему? Таким образом, любой модуль может делать все что угодно в этих ключевых моментах: например, вы можете посмотреть на удаленный узел и сделать что-то, если он удовлетворяет определенному условию (скажем, отправить электронное письмо администратору или запустить длительный процесс).

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

Это просто, действительно мощно и лежит в основе того, как Drupal работает как модульная система. Реализации хуков лежат в основе большинства модулей Drupal.

Просматривая код модуля Drupal, вы можете определить, какие функции происходят из ловушек (в отличие от функций, которые просто вызываются из самого кода модуля), так как сообщество Drupal применяет соглашение, согласно которому каждая реализация ловушки имеет комментарий перед ним, как это (обратите внимание на бит "Implements hook _..."):

/**
 * Implements hook_some_hook().
 *
 * Some descriptive summary of what this does
 */
function my_amazing_module_some_hook() {

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

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


53

Хуки, в основном, являются реализациями шаблонов Visitor и Observer .

Одна из наиболее распространенных реализаций хуков - hook_menu , которая позволяет модулям регистрировать новые пути в системе Drupal.

function my_module_menu() {
  return array('myawesomefrontpage' => array(
    'page callback' => 'function_that_will_render_frontpage'
  ));
}

В Drupal очень часто встречаются модели с [DATATYPE]_infoкрючком и [DATATYPE]_info_alterкрючком. Если вы хотите создать новый тип поля, вы реализуете соответствующий field_info -hook, а если вы хотите манипулировать существующим, вы реализуете соответствующий field_info_alter -hook.

Редактировать: Как указывает Chx в комментариях, паттерн наблюдателя является объектно- ориентированным, а Drupal 7 по-прежнему, в основном, нет. Однако есть вики-страница, программирование на Drupal с объектно-ориентированной точки зрения (созданная JonBob 4 апреля 2005 г.), где объясняется, как Drupal использует шаблоны объектно-ориентированного кода, несмотря на это. Интересно отметить, что здесь упоминаются наблюдатели, а не посетители.

Замечание о Drupal 8 Это все еще довольно рано и может быть изменено, но я хочу добавить, что хотя ловушки уже довольно давно стали стандартом де-факто для добавления функциональности в Drupal, концепция плагинов станет намного более заметной. в Drupal 8, и даст нам новые способы взаимодействия с Core. Актуальная проблема и документация .


2
Не будьте одурачены шаблонами ООП-дизайна. Это не один. Крючки Drupal являются АОП. Смотри ниже.

@chx, хотя я свободно признаю, что ты знаешь лучше, чем я :) и твой ответ правильный (я проголосовал за него), я не воспринимаю это как мой ответ, который был неверным. :) Если вы не согласны, я хотел бы узнать, как я неправильно понял схемы их реализации.
Летарион

4
Википедия: «Шаблон наблюдателя - это шаблон проектирования программного обеспечения, в котором объект, называемый субъектом, ведет список своих зависимых, называемых наблюдателями», здесь нет объекта, содержащего наблюдателей. Посетитель мрачнее, но применяется тот же общий принцип: то, что не является ООП, не может иметь шаблонов ООП.

33

С точки зрения непрофессионала, ловушки - это своего рода мосты, которые обеспечивают способ взаимодействия модулей друг с другом, изменения структуры и данных друг друга, предоставления новых данных и т. Д.

В большинстве случаев слово hook_в именах функций заменяется именем вашего модуля, и это дает возможность вашему модулю подключиться к работе другого модуля. Например, модуль ядра drupal под названием «узел» вызывает различные хуки. Один из них hook_node_updateвызывается каждый раз, когда обновляется существующий узел. Когда этот крюк вызываются, ваш модуль (скажем , мы называем его mymodule) реализацией hook_node_updateназывается, которая в данном случае будет являться функцией в .module файл вашего модуля называется mymodule_node_update(Очевидно , что эта функция может быть в любом файле в папке вашего модуля, пока он также включен в файл .module). В этот хук также будут переданы необходимые параметры (переменные), которые он может использовать, изменять и / или возвращать обратно в функцию, которая вызвала хук.

Когда я впервые начал изучать Drupal, я был в той же лодке, что и вы сейчас, сначала немного сложно понять, но как только вы его получите, это так просто и интуитивно понятно. Удачи.


1
Спасибо за ваш ответ. Это мне очень помогает. Подскажите, пожалуйста, что такое концепция начальной загрузки в drupal и как трактуются хуки в начальной загрузке простыми словами, как вы объясняете предыдущий ответ ..
GiLL

@Bayasa, пожалуйста, введите здесь свои мысли. Я просто добавляю свою. Вы можете думать об ускоренном подключении как о запуске компьютера. У Drupal есть много API, включая базу данных, файлы и формы. Они основаны на «платформе». Во время начальной загрузки Drupal определяет эти функции и другие параметры (соединение с базой данных, папки с файлами и т. Д.), Чтобы остальная часть системы могла продолжить работу с остальных.
АйешК

32

Один из разработчиков ядра недавно написал статью под названием «Программирование на Drupal с объектно-ориентированной точки зрения» . Он хорошо объясняет, как можно рассматривать хуки как реализацию многих общих шаблонов проектирования . Лучшее объяснение хуков можно найти в статье:

Система хуков Drupal является основой для его абстракции интерфейса. Хуки определяют операции, которые могут выполняться на модуле или с его помощью. Если модуль реализует ловушку, он входит в контракт для выполнения конкретной задачи или возвращает определенный тип информации, когда ловушка вызывается. Вызывающему коду не нужно ничего знать о модуле или о том, как реализована ловушка, чтобы получить полезную работу, вызвав ловушку.


1
Я исправил авторство этой статьи в соответствии с drupal.org/node/19964

@chx, спасибо. Я обдумываю удаление этого ответа сейчас. Я написал это, потому что раньше я выполнял много ОО-работ на простом С и привык к концепциям ОО без реальных объектов. Тем не менее, вы правы в отношении pointcut / weaver. Однако я не уверен, является ли цитата точным описанием аспекта (игнорируя часть «интерфейсная абстракция»).
mpdonadio

21

Bootstrap - это процесс, через который проходит Drupal для создания страницы, в основном работающей над всем ядром, темой и модульным кодом по порядку.
Это в основном то, как загружается Drupal, и готовится выполнить свою работу в качестве CMS.

Это умно, так как позволяет нам устанавливать хуки в любом месте наших модулей и тем, а процесс начальной загрузки гарантирует, что они запускаются в нужной точке.
Например, если вы используете 'hook_form_alter' для добавления настраиваемого флажка в форму, начальная загрузка Drupal удостоверится, что он выполняет этот код, непосредственно перед тем, как он отобразит вашу форму.

Одна из проблем начальной загрузки заключается в том, что весь процесс требует времени, даже если вы только возвращаете небольшой объем данных. При использовании Drupal с модулем services в качестве API и возврате множества небольших ответов XHTML или JSON выполнение всей начальной загрузки не очень эффективно. Некоторые умные люди ищут обходные пути для Drupal 8.

Но для рендеринга обычных страниц Drupal процесс начальной загрузки работает отлично, он использует систему кэширования Drupals для ускорения работы и дает вам полный контроль над каждой частью вашего сайта. Если вы обнаружите, что ваш сайт работает медленно, вы всегда можете использовать что-то вроде APC или MemCached, чтобы ускорить процесс.

Я надеюсь, что мой ответ был точным и объясняет вещи просто для вас, я не эксперт, но я думаю, что так оно и есть.


15

Bootstrap - это процесс, во время которого Drupal инициализирует себя; процесс на самом деле включает в себя:

  • Установка ошибки и обработчики исключений
  • Инициализация значения некоторых глобальных переменных, содержащихся в $_SERVER
  • Инициализация некоторых переменных с init_set()
  • Поиск кэшированной версии страницы для обслуживания
  • Инициализация базы данных
  • Установка обработчиков, которые загружают файлы, когда класс или интерфейс не найдены
  • Инициализация переменных Drupal
  • Инициализация сессии PHP
  • Инициализация языковой переменной
  • Загрузка включенных модулей

Некоторые из описанных мною операций специфичны для Drupal 7 или выше, но большинство операций не зависят от версии Drupal.

Хук - это PHP-функция, которую можно вызывать из Drupal или сторонних модулей, когда это необходимо для выполнения задачи. Вместо того, чтобы иметь префиксный список функций для вызова, этот список является сборкой, проверяющей включенные модули и функции, которые они реализуют.
Например, Drupal использует hook_node_update(); когда узел сохраняется с помощью node_save () , выполняется следующий код.

// Call the node specific callback (if any). This can be
// node_invoke($node, 'insert') or
// node_invoke($node, 'update').
node_invoke($node, $op);

Что делает node_invoke () :

  • Получение списка всех включенных модулей
  • Проверка, есть ли у включенных модулей функция, имя которой оканчивается на «_node_update» и начинается с короткого имени модуля
  • Вызов этой функции, передача в $nodeкачестве параметра

Хуки могут сохранять свои собственные данные в базе данных или изменять значение, возвращаемое функцией. Последний случай, например, происходит с hook_form_alter () , который изменяет значение, $formпереданное в качестве ссылки на drupal_prepare_form () .

Хуки Drupal обычно вызываются с помощью трех функций:

drupal_alter()является функцией, используемой для вызова определенных хуков, целью которых является изменение данных, переданных им в качестве ссылки, таких как hook_form_alter () , hook_hook_info_alter () и hook_tokens_alter () .

Есть и другие функции, которые используются для вызова хуков, например node_invoke(), но эти функции по существу используют одну из функций, которые я перечислил ранее.


12

Крючки являются точечными и module_invoke_allткачами (увы, мы не совсем понятны в реализации и есть другие функции плетения). Насколько мне известно, Drupal является единственной системой, которая реализует AOP с функциями PHP.

Посмотрите другое объяснение о том, как АОП работает в Drupal?


Как вы думаете, статья Джодгдона (упомянутая в моем ответе) точна?
mpdonadio

2
Это статья Джонбоба с 2005 года, атрибуция неверна. Я бы обсудил это, да.

6

Если вы хотите увидеть хуки, которые Drupal позволяет вам вызывать, перейдите на api.drupal.org , перейдите в окно поиска и введите «hook_». Это даст вам большой список большинства хуков, определенных Drupal. Сделайте то же самое для «_alter» и посмотрите еще больше.

Страница Hooks Node API предлагает хронологический список всех хуков, вызванных во время операций узла. Вы можете видеть модуль Node и системы Entity и Field, дающие друг другу повороты при вызове хуков.

Например, если вы прокрутите вниз и посмотрите на раздел node_load(): Модуль Node даст вам hook_load (), а затем передаст управление системе управления данными, которая загружает некоторые поля. Существует целый ряд перехватчиков полей, которых нет в списке, и затем, когда все закончится, активируется система управления данными hook_entity_load(), прежде чем передать управление обратно в Node, который вызывает hook_node_load().

Это дает вашему коду возможность воздействовать на рассматриваемый узел по мере его загрузки по частям. Изучение этих хуков и когда и почему они называются, является частью приключения Drupal кодирования. :-)

В других системах тоже есть крючки. Такие как hook_init()и hook_boot(). Это касается начальной части вашего вопроса. hook_boot()вызывается Drupal до загрузки системы кэширования. Поэтому, если вашему модулю нужно что-то сделать до того, как Drupal действительно запустится, и вы хотите, чтобы ваш код выполнялся независимо от кэширования, вы должны реализовать это hook_boot(). В противном случае, если вы заботитесь только о страницах, которые не кэшированы, вы бы реализовали hook_init().

Это дает вам возможность реализовать что-то в начале процесса загрузки, до полной загрузки Drupal, и при этом дает вам некоторую гибкость в отношении того, какой момент процесса вы хотите перехватить.

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

И, наконец, вы можете увидеть подробный документированный код для любой подсистемы в проекте примеров .


ОП запрашивает определение хука, а не список хуков, используемых Drupal.
kiamlaluno

6

Хуки - это php-функции, строительные блоки, основанные на соглашениях об именах «yourmodulename_hookname», они предназначены для облегчения возможности разработчиков создавать модули .

Модули - это реальная сделка, потому что они обеспечивают как CORE, так и пользовательские функции в вашей системе Drupal. Таким образом, модули состоят из хуков, и когда модуль активируется в вашей установке Drupal, его функции хуков могут вызываться из других модулей благодаря функции module.inc module_invoke_all ($ hook) или module_invoke.

Поэтому, чтобы правильно понять, что такое хуки, вы должны действительно испачкать руки и попробовать разработку модулей. Для этого, начав загружать и пробовать некоторые примеры Drupal для разработчиков , вы также должны ознакомиться с созданием модулей .

Вот некоторые из полезных примеров Drupal для разработчиков, упомянутых выше:

Пример реализации hook_block_view () в модуле block_example

/**
 * @file examples/block_example/block_example.module line 127
 *
 * Implements hook_block_view().
 *
 * This hook generates the contents of the blocks themselves.
 */
function block_example_block_view($delta = '') {
  //The $delta parameter tells us which block is being requested.
  switch ($delta) {
    case 'example_configurable_text':
      // The subject is displayed at the top of the block. Note that it
      // should be passed through t() for translation. The title configured
      // for the block using Drupal UI supercedes this one.
      $block['subject'] = t('Title of first block (example_configurable_text)');

Этот хук дает вам доступ к созданию блоков Drupal для отображения пользовательских блоков на вашем сайте. Это возможно потому, что в block.module есть функция _block_render_block, которая позволяет всем модулям определять свое представление hook_block (обратите внимание на последнюю строку module_invoke):

/**
 * @file modules/block/block.module, line 838
 *
 * Render the content and subject for a set of blocks.
 *
 * @param $region_blocks
 *   An array of block objects such as returned for one region by _block_load_blocks().
 *
 * @return
 *   An array of visible blocks as expected by drupal_render().
 */
function _block_render_blocks($region_blocks) {
  ...
  foreach ($region_blocks as $key => $block) {
    ...
    $array = module_invoke($block->module, 'block_view', $block->delta);

Пример реализации hook_menu () в модуле render_example

/**
 * @file examples/render_example/render_example.module line 22
 * 
 * Implements hook_menu().
 */
function render_example_menu() {
  ...
  $items['examples/render_example/arrays'] = array(
    'title' => 'Render array examples',
    'page callback' => 'render_example_arrays',
    'access callback' => TRUE,
  );

Этот хук связан с системой маршрутизации URL в Drupal и определяет шаблоны URL со связанными обратными вызовами рендеринга, используемыми вашим модулем. Он вызывается из system.module .

Что касается начальной загрузки, в основном вам просто нужно знать, что она выполняется при каждом запросе страницы. Я действительно советую вам прочитать этот ответ stackoverflow , он объясняет, как bootstrap и ловушки связаны, но разделены.

Что касается отображения веб-страницы, то отображение html веб-сайта Drupal в основном достигается с помощью массивов рендеринга и тематики.


3

Везде, где модуль вызывает module_implements () http://api.drupal.org/api/drupal/includes%21module.inc/function/module_implements/7 Drupal будет запускать все правильно названные функции в правильном порядке в зависимости от их веса. Они называются функциями перехвата, потому что в документации для модулей, которые используют module_implements, вы видите такие вещи, как hook_menu (когда меню вызывает все функции, предназначенные для возврата пунктов меню). Слово «крючок» просто нужно заменить на имя модуля, реализующего его, а Drupal сделает все остальное.

Есть также функция drupal_alter (), которая запускает все правильно названные функции alter с намерением позволить вам изменять вещи, которые были ранее зарегистрированы другим хуком.

Обычно alters передает аргументы по ссылке, так что вы можете редактировать объект напрямую, тогда как «обычные» ловушки обычно заставляют вас возвращать новые вещи.

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

На практике крючки чаще всего используются для:

  • реагировать на события, например, вызывается hook_user_login, когда пользователь входит в систему
  • зарегистрировать что-то новое, что можно использовать для расширения системы, например hook_menu
  • тема / визуализация HTML или сборка / проверка / отправка форм

1

У вас есть много ответов выше, но я хочу дать ответ гораздо более простым способом, чтобы понять основную концепцию, стоящую за крючками. Хуки на самом деле встроены в ядро ​​drupal для управления разными вещами и выполняют разные задачи в ядре. Вы можете синхронизировать свои собственные функции с этими встроенными функциями ядра drupal, чтобы добавить их функциональность в свои собственные функции, вызывая различные хуки.

Я надеюсь, что вы получите точку!


1

Для меня это все о функции module_implements, когда дело доходит до хуков и ядра (D7). Одна вещь, которую я считаю крайне важной для понимания, заключается в том, что, написав хук для изменения чего-либо, вы никоим образом не можете сказать, что происходит со структурами данных, с которыми вы имеете дело. Ваш хук просто попадает в строку (очередь) функций, которые ТАКЖЕ действуют на одни и те же структуры данных, будь то меню, ссылки меню, блоки, узлы, пользователи или любой объект или элемент рендеринга.

Таким образом, чтобы действительно увидеть, как ваши крючки используются ожидаемым образом, вам нужно знать или знать, где вы (ваш крючок) стоят в очереди. Это определяется весом вашего месяца. Ядро Drupal просто вызывает правильно именованные хуки в порядке возрастания веса, и происходит то, что происходит с данными.

Я писал хуки до того, как это не имело никакого эффекта, только для того, чтобы после нескольких часов ударов головой узнать, что вес моего модуля был слишком легким, а последующие хуки фактически не выполняли то, что я делал, или полностью игнорировали все это вместе.

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

И если говорить о «Линии» крючков. На протяжении многих лет я проверял Google для Drupal, это изображение, кажется, является хорошим представлением списка возможностей для предварительной обработки и перехвата процесса.
введите описание изображения здесь


1

Проще говоря, хуки помогают разработчику изменять существующую функциональность в соответствии с требованиями, не внося изменений в существующий код. Больше похоже на абстрактную функцию в php.

Пример: вы создали модуль для бронирования автобусного билета. Согласно вашему коду, если билет был забронирован, то место получения невозможно изменить, что было вашим требованием для этого проекта. Предположим, вашему другу нужен такой же модуль для аналогичного требования, за исключением того, что пользователь может изменить место получения. Каким-то образом он должен использовать ваш модуль, и вы не хотите, чтобы он делал какие-либо изменения кода. Таким образом, вы предоставляете интерфейс (зацепка в нашем случае), где он может реализовать свои изменения без внесения изменений в ваш модуль.

В drupal до drupal-7 у нас есть хуки для модулей и тем. Чтобы узнать , как проверить крюк работа является Drupal.org крючков для создания проверки пользовательского крюка этой ссылки


0

Крючки. Разрешить модулям взаимодействовать с ядром Drupal. Модульная система Drupal основана на концепции «крючков». Хук - это PHP-функция с именем foo_bar (), где «foo» - это имя модуля (имя файла которого, таким образом, foo.module), а «bar» - это имя хука.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.