Comment choisir entre module_exists et function_exists?

8

Je suis familier avec l'utilisation module_existsdans un module et je l'utilise dans des situations comme:

Cependant, il y en a aussi function_exists, comme le montre la réponse à " Est-il possible de déclarer une dépendance de bibliothèque Javascript sur Hook.info? ".

J'ai l'impression que l'utilisation function_existsest une approche plus robuste (sûre) par rapport à module_exists. Surtout si vous voulez être sûr qu'une fonction (ajoutée dans une nouvelle version d'un module) est disponible, alors qu'en utilisant simplement module_exists, vous risquez de rencontrer des erreurs comme celles-ci:

  • si un site est encore en utilisant une ancienne version d'un module, qui ne dispose pas de cette fonction encore (vous ne devriez pas essayer de l' utiliser encore ).
  • si un site est déjà en utilisant une nouvelle version d'un module, qui n'a pas cette fonction plus (vous ne devriez pas essayer de l' utiliser plus ).

Ma question : quels sont les critères typiques, ou les avantages / inconvénients, pour décider d'utiliser l'un module_existsou l' autre contre function_exists?

Pierre.Vriens
la source

Réponses:

13

Vous devez toujours programmer l'API et non l'implémentation. Si Drupal fournit un mécanisme pour faire quelque chose, utilisez-le.

module_exists()devrait presque toujours être utilisé pour les dépendances logicielles sur quelque chose fourni par un module Drupal. Vous pouvez toujours obtenir des informations sur la version et décider quoi faire en utilisant system_get_info(). Il y a eu des cas où des fonctions sont disponibles lorsque des modules ont été désactivés (certains modules de chargeur automatique de classe ont ce problème).

function_exists()doit être réservé pour vérifier si une fonctionnalité ou une bibliothèque PHP est disponible. Core en a quelques exemples dans certains drupal_wrappers pour la manipulation de chaînes et la conversion de jeux de caractères.

mpdonadio
la source
10

module_existsest une fonction de l'API Drupal utilisée pour déterminer si un module est installé , elle n'est pas conçue pour donner des garanties sur les fonctionnalités qu'un module peut contenir, y compris les fonctions qu'il déclare.

function_exists est une fonction de base PHP qui détermine littéralement si une fonction avec un nom donné existe dans la requête actuelle.

En tant que tels, ils ne sont pas vraiment comparables les uns aux autres, vous les utilisez pour différentes choses. En fait, il serait facile, quoique potentiellement redondant, de se compléter, par exemple

// Do something with a specific module 
if (module_exists('foo')) {
  // Check what's available 
  if (function_exists('foo_bar')) {
    // ...
  }
  elseif (function_exists('foo_baz')) {
    // ...
  }
}
Clive
la source
Je suis d'accord qu'ils ne sont pas vraiment comparables les uns aux autres
Jimmy Ko
Voulez-vous dire que le module de bibliothèque se connecte MODULENAME_requirementsdans le post lié? Oui, cela aurait plus de sens comme un appel à module_exists. Comme MPD l'a mentionné, la manière la plus avancée / la plus abstraite de garantir qu'une dépendance possède certaines fonctionnalités consiste à examiner le code pour une version et à faire en sorte que votre code s'appuie sur une version spécifique avec laquelle vous savez que votre code fonctionne. Tout comme le font Composer / NPM / Bundler / etc
Clive
4

Vous avez raison, function_existsest un moyen plus robuste de vérifier l'existence de la fonction API fournie par le module contrib. Il est très approprié pour utiliser directement l'API du module contrib.

J'utilise l' API Session Cache comme exemple:

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

Cependant, certains modules contrib ne fournissent que des propriétés ou fonctionnalités supplémentaires, il est très difficile de dire quelle fonction dépend. Dans ce cas, vous devez utilisermodule_exists

J'utilise Elements comme exemple:

if (module_exists('elements')) {
  $form['url'] = array(
    '#type' => 'urlfield',
    // other code
  );
}
else {
  $form['url'] = array(
    '#type' => 'textfield',
    // other code
  );
}
Jimmy Ko
la source
Intéressant! J'aurai besoin de plus de temps pour "digérer" ...
Pierre.Vriens
1
Comment sauriez-vous si session_cache_setest fourni par drupal.org/project/session_cache ou un autre module, et fait donc ce que vous voulez?
mpdonadio
1
@MPD Cela dépend si vous croyez que tout le monde utilise la même stratégie de nommage que celle suggérée. function_existspeut empêcher une erreur de fonction non définie lorsque le module contrib a changé son API après la mise à jour. Bien sûr, la méthode la plus garantie est envelopper function_existsavec module_exitscomme @Clive mentionné, mais, pour moi, il est trop fastidieux.
Jimmy Ko
1
@MPD Théoriquement, répondre à l'interface est une meilleure approche, et j'adorerais suivre. Mais en pratique, function_exitsévitez en effet que le site ne tombe complètement en panne ...
Jimmy Ko
4

Les 3 réponses (intéressantes) précédentes m'apparaissent comme confirmant en quelque sorte ma «perception» (comme je l'ai décrit dans ma question). Il est intéressant de noter que ces réponses ont été écrites à l'origine indépendamment les unes des autres (elles ont été publiées à peu près au même moment, comme illustré dans la chronologie de cette question , utilisez le "format bascule" pour voir les "minutes").

La réponse de Jimmy Ko (+ commentaires en dessous), illustre quelques autres exemples de la façon dont l'utilisation function_existspeut rendre un module plus robuste par rapport aux changements possibles dans un autre module qu'un module utilise (dépend).

La réponse de Clive montre que vous pouvez aussi bien combiner module_existset function_exists, alors que le commentaire ci-dessous résout mes doutes sur mon function_existsexemple (c'est-à-dire qu'il devrait plutôt utiliser module_exists).

La réponse de mpdonadio (+ commentaires en dessous) est, du moins pour moi, la plus difficile à digérer. Mais après avoir examiné le commentaire de Shawn Conn ci-dessous, j'ai trouvé quelques liens supplémentaires qui fournissent plus de détails sur tout cela, à savoir:

"Ma conclusion" (après avoir digéré les réponses précédentes): Laissez le Drupal core utiliser function_exists, et les modules contribués / personnalisés devraient essayer, autant que possible, de respecter module_exists... bien qu'il y ait des exceptions ...

Pierre.Vriens
la source