OOP in Drupal 8 and how to use it to create a custom module

OOP in Drupal 8 and how to use it to create a custom module


I had only one year of experience in web development in general, and basic knowledge of Drupal 7 in particular when I faced Drupal 8 for the first time. Drupal has a number of advantages for both web developers and clients which attracted me at first sight. 

When I started learning Drupal 8 I was surprised by the fact that getting to know the new version is rather easy. That’s how this little tutorial was born: I understood the way you can start working with Drupal 8 faster and now you can learn from my experience.

What do you need to know to start developing in Drupal 8? It doesn’t matter whether you have worked with Drupal’s earlier versions or not: development in Drupal 8 differs a lot. One of the main reasons - switching from procedural programming to the object-oriented approach. It means that now the biggest part of your code is placed in classes. It can be quite disturbing for programmers, but that’s how the modern programming practices work.

OOP in Drupal 8: what differs Drupal 8 from Drupal 7

Drupal 7 operates the solutions that are not similar to the Symfony’s or Wordpress’ ones. There is a lot of own Drupal solutions like Form API or Drupal DBAL, the functionality for batching process, the hooks system, etc. Learning all of these things can be tedious and difficult. You should always keep in mind weak places and particular qualities of different Drupal components. For instance, if you want to start writing a new module for Drupal 7, you should know how Drupal 7 works, how different hooks process and many more things. And, of course, you must read a lot of documentation beforehand. Yes, it’s difficult and takes a lot of time.

Drupal 8 is easier for development in comparison with the earlier Drupal versions. If you know the key OOP principles, design patterns (like Event Dispatcher, Factory or Dependency Injection) - you’ll be able to understand how the new system works.

What are the main differences that you should pay attention to while developing a Drupal module?

OOP usage

It’s much easier now for complete Drupal beginners to get to know this CMS if they know OOP and design patterns. For example, while bootstrapping Drupal the default container initializes and different services become available. What are those services? In plain language, service is a class that implements a particular functionality. You can create your own class, define it as a service and make it available in the container.

Drupal developers plan to completely refuse hooks in version 8. The pattern Event Dispatcher is used instead. This decision was based on hooks’ drawbacks, for example, hook_invoke_all is a rather resource-demanding one.

