2022-02-08 07:52:00 +00:00
|
|
|
..
|
|
|
|
TODO:
|
|
|
|
- Cron jobs
|
2022-02-08 10:08:46 +00:00
|
|
|
- Custom plugins (e.g. blocks)
|
|
|
|
- Drush commands
|
2022-02-08 07:52:00 +00:00
|
|
|
- Forms
|
2022-02-08 10:08:46 +00:00
|
|
|
- JSON:API (filtering, field names etc)
|
2022-02-08 07:52:00 +00:00
|
|
|
- Logging
|
|
|
|
- Querying the database
|
|
|
|
- Queues and workers
|
|
|
|
|
2022-02-02 18:00:00 +00:00
|
|
|
Drupal tips
|
|
|
|
###########
|
|
|
|
|
|
|
|
A collection of tips and tricks for working with `Drupal <https://www.drupal.org>`_ code. Ideas and PRs welcome.
|
|
|
|
|
|
|
|
Inspired by https://github.com/PovilasKorop/laravel-tips.
|
|
|
|
|
|
|
|
.. contents::
|
|
|
|
:depth: 2
|
2022-02-08 07:46:32 +00:00
|
|
|
|
2022-02-08 07:51:30 +00:00
|
|
|
Entity storage
|
|
|
|
==============
|
|
|
|
|
|
|
|
Loading a single entity by ID
|
|
|
|
-----------------------------
|
|
|
|
|
|
|
|
.. code:: php
|
|
|
|
|
|
|
|
\Drupal::entityTypeManager()->getStorage('node')->load(1);
|
|
|
|
|
|
|
|
The entity type manager can also be loaded using the ``entity_type.manager`` service name. For example:
|
|
|
|
|
|
|
|
.. code:: php
|
|
|
|
|
|
|
|
\Drupal::service('entity_type.manager')->getStorage('node')->load(1);
|
|
|
|
|
|
|
|
Loading multiple entities by ID
|
|
|
|
-------------------------------
|
|
|
|
|
|
|
|
.. code:: php
|
|
|
|
|
|
|
|
\Drupal::entityTypeManager()->getStorage('node')->loadMultiple([1, 2]);
|
|
|
|
|
|
|
|
Loading entities by properties
|
|
|
|
------------------------------
|
|
|
|
|
|
|
|
.. code:: php
|
|
|
|
|
2022-02-08 09:41:32 +00:00
|
|
|
use Drupal\node\NodeInterface;
|
|
|
|
|
2022-02-08 12:00:00 +00:00
|
|
|
$nodeStorage = \Drupal::entityTypeManager()->getStorage('node');
|
|
|
|
|
2022-02-08 07:51:30 +00:00
|
|
|
// Load all published `event` nodes.
|
2022-02-08 12:00:00 +00:00
|
|
|
$nodeStorage->loadByProperties([
|
2022-02-08 09:41:32 +00:00
|
|
|
'status' => NodeInterface::PUBLISHED,
|
2022-02-08 07:51:30 +00:00
|
|
|
'type' => 'event',
|
|
|
|
]);
|
|
|
|
|
|
|
|
// Load all published `talk` nodes.
|
2022-02-08 12:00:00 +00:00
|
|
|
$nodeStorage->loadByProperties([
|
2022-02-08 09:41:32 +00:00
|
|
|
'status' => NodeInterface::PUBLISHED,
|
2022-02-08 07:51:30 +00:00
|
|
|
'type' => 'talk',
|
|
|
|
]);
|
|
|
|
|
|
|
|
Querying for entities
|
|
|
|
---------------------
|
|
|
|
|
2022-02-08 09:43:17 +00:00
|
|
|
Returns an instance of ``Drupal\Core\Entity\Query\QueryInterface`` for the specified entity type.
|
2022-02-08 07:51:30 +00:00
|
|
|
|
|
|
|
.. code:: php
|
|
|
|
|
2022-02-08 12:00:00 +00:00
|
|
|
$nodeStorage = \Drupal::entityTypeManager()->getStorage('node');
|
|
|
|
|
|
|
|
// Load all nodes.
|
|
|
|
$nodeStorage->getQuery()->execute();
|
2022-02-08 07:51:30 +00:00
|
|
|
|
2022-02-08 12:00:00 +00:00
|
|
|
// Load nodes that match the specified conditions.
|
|
|
|
$nodeStorage->getQuery()
|
2022-02-08 07:51:30 +00:00
|
|
|
->condition('type', 'event')
|
|
|
|
->condition('title', '%Online%', 'LIKE')
|
|
|
|
->range(0, 10)
|
|
|
|
->addTag('node_access')
|
|
|
|
->execute();
|
|
|
|
|
2022-02-08 07:48:52 +00:00
|
|
|
Services
|
|
|
|
========
|
|
|
|
|
|
|
|
Using a class name as a service name
|
|
|
|
------------------------------------
|
|
|
|
|
|
|
|
Before:
|
|
|
|
|
|
|
|
.. code:: yaml
|
|
|
|
|
|
|
|
# my_module.services.yml
|
|
|
|
|
|
|
|
services:
|
|
|
|
my_module.example_service:
|
|
|
|
class: Drupal\my_module\Service\ExampleService
|
|
|
|
|
|
|
|
After:
|
|
|
|
|
|
|
|
.. code:: yaml
|
|
|
|
|
|
|
|
# my_module.services.yml
|
|
|
|
|
|
|
|
services:
|
|
|
|
Drupal\my_module\Service\ExampleService: []
|
|
|
|
|
|
|
|
Automatically inject dependencies with autowiring
|
|
|
|
-------------------------------------------------
|
|
|
|
|
|
|
|
Before:
|
|
|
|
|
|
|
|
.. code:: yaml
|
|
|
|
|
|
|
|
# my_module.services.yml
|
|
|
|
|
|
|
|
services:
|
|
|
|
Drupal\my_module\Service\ExampleService:
|
|
|
|
arguments: ['@entity_type.manager']
|
|
|
|
|
|
|
|
After:
|
|
|
|
|
|
|
|
.. code:: yaml
|
|
|
|
|
|
|
|
# my_module.services.yml
|
|
|
|
|
|
|
|
services:
|
|
|
|
Drupal\my_module\Service\ExampleService:
|
|
|
|
autowire: true
|
|
|
|
|
2022-02-08 07:50:41 +00:00
|
|
|
Controllers
|
|
|
|
===========
|
|
|
|
|
|
|
|
Controllers as services
|
|
|
|
-----------------------
|
|
|
|
|
|
|
|
.. code-block:: yaml
|
|
|
|
|
|
|
|
# my_module.services.yml
|
|
|
|
|
|
|
|
services:
|
|
|
|
Drupal\my_module\Controller\ExampleController: []
|
|
|
|
|
|
|
|
Single-action controllers
|
|
|
|
-------------------------
|
|
|
|
|
|
|
|
Before:
|
|
|
|
|
|
|
|
.. code-block:: yaml
|
|
|
|
|
|
|
|
# my_module.routing.yml
|
|
|
|
|
|
|
|
my_module.example:
|
|
|
|
path: '/example'
|
|
|
|
defaults:
|
|
|
|
_controller: 'Drupal\my_module\Controller\ExampleController::handle'
|
|
|
|
requirements:
|
|
|
|
_permission: 'access content'
|
|
|
|
|
|
|
|
.. code-block:: php
|
|
|
|
|
|
|
|
// modules/my_module/src/Controller/ExampleController.php
|
|
|
|
|
|
|
|
class ExampleController {
|
|
|
|
|
|
|
|
public function handle() {
|
|
|
|
// ...
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
After:
|
|
|
|
|
|
|
|
.. code-block:: yaml
|
|
|
|
|
|
|
|
# my_module.routing.yml
|
|
|
|
|
|
|
|
my_module.example:
|
|
|
|
path: '/example'
|
|
|
|
defaults:
|
|
|
|
_controller: 'Drupal\my_module\Controller\ExampleController'
|
|
|
|
requirements:
|
|
|
|
_permission: 'access content'
|
|
|
|
|
|
|
|
.. code-block:: php
|
|
|
|
|
|
|
|
// modules/my_module/src/Controller/ExampleController.php
|
|
|
|
|
|
|
|
class ExampleController {
|
|
|
|
|
|
|
|
public function __invoke() {
|
|
|
|
// ...
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-02-08 07:46:32 +00:00
|
|
|
Automated testing
|
|
|
|
=================
|
|
|
|
|
|
|
|
* `Workshop notes <https://github.com/opdavies/workshop-drupal-automated-testing>`_
|
|
|
|
* `Workshop code <https://github.com/opdavies/workshop-drupal-automated-testing-code>`_
|