Community Documentation

Namespaces

Last updated February 28, 2013. Created by Crell on November 26, 2011.
Edited by YesCT, ksenzee, xjm, jhodgdon. Log in to edit this page.

PHP 5.3 introduces namespaces to the language. This page documents how namespaces should be referenced within Drupal and it assumes that you are familiar with the concept of namespaces.

Not all files in Drupal declare a namespace. As of Drupal 8 an increasing number of files do, but not all. Prior to Drupal 8 virtually no code used namespaces, in order to remain compatible with PHP 5.2. There are therefore two slightly different standards.

"use"-ing classes

  • Classes and interfaces with a backslash \ inside their fully-qualified name (for example: Drupal\simpletest\WebTestBase) must not use their fully-qualified name inside the code. If the namespace differs from the namespace of the current file, put a use statement on the top of the file. For example:
    <?php
    namespace Drupal\mymodule\Tests\Foo;

    use
    Drupal\simpletest\WebTestBase;

    /**
    * Tests that the foo bars.
    */
    class BarTest extends WebTestBase {
    ?>
  • Classes and interfaces without a backslash \ inside their fully-qualified name (for example, the built-in PHP Exception class) must be fully qualified when used in a namespaced file. For example: new \Exception();.
  • In a file that does not declare a namespace (and is therefore in the global namespace), classes in any namespace other than global must be specified with a "use" statement at the top of the file.
  • When importing a class with "use", do not include a leading \. (The PHP documentation makes the same recommendation.)
  • When specifying a class name in a string, use its full name including namespace, without leading \.

    Escape the namespace separator in double-quoted strings: "Drupal\\Context\\ContextInterface"

    Do not escape it in single-quoted strings: 'Drupal\Context\ContextInterface'

    As stated elsewhere, single-quoted strings are generally preferred.

  • Specify a single class per use statement. Do not specify multiple classes in a single use statement.
  • API documentation (in .api.php files) should use full class names. Note that if a class is used more than once in multiple hook signatures, it must still be "use"ed, and then only the short names of the class should be used in the function.

Example:

<?php
/**
* @file
* Contains \Drupal\Subsystem\Foo.
*/

namespace Drupal\Subsystem;

// This imports just the Cat class from the Drupal\Othersystem namespace.
use Drupal\Othersystem\Cat;

// Bar is a class in the Drupal\Subsystem namespace in another file.
// It is already available without any importing.

/**
* Defines a Foo.
*/
class Foo {

 
/**
   * Constructs a new Foo object.
   */
 
public function __construct(Bar $b, Cat $c) {
   
// Global classes must be prefixed with a \ character.
   
$d = new \DateTime();
  }

}
?>

<?php
/**
* @file
* The Example module.
*
* This file is not part of any namespace, so all global namespaced classes
*  are automatically available.
*/

use Drupal\Subsystem\Foo;

/**
* Does stuff with Foo stuff.
*
* @param \Drupal\Subsystem\Foo $f
*   A Foo object used to bar the baz.
*/
function do_stuff(Foo $f) {
 
// The DateTime class does not need to be imported as it is already global
 
$d = new DateTime();
}
?>

Class aliasing

PHP allows classes to be aliased when they are imported into a namespace. In general that should only be done to avoid a name collision. If a collision happens, alias both colliding classes by prefixing the next higher portion of the namespace.

Example:

<?php
use Foo\Bar\Baz as BarBaz;
use
Stuff\Thing\Baz as ThingBaz;

/**
* Tests stuff for the whichever.
*/
function test() {
 
$a = new BarBaz(); // This will be Foo\Bar\Baz
 
$b = new ThingBaz(); // This will be Stuff\Thing\Baz
}
?>

That helps keep clear which one is which, and where it comes from. Aliasing should only be done to avoid name collisions.

Modules

Modules creating classes should place their code inside a custom namespace.
The convention for those namespaces is

namespace Drupal\example_module

To support autoloading, these classes should be placed inside the correct folder:
sites/all/modules/example_module/lib/Drupal/example_module
<module folder> /lib/ <namespace>

Comments

Some thoughts on names and `use`

I've been working in the the Drupal Extension project and it prompted some thinking on our choice of names (and our use of `use`). I'd like to contribute those thoughts to this page and hopefully start a conversation about it.

Here's my blog post: Improving Our Use of PHP Namespaces

The specific focus of the article is redundant identifiers, but I hope to also discuss lowering our resistance to using fully-qualified names in-context if the name is only needed once in our file and especially if it is simply being extended. The comment thread there already has some good thoughts.

A little confused w/ Namespaces & AutoLoading

The last paragraph:

To support autoloading, these classes should be placed inside the correct folder:
sites/all/modules/example_module/lib/Drupal/example_module
/lib/

conflicts w/ the examples of modules declaring their classes in the .info file.

How are we supposed to store class files using namespaces, and the advantages of autoload?

For example, Commerce declares in commerce_product.info:

files[] = includes/views/handlers/commerce_product_handler_area_empty_text.inc

seemingly creating class files arbitrarily in the includes folder.

Applies only to D8

After doing some research, found that the last paragraph above only applies to Drupal 8.

According to this comment by Crell:

http://drupal.org/node/1254488#comment-4885794

Drupal's autoloader in D7 will be replaced by Symfony's autoloader, which uses php 5.3's PSR-0 autoloader.

As Drupal modernizes more to OOP, the use of namespaces will help avoid class name clashes; but to take advantage of Symfony's autoloader, class files need to be created in the correct structure.

Hat tip to http://rbayliss.net/story/understanding-drupal-8-autoloading for helping me understand Drupal's (D7 & D8) autoloader works.

nobody click here