A module is a collection of functions that link into Backdrop, providing additional functionality for your Backdrop installation. Modules are the essential functional building blocks of a Backdrop site. The list of available modules on a site can be viewed /admin/modules/list (Functionality > Modules).
Sample module template
There is a template of a sample module on GitHub. You can use this as a "skeleton" for your own module; just change my_module
everywhere to the name of your desired module, then modify the individual functions and/or add your desired additional functionality.
Contents of a module directory
Modules are comprised of a module directory, usually named after the main module it contains, containing files and directories. Core modules are found in the BACKDROP_ROOT/core/modules directory; contributed modules in the BACKDROP_ROOT/modules directory. A module directory may have the following example structure (although not all of these are required, as explained below):
BACKDROP_ROOT/modules
my_module
my_module.info
my_module.module
my_module.theme.inc
my_module.admin.inc
my_module.pages.inc
css
my_module.css
my_module.admin.css
my_module.theme.css
js
my_module.js
my_other_js.js
templates
my_module_display.tpl.php
another_display.tpl.php
config
my_module.settings.json
libraries
libname
libname.php
libname.css
libname.js
includes
my_module.class.inc
modules
submodule
submodule.info
submodule.module
tests
my_module.tests.info
my_module.test
LICENSE.txt
README.md
About the module file components
The .info file
All modules require an .info file to tell Backdrop about the module. Contents of a module .info file may vary and are explained in greater detail below. The internal name of the module is also derived from this file. For example, if it is named "my_module.info", then Backdrop will see the name of the module as "my_module".
The .module file
The .module file usually contains the code which allows a module to do its magic.
Module files begin with the opening <?php
tag. As per the Coding standards, omit the closing ?>
tag. Including the closing tag may cause strange runtime issues on certain server setups. (Note that the examples in documentation will show the closing tag for formatting reasons only and you should not include it in your real code.)
All functions in your module that will be used directly by Backdrop are "hooks" named {modulename}_{functionname}, where "functionname" is a pre-defined function name suffix. Backdrop will call these functions to get specific data, so having these well-defined names means Backdrop knows where to look. We will come to hooks in a while.
Other contents of the module directory.
The .info and .module files are the only required files. Other files may be included to allow the module to work. The sample files shown in My Module above demonstrate the recommended conventions for organizing additional files within the module directory.
.theme.inc, .admin.inc, and.pages.inc files are recommended to be kept in the root of the module folder to allow ease of recognition of the way the module likely works. This makes it more obvious that the module provides theme functions, has an admin page, and probably provides display pages in some way. If there are multiple of these files however, it is reasonable to move these files to an includes folder in the module root.
JavaScript files are always kept in a /js folder, CSS in a /css folder, templates in a /templates folder, and tests in a /tests folder, as demonstrated in My Module above. CSS files follow a particular naming convention, see CSS naming conventions.
More about module .info files
The following is a sample .info file:
name = Dragon Builder
description = Provides a list of dragons.
backdrop = 1.x
package = Views
tags[] = Development
tags[] = Layouts
type = module
maintainers[dragon_drop] = Dragon Drop
maintainers_wanted = TRUE
dependencies[] = views
dependencies[] = panels
configure = admin/config/content/example
The .info file should have the same name as the .module file and reside in the same directory. For example, if your module is named example.module then your .info file should be named example.info.
This file is in standard .ini file format, which defines properties in key/value pairs separated by an equals sign (key = value). You may use quotation marks to wrap the value. Quoted values may contain newlines.
.info files may contain comments. A semi-colon [;] placed at the beginning of a line makes that line a comment, and that line will not be parsed.
Note: Whenever you create or change your .info file, you will need to clear your site's cache for your changes to take effect.
Properties
The .info file can contain the following properties:
name (Required)
name = Really Neat Widget
This displays the name of your module, which will appear on the Modules page. The general rules that apply to module names are:
- Since module names are proper names, they should be capitalized as such (capitalize all words in the name - including any "helper" words, such as "the", "of", "for" etc.). So it should for example be "Cool Things For Sites"; not "cool things for sites", nor "Cool things for sites", nor "Cool Things for Sites").
- It should be a human-readable name (not "cool_things_for_sites").
- If your module name includes an acronym (CSS, WYSIWYG, UI, etc.) or a third-party trade name (jQuery, JavaScript), of course follow the official capitalization for those (the way their owners capitalize them).
description (Recommended)
description = Provides a really neat widget for your site's sidebar.
A short, preferably one-line description that will tell the administrator what this module does on the module administration page. Remember, overly long descriptions can make this page difficult to work with, so please try to be concise. This field is limited to 255 characters.
Descriptions can contain links to documentation and sources. The following example shows a link to the author. It could be a link to a documentation node on Backdropcms.org. This is useful when the online documentation is better than the README.md file, and when you want to read about a module before switching it on.
description = Domain manager by <a href="http://dragonbuilder.com">DragonBuilder.com</a>.
backdrop (Required)
backdrop = 1.x
The version of Backdrop that your module is for. For Backdrop this would be 1.x, etc. Note that modules cannot specify the minor version of a branch of Backdrop. 1.x is correct; 1.2 is not.
type (Required)
type = module
The type of project. For a module, this will always be "module". Other available types are "theme" or "layout". Although this property is not required to enable the module, it is required to properly package the module on BackdropCMS.org and thus should always be included.
maintainers (Recommended)
maintainers[dragon_drop] = Dragon Drop
Adding the maintainer(s) of the project to the .info file will provide a reliable machine readable way of linking projects to the people responsible for them, providing benefits for maintainers but also for the wider Backdrop community. The maintainer's GitHub username must be in the square brackets ([]
) and a human readable name must be after the equals sign, though this can be the same if you only want your GitHub username to be used.
If there is no need or desire for other maintainers then that is all that is needed. If you wish to indicate that more maintainers would be welcome add the following line:
maintainers_wanted = TRUE
If a project has no registered maintainer then add the following line:
maintainers_none = TRUE
These lines will help to reliably populate lists of projects where maintainers are needed or wanted.
stylesheets (Optional)
stylesheets[all][] = node.css
Backdrop allows you to add CSS files in the module's .info file if it should be added on every page, just like theme .info files do. This is an example from the node module's .info file.
scripts (Optional)
scripts[] = somescript.js
You can now add Javascript in the module's .info file if it should be added on every page. This allows Javascript to be aggregated in an optimal way, and is the preferred method of adding Javascript that most visitors will need on a typical site visit.
files (deprecated)
Backdrop does not support loading of Classes from the .info files[] array, but uses the new hook_autoload_info(). See the change record "The class registry has been replaced with a static class map" for further information.
dependencies (Optional)
dependencies[] = taxonomy
dependencies[] = comment
An array of other modules that your module requires. If these modules are not present, your module cannot be enabled. If these modules are present but not enabled, the administrator will be prompted with a list of additional modules to enable and may choose to enable the required modules as well, or cancel at that point.
The string value of each dependency must be the module filename (excluding ".module") and should be written in lowercase. Spaces are not allowed.
If you need to specify that a certain module's version number is required Backdrop provides a way for this in the dependencies[] field. Version numbers are optional and only necessary if the module absolutely requires another module's specific version or branch.
The syntax for the dependencies[] field(s) is:
dependencies[] = modulename (major.minor.bugfix)
Where major is the numeric major version number and minor is the numeric or alphanumeric minor version number. x can be used to denote any minor or bugfix version. Some examples follow.
dependencies[] = exampleapi (1.x)
In the above .info code, the "Example" module requires an "Example API" module with the major version of 1 and any minor version.
dependencies[] = exampleapi (1.0.0)
This means that the module requires the 1.0.0 (and only the 1.0.0) version of the Example API module.
dependencies[] = exampleapi (1.x)
The above module requires any minor version of the module in the 1.x branch (1.0.0, 1.0.1, 1.1.0, 1.2-beta4, etc.)
The dependencies[] property in the .info file can also optionally specify versions:
dependencies[] = exampleapi (>1.0.0)
The above module requires any version greater than version 1.0.0.
You can optionally specify the core version number as well:
dependencies[] = exampleapi (>1.x-1.5.0)
The above module requires a 1.x version compatible version of the module and a version greater than 1.5.
Additionally, multiple version dependencies can be specified as comma-separated values within the parentheses:
dependencies[] = exampleapi (>1.0, <=3.2, !=3.0)
This facility can be used to specify a minimal core version by using system
as the module name:
dependencies[] = system (>=1.5.3)
This makes the module require at least Backdrop 1.5.3.
package (Optional)
package = Views
If your module comes with other modules or is meant to be used exclusively with other modules, enter the name of the package here. If left blank, the module will be listed as 'Other'. In general, this property should only be used by large multi-module packages, or by modules meant to extend these packages, such as Fields, Views, Commerce, Organic Groups, and the like. All other modules should leave this blank. As a guideline, four or more modules that depend on each other (or all on a single module) make a good candidate for a package. Fewer probably do not. An exception to this rule is the "Development" package, which should be used for any modules which are code development tool modules.
If present, the package string groups modules together on the module administration page (admin/modules); the string should therefore be the heading you would like your modules to appear under, and it needs to be consistent (in spelling and capitalization) in all .info files in which it appears. It should not use punctuation and it should follow the Backdrop capitalization standard as noted above.
Capitalization is important because package string is case sensitive, and using package = fields
in one module and package = Fields
in another would yield two different packages on the module administration page. This can be highly confusing as Seven (the default administrative theme) capitalizes fieldset legends, making fields
and Fields
indistinguishable. Using package = Fields
is the correct way.
For a complete list of Packages as provided by Backdrop core, see Module "Packages" and "Tags".
tags (Optional)
tags[] = Development
tags[] = Layouts
Tags are meant to supplement the "package" grouping. They are intended to better suit modules that either have no suitable package, or for those that have many suitable packages.
Choose any number of tags for your contributed module. Core packages may also be used as tags. If there are no suitable tags, feel free to add your own! Note: your module's package will automatically be included as a tag, there is no need to duplicate the Package.
For a complete list of Tags as provided by Backdrop core, see Module "Packages" and "Tags".
php (Optional)
php = 5.3
Modules and themes may specify a minimum PHP version that they require.
That specifies that the module/theme will not work with a version of PHP earlier than 5.3. That is useful if the module makes use of features added in later versions of PHP (improved XML handling, object iterators, JSON, etc.). If no version is specified, it is assumed to be the same as the required PHP version for Backdrop core. Modules should generally not specify a required version unless they specifically need a higher later version of PHP than is required by core. See the PHP Manual for further details on PHP version strings.
version (Optional)
version = 1.0.2
You can give your module whatever version string is appropriate.
configure (Optional)
configure = admin/config/content/example
The path of the module's (main) configuration page.
If a module is enabled, a "Configure" and "Permissions" link appear. This will be the path of the "Configure" link for this particular module on the modules overview page.
required (Optional)
required = TRUE
Modules and themes may specify that they are absolutely required and should never be disabled by adding required = TRUE
. These modules will be enabled automatically during install. In most cases it should only be used with the Backdrop core required modules (e.g. Node, User, etc.). Setting this property to TRUE
will also automatically hide the module/theme from the module/theme listing pages.
disabled (Optional)
disabled = TRUE
If this property is specified for a module or a theme and its value set to TRUE
, then the project will be visible in the list of modules/themes, but the checkbox for enabling/disabling it will be locked. Although this property may not be useful to be set directly in the .info file, it may be altered via a HOOK_system_info_alter()
hook implementation to prevent (other) modules/themes from being disabled when certain conditions apply.
hidden (Optional)
hidden = TRUE
Modules and themes may specify that they should not be visible on the modules page by adding hidden = TRUE
. This is commonly used with testing modules used with SimpleTest where end-users should never enable the testing modules.
About hooks
Hooks are fundamental to Backdrop modules. They allow you to integrate your module into the actions of Backdrop core.
A Backdrop module is a collection of files containing some functionality and is written in PHP. Because the module code executes within the context of the site, it can use all the functions and access all variables and structures of Backdrop core. In fact, a module is no different from a regular PHP file that can be independently created and tested and then used to drive multiple functionalities.
This approach allows Backdrop core to call at specific places certain functions defined in modules and enhance the functionality of core. The places where code can be executed are called "hooks" and are defined by a fixed interface.
Hooks are how modules can interact with the core code of Backdrop. They make it possible for a module to define new urls and pages within the site (hook_menu
), to add content to pages (hook_block
), to set up custom database tables (hook_schema
), and more. This page lists the hooks provided in the core, but modules can define hooks of their own.
Hooks occur at various points in the thread of execution, where Backdrop seeks contributions from all the enabled modules. For example, when a user visits a help page on a Backdrop site, as Backdrop prepares to save a node it will give each module a chance to alter the $node object. It does this by scanning all the module code for functions that have the name MYMODULE_node_update($node)
, where MYMODULE
is the module's name, e.g., the block module's node update hook is called block_node_update
. MYMODULE
can then act on the $node
object which is being updated.
A hook can be thought of as an event listener in the sense that an event triggers an action. The event in Backdrop, such as deleting a node, would trigger the hook hook_delete
. If your module implemented hook_delete
, that function would run when a node deletion occurred. As an example, your function might be to decrease the count of the total number of nodes, so when a node was deleted, your function would be called and lower the count by 1.
See also the overview of module hooks, in the Backdrop API Reference.
An example hook
-
hook_menu
allows you to define a menu item that Backdrop will respond to at a path-
If you are writing a module named
my_module
then you can define some path(s) where the module will provide content, user facing forms, or admin config forms withhook_menu
. Here is an example where we want to consume a feed from an external data source:
-
If you are writing a module named
/**
* Implements hook_menu().
*/
function my_module_menu() {
$items['my-path'] = array(
'title' => 'My Feed',
'description' => 'Get data from another website feed, parse it and display it on our Backdrop site.',
'page callback' => 'my_module_get_data',
'access callback' => TRUE,
);
return $items;
}
Let's break down the elements here:
-
'title' => 'My Feed',
- Sets the title on the page, replace "My Feed" with the title you want for your page.
-
'description' => 'Get data from another website feed, parse it and display it on our Backdrop site.',
- Describe the page you are going to display to users.
-
'page callback' => 'my_module_get_data',
-
This tells backdrop about the callback function to use for the page. When Backdrop receives a request in this case at
example.com/my-path
the hookmy_module_menu
will tell that request to use the callback function in this casemy_module_get_data
.
-
This tells backdrop about the callback function to use for the page. When Backdrop receives a request in this case at
-
You would then define the function
my_module_get_data
later in themy_module.module
file. That might look something like this:
/**
* Callback function for the path my-path.
* Process the data from the feed and define output markup.
*
* return string $markup
* The $markup to return for the page request to /my-path
*/
function my_module_get_data() {
// Make request to external data feed, parse, and store in $markup variable.
return $markup;
}
-
'access callback' => TRUE,
-
The access callback to use for this path. In this case
TRUE
indicates that anyone including anonymous users can see the content at this path.
-
The access callback to use for this path. In this case
Enabling modules
To interact with Backdrop, modules need to be first enabled. Click on Functionality > Modules on the Admin Bar in the Backdrop installation and search for the desired module in the list, or find the module by typing into the Fast Search field. Enable the module and click 'Save configuration'.
Testing with SimpleTest
Backdrop includes testing capabilities in core. The Backdrop SimpleTest module is based on the SimpleTest PHP Library. If you are familiar with that framework, you should have no trouble learning its application in Backdrop.
Backdrop testing focuses on functional testing rather than unit testing. Functional tests check the interface as a whole rather than individual functions or finite pieces of code. This approach is more effective for the way Backdrop is written.
Part of the challenge of writing good tests is knowing what you need to test. The information you'll get from these tests won't tell you much about how the module really functions. These tests will expose you to the testing environment and several of the assertions.
Submitting a contrib module
The Backdrop development community uses GitHub to manage contrib modules. If you are not familiar with GitHub, you can read through some excellent documentation available on GitHub and other sites.
To get started, find instructions at https://github.com/backdrop-ops/contrib.