Hi!
The general question:
What is the best way to get every field as a field object from inside a structure field?
The more specific question:
I have a page with a structure field that can contain blocks. I want to get the first image block that is stored somewhere in there. How do I do that?
If I do something like that
$structureArray = $route->steps()->toStructure()->toArray();
$blocks = array_map(function($item) {
return $item['blocks'];
}, $structureArray);
I only get the blocks in String form as the toArray() function converts them I suppose. I could ofc search for the first that contains a “src” and extract it, but it feels wrong.
Could you post your blueprint definition of the structure field, please?
Sure. Sorry, should’ve included that from the start.
sections:
content:
type: fields
fields:
steps:
label: Steps
type: structure
min: 1
fields:
blocks:
label: Blocks
type: blocks
fieldsets:
- image
So inside your structure you only have a blocks field which can only have image blocks, and you want to collect the first image block from all items in the structure into a single collection? Do I understand this correctly?
Yes! Ultimately I would just like to get the url of the image so I can have it as a preview-image. Which would be possible with the string, but I should be able to get the block object too, right?
// create a new Blocks instance
$blocks = new Kirby\Cms\Blocks();
// get an array of blocks fields from all structure items of the current page
$blockFields = $page->steps()->toStructure()->pluck('blocks');
// loop through these fields...
foreach ($blockFields as $field) {
// and convert each field to blocks, filter by type and add the first one to the Blocks instance
$blocks->add($field->toBlocks()->filterBy('type', 'image')->first());
}
// now that we have the blocks we are interested in, we can pluck the image fields
$imageFields = $blocks->pluck('image');
$urls = [];
foreach ($imageFields as $imageField) {
$urls[] = $imageField->toFile()->url();
}
Disclaimer: Not tested. And maybe there is a shorter way.
1 Like
Thank you texnixe! That worked!
I might have been unclear, but I actually only need the first image, so this much shorter version also did the trick:
$blockField = $route->steps()->toStructure()->pluck('blocks')[0]->blocks()->toBlocks()->first();
$previewImageURL = $blockField->toFile()->url();