
$parentBehaviorSettings = $paragraph->getAllBehaviorSettings();
$paragraphLayoutType = $parentBehaviorSettings['layout_paragraphs']['layout'];
First, we need to deine a couple of variables that can be used to migrate our layout Paragraph from one layout to another.When working on a recent project I found that layout Paragraphs was in use, which wasn’t a problem. The problem was that the site was quite simple, but had 12 different layouts to pick from. As a consequence, the pages consisted of a variety of different layouts that not only made the site difficult to edit, but also made the end result look a little messy.The hardest part in all of this was finding out the mechanism involved in performing these actions. Although the Layout Paragraphs module does have a mechanism to alter the layout of a Layout Paragraph in the administration area, it doesn’t perform this move in one go. In that case the change is made as the node is saved using the move_items part of the behavior settings system.You can have a look at this structure if you like, using the following database query.Let’s say we had a Layout Paragraph with the layout of “layout_twocol” that contains two other Paragraphs. This would be created like any other Paragraph using the Drupal administration pages.
Layout Paragraphs Structure
The behavior settings sometimes has an additional setting of more_items, which is used internally by the Layout Paragraphs module when a layout is manually moved from one type to another. This isn’t needed outside of this manual process. The Layout Paragraphs module is a great way of combining the flexibility of the layout system with the content component sytem of the Paragraphs module. Using this module you can set up a Paragraph that can understand different layouts and then inject Paragraphs into that layout, all within the confines of a single field.Using the above information about the structure of the layout Paragraphs we can now move them around.The solution was to move some of the existing layouts to a single type and remove those layouts from the selection. This made it easier to edit pages and also easier to predict how the site would look when we made some style changes.Here’s an example of a child of a Layout Paragraph.Alternatively, we can ask for all of the behavior settings in one go, and then extract the information we need from the relevant part of the array.The getBehaviorSetting() method takes two parameters, the first being the plugin ID to find data for (which is layout_paragraphs for this purpose) and the data that we would like to get access to.array (
'layout_paragraphs' => array (
'parent_uuid' => 'd635a666-f36f-4d76-a8a5-deee32736440',
'region' => 'first',
),
)
Whilst it is certainly possible to do this by hand, it’s not easy to track down every instance of a particular layout and convert them all. I also wanted a more automatic approach to the solution so that I could run a drush command and convert all of one type of Layout Paragraph to another.Using these variables we can now find the Layout Paragraphs that have the layout in question. As there isn’t a way to query PHP serialised arrays we need to instead load all of the Paragraphs in the system that have the type “layout“.What this means is that you users can build the layout they want within the edit pages of your Drupal site, without having to guess where Paragraphs will end up in the final site. It makes the site a little easier to edit and means that there should be less previewing of pages before publishing.$paragraphStorage = $this->entityTypeManager->getStorage('paragraph');
// Load all layout paragraphs.
$pids = $paragraphStorage->getQuery()
->condition('type', 'layout')
->accessCheck(FALSE)
->execute();
In the end, the layouts that weren’t needed on the site could then be uninstalled and removed, which simplified the backend editor experience. The site went from nearly 12 different layouts to just 3, with all of the existing layouts mapped correctly.Each child Paragraph that belongs to this layout will get a behavior_settings that will point to the parent Layout Paragraph (via a uuid). This setting will also contain the region within that Layout Paragraph that the child Paragraph belongs to.The Paragraphs that belong in this layout sit at the same level as the Paragraph in the database. Whilst I have called them children, there is actually no nesting or other recusion going on here. Consider the parent/child relationship more of an aid to understanding.// Grab all other Paragraphs from the same field.
$field_name = $paragraph->get('parent_field_name')->value;
/** @var DrupalparagraphsParagraphInterface $paragraph */
$contentParagraphs = $parentEntity->get($field_name)->referencedEntities();
foreach ($contentParagraphs as $contentParagraph) {
// Loop through the Paragraphs to find items that call this Paragraph
// the parent.
$behaviorSettings = $contentParagraph->getAllBehaviorSettings();
if (isset($behaviorSettings['layout_paragraphs']['parent_uuid']) && $behaviorSettings['layout_paragraphs']['parent_uuid'] === $paragraph->uuid()) {
// If we have a match then repoint the region and save the
// Paragraph.
$behaviorSettings['layout_paragraphs']['region'] = $layoutMovementMap[$behaviorSettings['layout_paragraphs']['region']];
$contentParagraph->setBehaviorSettings('layout_paragraphs', $behaviorSettings['layout_paragraphs']);
$contentParagraph->save();
}
}
// Save the current Paragraph with the new setting.
$parentBehaviorSettings = $paragraph->getAllBehaviorSettings();
$parentBehaviorSettings['layout_paragraphs']['layout'] = $newLayout;
$paragraph->setBehaviorSettings('layout_paragraphs', $parentBehaviorSettings['layout_paragraphs']);
$paragraph->save();
foreach ($pids as $pid) {
// Load the layout paragraph.
/** @var DrupalparagraphsParagraphInterface $paragraph */
$paragraph = $paragraphStorage->load($pid);
// -- Move the layout here.
}
Before we look at how to move layout pargraphs we should take a quick look at the structure of a Layout Paragraph. The structure of the Layout Paragraphs system is deceptivly simple for what appears to be a nested Paragraph structure.
- $matchLayoutParagraphType – This is the layout that we want to change.
- $newLayout – This is the layout that we want to change that layout to.
- $layoutMovementMap – This contains an array that is used to map layout regions from one region to another.
Moving a layout Paragraph from one type to another means altering both the parent and chlid Paragraphs. I was able to create a simple service that changed all of the Layout Paragraphs on a site with around 200 pages in a few seconds. The layout mapping was pretty much hard coded, but it suited my purposes quite well.array (
'layout_paragraphs' => array (
'layout' => 'layout_twocol',
'config' => array (
'label' => '',
),
'parent_uuid' => NULL,
'region' => NULL
),
)
In this article we will look at the structure of the Layout Paragraphs module and when how to move a Layout Paragraph from one layout to another using PHP.For the purposes of our layout the Layout Paragraph has the following structure in the behavior_settings field.Every Paragraph in the site has a field in the paragraphs_item_field_data table called behavior_settings where information about the Paragraph can be stored. This is a PHP serialised array field that is used by different modules to provide additional settings to the Paragraph to influence its functionality and create custom features. The Layout Paragraphs module uses this feature to store data pertaining to the layout.select nfp.bundle, nfp.entity_id, pi.uuid, pifd.`type`, pifd.behavior_settings
from node__field_paragraphs as nfp
inner join paragraphs_item pi on pi.id = nfp.field_paragraphs_target_id and pi.revision_id = nfp.field_paragraphs_target_revision_id
inner join paragraphs_item_field_data as pifd on pifd.id = nfp.field_paragraphs_target_id and pifd.revision_id = nfp.field_paragraphs_target_revision_id
where nfp.entity_id = 19
order by nfp.delta asc;
// Extract the layout behaviors setting for the layout paragraph and
// match the name of the layout.
$paragraphLayoutType = $paragraph->getBehaviorSetting('layout_paragraphs', 'layout');
if ($paragraphLayoutType === $matchLayoutParagraphType) {
// Move layout paragraph code.
}
$paragraphLayoutType = $paragraph->getBehaviorSetting('layout_paragraphs', 'layout');
If I get enough interest in this I’ll consider making this into a module and contributing it. Or even attempt contributing it back to the Layout Paragraphs module. My only concern is how to create the user interface since creating the mapping system might be quite complex. Making this hard coded in the system was pretty simple.This process is slightly more complex, but involves loading all of the Paragraphs in the field and looping through them until we find one that is connected to the parent Paragraph (using the uuid). Once we have one of the child Paragraphs we then need to re-map the region it has to the new region from the $layoutMovementMap variable.This code can (certainly) be improved by wrapping it in a batch system. The site I was working on at the time was quite small and only had around 100 Paragraphs to update, so the batch system wasn’t used.$matchLayoutParagraphType = 'layout_twocol_right';
$newLayout = 'layout_onecol';
$layoutMovementMap = [
'mappings' => [
'first' => 'content',
'second' => 'content',
],
];
The variables we have defined here are:





