I'm familiar with using module_exists in a module, and using it in situations like:

However, there is also function_exists, such as shown in the answer to "Is it possible to declare a Javascript library dependency at Hook.info?".

I have the impression that using function_exists is a more robust (safe) approach as compared to module_exists. Especially if you want to be sure that some function (added in a newer version of a module) is available, whereas by just using module_exists, you risk to run into errors like those:

  • if a site is still using an old version of a module, which doesn't have that function yet (so you shouldn't try to use it yet).
  • if a site is already using an new version of a module, which doesn't have that function anymore (so you shouldn't try to use it anymore).

My question: what are the typical criteria, or pros/cons, to decide for using either module_exists versus function_exists?

You should always program to the API and not the implementation. If Drupal provides a mechanism to do something, use it.

module_exists() should almost always be used for soft dependencies on something provided by a Drupal module. You can always get version info, and decide what to do, using system_get_info(). There have been cases where functions are available when modules have been disabled (some of the class autoloader modules have has this problem).

function_exists() should be reserved for checking whether a PHP feature or library is available. Core has some examples of this in some of the drupal_ wrappers for string manipulation and character set conversion.

module_exists is a Drupal API function used to determine whether a module is installed, it isn't designed to give any guarantees of the functionality a module might contain, including what functions it declares.

function_exists is a PHP core function which literally determines whether a function with a given name exists in the current request.

As such, they aren't really comparable with one another, you use them for different things. In fact it would be easy, albeit potentially redundant, for them to complement one another, e.g.

// Do something with a specific module 
if (module_exists('foo')) {
  // Check what's available 
  if (function_exists('foo_bar')) {
    // ...
  }
  elseif (function_exists('foo_baz')) {
    // ...
  }
}
  • I agree they aren't really comparable with one another – Jimmy Ko Aug 3 '16 at 18:20
  • Do you mean the library module check in MODULENAME_requirements in the linked post? Yes, that would make more sense as a call to module_exists. As MPD mentioned, the higher-level/more abstracted way to ensure that a dependancy has certain functionality is to examine the code for a release, and make your code rely on a specific version that you know your code works with. Just like Composer/NPM/Bundler/etc do it – Clive Aug 3 '16 at 20:45

You are right, function_exists is a more robust way to check the existence of the API function provided by contrib module. It is very suitable for directly using the contrib module's API.

I use Session Cache API as an example:

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

However, some contrib modules only provides some extra properties or feature, it is very hard to say which dependent function is. In this case, you need to use module_exists

I use Elements as an example:

if (module_exists('elements')) {
  $form['url'] = array(
    '#type' => 'urlfield',
    // other code
  );
}
else {
  $form['url'] = array(
    '#type' => 'textfield',
    // other code
  );
}
  • Interesting! I'll need some more time to "digest" ... – Pierre.Vriens Aug 3 '16 at 18:14
  • 1
    How would you know whether session_cache_set is being provided by drupal.org/project/session_cache or another module, and therefore does what you want? – mpdonadio Aug 3 '16 at 19:51
  • 1
    @MPD It depends on if you believe in everyone using the same naming strategy as suggested. function_exists can prevent undefined function error when the contrib module did change its API after update. Of course, the most guarantee method is wrap function_exists with module_exits as @Clive mentioned, but, to me, it is too tedious. – Jimmy Ko Aug 3 '16 at 20:06
  • 1
    @MPD Theoretically, replying interface is a better approach, and I would love to follow. But in practical, function_exits indeed prevent the site from completely brokering down... – Jimmy Ko Aug 3 '16 at 20:16
up vote 4 down vote accepted

The prior 3 (interesting) answers appear to me as somehow confirming my "perception" (as I described in my question). Interestingly enough, those answers were originally written independent from each other (they were posted at more or less the very same moment, as illustrated in the timeline of this question, use the "toggle format" to see "mins").

Jimmy Ko's answer (+ comments below it), illustrates some more examples of how using function_exists can make a module more robust with respect to possible changes in some other module that a module uses (depends on).

Clive's answer shows you could as well combine module_exists and function_exists, while the comment below it resolved my doubts about my function_exists example (ie it should rather use module_exists).

mpdonadio's answer (+comments below it) is, at least to me, the toughest to digest. But after reviewing Shawn Conn's comment below it, I found a few more links that provide more details about all this, i.e.:

"My conclusion" (after digesting the previous answers): Leave it to Drupal core to use function_exists, and contributed/custom modules should try, as much as possible, to stick to module_exists ... though there are exceptions ...

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.