Как выбрать между module_exists и function_exists?

8

Я знаком с использованием module_existsв модуле, и использовать его в таких ситуациях, как:

Тем не менее, есть также function_exists, как показано в ответе на вопрос « Можно ли объявить зависимость библиотеки Javascript на Hook.info? ».

У меня сложилось впечатление, что использование function_existsявляется более надежным (безопасным) подходом по сравнению с module_exists. Особенно, если вы хотите быть уверены, что какая-то функция (добавленная в более новой версии модуля) доступна, тогда как, просто используя ее module_exists, вы рискуете столкнуться с такими ошибками:

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

Мой вопрос : каковы типичные критерии, или плюсы / минусы, чтобы выбрать для использования либо module_existsпротив function_exists?

Pierre.Vriens
источник

Ответы:

13

Вы всегда должны программировать на API, а не на реализацию. Если Drupal предоставляет механизм для чего-то, используйте его.

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

function_exists()должен быть зарезервирован для проверки, доступна ли функция или библиотека PHP. В Core есть несколько примеров этого в некоторых drupal_оболочках для манипулирования строками и преобразования набора символов.

mpdonadio
источник
10

module_existsявляется функцией API Drupal используется для определения , является ли модуль установлен , он не предназначен , чтобы давать какие - либо гарантии функциональности модуля может содержать, в том числе , какие функции он заявляет.

function_exists является основной функцией PHP, которая буквально определяет, существует ли функция с данным именем в текущем запросе.

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

// Do something with a specific module 
if (module_exists('foo')) {
  // Check what's available 
  if (function_exists('foo_bar')) {
    // ...
  }
  elseif (function_exists('foo_baz')) {
    // ...
  }
}
Клайв
источник
Я согласен, что они на самом деле не сопоставимы друг с другом
Джимми Ко,
Ты имеешь в виду, что модуль библиотеки регистрируется MODULENAME_requirementsв связанном посте? Да, это будет иметь больше смысла, как призыв к module_exists. Как упоминалось в MPD, высокоуровневый / более абстрактный способ убедиться, что зависимость имеет определенные функции, - это проверить код для выпуска и заставить ваш код полагаться на конкретную версию, с которой, как вы знаете, работает ваш код. Точно так же, как это делают Composer / NPM / Bundler / etc
Клайв
4

Вы правы, function_existsэто более надежный способ проверить наличие функции API, предоставляемой модулем contrib. Это очень удобно для непосредственного использования API модуля contrib.

Я использую Session Cache API в качестве примера:

if (function_exists('session_cache_set')) {
  session_cache_set($bin, $data)
}

Однако некоторые модули contrib предоставляют только некоторые дополнительные свойства или функции, очень сложно сказать, какая это зависимая функция. В этом случае вам нужно использоватьmodule_exists

Я использую Элементы в качестве примера:

if (module_exists('elements')) {
  $form['url'] = array(
    '#type' => 'urlfield',
    // other code
  );
}
else {
  $form['url'] = array(
    '#type' => 'textfield',
    // other code
  );
}
Джимми Ко
источник
Интересно! Мне нужно еще немного времени, чтобы "переварить" ...
Pierre.Vriens
1
Как бы вы узнали, session_cache_setпредоставляется ли это drupal.org/project/session_cache или другим модулем и, следовательно, выполняет то, что вы хотите?
mpdonadio
1
@MPD Это зависит от того, верите ли вы, что каждый использует ту же стратегию именования, что и предложено. function_existsможет предотвратить неопределенную ошибку функции, когда модуль contrib изменил свой API после обновления. Конечно, наиболее гарантия способ обернуть function_existsс , module_exitsкак указано @Clive, но для меня это слишком утомительно.
Джимми Ко
1
@MPD Теоретически, отвечающий интерфейс - лучший подход, и я хотел бы следовать. Но на практике, function_exitsдействительно, препятствуйте тому, чтобы сайт полностью разрушился ...
Джимми Ко
4

Предыдущие 3 (интересные) ответы кажутся мне как-то подтверждающими мое «восприятие» (как я описал в своем вопросе). Интересно, что эти ответы изначально были написаны независимо друг от друга (они были опубликованы примерно в тот же момент, как показано на временной шкале этого вопроса , используйте «формат переключения», чтобы увидеть «мин»).

Ответ Джимми Ко (+ комментарии под ним) иллюстрирует еще несколько примеров того, как использование function_existsможет сделать модуль более устойчивым в отношении возможных изменений в каком-либо другом модуле, который модуль использует (зависит от).

Ответ Клайва показывает, что вы также можете объединить, module_existsи function_existsхотя приведенный ниже комментарий разрешил мои сомнения по поводу моего function_existsпримера (то есть его лучше использовать module_exists).

Ответ mpdonadio (+ комментарии под ним), по крайней мере для меня, самый сложный для восприятия. Но после просмотра комментария Шона Конна под ним я нашел еще несколько ссылок, которые предоставляют более подробную информацию обо всем этом, а именно:

«Мой вывод» (после переваривания предыдущих ответов): оставьте это для использования ядром Drupal function_exists, и добавленные / пользовательские модули должны стараться, насколько это возможно, придерживаться module_exists... хотя есть исключения ...

Pierre.Vriens
источник