Я использую, hook_init()
чтобы проверить время последнего доступа пользователей. Если последнее время доступа вчера, я увеличиваю счетчик и устанавливаю некоторые переменные.
Проблема в том, что hook_init()
иногда выполняется более одного раза (я вижу это, используя dsm()
) для одной и той же загрузки страницы, поэтому мой код выполняется несколько раз, что приводит к неправильным переменным.
Почему hook_init()
выполняется более одного раза?
Каков наилучший подход к моей проблеме? Должен ли я использовать другой крючок?
Я еще немного покопался в этом:
я ищу вызовы в hook_init () (искал строку module_invoke_all('init');
), но нашел только основной вызов). Я не знаю, можно ли это назвать по-другому.
Это мой hook_init ()
function episkeptis_achievements_init(){
dsm('1st execution');
dsm('REQUEST_TIME: '.format_date(REQUEST_TIME, 'custom', 'd/m/Y H:i:s').' ('.REQUEST_TIME.')');
}
и это вывод:
1st execution
REQUEST_TIME: 09/07/2012 11:20:32 (1341822032)
затем изменили сообщение dsm () dsm('2nd execution');
и снова выполнили, это вывод:
1st execution
REQUEST_TIME: 09/07/2012 11:20:34 (1341822034)
2nd execution
REQUEST_TIME: 09/07/2012 11:22:28 (1341822148)
Вы можете видеть, что код выполняется дважды. Однако в первый раз выполняется старая копия кода, а во второй раз обновленная копия. Разница во времени составляет 2 секунды.
Это версия d7 с php 5.3.10
REQUEST_TIME
будет одинаковым.REQUEST_TIME
исходить из того же запроса страницы, его значение одинаково; нет даже разницы в две секунды. Проверьте, нет ли кода, который изменяет значениеREQUEST_TIME
.Ответы:
hook_init()
вызывается Drupal только один раз для каждой запрашиваемой страницы; это последний шаг, выполненный в _drupal_bootstrap_full () .Если
hook_init()
выполняется более одного раза, вы должны выяснить, почему это происходит. Насколько я могу судить, ни один изhook_init()
реализаций в Drupal проверки она исполняется дважды (см, например , system_init () , или update_init () ). Если это то, что обычно происходит с Drupal, тоupdate_init()
сначала проверит, выполнено ли оно уже.Если счетчик - это число последовательных дней, когда пользователь вошел в систему, я бы предпочел реализовать
hook_init()
код, подобный следующему.Если
hook_init()
вызывается два раза подряд во время одного и того же запроса страницы,REQUEST_TIME
содержит одно и то же значение, и функция вернетсяFALSE
.Код в
mymodule_increase_counter()
не оптимизирован; это просто чтобы показать пример. В реальном модуле я бы предпочел использовать таблицу базы данных, где сохраняются счетчик и другие переменные. Причина в том, что все переменные Drupal загружаются в глобальную переменную$conf
при загрузке Drupal (см. _Drupal_bootstrap_variables () и variable_initialize () ); если вы используете для этого переменные Drupal, Drupal будет загружать в память информацию обо всех пользователях, для которых вы сохранили информацию, когда для каждой запрашиваемой страницы в глобальной переменной сохраняется только одна учетная запись пользователя$user
.Если вы подсчитываете количество посещенных пользователями страниц в последовательные дни, я бы применил следующий код.
Вы заметите, что в моем коде я не использую
$user->access
. Причина в том, что это$user->access
может быть обновлено во время начальной загрузки Drupal, прежде чемhook_init()
вызываться. Обработчик записи сеанса, используемый в Drupal, содержит следующий код. (Смотрите _drupal_session_write () .)Что касается другого хука, который вы можете использовать, с Drupal 7 вы можете использовать hook_page_alter () ; вы просто не изменяете содержимое
$page
, а увеличиваете счетчик и меняете свои переменные.В Drupal 6 вы можете использовать hook_footer () , ловушку, вызываемую из template_preprocess_page () . Вы ничего не возвращаете, но увеличиваете свой счетчик и меняете свои переменные.
На Drupal 6 и Drupal 7 вы можете использовать hook_exit () . Имейте в виду, что крюк также вызывается, когда начальная загрузка не завершена; код не может иметь доступа к функциям, определенным из модулей, или другим функциям Drupal, и вы должны сначала проверить, доступны ли эти функции. Некоторые функции всегда доступны из
hook_exit()
, например, определенные в bootstrap.inc и cache.inc . Разница в том, чтоhook_exit()
он вызывается также для кэшированных страниц, аhook_init()
не для кэшированных страниц.Наконец, в качестве примера кода, используемого из модуля Drupal, см. Statistics_exit () . Модуль Статистика регистрирует статистику доступа для сайта, и, как вы видите, он использует
hook_exit()
, а неhook_init()
. Чтобы иметь возможность вызывать необходимые функции, он вызывает drupal_bootstrap (), передавая правильный параметр, например, в следующем коде.Обновить
Может быть, есть некоторая путаница о том, когда
hook_init()
вызывается.hook_init()
вызывается для каждого запроса страницы, если страница не кэширована. Он не вызывается один раз для каждого запроса страницы от одного и того же пользователя. Если вы посетите, например, http://example.com/admin/appearance/update , а затем http://example.com/admin/reports/status ,hook_init()
то вызовется дважды: по одному для каждой страницы.«Хук вызывается дважды» означает, что есть модуль, который выполняет следующий код, как только Drupal завершил свою загрузку.
Если это так, то следующая реализация
hook_init()
покажет одно и то же значение дважды.Если ваш код показан для
REQUEST_TIME
двух значений, для которых разница составляет 2 минуты, как в вашем случае, то ловушка не вызывается дважды, а вызывается один раз для каждой запрашиваемой страницы, как и должно быть.REQUEST_TIME
определяется в bootstrap.inc следующей строкой.Пока запрашиваемая в данный момент страница не возвращается в браузер, значение
REQUEST_TIME
не изменяется. Если вы видите другое значение, то вы смотрите значение, назначенное на другой странице запроса.источник
Я помню, как это часто происходило в Drupal 6 (не уверен, что это все еще происходит в Drupal 7), но я так и не понял, почему. Кажется, я помню, что где-то видел, что ядро Drupal не вызывает этот хук дважды.
Я всегда находил самый простой способ обойти это, используя статическую переменную, чтобы увидеть, был ли код уже запущен:
Это обеспечит запуск только один раз при загрузке одной страницы.
источник
hook_init()
реализациях, и некоторые из них с радостью избегают выполнения дважды подряд. Также возможно, что OPhook_init()
будет выполняться один раз в день, если счетчик подсчитывает количество последовательных дней, когда пользователи вошли на сайт.hook_init
проверки ОП, чтобы увидеть, запущен ли он уже один раз за день, и выручит ли он. Тогда все это становится не проблема в любом случаеВы можете обнаружить, что hook_init () вызывается несколько раз, если на странице происходит какой-либо AJAX (или вы загружаете изображения из частного каталога - хотя в этом я и не уверен). Есть несколько модулей, которые используют AJAX, чтобы помочь, например, обойти кеширование страниц для определенных элементов. Самый простой способ проверить это - открыть сетевой монитор в выбранном вами отладчике (Firefox или веб-инспектор) и проверить, есть ли какие-либо запросы. сделаны, которые могут запускать процесс начальной загрузки.
Вы получите dpm () только при загрузке следующей страницы, если это AJAX-вызов. Допустим, вы обновили страницу через 5 минут, вы получите вызов AJAX из сообщения инициализации 5 минут назад, а также свежее сообщение.
Альтернативой hook_init () является hook_boot (), который вызывается до того, как будет выполнено какое-либо кэширование. Модули еще не загружены, так что у вас действительно нет особой мощности, кроме установки глобальных переменных и запуска нескольких функций Drupal. Это полезно для обхода обычного уровня кэширования (но не будет обходить агрессивное кэширование).
источник
В моем случае это было вызвано модулем Меню администрирования (admin_menu).
hook_init не вызывается при каждом запросе, но меню администратора может привести к тому, что / js / admin_menu / cache / 94614e34b017b19a78878d7b96ccab55 будет загружен браузером пользователя вскоре после основного запроса, что вызовет еще одну загрузку drupal.
Будут другие модули, которые делают подобные вещи, но admin_menu, вероятно, является одним из наиболее распространенных.
источник