Randomized collection of all blocks from all pages

I’m trying to create a randomized collection of all the blocks from all pages (with the template “project”). But can’t find how I would do that.

The only thing I have achieved so far is this which returns the blocks randomized but still group them by their project/collection.

    <?php
    foreach($kirby->collection('projects') as $project) {
        foreach($project->layout()->toBlocks()->shuffle() as $block) {
            echo $block;
        }
    }
    ?>

What I can’t figure out is how to first gather all blocks to one collection and that randomize that collection.

I’ve tried something like this but it doesn’t work and gives me the error: Class “Blocks” not found

    <?php
    $allBlocks = new Blocks();

    foreach($kirby->collection('projects') as $project) {
        foreach($project->layout()->toBlocks() as $blocks) {
           $allBlocks->add($blocks);
        }
    }
    ?>

Would be forever grateful if someone could help me figure this out!

Should be

$allBlocks = new Kirby\Cms\Blocks();

Or you have to use a use statement to import the class into your template first.

You can get rid of the two foreach loops like this:

$blocks = new Kirby\Cms\Blocks();
$fields = $kirby->collection('projects')->pluck('layout');
foreach($fields as $field) {
  $blocks->add($field->toBlocks());
}
dump($blocks);

Thanks a lot for your fast answer!

It eliminated the error but it only returns one collection. I guess the error could be in my collections(‘project’). So for the sake of clarity I’ve included what where in that ‘projects’ collection().

<?php
$blocks = new Kirby\Cms\Blocks();
$fields = $site->children()->template('project')->listed()->pluck('layout');
foreach($fields as $field) {
  $blocks->add($field->toBlocks());
}


foreach($blocks->shuffle() as $block) {
   echo $block;
}

?>

Are the pages you are looking direct children of the content folder? If in doubt, please post your content structure.

Yes they are! :slight_smile: it is as following:

content
–1_project
–2_project
–[etc…]
–error
–home

It is only the last project that is being returned. Could it be so that $blocks gets rest by each for each loop? So $blocks will only contain the blocks from the last project page?

What do you get when you

dump($site->children()->template('project')->listed());

And what when you

dump($site->children()->template('project')->listed()->pluck('layout'));

This is what i get:

