Understanding Drupal 8, part 4: other Drupal 8 concepts

Part 4: Other Drupal 8 concepts

During the last weeks we have learned about the structure and internal request handling of Drupal 8. We have not learned much about how Drupal 8 is built up. Before you dive into the specific core module code, there are some important new or changed Drupal 8 concepts that you should know about. I describe them in this final part of the article.

Configuration

The configuration system has changed in an exciting way in Drupal 8. Most notably, configuration is now stored in a lot of YAML-files in the '/sites/{name}/files/config_{HASH}/active' directory. The filenames define what is configured in the file. For example, 'node.settings.yml' contain settings of the node module, while 'views.view.content.yml' contains a complete definition of the view with machine name 'content'! Drupal does this by using config prefixes.

You may think that configuration files are very inflexible. But in practice, you can build associative arrays of information using YAML-syntax. Furthermore, Drupal provides a Config object which can be used to change the configuration files on the fly, without ever having to edit such a file manually! When you create a new field, node type, block type or view via the Drupal UI a new file will be created. Content (nodes) and data are still stored in the database because otherwise you wouldn't be able to build fast queries.

A module may ship with a conf subdirectory. When a module is enabled, all configuration files from that directory are copied to the site's configuration directory. When files are added here (and the cache is cleared) they are auto-discovered and applied directly. In this way, a module can provide additional new node types, image styles, views, etc. without having to implement some hook like hook_node_info in Drupal 7.

Configuration files can be easily copied to another location. This has the advantage that you can now finally stage configuration changes!

Configuration files may also have an associated schema, that describes in detail what a view / block / image style / etc. configuration should look like. Because of this, configuration can be validated and translated better.

Entities

Drupal 7 introduced entities. These were generalized objects with the same functionality. For example, fields could be attached, access methods were generalized, they could be referenced in views, etc. The entity concept was found to be extremely powerful. In Drupal 8, the concept has become even more central to the CMS. Not only content data (nodes, taxonomy terms, users) are now entities, but also non-fieldable data such as views, actions, menus, image styles, etc. are all extending the Entity class. And also bundles such as node types and vocabularies are now entities. The reasoning behind this is that, even though these object types are not fieldable, some other generalized functionality is handy, such as generalized storage in configuration files or automatic route parameter conversion based on the entity name.

The properties of an entity are defined using attributes. For example, it can be specified here whether or not an entity is fieldable or if it should serve as a bundle for another entity. An entity may or not be saved in configuration files, depending on the controller. If the controller is or extends ConfigStorageController, these will be saved as configuration files. Although configuration files have benefits, it means that you cannot use database queries on them. If you want to search them, you will have to load all items and use a PHP 'for loop'. If database storage is preferred, for example in the case of nodes and users, the FieldableDatabaseStorageController can be used. This is the case for nodes, users, taxonomy terms, etc. The end result is, of course, that this content can't be transferred via configuration files. To me, it is yet unclear if it is possible to have a fieldable config storage controller!

To get an understanding of the entity properties I suggest that you have a look at the (annotations of the) ImageStyle class, which is a pure configuration-based entity, the (taxonomy) Term, which is a fieldable and database-stored entity, and Vocabulary, which is a bundle entity.

Plugins

Plugins can be seen as the object-oriented version of hooks. They can be used to modularly include custom blocks, image effects, etc.

A great example of a plugin is the abstract BlockBase class. To add a new custom block, this class should be extended, such as done by the ActiveTopicsBlock of the forum module. Some methods can or must be overridden for access checks, building the view, altering the block form, etc.

A plugin manager is used to define a plugin type. A list of namespaces and a subdirectory are specified to define where the plugins can be found. In this way, any module can add plugins. An annotation class is set to be able to identify the plugins. Furthermore, several configuration properties must be specified in the annotations, depending on the plugin type.

Drupal class

The Drupal 8 core code is mostly object-oriented. However, the code in module hooks is still mostly procedural. This presents challenges because Symfony is completely object-oriented! In Symfony, if you would need to create some functionality that depends on another service, you would create a new service and define the required dependency in the service container. But if you need a particular service in a Drupal hook, you can't use this mechanism as you are not working in a class in the first place! For this situation, the static Drupal class is created. It can be used to get services in a procedural context by using Drupal::service('{service id}'), or using specific service accessors like Drupal::request(), Drupal::currentUser(), Drupal::entityManager(). The latter have the advantage of providing better code-completion in your editor. Furthermore, it provides some handy helper functions such as Drupal::url(), which is the equivalent of the Drupal 7 url() method.

An example of the node_access function in node.module using the Drupal class:

function node_access($op, $node, $account = NULL, $langcode = NULL) {
  $access_controller = \Drupal::entityManager()->getAccessController('node');
  ...
  return $access_controller->access($node, $op, $langcode, $account);
}

Conclusion

In this article we have seen how Drupal 8 is structured, and how this compares to the structure of Symfony2. We have seen that the service container manages all services and that it can be configured. Then we learned about routing and request handling by the Drupal Kernel. Finally we introduced some important new concepts of Drupal 8: the Drupal class, plugins and configuration in Drupal 8.

I hope that all of this information will help you to explore and learn about Drupal 8. I hope you will be able to learn about Drupal 8 module development and contribute to this great project.

Good luck!

Other parts

Part 1: The Structure of Drupal 8
Part 2: Service Container
Part 3: Routing
Part 4: Plugins and Entities

Click here for more info on Cipix Internet Agency.

Interesse? 

Delen