For ease of maintenance I want to split out related functionality in a module into separate .inc files.
e.g. "kat_foo_logic.inc"

If I do this do I just use "include_once" with the relative path name?

The coding standards state that from Drupal 7 onwards I should use:

require_once DRUPAL_ROOT . '/' . variable_get('cache_inc', 'includes/cache.inc');

but I have no idea why I would call "variable_get" as I never set anything with "variable_set"!

Thanks to anyone who can help.

Comments

redsd’s picture

it depends on how you load the data.

if your function points to a file other then your .module you can use:

function node_menu() {
  $items['admin/content'] = array(
    'title' => 'Content',
    'description' => 'Find and manage content.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('node_admin_content'),
    'access arguments' => array('access content overview'),
    'weight' => -10,
    'file' => 'node.admin.inc',
  );

This is from the node.module, node.admin.inc is in the same directory as the node.module.

if you want to load a file in a function you can use:

drupal_get_path('module', 'name_of_module');

replace name_of_module with your module name to retrieve the path of you module.
for more info: http://api.drupal.org/api/drupal/includes!common.inc/function/drupal_get_path/7

aBrookland’s picture

If you put class or interface declarations into a .inc file (eg my_module.foo.inc) and then reference that file in the files section of my_module.info then Drupal 7 will auto discover and remember the classes and interfaces in that .inc file and use PHP auto loading functionality whenever any of them are used so is no need to include or require the .inc file.

The my_module.info would look like this:

name = My module
core = 7.x
files[] = my_module.foo.inc

Drupal 7 only does the auto discover when the module is enabled so if you're developing a module and add the files[] line after the module is already enabled you'll need to clear the cache to get it working.

If you want to put functions in and inc file then you still need to include the file but the Drupal way of doing it is with module_load_include() which in this instance would be called:

module_load_include('inc', 'my_module', 'my_module.foo');

This way you don't need to know the full path to your module.

petr.hajek’s picture

In .module file can be included via

require_once dirname(__FILE__).'/my_module_include.inc';
Jaypan’s picture

That's not the Drupal way to do it.


Checkout my Japan podcasts.
TygrLili’s picture

I came across this thread to double-check my syntax and I started getting a little confused about the best practice for splitting some of my functions into a separate .inc file and having my module still know where to find them.

If the comment above is "not the Drupal way to do it," is there a more specific/helpful comment, example, documentation, etc. you can give or point us to that iterates "the Drupal way"?

leramos’s picture

Hi Nina,

You can use module_load_include function.

Refer to https://api.drupal.org/api/drupal/includes!module.inc/function/module_lo...

redsd's and aBrookland's comments also pointed out the "Drupal Way".

Regards

Jaypan’s picture

Hi Nina

Sorry I wasn't more specific with my comments - as leramos has pointed out, other posters had already pointed out the Drupal way, which is why I did not elaborate.


Checkout my Japan podcasts.
petr.hajek’s picture

Hi,
thanks for your answer, but in documentation of module_load_include is written

Do not use this function to load an install file, use module_load_install() instead. Do not use this function in a global context since it requires Drupal to be fully bootstrapped, use require_once DRUPAL_ROOT . '/path/file' instead.

So when I just want to split the code into more files for better readability, I think require_once is good way to do this. I use module_load_include in situactions when I want to load include in one specific function.

Thank you and best regards

Jaypan’s picture

That's still not the Drupal way to do it.

If you really want to split your module into multiple files, you are better using hook_hook_info() and putting your hooks into other files (that will be loaded automatically as necessary), and putting any other callbacks into .inc files that are loaded using module_load_include() as necessary.


Checkout my Japan podcasts.
ssibal’s picture

"hook_hook_info should be implemented by modules declaring new hooks for other modules to implement."

You can read more:
https://heine.familiedeelstra.com/hook-groups-are-for-hook-owners-only
https://www.drupal.org/node/960260

jmuzz’s picture

There are some good examples here about how to do other things the Drupal way such as including hooks in other files, including classes in other files, and including files from inside another function. The question though is how do we include a file with (for example) general purpose utility functions so we can call them from any of other place in our module without having to worry about whether or not it's loaded yet, just like when putting a function inside a .module file. The Drupal documentation quoted above recommends using require_once and so far it seems to be the only option suggested which will accomplish this.

Jaypan’s picture

The Drupal (7) way to do it is to put the functions in the .module file. Putting them in a separate file that is included on every page load just adds unnecessary page load.


Checkout my Japan podcasts.
jmuzz’s picture

Yeah but those files can get awfully big doing things that way.

I looked at some popular modules and it turns out entity and date are both using module_load_inc from the "global" context of their .module files. If modules don't get loaded until the bootstrapping is done then that might not be what they were trying to warn about.

Edit: Core modules file, field, and image all use require_once at the top of their module files.

sydkoh’s picture

you tend to do that tho... i've noticed

alexharries’s picture

I appreciate this is an old issue, but for completeness I thought it might be worth mentioning how Features includes files from the same directory, which is to add the following at the top of the .module file (and in fact, the Features .module files usually only contain these lines, unless you add custom code into yours):

<?php
/**
 * @file
 * Code for the Feature Name feature.
 */

include_once 'feature_name.features.inc';
?>

The problem with using module_load_include is that you have to put it into a hook_init or hook_boot, and sometimes neither has been run early enough if, for example, your .inc file contains a function which you want to call from another module whose weight is lower than the module providing the function, which will result in an undefined function fatal error.

Which isn't exactly ideal :)

So it's fine to use include, include_once, etc, if you are calling files from the same module, because you can use a relative path, but if you need to include a file from another module, there's no safe way to determine the correct include path without using module_load_include, as you need to get the path from the system table in the database.