hook_module_implements_alter (), чтобы помещать реализации крюка в отдельные файлы - плохая практика?

В ряде модулей, которые я написал, я использую hook_module_implements_alter (), чтобы разбить файл * .module и переместить реализации крюка в отдельные файлы.

Основная причина в том, что я страстно ненавижу длинные файлы. (и да, это делает меня недовольным большим количеством файлов в Drupal 7 и contrib)

Примеры:

Я знаю, что есть несколько вещей, которые следует учитывать:

  1. Это может не сработать для всех перехватчиков. Например. загрузите или установите, или перехватчики, которые не вызываются через module_implements ().
  2. Важно включить соответствующий файл из реализации hook_module_implements_alter () из-за того, как работает module_implements ().

Теперь я услышал от давнего и известного разработчика Drupal, что эта практика проблематична. https://drupal.org/node/2230319 (тема стартера и комментарии # 5 и # 11) .

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

EDIT: Я думаю, это можно разделить на два вопроса:

  1. Хорошо или плохо разделить ваш файл * .module, чтобы реализация перехвата выполнялась в другом месте?
  2. Достаточно ли hook_module_implements_alter () достаточно, или я должен использовать include_once __DIR__ . '/MYMODULE.filename.inc' непосредственно в файле * .module? Что может пойти не так, используя hook_module_implements_alter () для этого?
7 голосов | спросил donquixote 2 PMpWed, 02 Apr 2014 23:29:58 +040029Wednesday 2014, 23:29:58

3 ответа


4

Я просто нашел часть информации, которая отсутствовала.
EDIT: И еще один.

Проблема с module_invoke ()

module_invoke_all() всегда вызывает module_implements(), который проверяет модуль, включает файл, проверяя как hook_hook_info() и hook_module_implements_alter().

Однако module_invoke() проверяет только hook_hook_info() и не hook_module_implements_alter().

module_invoke() вызывается, например. в _block_render_blocks() для hook_block_view(). Это означает, что hook_module_implements_alter() не является хорошим решением для разделения hook_block_view() в отдельный файл.

Это проблема в крошках, см. https://www.drupal.org/node/2328535 .

Для других крючков он обычно работает нормально, но вы никогда не знаете, хочет ли конкретный модуль использовать module_invoke() вместо module_invoke_all()

Ключ module_implements (), загрязненный в бутстрапе.

Другая проблема связана с основной проблемой, описанной здесь:
module_implements_cache () может быть загрязнен hook_boot (), которые прямо или косвенно вызывают module_invoke_all ()

Это относится только к не-загрузочным модулям , где может случиться, что реализация hook_module_implements_alter() никогда не было обнаружено.

  1. Неожиданная цепочка событий вызывает вызов module_implements($hook) из hook_boot()
    . $hook может быть любым случайным крючком, он не должен быть связан с модулем, над которым мы работаем.
  2. Это вызывает вызов module_implements('module_implements_alter').
  3. Drupal ищет все реализации hook_module_implements_alter(). В это время MODULENAME.module еще не включен.
    Поэтому для остальной части запроса Drupal предполагает, что реализация MODULENAME_module_implements_alter() не существует.
  4. Позже в запросе обнаруживаются реализации других крючков, но реализации MODULENAME не найдены, потому что MODULENAME_module_implements_alter() не выполняется.

Альтернативы

require_once

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

Но вместо использования module_load_include(), я бы предложил более прямое решение:

require_once __DIR__ . '/crumbs.block.inc';

Или для совместимости с PHP 5.2:

require_once dirname(__FILE__) . '/crumbs.block.inc';

Почему не module_load_include ()?

Как правило, нет необходимости вызывать module_load_include(), это может быть даже вредным, если файл * .module включен из вас - dont-know-where (например, из settings.php), и вы не знаете, если module_load_include().

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

Вызов вспомогательной функции

Как упоминалось в Jimajamma, вы также можете реализовать hook в главном файле *.module, а затем включить другой файл и вызвать помощника функция оттуда. Это делается, например, в окне отображения.

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

И здесь вы также можете использовать require_once вместо module_load_include(), если он находится в одном модуле.

ответил donquixote 8 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowMon, 08 Sep 2014 20:17:44 +0400 2014, 20:17:44
2

Любой крупный проект, над которым я работал, разбил все на управляемые и легко назначаемые части; в основном заканчивается, как упоминается здесь @tenken, или до точки, в которой foo.module заканчивается только включением:

<?php

module_load_include('inc', 'foo', 'foo.defines');         // bring in our define()s
module_load_include('inc', 'foo', 'foo.HOOK1');           // bring in our HOOK1 functions
module_load_include('inc', 'foo', 'foo.HOOK2');           // bring in our HOOK2 functions

// ...etc

Конечно, я также видел и использовал ситуации, в которых только администратор или иначе редко использовал крючки, например:

function foo_HOOK(/* $args */) {
  module_load_include('inc', 'foo', 'foo.HOOK');
  return _foo_HOOK(/* $args */);  // _foo_hook() is defined in foo.HOOK.inc
}
ответил Jimajamma 3 AMpThu, 03 Apr 2014 08:15:21 +040015Thursday 2014, 08:15:21
1

Если я пытаюсь разбить мой файл .module на несколько файлов, я, как правило, делаю то, что делает для D7 для своих «включенных» файлов, которые он использует include_once () для:

include_once('MYMODULE.features.inc');

Для D7 я по-прежнему использую имя моего модуля «пространство имен функций» для этих включенных файлов, а функции частного модуля обычно префиксны как «_MYMODULE_foo ()».

Этот ответ kinda игнорирует ваше желаемое использование классов автозагрузки и любых связанных с OO шаблонов, которые вы пытаетесь использовать в своем коде (зависимости от кода и т. д.).

В вашей связанной проблеме похоже, что вы хотите использовать hook_module_implements_alter (), чтобы быть читаемым индексом того, какие файлы имеют то, что функционирует в вашем файле .module. Я думаю, что достаточно просто использовать «MYMODULE.PURPOSE.inc» для того, чтобы определить разработчика этого файла include в вашем модуле.

ответил tenken 3 AMpThu, 03 Apr 2014 04:52:23 +040052Thursday 2014, 04:52:23

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132