Drupal is a registered trademark of Dries Buytaert
drupal 11.3.8 Update released for Drupal core (11.3.8)! drupal 11.3.7 Update released for Drupal core (11.3.7)! drupal 11.2.11 Update released for Drupal core (11.2.11)! drupal 10.6.7 Update released for Drupal core (10.6.7)! drupal 10.5.9 Update released for Drupal core (10.5.9)! cms 2.1.1 Update released for Drupal core (2.1.1)! drupal 11.3.6 Update released for Drupal core (11.3.6)! drupal 10.6.6 Update released for Drupal core (10.6.6)! cms 2.1.0 Update released for Drupal core (2.1.0)! linkit 7.0.14 Minor update available for module linkit (7.0.14). masquerade 8.x-2.2 Minor update available for module masquerade (8.x-2.2). video_embed_field 3.1.0 Minor update available for module video_embed_field (3.1.0). bootstrap 8.x-3.40 Minor update available for theme bootstrap (8.x-3.40). menu_link_attributes 8.x-1.7 Minor update available for module menu_link_attributes (8.x-1.7). editoria11y 3.0.0 Major update available for module editoria11y (3.0.0). trash 3.0.27 Minor update available for module trash (3.0.27). twig_tweak 4.0.0-alpha2 New alpha version released for module twig_tweak (4.0.0-alpha2). twig_tweak 4.0.0-alpha1 First alpha version released for module twig_tweak (4.0.0-alpha1). node_revision_delete 2.1.1 Minor update available for module node_revision_delete (2.1.1). commerce_paypal 2.1.2 Minor update available for module commerce_paypal (2.1.2).

drupal_helpers

40 sites Security covered
View on drupal.org

Development of this project takes place on GitHub.
Please submit issues there.

Helper utilities for Drupal

Features

Static facade for clean deploy hooks

Access all helpers through Helper::term(), Helper::config(), etc. — no need to inject services or know container names. One use statement is all you need.

use Drupal\drupal_helpers\Helper;

Helper::term()->createTree('tags', ['News', 'Events', 'Blog']);
Helper::config()->set('system.site', 'name', 'My Site');

Batch processing for large datasets

Pass the $sandbox array from your deploy hook and the helper automatically batches operations across multiple requests — no manual tracking of $sandbox['#finished'].

// Batch-update every article node:
function my_module_deploy_001(array &$sandbox): ?string {
  return Helper::entity($sandbox)->batchEntity('node', 'article', function ($node) {
    $node->set('field_migrated', TRUE);
    $node->save();
  });
}

// Batch-delete all articles:
function my_module_deploy_002(array &$sandbox): ?string {
  return Helper::entity($sandbox)->deleteAll('node', 'article');
}

// Batch-process arbitrary items with a callback:
function my_module_deploy_003(array &$sandbox): ?string {
  $emails = ['[email protected]', '[email protected]', /* ... hundreds more */];
  return Helper::user($sandbox)->batch($emails, function ($email) {
    Helper::user()->create($email, ['editor']);
  }, 'users');
}

Taxonomy, menu, field, entity, config, user, and redirect helpers

Common deploy hook operations covered out of the box:

  • Create taxonomy term trees (flat or nested) with duplicate detection.
  • Build menu link hierarchies from arrays.
  • Delete fields and field instances with automatic data purging.
  • Import config YAML from modules.
  • Create users with roles and auto-generated passwords.
  • Create, import (CSV), and clean up redirects.

Extendable via Drupal services

Every helper is a standard Drupal service registered in drupal_helpers.services.yml. You can override, decorate, or inject them into your own services using Drupal's dependency injection container.

# Use a helper as a dependency in your own service:
services:
  my_module.migrator:
    class: Drupal\my_module\Migrator
    arguments: ['@drupal_helpers.term', '@drupal_helpers.entity']

Module requirement checking

Helpers that depend on contrib modules (e.g., Redirect requires the redirect module) declare their requirements via requiredModules(). The facade checks these at access time and throws a clear error if a module is missing — no cryptic "service not found" exceptions.

Usage

All helpers are accessed via the Helper facade:

use Drupal\drupal_helpers\Helper;

// Simple — no sandbox:
Helper::term()->createTree('topics', $tree);
Helper::field()->delete('field_old');

// Batched — with sandbox:
function my_module_deploy_001(array &$sandbox): ?string {
  return Helper::entity($sandbox)->deleteAll('node', 'article');
}

Available methods

Helper Description Config Configuration helpers for deploy hooks. Entity Entity helpers for deploy hooks. Field Field helpers for deploy hooks. Menu Menu link helpers for deploy hooks. Redirect Redirect helpers for deploy hooks. Term Taxonomy term helpers for deploy hooks. User User helpers for deploy hooks.

Config

Configuration helpers for deploy hooks.

set(string $config_name, string $key, mixed $value): void

Set a value in a configuration object.

Helper::config()->set('system.site', 'name', 'My Site');

get(string $config_name, string $key): mixed

Get a value from a configuration object.

$site_name = Helper::config()->get('system.site', 'name');

delete(string $config_name): void

Delete a configuration object.

Helper::config()->delete('my_module.settings');

import(string $module_name, string $config_name, string $subdirectory = 'install'): void

Import a config from a module's config/install directory.

