Creating content blocks programmatically in Drupal 8

01 Aug · by Tim Kamanin · 2 min read

Let's picture this: you've created a custom content block type (let's say, Ad block) in your shiny new Drupal 8 installation and you want to automaticaly create a fresh new block of that type each time you create a taxonomy term (Ad group), so that every ad group has a corresponding ad block.

How do I do that? Simple! Follow ~~the white rabbit~~ me:

  1. We add the entity_insert hook and catch our taxonomy term insert event:
<?php
/**
 * Implements hook_entity_insert().
 */
function pabc_ads_entity_insert(Drupal\Core\Entity\EntityInterface $entity) {
  // Catching a term that belongs to the ad_group vocabulary.
  if ($entity->getEntityTypeId() == 'taxonomy_term' && $entity->bundle() == 'ad_groups') {

  }
}
  1. Next we create our block via EntityManager Drupal service:
<?php
// Grab a block entity manager from EntityManager service
$blockEntityManager = \Drupal::service('entity.manager')
->getStorage('block_content');

// Tell block entity manager to create a block of type "ad_block"
$block = $blockEntityManager->create(array(
'type' => 'ad_block'
));

// Every block should have a description, but strangely it's property
// is not 'description' but 'info'
// in my case, I want it to be equal to my ad_group's term name.
$block->info = $entity->name->value;

// This is optional part, my ad_block has a field field_ad_group
// which is a taxonomy reference to the ad_group taxonomy,
// that way I link ad_group and ad_block together.
$block->field_ad_group = $entity;

// In the end, save our new block.
$block->save();
  1. So in the end you code snippet should look like this:
<?php
/**
 * Implements hook_entity_insert().
 */
function pabc_ads_entity_insert(Drupal\Core\Entity\EntityInterface $entity) {

  // Catching a term that belongs to the ad_group vocabulary.
  if ($entity->getEntityTypeId() == 'taxonomy_term' && $entity->bundle() == 'ad_groups') {

// Grab a block entity manager from EntityManager service
$blockEntityManager = \Drupal::service('entity.manager')
->getStorage('block_content');

// Tell block entity manager to create a block of type "ad_block"
$block = $blockEntityManager->create(array(
  'type' => 'ad_block'
));

// Every block should have a description, but strangely it's property
// is not 'description' but 'info'
// in my case, I want it to be equal to my ad_group's term name.
$block->info = $entity->name->value;

// This is optional part, my ad_block has a field field_ad_group
// which is a taxonomy reference to the ad_group taxonomy,
// that way I link ad_group and ad_block together.
$block->field_ad_group = $entity;

// In the end, save our new block.
$block->save();
  }

}

As you see, creating content blocks in Drupal 8 is pretty similar to creating any other type of entity (node or taxonomy), you just need to figure out a correct service to do that and check what fields should be filled in.

Comments

Required for comment verification



Mark Fullmer

Nice write up. To be complete, it would probably be a good idea to delete the blocks when the entity is deleted. Following the example:

/**
 * Implements hook_entity_delete().
 *
 * When a a given is deleted, we want to clean up any blocks that
 * reference that entity ID, as they will no longer work.
 */
function pabc_ads_entity_delete(EntityInterface $entity) {
  if ($entity->getEntityTypeId() == 'taxonomy_term' && $entity->bundle() == 'ad_groups') {
$entity_type = 'ad_block';
$ids = \Drupal::entityQuery('block_content')
  ->condition('type', $entity_type)
  ->condition('field_ad_group.target_id', $entity->get('id')->value)
  ->execute();
if (!empty($ids)) {
  $storage_handler = \Drupal::entityTypeManager()->getStorage('block_content');
  $entities = $storage_handler->loadMultiple($ids);
  $storage_handler->delete($entities);
}
  }
}
Reply · 1 year, 1 month ago