All in all, you don’t have to learn the hooks system now. If you know how a particular pattern (for example, (Event Dispatcher, Dependency Injection) works, you should only implement it in your module.

For example, you have to use hook_node_type_insert() to create a new content type in Drupal 7. Now you only should implement Dispatcher and bind your method 'createRequest' to the event that was defined in the method getSubscribedEvents. See the example below:

Besides that, you couldn’t redefine the core’s functionality with the hooks system. The transition to OOP releases many options: the possibility to build more complex architecture, data encapsulation, methods’ redefining.

Symfony components usage

Symfony components are the universal and flexible solutions, especially in comparison with Drupal’s solutions in the earlier versions: they proved themselves as stable ones and they can solve much more problems. You know that it isn’t a good practice - to reinvent the wheel, - so don’t be afraid to use ready-made solutions. Also, Symfony follows the standards such as PSR-4, PSR-7. Symfony’s components are used in the Drupal core, so it is likely to facilitate Drupal’s transition to the standards’ usage. When it happens, it will simplify the Drupal’s learning curve.

Annotations usage

Drupal 8 uses annotations (the comments in your code that contain meta information). The main advantage of the annotations is that they improve performance due to the less memory usage. The annotations are placed in the same file as a class is. Below you can see the example of the annotations’ usage at the block’s class.

Drupal 8 routing

In Drupal 8 the component Routing replaced the hook hook_menu. Now you create a controller class with the method that returns data along a certain path. For the description of routes, Drupal 8 uses the YAML format. All the information about routes of a module is kept in the file MODULE_NAME.routing.yml.

Each route is described separately from the others and it must have the following characteristics:

  • a name that identifies the route;
  • a path that begins with a slash;
  • a route’s processor;
  • conditions that manage an access to the route.

Of course, that’s not the complete list of the changes in Drupal 8. However, the understanding of the mentioned changes is enough to write a custom module - and that’s what we’re going to do now.

Custom module creation in Drupal 8

We have already discussed the crucial aspects of Drupal 8 development, but practice is very important. Let’s create a simple module to understand how classes are used and how the changes of Drupal 8 affect a coding process. I commented the code; it will help you to understand the process.
Our module will change status messages through the admin menu. Our module will allow to set a width, a height, and a background color of a pop-up window.

Step 1

I’ll show you the module’s structure in Drupal 8 right away: it was changed a lot. Classes are kept in the src folder now, this folder is divided into subfolders, too. In our example, it’s just one class of a form.

The module’s structure in Drupal 8
The module’s structure in Drupal 8

The list of the necessary parameters of the info file differs from Drupal 7. Now we specify name, core, and type. Type can be any of these kinds: module, theme or profile. Our module will have the configuration form where we will set parameters of the status messages, and due to that, we can add the characteristic Configure - a path to this configuration form.

Step 2

Let’s create the routing file status_message.routing.yml next. I’ll show you how I created a route for a list, a submenu for an administrative form, and a route for the form itself.

status message.admin_config (in the format MODULE_NAME.KEY) creates the submenu: we define a path to the class SystemController and its method systemAdminMenuBlockPage' with the help of the key _controller.

The admin menu will contain a list of links, and we will specify a path to that admin menu with the help of Path.

Next, we create a route for the setting form with the key modal_window.admin_settings, but this time we define a path to the class of our form in the key _form. The class will be situated in the directory of the module status_message in the folder Form.

There are few things left to do before our form will appear in the admin panel. You should create the file status_message.links.menu.yml and place the code below in this folder. The first line, likewise in the case with the route file, allocates a place in the namespace. This line is the key. In the parent, we indicate the parent menu link. In the route_name we indicate the key from the routing file and that key should be relevant to the link we talked about earlier. It means that the parent of status_message.admin_config is system.admin_config: thus the submenu should be at the address admin/config. Yes, we wrote the addresses in the routing file, but without the links.menu.yml file. If you switched to the address /admin/config/status-message back then, you would see the submenu configured in the routing file - but you wouldn’t find anything in the list of links at the address admin/config.

The form of configuration of the status messages has the parent status_message.admin_config due to the fact that we built the hierarchy of links.

Now if you go to /admin/config/status-message, you’ll see this:

Settings for status messages
Settings for status messages

You can’t proceed to the configuration page Modal window because we didn’t create the class of the form. Let’s do it right now!

Step 3

Create the file StatusMessageSettings.php with the address status_message/src/Form. In the first part, we talked about the PSR-4 standard and an autoloading of classes. If you have a look at “use”, you’ll see the list of the classes that we upload for the further usage. Define a way to our class in Namespace. According to the standard, we omit the src folder then.

The class StatusMessageSettings is inherited from the class ConfigFormBase and even expands its possibilities. What happens here: using the OOP principles, we describe our class that is based on the already existing class; at the same time, we don’t have to bother about the implementation of the class ConfigFormBase.

In the method getFormId we only return the unique form’s ID, in the method getEditableConfigNames() we return the key settings form. Bear in mind: any class that expands ConfigFormBase must implement the method getEditableConfigNames and return the array of the configuration’s names of the fields.

In the method buildForm, we describe the way our form will look like: what fields, width, height, and background it will have.

A form’s class in Drupal 8 must implement the method submitForm, that’s why the last thing we have to do is to add the submit method that will return the form’s values.

Now when you go to admin/config/status-message/modal-window, you’ll see this form:

Settings for modal window
Settings for modal window

Step 4

We created the admin form; the thing is, the values that we can set there don’t affect the way the status messages look like. Let’s correct it.

Create the file status_message.libraries.yml (it’s the replacement of the characteristics stylesheets and scripts for the switch-on of JS and CSS files in Drupal 7) where we will specify dependencies. Drupal 8 doesn't add jQuery to each page jQuery on all pages by default: only where it’s needed. For that reason, we will define that the library of our module (file modal_window_jq.js) depends on the library that contains jQuery (core/drupal.dialog.ajax).

The next step is creating the file status_message.module. Unfortunately, we are forced to use two hooks here: the first hands over values of form’s fields to a JS file so that the parameters of the status messages are changed; the second turns on the Twig file that is the replacement of the template.php file in Drupal 8.

We included one JS file in the file libraries.yml earlier; now we can turn another one that doesn’t depend on jQuery with the help of attachments.

An access to the values of form’s fields can be obtained by
$config = \Drupal::config('status_message.settings');
But we can also do it with the help of use tag for class download like we did it before.

Next, create the file status_message.html.twig with the address status_message/templates. As it was said before, Drupal uses Twig template engine. Our Twig inherits from status_messages.html.twig template, and that’s really important. In our example, we inherit from the status_messages.html.twig template with the help of the tag extends. This way we can manage all of the aspects of the parent file and change it, too.

What I’ll do next is changing div’s styles with id modal_window. Earlier we defined this HTML structure in the Twig file. Try to change other attributes by doing the same actions to the width and height. Feel free to experiment! You can add drag-and-drop of the window, for example, and whatever you like, but this is another story that relates to JS and jQuery, but not to Drupal.

I changed the background color of the module in the admin menu: now I receive the status messages in pink. I showed how to include a CSS file in the file libraries, so you can change it on the front-end side whatever way you like.

Status messages
Status messages

Congratulations - we have the first results! We learned how to create forms, got to know Twig files and even JS a little bit. Of course, it’s a small step and we learned just the basic principles and saw the differences in development between Drupal’s versions. But I hope it was the useful and pleasant development adventure for you.


That’s it: we created our first module for Drupal 8. I think it wasn’t difficult for you. I really love Drupal 8 because it’s rather simple and has a great architecture. Yes, you must know OOP, design patterns, Twig, and modern PHP trends. But on the Internet, you can find information about everything that I’ve just mentioned. Instead of learning internal Drupal mechanisms, you should learn only the basics of web development that can be applied to other technologies. A large part of the PHP frameworks uses the same Symfony components, Twig, and the same design patterns. This way learning Drupal 8 you’re learning how the most of PHP-frameworks work. Have fun!

You might also like