woyzeck
November 25, 2022, 4:12pm
1
hopefully someone could help me with that – I’ve read several threads here and tried many versions, but nothing really worked as I want … I am pretty new to php, so maybe it’s a silly question …
I have a page (produktionen) with some children (project); each child (project) has a structured field (termine):
project.yml:
sections:
daten:
type: fields
fields:
obertitel:
label: Obertitel
type: text
untertitel:
label: Untertitel
type: text
untertitel2:
label: Untertitel 2
type: text
inhalt:
extends: fields/blockEditor
help: Inhalt und Mitwirkende
presse:
extends: fields/blockEditor
help: Pressestimmen
sections:
termindaten:
type: fields
fields:
termine:
label: Termine
type: structure
fields:
datum:
label: Datum
type: date
zeit:
label: Uhrzeit
type: text
zusatz:
label: Text
type: text
my goal is to get something like a lineup from listed children of which i can post on a new page like lineup.php
date / title / untertitel … sorted by date asc
for example:
Apr 23 2022 - Project A
Project B
May 4 2022 - Project A
and so on …
my lineup.php:
<?php $projects = page('produktionen')->children(); ?>
<?php foreach ($projects->listed() as $items): ?>
<?= $items as $item->termine()->toStructure(); ?>
<?php foreach ($item->termine()->datum()->toDate()); ?>
<? $item->datum()->toDate(); ?>
<?php endforeach ?>
<?= $item->title() ?>
<?= $item->untertitel() ?>
<?php endforeach ?>
unfortunately this isn’t working … thx for any help!
texnixe
November 25, 2022, 5:02pm
2
Something went a bit wrong in your code. I renamed your variables a bit to make the structure a bit clearer:
<?php $projects = page('produktionen')->children()->listed(); ?>
<?php foreach ($projects as $project): ?>
<?php $data = $project->termine()->toStructure(); /* fetch the structure items into $data variable */?>
<?php foreach ($data as $dataItem): ?>
<?= $dataItem->datum()->toDate(); ?>
<?php endforeach ?>
<?= $project->title() ?>
<?= $project->untertitel() ?>
<?php endforeach ?>
woyzeck
November 26, 2022, 7:24am
3
thx a lot!!! that works!
there was a “-” missing in your code
<?= $project->title() ?>
just to help others with that stuff
perfect, thx @texnixe !!!
woyzeck
November 26, 2022, 8:56am
4
another question:
how can I achieve to group the dates and sort them ascending?
i’m not sure if I have to ->group or ->groupBy …?
if possible I’d like to get an output like:
Apr 23 2022 - Project A, Project B, …
May 4 2022 - Project C …
thx in advance!
texnixe
November 26, 2022, 9:24am
5
You would use group
and then a day based format, see first example in this section: Grouping collections | Kirby CMS
While the example uses a page, this works just as well for structure items.
woyzeck
November 26, 2022, 10:37am
6
thx for your hint with grouping collections - my code works, but still not grouping per date …?
any help is much appreciated!
<?php $projects = page('produktionen')->children()->listed(); ?>
<?php foreach ($projects as $project): ?>
<?php $data = $project->termine()->toStructure(); /* fetch the structure items into $data variable */?>
<?php
// function that returns the formatted date
$callback = function($data) {
return $data->datum()->toDate('EE, dd. MMM YYYY');
};
// group items using $callback
$groupedItems = $data->group($callback);
// output items by date
foreach ($groupedItems as $datum => $itemsPerDatum): ?>
<h2><?= $datum ?></h2>
<?php foreach ($itemsPerDatum as $dataItem) : ?>
<?= $project->title() ?>
<?= $project->untertitel() ?>
<?= $dataItem->zeit() ?> Uhr
<?= $dataItem->zusatz() ?></br>
<?php endforeach ?>
<?php endforeach ?>
<?php endforeach ?>
texnixe
November 26, 2022, 10:49am
7
Sorry, my suggestion didn’t make sense, because that only groups the structure items. But you want to group the projects by the data in the structure items…
The easiest approach would probably be to collect all dates from all project into an array.
Then loop through that array and filter out the projects that have this date in their structure field.
woyzeck
November 26, 2022, 11:42am
8
ah, I understand!
well, that sounds a bit complex for a noob like me
any advice where to start?
thank you very much!
texnixe
November 26, 2022, 1:15pm
9
Another option would be virtual pages collection, where each project appears multiple times with a new slug:
// This code should go into a controller or maybe better collection
$projects = page('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')]
),
];
}
}
$projectPages = Pages::factory($collection)->sortBy('date')->groupBy('date');
?>
This would then be the template part
<?php foreach ($projectPages as $date => $items): ?>
<h2><?= $date ?></h2>
<?php foreach ($items as $project) : ?>
<?= $project->title() ?>
<?= $project->untertitel() ?>
<?= $project->zeit() ?> Uhr
<?= $project->zusatz() ?></br>
<?php endforeach ?>
<?php endforeach ?>
woyzeck
November 26, 2022, 2:01pm
10
sorry for bothering …
I put the first part of your code in a collection (site/collections/lineup.php)
this is the code of my template (also called lineup.php):
<?php $kirby->collection("lineup"); ?>
<?php foreach ($projectPages as $date => $items): ?>
<h2><?= $date ?></h2>
<?php foreach ($items as $project) : ?>
<?= $project->title() ?>
<?= $project->untertitel() ?>
<?= $project->zeit() ?> Uhr
<?= $project->zusatz() ?></br>
<?php endforeach ?>
<?php endforeach ?>
now i got the following error:
ParseError thrown with message "syntax error, unexpected variable "$collection""
do I have to put something in there [ ]?
$collection = [];
texnixe
November 26, 2022, 3:05pm
11
woyzeck:
foreach ($projectPages
You have to replace this with
<?php foreach ($kirby->collection('lineup') as $date => $items): ?>
Or assign the collection to $projectPages variable.
In your collection, I don’t know what’s wrong, because you didn’t post the code.
woyzeck
November 26, 2022, 4:13pm
12
ok, I replaced the line in my template now;
this is my collection file: (lineup.php)
<?php
// This code should go into a controller or maybe better collection
$projects = page('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')]
),
];
}
}
$projectPages = Pages::factory($collection)->sortBy('date')->groupBy('date');
I get a parse error
syntax error, unexpected variable “$collection”
in line 4 site/theme/collections/lineup.php
I am not sure if I have to put something in the brackets in the collection-file?
$collection = [];
thx for your patience!
texnixe
November 26, 2022, 4:18pm
13
Missing semicolon at the end
Also, please check out the docs how a collection file has to look like: Collections | Kirby CMS
woyzeck
November 26, 2022, 5:55pm
14
ok … I read the docs, watched the video about collections but I have no idea
when I attach the missing semicolon as you mentioned above, now I get the error:
“The collection cannot be found” …?
I did nothing more, just added the semicolon …
but it is found without the semicolon and then there comes the error which I mentioned before …
this is strange :-/
texnixe
November 26, 2022, 6:24pm
15
I don’t know what you are doing, but this is what your collection should look like
<?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
November 26, 2022, 9:46pm
16
finally it works
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')->groupBy('datum', 'asc');
};
and this ist my template-file:
<?php $kirby->collection('lineup'); ?>
<?php foreach ($kirby->collection('lineup') as $date => $items): ?>
<h2><?= $date ?></h2>
<?php foreach ($items as $project): ?>
<?= $project->title() ?>
<?= $project->untertitel(); ?>
<?= $project->zeit() ?> Uhr
<?= $project->zusatz() ?></br>
<?php endforeach ?>
<?php endforeach ?>
the only thing left is: the sorting by date …
for now it seems the dates are sorted kind of weired … I tried to add ‘asc’ as you can see in the collection-file - but that has no effect … maybe you have an idea?
many many many thanks so far!!!
texnixe
November 26, 2022, 9:55pm
17
Don’t know why you are formatting the date here like that, that doesn’t make sense. Keep it at (‘Y-m-d’) or equivalent with the intl formatter.
Then format your date as desired when rendering in the frontend.
woyzeck
November 27, 2022, 3:08pm
18
interesting … I used the date handler ‘intl’ in my config.php and sorting went wrong,
when I use ‘date’ sorting works perfect!
maybe this is because I use kirby 3.7.3 … I think I have read something about an issue with date handlers in kirby 3.7.x?
anyway, now it works
thk u very much!