Kirby\Cms\Pages Object
(
    [0] => slope-democracy
    [1] => h-m-knitwear
    [2] => favorit
)
Array
(
    [0] => Kirby\Cms\Field Object
        (
            [layout] => [{"content":{"location":"kirby","image":["sg_layout-e1629978737534.jpeg"],"src":"","alt":"","caption":"","ratio":"","crop":"false","islink":"false","newtab":"false","link":""},"id":"a3ca2440-b86f-45dc-9649-5f395bde4c34","isHidden":false,"type":"image"},{"content":{"location":"kirby","image":["sg_layout3-e1629978676509.jpeg"],"src":"","alt":"","caption":"","ratio":"","crop":"false","islink":"false","newtab":"false","link":""},"id":"82e6105f-dd1f-4d9c-9fb5-f6cf1d9d05ca","isHidden":false,"type":"image"},{"content":{"location":"kirby","image":["skarmavbild-2021-08-30-kl-10-31-26-e1630312461734.png"],"src":"","alt":"","caption":"","ratio":"","crop":"false","islink":"false","newtab":"false","link":""},"id":"04666de2-03e2-4c1b-a4ba-48557d1a1fd7","isHidden":false,"type":"image"},{"content":{"location":"kirby","image":["v1-0009_lucky_00-e1629986036464.jpeg"],"src":"","alt":"","caption":"","ratio":"","crop":"false","islink":"false","newtab":"false","link":""},"id":"f9e47712-bb65-4380-898c-d5ff2b48ff3b","isHidden":false,"type":"image"}]
        )

    [1] => Kirby\Cms\Field Object
        (
            [layout] => [{"content":{"location":"kirby","image":["instadrop-10844-e1634819262112.jpeg"],"src":"","alt":"","caption":"","ratio":"","crop":"false","islink":"false","newtab":"false","link":""},"id":"a3ca2440-b86f-45dc-9649-5f395bde4c34","isHidden":false,"type":"image"},{"content":{"location":"kirby","image":["instadrop-10847-e1634819317431.jpeg"],"src":"","alt":"","caption":"","ratio":"","crop":"false","islink":"false","newtab":"false","link":""},"id":"82e6105f-dd1f-4d9c-9fb5-f6cf1d9d05ca","isHidden":false,"type":"image"},{"content":{"location":"kirby","image":["instadrop-108411-e1634821167521.jpeg"],"src":"","alt":"","caption":"","ratio":"","crop":"false","islink":"false","newtab":"false","link":""},"id":"04666de2-03e2-4c1b-a4ba-48557d1a1fd7","isHidden":false,"type":"image"},{"content":{"location":"kirby","image":["instadrop-108414-e1635168642265.jpeg"],"src":"","alt":"","caption":"","ratio":"","crop":"false","islink":"false","newtab":"false","link":""},"id":"f9e47712-bb65-4380-898c-d5ff2b48ff3b","isHidden":false,"type":"image"}]
        )

    [2] => Kirby\Cms\Field Object
        (
            [layout] => [{"content":{"location":"kirby","image":["180313_favorite_look_7_071-e1630496902792.jpeg"],"src":"","alt":"","caption":"","ratio":"","crop":"false","islink":"false","newtab":"false","link":""},"id":"a3ca2440-b86f-45dc-9649-5f395bde4c34","isHidden":false,"type":"image"},{"content":{"location":"kirby","image":["cover-magazine-no-3-v12.gif"],"src":"","alt":"","caption":"","ratio":"","crop":"false","islink":"false","newtab":"false","link":""},"id":"82e6105f-dd1f-4d9c-9fb5-f6cf1d9d05ca","isHidden":false,"type":"image"},{"content":{"location":"kirby","image":["favorite-magazine-issue-no-1-all3.jpeg"],"src":"","alt":"","caption":"","ratio":"","crop":"false","islink":"false","newtab":"false","link":""},"id":"04666de2-03e2-4c1b-a4ba-48557d1a1fd7","isHidden":false,"type":"image"},{"content":{"location":"kirby","image":["hm_avd_winter-fashion.jpeg"],"src":"","alt":"","caption":"","ratio":"","crop":"false","islink":"false","newtab":"false","link":""},"id":"f9e47712-bb65-4380-898c-d5ff2b48ff3b","isHidden":false,"type":"image"}]
        )

)

I played around a little bit with the loops and tried using toBlocks() in the loop last loop thats rendering the blocks. It gave me all blocks but randomized by their original collection.

<?php
    $blocks = new Kirby\Cms\Blocks();
    $fields = $site->children()->template('project')->listed()->pluck('layout');
    foreach($fields as $field) {
    $blocks->add($field);
    }
?>

<?php 
        foreach($blocks->shuffle() as $block) {
            echo $block->toBlocks();
            }
?>

So it seems like the toBlocks somehow erase all other blocks in $blocks when using it in the first loop.

So I think I’ve found what the problem is. When the blocks are added to the new $blocks collection, if there is any block that have been added previously it will overwrite it if they have same position in their original collection.

So how would you give the blocks a new position in the order and not just overwrite the previous one?

<?php
    $blocks = new Kirby\Cms\Blocks();
    $fields = $site->children()->template('project')->listed()->pluck('layout');
    foreach($fields as $field) {
    $blocks->add($field->toBlocks());
    }
    dump($blocks);
    
?>

Output:
Kirby\Cms\Blocks Object
(
[0] => a3ca2440-b86f-45dc-9649-5f395bde4c34 [Block 1/4 of the last collection]
[1] => 82e6105f-dd1f-4d9c-9fb5-f6cf1d9d05ca [Block 2/4 of the last collection]
[2] => 04666de2-03e2-4c1b-a4ba-48557d1a1fd7 [Block 3/4 of the last collection]
[3] => f9e47712-bb65-4380-898c-d5ff2b48ff3b [Block 4/4 of the last collection]
[4] => 1dd3ba02-6be8-4bda-97bd-0270a7e47954 [Block 5/5 of the second last collection]
)

I don’t think it’s a problem with the position but with blocks that have for some reason the same ID. Just wondering why this is happening at all. did you manually copy blocks?

1 Like

Hahaha oh yes I did and not copying them solved the problem! Good to know that they get the same ID if you do so.

Thanks so much for your help!! :heart: