Drupal development concepts
What can Drupal custom code do?
- Alter existing or add a new functionality
- Integrate with third party systems
- Provide new ways to manage, display or interact with content or users
- ...
Let's see which Drupal concepts are used to achieve this.
There is a module for that! ™
Drupal is a modular system. It means that it is built from small pieces of code that can be enabled or disabled. These pieces of code are called modules.
One of the newcomer mistake is programming too much (opens in a new tab). If you need to implement a rather common feature, chances are that there is a module for that, so you don't have to reinvent the wheel.
Here is a short list of the most used modules.
Drupal is also pretty well integrated with the PHP ecosystem (Symfony (opens in a new tab), Composer (opens in a new tab) / Packagist (opens in a new tab), PSR's (opens in a new tab)) since version 8, so you can still find documentation outside of the Drupal scope.
OK, now it's really time to see what Drupal provides to build custom code.
Hooks and events: react to changes
Hooks
Hooks are functions that are called at a specific moment of the execution. Modules are able to implement these hooks to alter the behavior of Drupal core or other contributed modules.
They are defined in the module's .module
file.
For themes, they are defined in the .theme
file.
How can I find which hooks are available?
For the core, hooks are defined in the API documentation (opens in a new tab).
A module can also define its own hooks. They are usually discoverable through the modules .api.php
file.
A simple way to find hooks is to search for hook_
in the codebase or just let PHPStorm autocomplete the function name for you when Drupal is configured (opens in a new tab).
Then type your module name and PHPStorm will provide you with a list of available hooks.
Examples of hooks
hook_form_alter
This hook is called when a form is built. It allows to alter the form rendering and its state.
Has this hook has a pretty large scope, it is preferred to use more specific hooks when possible, like hook_form_FORM_ID_alter
or hook_form_BASE_FORM_ID_alter
.
hook_entity_type_alter
This hook is called when an entity type is defined. It allows to alter the entity type definition, for example to add a new field to all nodes.
hook_entity_insert
This hook is called when an entity is inserted in the database. It allows to react to the creation of an entity.
There are various other hooks like this one, for example hook_entity_update
or hook_entity_delete
.
Like hook_form_alter
, it is preferred to use more specific hooks when possible, like hook_ENTITY_TYPE_insert
or hook_ENTITY_TYPE_update
.
Events
Events are objects that are dispatched at a specific moment of the execution. They are roughly similar to hooks, they are just implemented in a different way, that follows object oriented principles. Hooks are still used in Drupal, because there is a lot of legacy code that uses them, but events are the recommended way to alter the behavior of Drupal Core if it is possible to use them.
Subscribers
React to events, like Symfony RequestEvent
Dispatchers
Dispatch events, with EventDispatcher
Services: provide reusable code
How can I find which services are available?
Here is a List of core services (opens in a new tab)
Similar to hooks, PHPStorm shines here, especially with the Symfony plugin installed.
Drush can also do that: drupal debug:container
then pipe it to grep
to find a specific service.
Routes: define URLs
Structure of routes
Most of the time, the only thing that you need to do is to define a route in your module via a .routing.yml file.
Here is a very minimal example from the core Book module, that defines the route for a Controller method.
book.render:
# The path always starts with a leading forward-slash.
path: '/book'
# Defines the default properties of a route.
defaults:
# For page callbacks that return a render array use _controller.
_controller: '\Drupal\book\Controller\BookController::bookRender'
# Require a permission to access this route.
requirements:
_permission: 'access content'
Same goes for a form:
my_module.route_machine_name:
path: '/my_module/personal-info'
defaults:
_form: 'Drupal\my_module\Form\InfoForm'
_title: 'Personal information'
requirements:
_permission : 'custom_module_permission'
Read more (opens in a new tab) - Drupal.org
How can I discover existing routes?
With Drush drush route
or the Devel (opens in a new tab) module.
And how can I find the current route used by the frontend.
There are several ways to do that:
- Without any dependency (Drush, Devel, ...): implement a rather global hook like
hook_preprocess_page
and dump\Drupal::routeMatch()->getRouteName()
; drush route --path=/the-path
Read more about Drush route (opens in a new tab)
Alter existing routes
Useful e.g. to add a new access control or to change the controller method that is called.
This is rather straigthforward, you just need to implement a RouteSubscriberInterface
and implement the alterRoutes
method.
Read more (opens in a new tab)
Dynamic routes
Read more (opens in a new tab) - Drupal.org
Controllers and response types: return content
- Render array
- Response / cacheable response
- JSON response / JSON cacheable response
- Binary file response
Content entities: manage content
Core entity types
- Node:
node_types
are providingnode
content - Taxonomy term:
vocabulary
are providingtaxonomy_term
content - User
Custom content entities
Extend content entities
Configuration entities: manage configuration
Core configuration entities
We already discovered some of them: node_types and vocabularies.
user_role
contains a set ofpermission
configuration
Custom configuration entities
Extend configuration entities: third pary settings
Forms: provide user interaction
APIs: integrate with third party systems
Consume APIs
Serve APIs
Migration: import data from other systems
This can be used to import data from a legacy system or to migrate from another CMS once.
But it can also be used to import data from a third party system on a regular basis.
Import from another CMS or Drupal 7 site
Drupal 7 sites have their own migration system, as version 8 introduced many breaking changes in the model.
Plugin: provide extensibility and extend existing systems
Plugin manager, plugin types, plugin discovery
Field plugins
Mailing: send emails
Decorators: alter existing code
Permission: define access to content and functionality
- Access handlers
Caching
Cache API (opens in a new tab) - Drupal.org
Validation: forms and contraints
Validate a form
Form API - validation (opens in a new tab) - Drupal.org
Alter an existing form
Constraints
Entity validation API overview (opens in a new tab) - Drupal.org Validation constraints (opens in a new tab) - Drupal.org