Skip to main content
Version: v1

Drupal helpers

Deploy hooks and update scripts keep doing the same jobs: create a taxonomy tree, add menu links, place a block, delete a field, import redirects from a CSV file. Drupal helpers turns each of those jobs into a method on a static facade, so a deploy hook reads as a short list of changes instead of entity API boilerplate.

This page is for developers writing deploy hooks on a project built from Vortex. It shows how to call the helpers, which facades exist, and how to spread a large job across several deploy hook passes. The module documentation is the reference for its full API.

Vortex requires the module but doesn't install it during provisioning. Only the ys_demo demo module installs it, as a dependency. Declare the same dependency in the .info.yml file of every module whose code calls the helpers, so they stay available without the demo module:

dependencies:
- drupal_helpers:drupal_helpers

Helper facade​

The Helper class hands out the helper services without dependency injection, so a deploy hook can call them directly:

use Drupal\drupal_helpers\Helper;

// Create taxonomy terms.
Helper::term()->createTree('tags', ['News', 'Events', 'Blog']);

// Create menu links.
Helper::menu()->createTree('main', [
'About' => '/about',
'Contact' => '/contact',
]);

// Delete all entities of a type.
Helper::entity()->deleteAll('node', 'page');

4 helpers declare a module they need, and the facade checks that module before it returns the helper. When the module is missing, the facade throws a RuntimeException that names it, for example Required modules not installed: redirect. The deploy hook then stops before that helper changes anything.

The following facades run the check:

  • Helper::block() needs the Block module.
  • Helper::redirect() needs the Redirect module.
  • Helper::role() needs the User module.
  • Helper::translation() needs the Locale module.

Available helpers​

The following table lists all 13 facades. The Examples column names some of the methods each one exposes, and the module documentation lists them all.

HelperAccessExamples
TermHelper::term()createTree(), deleteAll(), find()
MenuHelper::menu()createTree(), deleteTree(), findItem(), updateItem()
EntityHelper::entity()create(), update(), deleteAll(), batchQuery()
ConfigHelper::config()get(), set(), import(), setFrontPage()
UserHelper::user()create(), createMultiple(), assignRoles(), removeRoles()
RedirectHelper::redirect()create(), deleteBySource(), importFromCsv()
FieldHelper::field()delete(), deleteInstance()
ModuleHelper::module()install(), uninstall()
AliasHelper::alias()create(), findByPath(), updateByPath(), deleteAll(), importFromCsv()
BlockHelper::block()place(), remove(), createContent(), deleteContent()
RoleHelper::role()create(), delete(), grantPermissions(), revokePermissions()
DisplayHelper::display()setFormComponent(), setViewComponent(), hideFormComponent(), hideViewComponent()
TranslationHelper::translation()set()

The class has 2 more static methods. Helper::report() returns a summary of what the helpers did and resets the tally, so a deploy hook that ends with return Helper::report(); reports only its own work. Helper::reporter() returns the reporter service behind that summary.

Batched operations​

The following facades accept the deploy hook's $sandbox array as their first argument:

  • Helper::term()
  • Helper::menu()
  • Helper::field()
  • Helper::entity()
  • Helper::user()
  • Helper::redirect()
  • Helper::alias()
  • Helper::block()

With a sandbox, batch() and batchEntity() spread large datasets across multiple deploy hook passes:

function ys_base_deploy_update_pages(array &$sandbox): ?string {
return Helper::entity($sandbox)->batchEntity('node', 'page', function ($node) {
$node->set('field_migrated', TRUE);
$node->save();
});
}

Without a sandbox, both methods process every item in 1 pass. The batchEntity() method builds the entity query itself from the type, the bundle, and optional conditions, while batch() takes any array of items.

Both return NULL while batches remain, and the completion message, such as Processed 120 node entities., after the last one finishes. That's what a deploy hook returns for Drush to print. Each pass handles 50 items by default. To change that, pass a second argument to the facade, for example Helper::entity($sandbox, 100).

Example in Vortex​

The ys_demo.deploy.php file uses Helper::menu() to add a Pages link to the main navigation during deployment. It looks for the link with findItem() first, as an extra guard. In its default safe mode, createTree() already matches links by title within their parent and creates only the missing ones, so running the hook again doesn't create a duplicate.