# Group foreach items from collection

**URL:** <https://forum.getkirby.com/t/group-foreach-items-from-collection/27165>\
**Category:** Questions\
**Tags:** v3\
**Created:** [December 1, 2022, 3:36pm UTC](https://forum.getkirby.com/t/group-foreach-items-from-collection/27165 "2022-12-01T15:36:36Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![woyzeck](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/woyzeck/32/12645_2.png) [@woyzeck](https://forum.getkirby.com/u/woyzeck)\
**Post date:** [December 1, 2022, 3:36pm UTC](https://forum.getkirby.com/t/group-foreach-items-from-collection/27165/1 "2022-12-01T15:36:36Z")

</div>

dear community,  
I got stuck with following issue:

the plan is to get an overview/programme/lineup of all project-dates - the projects are child pages and each project-page contains a structure field with date / time / location …  
@texnixe helped me a lot sorting things out - see here:

> [@Dates in structure field from child pages](https://forum.getkirby.com/t/dates-in-structure-field-from-child-pages/27113/16):
>
> finally grinning it works wink this is my collection-file: \<?php return function ($site) { $projects = $site-\>find('produktionen')-\>children()-\>listed(); $collection = []; foreach ($projects as $project) { foreach ($project-\>termine()-\>toStructure() as $item) { $collection[] = [ 'slug' =\> $project-\>slug() . '-' . $item-\>datum()-\>toDate('EE, dd. MMM YYYY'), 'template' =\> $project-\>intendedTemplate()-\>name(), …

I’d like to have the output like this:

September 2022 (month)

 23. (day)- Project A, 20:00
- Project B, 21:00

Oktober 2022

10.- Project B, 20:00

15.- Project B, 20:00

 and so on ...

with my current code it looks like this:

September 2022 (month)

 23. (day)- Project A, 20:00
- Project B, 21:00

Oktober 2022

10.- Project B, 20:00

Oktober 2022
15.- Project B, 20:00

I’d like to group the months like the days … I’ve tried it with group function but without success :-/

this is my template:

```auto
<?php $kirby->collection('lineup'); ?>

<?php foreach ($kirby->collection('lineup') as $date => $items):

    $groupedMonths = $items->sortBy('datum')->group(function($p) {
      return $p->datum()->toDate('Y-m');
      }); ?>  

          <h3>
          <?= $groupedMonths ?>
          </h3>
  
    <?php   
    $groupedDays = $items->sortBy('datum')->group(function($p) {
      return $p->datum()->toDate('d.');
      }); ?>
          
          <p>
          <?= $groupedDays ?>
          </p>
      
    <?php foreach ($items as $project): ?>
    <?= $project->title() ?>
    <?= $project->untertitel(); ?>
    <?= $project->zeit() ?>
    <?= $project->zusatz() ?>
    <?php endforeach ?>          

<?php endforeach ?>

```

this is my collection:

```auto
<?php

return function ($site) {
    $projects = $site->find('produktionen')->children()->listed();
    $collection = [];

    foreach ($projects as $project) {
        foreach ($project->termine()->toStructure() as $item) {
            $collection[] = [
                'slug' => $project->slug() . '-' . $item->datum()->toDate('Y-m-d'),
                'template' => $project->intendedTemplate()->name(),
                'content' => array_merge(
                    $project->content()->toArray(),
                    ['datum' => $item->datum()->toDate('Y-m-d'),
                     'zeit' => $item->zeit(),
                     'zusatz' => $item->zusatz()]
                ),
            ];
        }
    }
  

  return Pages::factory($collection)->sortBy('datum', 'asc')->groupBy('datum', 'asc');
  };

```

any help would be appreciated!

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [December 1, 2022, 5:06pm UTC](https://forum.getkirby.com/t/group-foreach-items-from-collection/27165/2 "2022-12-01T17:06:58Z")

</div>

You need to group the collection by month in this case, then within each month collection, group by day.

So you got to start at the collection definition.

---

<div class="post-metadata">

**Author:** ![woyzeck](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/woyzeck/32/12645_2.png) [@woyzeck](https://forum.getkirby.com/u/woyzeck)\
**Post date:** [December 2, 2022, 6:39am UTC](https://forum.getkirby.com/t/group-foreach-items-from-collection/27165/3 "2022-12-02T06:39:35Z")

</div>

so do I need to create two different collections - one for months and one for days?

---

<div class="post-metadata">

**Author:** ![woyzeck](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/woyzeck/32/12645_2.png) [@woyzeck](https://forum.getkirby.com/u/woyzeck)\
**Post date:** [December 3, 2022, 1:48pm UTC](https://forum.getkirby.com/t/group-foreach-items-from-collection/27165/4 "2022-12-03T13:48:50Z")

</div>

I tried to create a collection for months, but I am not sure, if this is correct …?  
this is the `dump` output:

```auto
Array
(
    [0] => Array
        (
            [0] => 2022-12
        )

    [1] => Array
        (
            [0] => 2022-12
        )

    [2] => Array
        (
            [0] => 2022-12
        )

    [3] => Array
        (
            [0] => 2023-01
        )

    [4] => Array
        (
            [0] => 2023-01
        )

    [5] => Array
        (
            [0] => 2023-01
        )

    [6] => Array
        (
            [0] => 2023-01
        )

    [7] => Array
        (
            [0] => 2023-01
        )

    [8] => Array
        (
            [0] => 2022-09
        )

    [9] => Array
        (
            [0] => 2022-09
        )

    [10] => Array
        (
            [0] => 2022-10
        )

    [11] => Array
        (
            [0] => 2022-10
        )

    [12] => Array
        (
            [0] => 2022-10
        )

    [13] => Array
        (
            [0] => 2022-10
        )

)

```

this is the collection month.php:

```auto
<?php 

return function ($site) {
  $projects = $site->find('produktionen')->children()->listed();

  foreach ($projects as $project) {
    foreach ($project->termine()->toStructure() as $item) {
        $collection[] = [
            $item->datum()->toDate('Y-m')
        ];
            }
  }
  
  return $collection;
};

```

I am not sure, but I think things like sortBy and groupBy don’t work with arrays …?

thx for any advice!

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [December 3, 2022, 3:43pm UTC](https://forum.getkirby.com/t/group-foreach-items-from-collection/27165/5 "2022-12-03T15:43:25Z")

</div>

Why didn’t you create the collection exactly as originally, with the only difference being the date formated by Y-m instead Y-m-d?

> [@woyzeck](#):
>
> but I think things like sortBy and groupBy don’t work with arrays …?

Yes, of course not, sortBy and groupBy are member methods of their class and can only be used with objects or that class.

---

<div class="post-metadata">

**Author:** ![woyzeck](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/woyzeck/32/12645_2.png) [@woyzeck](https://forum.getkirby.com/u/woyzeck)\
**Post date:** [December 3, 2022, 4:36pm UTC](https://forum.getkirby.com/t/group-foreach-items-from-collection/27165/6 "2022-12-03T16:36:51Z")

</div>

> [@texnixe](#):
>
> Why didn’t you create the collection exactly as originally, with the only difference being the date formated by Y-m instead Y-m-d?

yes, that’s what I tried first, but then I got the following output (with the template I postet above):

2022-09 (month)

1. (day)  
Project A  
Project A

2022-10 (month)

1. (day)  
Project A  
Project B  
and so on …

it seems `$groupedDays` can`t get the whole date …?

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [December 3, 2022, 6:57pm UTC](https://forum.getkirby.com/t/group-foreach-items-from-collection/27165/7 "2022-12-03T18:57:09Z")

</div>

Sorry, I got confused myself now.

The collection has to be created a originally with the full date. But then do not group the collection or group by month:

```auto
<?php

return function ($site) {
    $projects = $site->find('produktionen')->children()->listed();
    $collection = [];

    foreach ($projects as $project) {
        foreach ($project->termine()->toStructure() as $item) {
            $collection[] = [
                'slug' => $project->slug() . '-' . $item->date()->toDate(),
                'template' => $project->intendedTemplate()->name(),
                'content' => array_merge(
                    $project->content()->toArray(),
                    ['date' => $item->date()->date('Y-m-d')]
                ),
            ];
        }
    }

    return Pages::factory($collection)->sortBy('date')->groupBy('date');

woyzeck
7d

finally :grinning: it works :wink:

this is my collection-file:

<?php

return function ($site) {
    $projects = $site->find('produktionen')->children()->listed();
    $collection = [];

    foreach ($projects as $project) {
        foreach ($project->termine()->toStructure() as $item) {
            $collection[] = [
                'slug' => $project->slug() . '-' . $item->datum()->toDate('EE, dd. MMM YYYY'),
                'template' => $project->intendedTemplate()->name(),
                'content' => array_merge(
                    $project->content()->toArray(),
                    ['datum' => $item->datum()->toDate('EE, dd. MMM YYYY'),
                     'zeit' => $item->zeit(),
                     'zusatz' => $item->zusatz()]
                ),
            ];
        }
    }
  

  return Pages::factory($collection)->sortBy('datum', 'asc');
};

```

With that you have a standard ungrouped pages collection, one page for each date.

Now in your template, you can group this collection by month:

```auto
<?php $collection = collection('mycollection'); ?>
<?php foreach($collection->group(fn ($p) => $p->date()->toDate('Y-m')) as $month => $items): ?>
    <?= $month ?>
    <?php foreach ($items->groupBy('date') as $day => $dayItems) : ?>
        <?= $day ?>
        <?php foreach ($dayItems as $event): ?>
            <?= $event->title() ?>
        <?php endforeach ?>
    <?php endforeach ?>
<?php endforeach ?>

```

(Not tested)

---

<div class="post-metadata">

**Author:** ![woyzeck](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/woyzeck/32/12645_2.png) [@woyzeck](https://forum.getkirby.com/u/woyzeck)\
**Post date:** [December 4, 2022, 8:25am UTC](https://forum.getkirby.com/t/group-foreach-items-from-collection/27165/8 "2022-12-04T08:25:04Z")

</div>

good morning and thx again for your patience!

the collection works as expected:

```auto
Kirby\Cms\Collection Object
(
    [0] => 2022-09-29
    [1] => 2022-09-30
    [2] => 2022-10-01
    [3] => 2022-10-06
    [4] => 2022-10-07
    [5] => 2022-12-16
    [6] => 2022-12-17
    [7] => 2022-12-31
    [8] => 2023-01-06
    [9] => 2023-01-07
    [10] => 2023-01-12
    [11] => 2023-01-13
    [12] => 2023-01-14
)

```

unfortunately i get an error `Call to a member function toDate() on null` for this line:

```auto

```

```auto
<?php foreach($collection->group(fn ($p) => $p->date()->toDate('Y-m')) as $month => $items): ?>

```

```auto

```

this seems to be really tricky … 🙈

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [December 4, 2022, 9:05am UTC](https://forum.getkirby.com/t/group-foreach-items-from-collection/27165/9 "2022-12-04T09:05:56Z")

</div>

Rather you seem to have named the field differently maybe, datum instead of date?

---

<div class="post-metadata">

**Author:** ![woyzeck](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/woyzeck/32/12645_2.png) [@woyzeck](https://forum.getkirby.com/u/woyzeck)\
**Post date:** [December 4, 2022, 9:10am UTC](https://forum.getkirby.com/t/group-foreach-items-from-collection/27165/10 "2022-12-04T09:10:25Z")

</div>

yes I did, but I edited the names according to my field-names …

---

<div class="post-metadata">

**Author:** ![texnixe](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/texnixe/32/5754_2.png) [@texnixe](https://forum.getkirby.com/u/texnixe)\
**Post date:** [December 4, 2022, 9:12am UTC](https://forum.getkirby.com/t/group-foreach-items-from-collection/27165/11 "2022-12-04T09:12:35Z")

</div>

If you want, send me a download link via PM to your project, then I can look into it instead of having to set up a test case myself.

---

<div class="post-metadata">

**Author:** ![woyzeck](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/woyzeck/32/12645_2.png) [@woyzeck](https://forum.getkirby.com/u/woyzeck)\
**Post date:** [December 4, 2022, 9:24am UTC](https://forum.getkirby.com/t/group-foreach-items-from-collection/27165/12 "2022-12-04T09:24:32Z")

</div>

you’ve got mail 😉 thx!!!

---

<div class="post-metadata">

**Author:** ![woyzeck](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/woyzeck/32/12645_2.png) [@woyzeck](https://forum.getkirby.com/u/woyzeck)\
**Post date:** [December 4, 2022, 10:10am UTC](https://forum.getkirby.com/t/group-foreach-items-from-collection/27165/13 "2022-12-04T10:10:20Z")

</div>

> [@texnixe](#):
>
> `return Pages::factory($collection)->sortBy('date')->groupBy('date');`

it works!!!  
deleting `->groupBy('date')` in the collection brought success!

THX A LOT!!!
