Coding standards

Last modified: June 20, 2009 - 21:06

Note: The Drupal Coding Standards applies to code within Drupal and its contributed modules. This document is based on the PEAR Coding standards. Comments and names should use US English spelling ("color" not "colour" etc.).

Contents of this Page

Indenting and Whitespace

Use an indent of 2 spaces, with no tabs.

Lines should have no trailing whitespace at the end.

Files should be formatted with \n as the line ending (Unix line endings), not \r\n (Windows line endings).

Operators

All operators, such as +, -, =, !=, ==, >, etc. should have a space before and after the operator, for readability. For example, an assignment should be formatted as $foo = $bar; rather than $foo=$bar;.

Control Structures

Control structures include if, for, while, switch, etc. Here is a sample 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;
}

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 inserts 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.

Arrays

Arrays should be formatted with a space separating each element (after the comma), and spaces around the => key association operator, if applicable:

$some_array = array('hello', 'world', 'foo' => 'bar');

Note that if the line declaring an array spans longer than 80 characters (often the case with form and menu declarations), each element should be broken into its own line, and indented one level:

$form['title'] = array(
  '#type' => 'textfield',
  '#title' => t('Title'),
  '#size' => 60,
  '#maxlength' => 128,
  '#description' => t('The title of your node.'),
);

Note the comma at the end of the last array element; This is not a typo! It helps prevent parsing errors if another element is placed at the end of the list later.

Quotes

Drupal does not have a hard standard for the use of single quotes vs. double quotes. Where possible, keep consistency within each module, and respect the personal style of other developers.

With that caveat in mind: single quote strings are known to be faster because the parser doesn't have to look for in-line variables. Their use is recommended except in two cases:

  1. In-line variable usage, e.g. "<h2>$header</h2>".
  2. Translated strings where one can avoid escaping single quotes by enclosing the string in double quotes. One such string would be "He's a good person." It would be 'He\'s a good person.' with single quotes. Such escaping may not be handled properly by .pot file generators for text translation, and it's also somewhat awkward to read.

String Concatenations

Always use a space between the dot and the concatenated parts to improve readability.

<?php
  $string
= 'Foo' . $bar;
 
$string = $bar . 'foo';
 
$string = bar() . 'foo';
 
$string = 'foo' . 'bar';
?>

When you concatenate simple variables, you can use double quotes and add the variable inside; otherwise, use single quotes.

<?php
  $string
= "Foo $bar";
?>

When using the concatenating assignment operator ('.='), use a space on each side as with the assignment operator:

<?php
$string
.= 'Foo';
$string .= $bar;
$string .= baz();
?>

Comments

Inline documentation for source files should follow the Doxygen formatting conventions.

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.

Non-documentation comments should use capitalized sentences with punctuation. Sentences should be separated by single spaces. All caps are used in comments only when referencing constants, for example TRUE. Comments should be on a separate line immediately before the code line or block they reference. For example:

// Unselect all other contact categories.
db_query('UPDATE {contact} SET selected = 0');

If each line of a list needs a separate comment, the comments may be given on the same line and may be formatted to a uniform indent for readability.

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 file name to be included.

When including code from the same directory or a sub-directory, start the file path with ".":
include_once ./includes/mymodule_formatting.inc
In Drupal 7.x and later versions, use DRUPAL_ROOT:
require_once DRUPAL_ROOT . '/' . variable_get('cache_inc', 'includes/cache.inc');

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 set-ups.

Note that as of Drupal 4.7, the ?> at the end of code files is purposely omitted. This includes for module and include files. The reasons for this can be summarized as:

  • Removing it eliminates the possibility for unwanted whitespace at the end of files which can cause "header already sent" errors, XHTML/XML validation issues, and other problems.
  • The closing delimiter at the end of a file is optional.
  • PHP.net itself removes the closing delimiter from the end of its files (example: prepend.inc), so this can be seen as a "best practice."

Semicolons

The PHP language requires semicolons at the end of most lines, but allows them to be omitted at the end of code blocks. Drupal coding standards require them, even at the end of code blocks. In particular, for one-line PHP blocks:

<?php print $tax; ?> -- YES
<?php print $tax ?> -- NO

