Drupal 8 represents a major shift away from “Drupalisms” to mainstream object-orientated PHP. Experienced developers who are used to other frameworks like Symfony, should find it much easier to pick up Drupal now than they would have in Drupal 7 and previous versions. But this shift presents challenges for those of who are used to the Drupal 7 way of doing things and aren’t necessarily up to speed with all the new PHP best practices.

Over the next few weeks, I’ll be sharing tutorials on some of the key concepts you need to understand in order to master Drupal 8 module development. This week, we are going to look at namespaces.

The Drupal 7 way

In Drupal 7, all functions in the system had to have a unique name or you would get a fatal error. If the name was not unique, then the system would not know which function code to use when the function is called in another function.

Module developers can’t rely on other functions not having the same name that they use. So to get around this, it is common practice to start each function name in Drupal 7 with the same name as the module. This makes the function name unique when if another module uses the same name.

But having to use these unique names for functions is far from ideal. For starters, it makes function names longer that they would otherwise be.

Drupal 8 and namespaces

With the introduction of Drupal 8, we can now use a different method for making our code unique. Drupal 8 extensively uses PHP classes instead of simple functions. Two classes can have the same name as they have a different namespace.

You can think of it as a way of organising classes into folders and subfolders and the namespace as the path to the file. If you try and create the same file with the same name in the same folder, you will get an error. You could change the name of the file, but if you really want to keep the same file name, you would most likely create a sub folder and put the file in there. This makes the file unique because it has a different path. Namespacing works in the same way.

Let’s have a look at an example. We’ll start off by creating a basic module to illustrate how namespaces work. If you already have a module and just want an explanation of namespaces, jump to the namespace section.

Setup a basic module

You are going to create a module called hello for demonstration purposes. In the /module folder, create a directory called hello.

Create an info .yml file

The info .yml file tells Drupal that your module exists and provides important information. This is similar to creating a .info file in Drupal 7.

The filename should be the machine name of your module with the .info.yml extension. In this case, it will be hello.info.yml.

  • Create hello.info.yml in the root of the hello directory.
name: Hello
description: An experimental module to build our first Drupal 8 module
package: Custom
type: module
version: 1.0
core: 8.x

Create the src directory

In Drupal 8, most modules can have controllers, plugins, forms, templates and/or tests. These are stored in a folder called src, which is short for source.

  • Create a folder inside the hello module folder called src, which is short for source.

Create a basic controller

We need a page controller to output content to the page.

Here are the steps to create the basic controller for the module:

  • Create a folder within src called Controller.
  • Within the Controller folder, create a file called HelloController.php.

In HelloController.php, we will create a simple “hello world” message so that we know it is working.

<?php
/** 
 * @file 
 * Contains \Drupal\hello\Controller\HelloController. 
 */
namespace Drupal\hello\Controller;

use Drupal\Core\Controller\ControllerBase;

class HelloController extends ControllerBase {
  public function content() {
    return array(
      '#type' => 'markup',
      '#markup' => t('Hello world'),
    );
  }
}

Let’s dive into the namespace line in this code.

Namespaces

You can see from the above code that the namespace has been defined as Drupal\hello\Controller.

You might be thinking that doesn’t exactly match the folder structure because if it did, the namespace would be Drupal\modules\hello\src\Controller.

The reason why modules\src is missing from the namespace is because namespaces for Drupal modules are automatically mapped to the module’s src folder. This is why it is critical that you follow this standard folder structure in modules(fn).

If you were to use this HelloController class in different namespaces, you would include it with the use keyword and its namespace.

use Drupal\hello\Controller\HelloController

You can see this in action with the use statement in the example above. HelloController is extending another class called ControllerBase. In order to get access to that class, it has been added with it’s namespace via the following use statement:

use Drupal\Core\Controller\ControllerBase;

If this use statement was not included, then PHP would be looking for ControllerBase in the current namespace (Drupal\hello\Controller). It wouldn’t find it there, so you would get a fatal error. So the use statement allows you make use of classes from other namespaces.

Add a route file

The controller we created above will not do anything at this stage. Let’s round this off by making it return the string when you hit a URL.

In order for a controller like this to be called and executed, it needs to map a route from the URL to the controller.

  • Create a file called hello.routing.yml in the root of the hello folder
  • Add the following code to hello.routing.yml
hello.content:
  path: '/hello'
  defaults:
    _controller: 'Drupal\hello\Controller\HelloController::content'
    _title: 'Hello world'
  requirements:
    _permission: 'access content'

View the content

If you haven’t already done so, enable the hello module and clear the cache. If you now go to /hello, you will see the Hello World message that is being returned from the controller.

Namespaces in a nutshell

A namespace is a way of organising your classes into virtual folders and ensures that your class does not conflict with another class with the same name (the class name can be the same but the namespace is unique). The use keyword allows you to use classes from other namespaces when you need them.