0

I have a content type, page, that has layout builder enabled for the full view mode, with each node able to have its layout overridden.

I need to programmatically create a page node, and customize its layout-builder layout to show the following two blocks in a single-colum (vertically-stacked):

  • field_banner (entity reference field to an entity of type banner)
  • body (node body field)

How can I create this node with an overridden layout programmatically?

1 Answer 1

0

Layout is constructed from Section and SectionComponent entities, which are then added to the field with the ID of OverridesSectionStorage::FIELD_NAME.

// Create the node, but don't save it just yet.
$node = \Drupal\node\Entity\Node::create([
  'type' => 'page',
  'title' => 'Custom Page',
  'body' => [
    'value' => 'This is the body of the node',
    'format' => 'full_html',
  ],
]);

// Load the field that stores the layout.
$layout_field = $node->get(\Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage::FIELD_NAME);

// Create a new section with a one-column layout.
$section = new \Drupal\layout_builder\Section('layout_onecol');
$region = 'Content';

// Create the configuration for the entity reference to field_banner
// on Nodes of type page.
$banner_configuration = [
  'id' => 'field_block:node:page:field_banner',
  'provider' => 'layout_builder',
  'label_display' => 0,
  'label' => 'Banner',
  'formatter' => [
    'label' => 'hidden',
    'type' => 'entity_reference_entity_view',
    'settings' => [
      'view_mode' => 'full',
    ],
    'third_party_settings' 
  ],
  'context_mapping' => [
    'entity' => 'layout_builder.entity',
    'view_mode' => 'view_mode',
  ],
];

// Create the layout builder component (item/block).
$banner_component = new \Drupal\layout_builder\SectionComponent(\Drupal::service('uuid')->generate(), $region, $banner_configuration);

// Append the component to the section.
$section->appendComponent($banner_component);

// Create the configuration for the body field.
$body_config = [
  'id' => 'field_block:node:page:body',
  'provider' => 'layout_builder',
  'label' => 'Content',
  'formatter' => [
    'label' => 'hidden',
    'type' => 'text_default',
    'settings' => [],
    'third_party_settings' => [],
  ],
  'context_mapping' => [
    'entity' => 'layout_builder.entity',
    'view_mode' => 'view_mode',
  ],
];

// Create a new layout component.
$body_component = new \Drupal\layout_builder\SectionComponent(\Drupal::service('uuid')->generate(), $region, $body_config);

// Append the component to the section.
$section->appendComponent($body_component);

// Set the entire section to the layout field of the node.
$layout_field->appendItem($section);

// Save the node.
$node->save();

To determine the values to use for $banner_configuration and $body_config, I first created a node through the UI, then set it up with the layout builder components I wanted through the UI. Then, I got the NID of the new entity, and dumped it with Drush to determine the values in the layout field:

# 12345 is the Node ID of the node to dump:
drush ev "echo print_r(\Drupal::entityTypeManager()->getStorage('node')->load(12345)->toArray(), TRUE)"

I analyzed the dumped values in the field layout_builder__layout to determine what values to use for the configuration arrays to create the layout component configuration.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.