Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Drupal 8 programmatic solutions

Render custom blocks

$bid = 'myblock';
$block = \Drupal\block_content\Entity\BlockContent::load($bid);
$render = \Drupal::entityTypeManager()->getViewBuilder('block_content')->view($block);

Render plugin blocks

$block_manager = \Drupal::service('plugin.manager.block');
$config = [];
$plugin_block = $block_manager->createInstance('system_breadcrumb_block', $config);
$access_result = $plugin_block->access(\Drupal::currentUser());
if (is_object($access_result) && $access_result->isForbidden() || is_bool($access_result) && !$access_result) {
  return [];
$render = $plugin_block->build();


Get a config.


Update a config value.

\Drupal::service('config.factory')->getEditable('system.performance')->set('', 1)->save();


Update a state value.

\Drupal::service('state')->set('du_admission_steps.importer.last_run', NULL);

DB Stuff

Simple database query.

$results = \Drupal::database()->query('select * from purge_queue')->fetchAll();

Debugging an entity query, enable the devel module and add tag before execute.


BETWEEN checks on entityQuery.

$result = \Drupal::entityQuery('node')
  ->condition('field_number', [1, 3], 'BETWEEN')

IS NULL (and IS NOT NULL) checks on entityQuery.

$result = \Drupal::entityQuery('node')
  ->condition('field_banner_code', NULL, 'IS NULL')

Delete all 'event' nodes.

$result = \Drupal::entityQuery('node')
  ->condition('type', 'event')
entity_delete_multiple('node', $result);
// Add ->range(0, 10) to delete a range

Insert statement.

$query = \Drupal::database()->insert('purge_queue');
$query->fields(['data', 'created']);
$query->values(['a:4:{i:0;s:3:"url";i:1;a:4:{s:10:"66849f6f11";i:3;s:10:"c990b129a0";i:3;s:10:"c618828456";i:3;s:10:"453d844ea2";i:3;}i:2;s:66:"";i:3;a:0:{}}', time()]);

Update statement.

$query = \Drupal::database()->update('mcpl_events_feeds_item');
$query->fields(['hash' => 'update']);
$query->condition('nid', 1);

Delete statement.

$query = \Drupal::database()->delete('purge_queue');
$query->condition('data', '%url%', 'LIKE');


Display all errrors.

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);

Display error messages to the screen

Set this in settings.local.php so that it displays locally, but not on prod. The default Logging and errors should be 'None'.

// none - display none
// some - errors and warning
// all - all messages
// verbose - all messages with backtrace information
$config['system.logging']['error_level'] = 'all';

Set kint debug max level.

If kint is taking forever to load or crashing the page, try reducing the max level.

// Change kint maxLevels setting.
include_once(DRUPAL_ROOT . '/modules/contrib/devel/kint/kint/Kint.class.php');
  Kint::$maxLevels = 5;

Services.yml debugging.

You will need to copy sites/example.settings.local.php to sites/default/settings.local.php (and ensure settings.php includes settings.local.php) or put this in your settings.php file: $settings['container_yamls'][] = DRUPAL_ROOT . '/sites/';.

Update /sites/

  http.respone.debug_cacheability_headers: true
    debug: true
    auto_reload: true
    cache: false

Pretty print arrays/objects printed to watchdog.

\Drupal::logger('my_module')->debug(kpr($var, TRUE));

Debug backtrace any error.

