Coding standards
Drupal Coding Standards
Note: The Drupal Coding Standards applies to code that is to become a part of Drupal. This document is based on the PEAR Coding standards.
Indenting
Use an indent of 2 spaces, with no tabs.
Control Structures
These include if, for, while, switch, etc. Here is an example if statement, since it is the most complicated of them:
if (condition1 || condition2) { action1; } elseif (condition3 && condition4) { action2; } else { defaultaction; }
Control statements should have one space between the control keyword and opening parenthesis, to distinguish them from function calls.
You are strongly encouraged to always use curly braces even in situations where they are technically optional. Having them increases readability and decreases the likelihood of logic errors being introduced when new lines are added.
For switch statements:
switch (condition) { case 1: action1; break; case 2: action2; break; default: defaultaction; break; }
Function Calls
Functions should be called with no spaces between the function name, the opening parenthesis, and the first parameter; spaces between commas and each parameter, and no space between the last parameter, the closing parenthesis, and the semicolon. Here's an example:
$var = foo($bar, $baz, $quux);
As displayed above, there should be one space on either side of an equals sign used to assign the return value of a function to a variable. In the case of a block of related assignments, more space may be inserted to promote readability:
$short = foo($bar); $long_variable = foo($baz);
Function Declarations
function funstuff_system($field) { $system["description"] = t("This module insert funny text into posts randomly."); return $system[$field]; }
Arguments with default values go at the end of the argument list. Always attempt to return a meaningful value from a function if one is appropriate.
Comments
Inline documentation for classes should follow the Doxygen convention. More information about Doxygen can be found here:
Note that Drupal uses the following docblock syntax:
/** * Comments. */
And all Doxygen commands should be prefixed with a @ instead of a /.
Non-documentation comments are strongly encouraged. A general rule of thumb is that if you look at a section of code and think "Wow, I don't want to try and describe that", you need to comment it before you forget how it works.
C style comments (/* */) and standard C++ comments (//) are both fine. Use of Perl/shell style comments (#) is discouraged.
Including Code
Anywhere you are unconditionally including a class file, use require_once(). Anywhere you are conditionally including a class file (for example, factory methods), use include_once(). Either of these will ensure that class files are included only once. They share the same file list, so you don't need to worry about mixing them - a file included with require_once() will not be included again by include_once().
Note: include_once() and require_once() are statements, not functions. You don't need parentheses around the filename to be included.
PHP Code Tags
Always use <?php ?> to delimit PHP code, not the <? ?> shorthand. This is required for Drupal compliance and is also the most portable way to include PHP code on differing operating systems and setups.
Header Comment Blocks
All source code files in the core Drupal distribution should contain the following comment block as the header:
<?php /* $Id$ */
This tag will be expanded by the CVS to contain useful information
<?php /* $Id: CODING_STANDARDS.html,v 1.4 2004/10/27 11:55:32 uwe Exp $ */
Using CVS
Include the Id CVS keyword in each file. As each file is edited, add this tag if it's not yet present (or replace existing forms such as "Last Modified:", etc.).
The rest of this section assumes that you have basic knowledge about CVS tags and branches.
CVS tags are used to label which revisions of the files in your package belong to a given release. Below is a list of the required CVS tags:
-
DRUPAL-X-Y
- (required) Used for tagging a release. If you don't use it, there's no way to go back and retrieve your package from the CVS server in the state it was in at the time of the release.
Example URLs
Use "example.com" for all example URLs, per RFC 2606.
Naming Conventions
Functions and Methods
Functions and methods should be named using lower caps and words should be separated with an underscore. Functions should in addition have the grouping/module name as a prefix, to avoid name collisions between modules.
Private class members (meaning class members that are intended to be used only from within the same class in which they are declared; PHP 4 does not support truly-enforceable private namespaces) are preceded by a single underscore. For example:
_node_get() $this->_status
Constants
Constants should always be all-uppercase, with underscores to separate words. Prefix constant names with the uppercased name of the module they are a part of.
Global Variables
If you need to define global variables, their name should start with a single underscore followed by the module/theme name and another underscore.
Filenames
All documentation files should have the filename extension ".txt" to make viewing them on Windows systems easier. Also, the filenames for such files should be all-caps (e.g. README.txt instead of readme.txt) while the extension itself is all-lowercase (i.e. txt instead of TXT).
Examples: README.txt, INSTALL.txt, TODO.txt, CHANGELOG.txt etc.
Doxygen formatting conventions
Doxygen is a documentation generation system. The documentation is extracted directly from the sources, which makes it much easier to keep the documentation consistent with the source code.
There is an excellent manual at the Doxygen site. The following notes pertain to the Drupal implementation of Doxygen.
-
General documentation syntax
-
To document a block of code, the syntax we use is:
/** * Documentation here */
Doxygen will parse any comments located in such a block. Our style is to use as few Doxygen-specific commands as possible, so as to keep the source legible. Any mentions of functions or file names within the documentation will automatically link to the referenced code, so typically no markup need be introduced to produce links.
Documenting files
-
It is good practice to provide a comment describing what a file does at the start of it. For example:
<?php /* $Id: theme.inc,v 1.202 2004/07/08 16:08:21 dries Exp $ */ /** * @file * The theme system, which controls the output of Drupal. * * The theme system allows for nearly all output of the Drupal system to be * customized by user themes. */
The line immediately following the @file directive is a short description that will be shown in the list of all files in the generated documentation. Further description may follow after a blank line.
Documenting functions
-
All functions that may be called by other files should be documented; private functions optionally may be documented as well. A function documentation block should immediately precede the declaration of the function itself, like so:
/** * Verify the syntax of the given e-mail address. * * Empty e-mail addresses are allowed. See RFC 2822 for details. * * @param $mail * A string containing an email address. * @return * TRUE if the address is in a valid format. */ function valid_email_address($mail) {
The first line of the block should contain a brief description of what the function does. A longer description with usage notes may follow after a blank line. Each parameter should be listed with a @param directive, with a description indented on the following line. After all the parameters, a @return directive should be used to document the return value if there is one. Functions that are easily described in one line may omit these directives, as follows:
/** * Convert an associative array to an anonymous object. */ function array2object($array) {
The parameters and return value must be described within this one-line description in this case.
Documenting hook implementations
-
Many modules consist largely of hook implementations. If the implementation is rather standard and does not require more explanation than the hook reference provides, a shorthand documentation form may be used:
/** * Implementation of hook_help(). */ function blog_help($section) {
This generates a link to the hook reference, reminds the developer that this is a hook implementation, and avoids having to document parameters and return values that are the same for every implementation of the hook.
Documenting themeable functions
-
In order to provide a quick reference for theme developers, we tag all themeable functions so that Doxygen can group them on one page. To do this, add a grouping instruction to the documentation of all such functions:
/** * Format a query pager. * * ... * @ingroup themeable */ function theme_pager($tags = array(), $limit = 10, $element = 0, $attributes = array()) { ... }
The same pattern can be used for other functions scattered across multiple files that need to be grouped on a single page.
Comments
Inline documentation for classes should follow the PHPDoc convention, similar to Javadoc. More information about PHPDoc can be found here: http://phpdocu.sourceforge.net/spec/howto.html
Non-documentation comments are strongly encouraged. A general rule of thumb is that if you look at a section of code and think "Wow, I don't want to try and describe that", you need to comment it before you forget how it works.
C style comments (/* */
) and standard C++ comments (//
) are both fine. Use of Perl/shell style comments (#
) is discouraged.
Configuring vim
Identation
The following commands will indent your code the right amount, using spaces rather than tabs and automatically ident after you start
set expandtab set tabstop=2 set shiftwidth=2 set autoindent set smartindent
Syntax highlighting
If you enjoy syntax highlighting, it is may be worth remembering that many of drupal's php files are *.module or *.inc, among others.
Using these settings only with drupal
- Copy your .vimrc to .vimrc-drupal
- Append these settings to the end
- Run
vim -u ~/.vimrc-drupal
To make this easier (using bash on linux), you could create an alias by typing:
alias vid="vim -u ~/.vimrc-drupal"
This allows you to just use the vid command instead of vi when you want to edit a drupal file.
Vim seems to syntax highlight *.inc files properly by default but doesn't kow that *.module is php content. For *.modules use this snippet in .vimrc:
if has("autocmd")
" Drupal *.module files.
augroup module
autocmd BufRead *.module set filetype=php
augroup END
endif
Indenting
Use an indent of 2 spaces, with no tabs. No trailing spaces.
PHP Code tags
Always use <?php ?>
to delimit PHP code, not the <? ?>
shorthand. This is required for Drupal compliance and is also the most portable way to include PHP code on differing operating systems and setups.
SQL naming conventions
- Don't use (ANSI) SQL / MySQL / PostgreSQL / MS SQL Server / ... Reserved Words for column and/or table names. Even if this may work with your (MySQL) installation, it may not with others or with other databases. Some references:
- (ANSI) SQL Reserved Words
- MySQL Reserved Words: 4.x, 3.23.x, 3.21.x
- PostgreSQL Reserved Words
- MS SQL Server Reserved Words
Some commonly misused keywords:
TIMESTAMP, TYPE, TYPES, MODULE, DATA, DATE, TIME, ...
See also [bug] SQL Reserved Words. - Capitalization, Indentation
- UPPERCASE reserved words
- lowercase (or Capitalize) table names
- lowercase column names
Example:
SELECT r.rid, p.perm FROM {role} r LEFT JOIN {permission} p ON r.rid = p.rid -- may be on one line with prev. ORDER BY name
- Naming
- Use plural or collective nouns for table names since they are sets and not scalar values.
- Name every constraint (primary, foreign, unique keys) yourself. Otherwise you'll see funny-looking system-generated names in error messages. This happened with the
moderation_roles
table which initially defined a key without explicite name asKEY (mid)
. This got mysqldump'ed asKEY mid (mid)
which resulted in a syntax error asmid()
is a mysql function (see [bug] mysql --ansi cannot import install database). - Index names should begin with the name of the table they depend on, eg.
INDEX users_sid_idx
.
References:
String concatenations
Always use a space between the dot an the concatenate part, unless it is a quote. So there is no space between the dot and the quote.
Examples:
<?php
$string = 'Foo'. $bar;
$string = $bar .'foo';
$string = bar() .'foo';
?>
When you concatenate simple variables, you can use double quotes and add the string inside, otherwise use single quotes.
Example:
<?php
$string = "Foo $bar"
?>
Functions
Functions should be named using lower caps and words should be separated with an underscore. Functions should have the grouping/module name as a prefix, to avoid name collisions between modules.
Constants
Constants should always be all-uppercase, with underscores to separate words. Prefix constant names with the uppercased name of the module they are a part of.
Control structures
These include if
, for
, while
, switch
, etc. Here is an example if
statement, since it is the most complicated of them:
if ((condition1) || (condition2)) { action1; } elseif ((condition3) && (condition4)) { action2; } else { defaultaction; }
Control statements should have one space between the control keyword and opening parenthesis, to distinguish them from function calls.
You are strongly encouraged to always use curly braces even in situations where they are technically optional. Having them increases readability and decreases the likelihood of logic errors being introduced when new lines are added.
For switch statements:
switch (condition) { case 1: action1; break; case 2: action2; break; default: defaultaction; break; }
Header comment blocks
All Drupal source code files should start with a header containing the RCS $Id$ keyword:
<?php // $Id: CODING_STANDARDS,v 1.1 2001/11/05 07:32:17 natrak Exp $
Note that everything after the starting $Id and before the closing $ is automatically generated by CVS - you shouldn't edit this manually. If you add a new file to CVS, just write // $Id$
.