Helper::config()->import('my_module', 'views.view.my_view');
Helper::config()->import('my_module', 'node.type.page', 'optional');

importMultiple(string $module_name, array $config_names, string $subdirectory = 'install'): void

Import multiple configs from a module.

Helper::config()->importMultiple('my_module', [
  'views.view.my_view',
  'field.storage.node.field_custom',
]);

setFrontPage(string $path): void

Set the site front page.

Helper::config()->setFrontPage('/node/1');

Entity

Entity helpers for deploy hooks.

deleteAll(string $entity_type, ?string $bundle = NULL): ?string

Delete all entities of a given type and optional bundle.

Helper::entity()->deleteAll('node', 'article');

// With sandbox for large datasets:
function my_module_deploy_001(array &$sandbox): ?string {
  return Helper::entity($sandbox)->deleteAll('node', 'article');
}

Field

Field helpers for deploy hooks.

delete(string $field_name): void

Delete a field from all entity bundles and purge its data.

Helper::field()->delete('field_subtitle');

deleteInstance(string $field_name, string $entity_type, string $bundle): void

Delete a field instance from a specific entity bundle.

Helper::field()->deleteInstance('field_subtitle', 'node', 'article');

Menu link helpers for deploy hooks.

createTree(string $menu_name, array $tree, ?string $parent_id = NULL): array

Create menu links from a nested tree structure.

$tree = [
  'Home' => '/',
  'About' => [
    'path' => '/about',
    'children' => [
      'Team' => '/about/team',
      'Contact' => '/about/contact',
    ],
  ],
  'External' => 'https://example.com',
];
Helper::menu()->createTree('main', $tree);

deleteTree(string $menu_name): ?string

Delete all menu links from a menu.

Helper::menu()->deleteTree('main');

findItem(string $menu_name, array $properties): ?MenuLinkContentInterface

Find a menu link by properties.

$link = Helper::menu()->findItem('main', ['title' => 'About']);

updateItem(string $menu_name, array $find_properties, array $updates): ?MenuLinkContentInterface

Update properties on an existing menu link found by properties.

Helper::menu()->updateItem('main', ['title' => 'About'], [
  'path' => '/about-us',
  'weight' => 5,
]);

Redirect

Redirect helpers for deploy hooks.

create(string $source_path, string $redirect_path, int $status_code = 301, bool $skip_existing = TRUE): mixed

Create a redirect.

Helper::redirect()->create('old-page', '/new-page');
Helper::redirect()->create('legacy', 'https://example.com', 302);

createMultiple(array $redirects): int

Create multiple redirects.

Helper::redirect()->createMultiple([
  ['source' => 'old-page', 'target' => '/new-page'],
  ['source' => 'legacy', 'target' => 'https://example.com', 'status_code' => 302],
]);

deleteBySource(string $source_path): int

Delete redirects by source path.

Helper::redirect()->deleteBySource('old-page');

deleteAll(): ?string

Delete all redirect entities.

Helper::redirect()->deleteAll();

importFromCsv(string $file_path): ?string

Import redirects from a CSV file.

Helper::redirect()->importFromCsv('/path/to/redirects.csv');

// With sandbox for large files:
function my_module_deploy_001(array &$sandbox): ?string {
  return Helper::redirect($sandbox)->importFromCsv('/path/to/redirects.csv');
}

Term

Taxonomy term helpers for deploy hooks.

createTree(string $vocabulary, array $tree, bool $preserve_existing = TRUE, int $parent_tid = 0): array

Create terms from a nested tree structure.

// Flat list:
Helper::term()->createTree('tags', ['News', 'Events', 'Blog']);

// Nested hierarchy:
Helper::term()->createTree('topics', [
  'Finance' => [
    'Budgets',
    'Grants',
  ],
  'Governance' => [
    'Policy' => [
      'Internal',
      'External',
    ],
    'Compliance',
  ],
  'Operations',
]);

deleteAll(string $vocabulary): ?string

Delete all terms from a vocabulary.

Helper::term()->deleteAll('tags');

find(string $name, ?string $vocabulary = NULL): ?TermInterface

Find a term by name in a vocabulary.

$term = Helper::term()->find('News', 'tags');

User

User helpers for deploy hooks.

create(string $email, array $roles = [], array $fields = []): UserInterface

Create a user account.

Helper::user()->create('[email protected]', ['administrator']);
Helper::user()->create('[email protected]', ['editor'], [
  'name' => 'editor1',
  'status' => 1,
]);

createMultiple(array $emails, array $roles = [], array $fields = []): array

Create multiple user accounts.

Helper::user()->createMultiple([
  '[email protected]',
  '[email protected]',
], ['editor']);

assignRoles(string $user_identifier, array $roles): void

Assign roles to an existing user.

Helper::user()->assignRoles('[email protected]', ['administrator']);

removeRoles(string $user_identifier, array $roles): void

Remove roles from an existing user.

Helper::user()->removeRoles('[email protected]', ['administrator']);

Requirements

  • PHP 8.2+
  • Drupal 10 or Drupal 11
  • The redirect module is optional — only needed for redirect helpers.

Activity

Total releases
1
First release
Mar 2026
Latest release
1 month ago
Release cadence
Stability
100% stable

Releases

Version Type Release date
2.0.0 Stable Mar 9, 2026