// This function exists in core/includes/
// Just need to add lines 6-8 to it.
function _drupal_error_handler($error_level, $message, $filename, $line, $context) {
  require_once DRUPAL_ROOT . '/includes/';
  require_once DRUPAL_ROOT . '/modules/contrib/devel/kint/kint.module';
  $d = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
  ksm($message, $d);
  _drupal_error_handler_real($error_level, $message, $filename, $line, $context);

Debugging search API solr queries:

// You can output the Request object using kint/kpm, but it can be hard
// to figure out where to set the debugging code. The best place is in
// the executeRequest function in the following file:
// search_api_solr/src/SolrConnector/SolrConnectorPluginBase.php

Starting point for debugging ElasticSearch stuff, in the file

// src/ElasticSearch/Parameters/Builder/SearchBuilder.php:
// Add ksm at the end of build() and getSearchQueryOptions()



    class: Drupal\du_user_management\UserManagementService
    arguments: ['@cache.default', '']
    class: Drupal\Core\Logger\LoggerChannel
    factory: logger.factory:get
    arguments: ['du_user_management']

Service file

   * Constructor.
   * @param \Drupal\Core\Cache\CacheBackendInterface $cache
   *   The cache.
   * @param \Drupal\Core\Logger\LoggerChannelInterface $logger
   *   The logger channel.
  public function __construct(CacheBackendInterface $cache, LoggerChannelInterface $logger) {
    $this->cache = $cache;
    $this->logger = $logger;

Controller or Form

Controller/Form File

   * {@inheritdoc}
  public function __construct(UserManagementService $user_management) {
    $this->userManagement = $user_management;

   * {@inheritdoc}
  public static function create(ContainerInterface $container) {
    return new static(


Plugin File

   * {@inheritdoc}
  public function __construct(array $configuration, $plugin_id, $plugin_definition, UserManagementService $client, ConfigFactoryInterface $config_factory) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->client = $client;
    $this->configFactory = $config_factory;

   * {@inheritdoc}
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(


Load an entity. Can be a config entity also.

$node = \Drupal::entityTypeManager()->getStorage('node')->load(23);
$search_api_index = \Drupal::entityTypeManager()->getStorage('search_api')->load('title_records');

Load multiple entities (if no param is passed, all entities are loaded).

$node = \Drupal::entityTypeManager()->getStorage('node')->loadMultiple($entity_ids);

Delete multiple entities.

$result = \Drupal::entityQuery('taxonomy_term')
      ->condition('vid', 'libraries')
entity_delete_multiple('taxonomy_term', $result);

Adding a new field to a custom entity.

$new_field = BaseFieldDefinition::create('string')
  ->setLabel(new TranslatableMarkup('New Field'))
  ->setDescription(new TranslatableMarkup('New field description.'));
\Drupal::entityDefinitionUpdateManager()->installFieldStorageDefinition('<field_name>', '<entity_type_id>', '<provider>', $new_field);

Apply all updates to entities.


Checking for existence of fields on entities

Code Field not empty Field empty Not a field
!empty($node->field_entity_ref) TRUE TRUE FALSE
!empty($node->field_entity_ref->first()) TRUE FALSE PHP Error
!empty($node->field_entity_ref->first()->entity) TRUE FALSE PHP Error


$node->field_example will return a FieldItemList object (or another class that extends FieldItemList

If you want to drill down to values under the field, you can add ->first() or leave it off and it'll automatically use the first item. This is true if the field is a single item or multi-values. Example: $node->field_example->target_id or $node->field_example->first()->target_id.

If the field is an entity reference, you can get the full entity: $node->field_example->entity (this gets the first entity if it's a multi-value).

On multi-value fields to get something other than the first you can use the array index: $node->field_example[1].

Entity reference

// Both of these return the same Entity ID value.

// Get the full entity. "->entity" is only valid when the field is an entity reference.

// Get the value as an array: ['target_id' => '1'].

// Will return null.


$node->field_url->options; // Array of options.
$node->field_url->entity; // Returns null because it isn't an entity.
$node->field_url->getValue(); // Returns ['uri' => '', 'title' => '', 'options => []]
$node->field_url->value; // Returns null.

Text values

// Get the value as a string.

// Get the value as an array: ['value' => 'text'].

Load a file

$file = \Drupal\file\Entity\File::load(1007);
$file = \Drupal::entityTypeManager()->getStorage('file')->load(1007);

Working with file entities

// Get the URI (including wrapper, such as public://).
$uri = $file->getFileUri();

// Get the full URL path.
$url = file_create_url($file->getFileUri());

// Get relative path of the URL (w/o domain).
$path = file_url_transform_relative($url);


Render array for an image style.

$render = [
  '#theme' => 'image_style',
  '#style_name' => 'thumbnail',
  '#uri' => 'public://my-image.png',

Image style, get URL (full URL including http://).

$style = \Drupal::entityTypeManager()->getStorage('image_style')->load('thumbnail');
$image_url = $style->buildUrl('public://du_content_gallery-article.jpg');

Image style, get URI (public://path-to-image-style).

$style = ImageStyle::load('thumbnail');
$image_url = $style->buildUri('public://du_content_gallery-article.jpg');

Example Library

In a module.libraries.yml file.

    js/dashboard.js: {}
    - core/drupal
    - core/jquery

Adding Libraries

In preprocess function or controller function.

$variables['#attached']['library'][] = 'lotus/lotus-js';

In twig template file.

{{ attach_library('hcpl_zen/title-record') }}

In a view (pre render hook).

$view->element['#attached']['library'][] = 'custom/custom_view';


Overriding libraries

// Libraries is an array of the library data.
// Extension is 'core' or the module/theme that defined the libraries.
function hook_library_info_alter(&$libraries, $extension)


Run an update migration.

// Remove the prepareUpdate() section if you just want a normal import.
// To rollback just change 'import' to 'rollback'.
$migration = \Drupal::service('plugin.manager.migration')->createInstance('machine_name');
$executable = new \Drupal\migrate_tools\MigrateExecutable($migration, new \Drupal\migrate\MigrateMessage());

// MigrateExecutable takes an optional third argument where you can provide options including
// limit to limit the number of migrations to perform, and idlist to only migrate certain source
// IDs.
// Example: ['limit' => 10, 'idlist' => '1,2,3']

Interrupt a migration (stop it).

$migration = \Drupal::service('plugin.manager.migration')->createInstance('machine_name');

Set a migration status to Idle.

$migration = \Drupal::service('plugin.manager.migration')->createInstance('machine_name');

Run a migration on page load (w/?start-migration appended) for xdebug walkthrough.

use Drupal\migrate\MigrateExecutable;
use Drupal\migrate\MigrateMessage;

 * Implements hook_preprocess_page().
function example_module_preprocess_page(&$vars) {
  if ($qs = \Drupal::requestStack()->getCurrentRequest()->getQueryString()) {
   if (strpos($qs, 'start-migration') !== FALSE) {
      $migration_id = 'your_migration_id';
      $migration = \Drupal::service('plugin.manager.migration')->createInstance($migration_id);
      $executable = new MigrateExecutable($migration, new MigrateMessage());


Get the node from the current path.

$node = \Drupal::routeMatch()->getParameter('node');

Get current path.

$path = \Drupal::service('path.current')->getPath();

Get path arguments (from path above).

$path_args = explode('/', $path);

Get the current route.

$route_name = \Drupal::service('current_route_match')->getRouteName();


use Symfony\Component\HttpFoundation\RedirectResponse;
new RedirectResponse(\Drupal::url($route_name));

Add t() to classes (services, controllers, etc)

use Drupal\Core\StringTranslation\StringTranslationTrait;
class MyClass {
  use StringTranslationTrait;


Installing and uninstalling modules.



Render an entity.

$nid = 1;
$entity_type = 'node';
$view_mode = 'teaser';
$view_builder = \Drupal::entityTypeManager()->getViewBuilder($entity_type);
$storage = \Drupal::entityTypeManager()->getStorage($entity_type);
$node = $storage->load($nid);
$build = $view_builder->view($node, $view_mode);
$output = render($build);

Render a field.

$view_builder = \Drupal::entityTypeManager()->getViewBuilder('node');
$storage = \Drupal::entityTypeManager()->getStorage('node');
$nid = 1;
$node = $storage->load($nid);
$view = $view_builder->viewField($node->get('body'), [
  'type' => 'string', // string, entity_reference_label
  'label' => 'hidden',
  'settings' => ['link' => FALSE],
$output = render($view);

Rendering something outside of a Drupal bootstrap (ex: testing)

When you can't use render() then you need to do this:


Get headers.

$referer = \Drupal::request()->headers->get('referer');

Parameter bag ($_GET and $_POST values).

// GET parameter bag.
$bag = \Drupal::request()->query;

// POST parameter bag.
$bag = \Drupal::request()->request;

// Get all parameters as array.

// Get individual result.

// Get count of parameters.

Get the host (ex:

$host = \Drupal::request()->getHost();

Example route
  path: '/example/{name}'
    _controller: '\Drupal\example\Controller\ExampleController::content'
    name: 'My name'
    _permission: 'access content'

Using roles instead of permissions

Using a , among multiple roles means the user has to have all roles. Using a + means they need to have one.

  _role: admin,accountant

Allowing all access

  _access: TRUE


Trigger select entities to be re-indexed through the Search API.

// This is for Title Record entities, but any entity will do.
use Drupal\search_api\Plugin\search_api\datasource\ContentEntity;
use Drupal\omega_hub\Entity\TitleRecord;
$entity_ids = [507863, 509240, 513703, 515100, 536124, 537058, 541569];
$combine_id = function ($entity_id) {
  return $entity_id . ':und';
$update_ids = array_map($combine_id, $entity_ids);
$entity = TitleRecord::load(507863);
$indexes = ContentEntity::getIndexesForEntity($entity);
foreach ($indexes as $index) {
  $index->trackItemsUpdated('entity:title_record', $update_ids);


Load a user.

$node = \Drupal::entityTypeManager()->getStorage('user')->load(23);

Get current user.

$account = \Drupal::currentUser();

Get current user ID.

$account = \Drupal::currentUser()->id();

Get render array for view.

use Drupal\views\Views;
$args = [];
$view = Views::getView('my_view');
$render_array = $view->buildRenderable('my_display', $args);

Get rendered markup from above:


Get various IDs and objects.

// Get query object (only after executing the view).
$query = $view->query;

// Get view ID.

// Get current display.

// Get results (after execution).
Copy link

JayKandari commented Feb 25, 2021

This is awesome <3

Copy link

bdlangton commented Feb 25, 2021

I'm glad you like it!

Copy link

wildthreshold commented Feb 26, 2021

many thanks !!

Copy link

mightyselwyn commented Mar 24, 2021

Nice job!

Copy link

shinvdu commented Jun 15, 2021


Copy link

johnfallen commented Sep 8, 2021

Great page. goto 'this page'.

Copy link

vladdancer commented Nov 5, 2021

Migration: recreate migrate map tables for specific migration.

drush scr recreateMigrationMapTables.drush.php [MIGRATION_ID]

 * @file
 * recreateMigrationMapTables.drush.php

$migrationId = $extra[0] ?? NULL;

if (empty($migrationId)) {
  print "You should provide 'migration_id' argument\n";

$migration = \Drupal::service('plugin.manager.migration')

$idMapConfiguration = [];

/** @var \Drupal\migrate\Plugin\migrate\id_map\Sql $idMap */
$idMap = \Drupal::service('plugin.manager.migrate.id_map')
  ->createInstance('sql', $idMapConfiguration, $migration);

// Invoke $idMap->ensureTables() via:
print "Migration map tables recreated for $migrationId\n";

Copy link

emb03 commented Dec 21, 2021


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment