7

I have a module that I am porting to Drupal 7 (specifically, Taxonomy Views Integrator) and there are 2 include files tvi.admin.inc which were included via the module's .info file:

files[] = includes/tvi.admin.inc

The tvi.admin.inc houses the functions that the tvi.module's hook_form_alter() uses, including the validation & submit functions

Although alterations made using the hook_form_alter() work properly, after submit the validation & submit functions in tvi.admin.inc are not available and throw an undeclared function error.

p.s.

I've checked the initial issue for the extended .info module registry via: http://drupal.org/node/224333#registry and it does say the following which may provide us with an answer:

Files containing only functions need not be listed in the .info file.

As a Workaround,

I now use module_load_include() to load the tvi.admin.inc at the top of the tvi.module which, on form submit, still includes the inc and thus the validation / submit functions.

2 Answers 2

16

Files listed in .info files are not automatically included when the module is loaded; they are loaded when a module tries to create an object for a class that PHP doesn't find. In that case, a callback registered with spl_autoload_register() will check the content of the Drupal registry to find which file needs to be loaded to allow the creation of the object.

The only way to load a file containing a function is to use module_load_include().
In the specific case, where the function to load is a form validation handler (or a form submission handler) that is added to a form altered with hook_form_alter() (or hook_form_FORM_ID_alter()), I would rather keep the form handlers in the same file containing the hook implementation. Technically, the file is loaded by hook_form_alter() when it is not necessary, as the form handlers are used after the form has been submitted; so far the code worked, but it is not said that it would not work in future versions of Drupal.

Drupal 7 allows modules to implement hook_hook_info(), which is used from Drupal to know in which files the hook implementations are defined. The System module define its own implementation, which contains the following code:

function system_hook_info() {
  $hooks['token_info'] = array(
    'group' => 'tokens',
  );
  $hooks['token_info_alter'] = array(
    'group' => 'tokens',
  );
  $hooks['tokens'] = array(
    'group' => 'tokens',
  );
  $hooks['tokens_alter'] = array(
    'group' => 'tokens',
  );

  return $hooks;
}

With this implementation of the hook, when Drupal is looking for the file containing the implementation of hook_tokens() for the module custom.module, it will look for the file custom.tokens.inc contained in the directory where the module custom.module is installed.
Third-party modules are allowed to implement their own hook_hook_info(), but it should be remembered they are modifying where Drupal looks for the hook implemented by other modules too, which means that changing the group for hook_token_alter() changes the files where Drupal looks for any implementation of hook_token_alter().

It is possible to use hook_hook_info() to keep some hooks in a file that is different from the module file, using an implementation similar to the following:

function custom_hook_info() {
  return array(
    'form_alter' => array(
      'group' => 'form',
    ),
  );
}

What I reported before is still valid; future versions of Drupal could stop working because they would not find where the form handlers are, even though they know where to find the implementation of hook_form_alter().
This is the reason I keep to put the implementation of hook_form_alter() (or hook_form_FORM_ID_alter()) and every related form handler in the module file.

3
  • So creating mymodile.forms.inc and having hook_form_alter, and post-processing functions (submit / validate) in there makes sense? (and of course using module_load_include() in the mymodule.module to get it loaded properly)
    – electblake
    Commented Mar 16, 2011 at 18:24
  • 1
    I will expand my answer to reply in detail about that.
    – avpaderno
    Commented Mar 16, 2011 at 18:32
  • 3
    The standard is to have a module.pages.inc and a module.admin.inc to place all page callbacks (including forms) in their (admin for admin-specific callbacks). The advantage of that is that these files only need to be parsed if your module is serving the current page. If you move functions in separate files but include them on every request, then you're not gaining much. Performance is worse (a tiny bit) and you need to manually take care of loading the files. Drupal 7 has support for defining that certain hooks can be in a module.hook_group.inc file, they will be automatically loaded then.
    – Berdir
    Commented Mar 16, 2011 at 18:33
2

Only classes are tracked and automatically included. Everything else needs to be included manually.

Also, I'm not really sure what you are doing here, you do not need to alter your own forms. Second, _submit()/_validate() callbacks should be in the same file as the form function itself then you don't need to include them manually.

1
  • I inherited the files[] in .info so wasn't sure the decision there - but it did seem to make sense at the beginning. As for the form, it is not my own, it's a vocabulary/term forms - it adds additional settings specific to the TVI module. I've actually already restructured so that all form stuff is in one file vs. separated like it was. Thanks tho on classes vs. functions in files[] though!
    – electblake
    Commented Mar 16, 2011 at 16:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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