CVS Header

All source code files in the core Drupal distribution should contain the following comment block in the header:

<?php
// $Id$

This tag will be expanded by CVS to contain useful information

<?php
// $Id: CODING_STANDARDS.html,v 1.15 2008/12/22 15:27:26 keithsmith Exp $

Example URLs

Use "example.com" for all example URLs, per RFC 2606.

Naming Conventions

Functions

Functions should be named using lowercase, 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.

Constants

Constants should always be all-uppercase, with underscores to separate words. This includes pre-defined PHP constants like TRUE, FALSE, and NULL. Module-defined constant names should also be prefixed by an uppercase spelling of the module they are defined by.

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.

Classes

Classes should be named using "CamelCase." For example:

<?php
abstract class DatabaseConnection extends PDO {
?>

Class methods and properties should use "lowerCamelCase":

<?php
public $lastStatement;
?>

The use of private class methods and properties should be avoided -- use protected instead, so that another class could extend your class and change the method if necessary. The names of protected (or private) class methods and properties should begin with an underscore.

File names

All documentation files should have the file name extension ".txt" to make viewing them on Windows systems easier. Also, the file names 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.

Helper Script

There is a helper command line script included with Drupal to check your code for style compliance. The code-style.pl file is located in the /scripts directory. To use the script just give your file as an argument when you execute the script (make sure the script is executable):

./code-style.pl path/to/file/example.module

This will output a list of suggestions for where to improve your code. You will need to make the actual changes to the code yourself.

Helper Module

There is a contributed module for assisting with code review. To use this module you must complete the following steps:

  • Install the Coder module.
  • Click on the "Code Review" link in your navigation menu.
  • Scroll down to "Select Specific Modules".
  • Select the module you wish to review, and click the "Submit" button.

As an alternative to starting from the Code Review link in navigation, you can also review a particular module's code by clicking on the link on the Modules admin screen.

The Coder module also comes with a command-line script called "Coder Format", which will not only check your files for standards compliance, but fix them. Use with care!

It would be desirable to create a section about functions

trunks - October 9, 2007 - 12:41

From C Coding Standards:

Functions should be short and sweet. If a function won't fit on a single screen, it's probably too long. Don't be afraid to break functions down into smaller helper functions. If they are static to the module an optimizing compiler can inline them again, if necessary. Helper functions can also be reused by other functions.

However, sometimes it is hard to break things down. Since functions don't nest, variables have to be communicated through function arguments or global variables. Don't create huge interfaces to enable a decomposition that is just not meant to be.

API module depends on these standards

seanburlington - June 29, 2008 - 23:21

It's worth noting that the API module (responsible for api.drupal.org) depends upon adherence to the above standards.

function foo($bar){

will not be documented properly (there's a missing space before the opening brace)

Sean Burlington
www.practicalweb.co.uk
London

Here is the api project

vkr11 - November 19, 2008 - 07:08

Here is the api project http://drupal.org/project/api , you can also see steps on creating your own api documentation for your own module and drupal standard module at http://drupal.org/node/26669

- Victor
Better Way to Search Drupal.org | Drupal Jobs | Income Tax India

Some questions

DamienMcKenna - September 25, 2008 - 15:52

A few thoughts after reading through this and working with many modules:

  • Which is the preferred syntax for returning from functions:
    <?php
    $output
    = "blah";
    return
    $blah;
    ?>

    or:
    <?php
    return "blah";
    ?>
  • I think there needs to be more emphasis on some of the practices that E_ALL will report, e.g. $arr[key] syntax, not declaring variables before use, etc. I suggest merging the E_ALL sub-page into the main Coding Standards page and specifically listing some of the key issues, given how much of a problem it appears to be.
  • There's a lot of code in D5 that doesn't declare variables before use, especially when running foreach loops on node fields. Is it worth still submitting patches for it?

Text Encoding

muli - January 8, 2009 - 15:58

I miss information about the text encoding that should be used.

muli

String concatenation?

martinquested - February 6, 2009 - 14:26

Is there a standard way to format long string concatenations or long embedded SQL commands? It is not good to have them run over many lines and a multi-line format with indentation (a bit like formatting an array) would be really good. I am just not sure quite how it should be done. Would the following be OK?

$text = function1($variable_a, $variable_b, $variable_c) .
  "another bit of text" .
  function2() .
  "more text"
  function3(
    $long_variable_name_1,
    $long_variable_name_2,
    $long_variable_name_3,
    $long_variable_name_4
  ) .
  "final bit of text";

Or should you include a newline after the '='?

Try this

dman - February 6, 2009 - 15:14

I read once (and then tried, and really liked) placing the operator at the beginning of any broken line.
A quick search shows this is recommended by (at least) Zend - Doctrine - others...
Maybe it's old news to some folk (who had good teachers or good books) but I felt I'd learned something when I found out about it.

The theory is that you are less likely to miss or mistake things this way around then when the logical joiner trails the line. And it does work. Although it feels unnatural to write, it's much better to read - and that counts. Means even long lines don't lose their logic when shown in small screens.
See, even in your above example is a syntax error - that would be harder to make if you did it this way:

$text = function1($variable_a, $variable_b, $variable_c)
  . "another bit of text"
  . function2()
  . "more text"
  . function3(
    $long_variable_name_1,
    $long_variable_name_2,
    $long_variable_name_3,
    $long_variable_name_4
  )
  . "final bit of text";

The operator (verb) comes at the beginning. Feels a bit more grammatical and clearer to grok. One line says one thing.

This
and this
and this.

:-B
vs
This and
this and
this.

>:-{

I even use this convention in other contexts:

if (
  really_long_expression()
  || another_really_long_expression()
  || ( some_other_condition() && this_is_true($also) )
) {
  # then do something, knowing exactly why I'm doing it
}

$query = "
  SELECT mlid,plid,menu_name
  FROM {menu_links}
  WHERE link_path = '%s'
  LIMIT 1
";

That's a tiny example - please imagine huge SQL nested statements there
... but I won't defend it too loudly. This is opinion right? I just like readable code logic.

.dan.

My preference with long SQL

Dewi Morgan - February 19, 2009 - 14:34

My preference with long SQL queries at least is to:

$query = "
  SELECT t1.field1, t1.field2, t2.field
  FROM
    {table1} AS t1
  RIGHT OUTER HYPERBOLIC QUADRANT JOIN
    {table2} AS t2
  USING
    t2.crazystuff == t1.crazystuff
  ORDER BY
    coolness
  LIMIT
    42
";

rather than the harder-to-maintain (and harder-to-read, imho):

$query = "SELECT t1.field1, t1.field2, t2.field"
  . " FROM"
  . " {table1} AS t1"
  . " RIGHT OUTER HYPERBOLIC QUADRANT JOIN"
  . " {table2} AS t2"
  . " USING"
  . " t2.crazystuff == t1.crazystuff"
  . " ORDER BY"
  . " coolness"
  . " LIMIT"
  . " 42";

php coding standards exceptions

puradata - April 7, 2009 - 04:36

Should add a section for try and catch. Suggest use the same format as javascript.

Ternary Operators

BassistJimmyJam - April 24, 2009 - 00:26

I'm just curious as to what the preference is for ternary operators (?:). Are if statements preferred for readability? I personally don't find ternary operators difficult to use, but I write and read them every day. Would the two blocks of code below be considered valid?

<?php
$value = condition ? 'pass' : 'fail';

<?php
$string = 'This will ' . (condition ? 'pass' : 'fail');

Thanks,
~JimmyJam

Depends on ambiguity

DamienMcKenna - April 28, 2009 - 18:58

I've found it best to wrap the entire ternary structure in brackets if there could be any confusion on what would happen due to other statements, e.g. the first one is pretty obvious but the latter might confuse people. It's all down to the PHP operator precedence. FYI the PHP manual says "Surrounding ternary expressions with parentheses is a very good idea" so I'd suggest following your second example unless it's a super-simple, no-brainer statement like the first example.

Is there any position about conditional assignments?

hanoii - June 10, 2009 - 18:18

Something like:

<?php
if ($demo = get_demo()) {
  print
$demo;
}
?>

May be it's not a good practice overall but it saves a few unnecessary lines.

 
 

Drupal is a registered trademark of Dries Buytaert.