Hi there!
I am new to kirby and new to the forum and I hope someone can help me.
Is it possible to display a different amount of posts (one less to be specific) on the first page of a category?
This is my Code so far and ChatGPT had different ideas for solving this. But none of them worked.
<?php
$categoryFilters = get('category');
$tagFilters = get('tag');
$unfiltered = $page->children()->listed();
$postsPerPage = 2;
$posts = $unfiltered
->when($categoryFilters, function($categoryFilters) {
return $this->filterBy('category', $categoryFilters);
})
->when($tagFilters, function($tagFilters) {
return $this->filterBy('tag', $tagFilters);
})
->paginate($postsPerPage);
$pagination = $posts->pagination(); // $pagination neu zuweisen
$categories = $unfiltered->pluck('category', ',', true);
$tags = $unfiltered->pluck('tag', ',', true);
?>
Thanks in advance.
The easiest way to achieve this would probably be with a little hack:
Prepend a virtual page
$posts = $unfiltered
->when($categoryFilters, function($categoryFilters) {
return $this->filterBy('category', $categoryFilters);
})
->when($tagFilters, function($tagFilters) {
return $this->filterBy('tag', $tagFilters);
});
$posts = $posts->prepend(Page::Factory(['slug' => 'trash', 'template' => 'trash']);
$posts = $posts->paginate(postsPerPage);
When you loop through the posts, skip the one with the wrong template.
foreach ($posts as $post) {
if ($post->intendedTemplate()->name() === 'trash') continue;
// do stuff with the rest
}
Thanks for the quick reply. This helped kinda. But I figured out another solution to this and it works nicely.
<?php
$categoryFilters = get('category');
$tagFilters = get('tag');
$unfiltered = $page->children()->listed();
$postsPerPage = 2;
$posts = $unfiltered
->when($categoryFilters, function($categoryFilters) {
return $this->filterBy('category', $categoryFilters);
})
->when($tagFilters, function($tagFilters) {
return $this->filterBy('tag', $tagFilters);
});
$posts = $posts->paginate($postsPerPage);
$pagination = $posts->pagination();
$categories = $unfiltered->pluck('category', ',', true);
$tags = $unfiltered->pluck('tag', ',', true);
// Auf der ersten Seite einer Kategorie ein Beitrag weniger
if ($categoryFilters && $pagination->page() === 1) {
$posts = $posts->paginate(1);
}
// Auf der ersten Seite eines Schlagworts ein Beitrag weniger
if ($tagFilters && $pagination->page() === 1) {
$posts = $posts->paginate(1);
}
?>
I doubt that the pagination links will still work
Yeah, well, it still kinda works. But it brought a new problem. It no longer shows the second post in the list. There is post no.1 on page 1 and if I click to the second page, it starts with post no.3.
Maybe I find a different solution.
A non-hacky way would be to group your posts, then paginate the groups, similar to what I suggested here, with the only difference that you need to find a grouping scheme that returns the first page in one group, and the following pages in chunks of two, for example based on index number
https://forum.getkirby.com/t/paginate-by-months/13886/8
For your example you could create a method like this in a model:
public function groupIndex($collection) {
//return $this->indexOf($collection);
return $this->indexOf($collection) === 0 ? 'group0' :
($this->indexOf($collection) % 2 !== 0 ? 'group' . ($this->indexOf($collection)) : 'group' . ($this->prev($collection)?->indexOf($collection)));
}
Controller:
$posts = $page->children()->listed()->group(fn($item) => $item->groupIndex($page->children()->listed()));
$pagination = Pagination::For($posts, ['limit' => 1]);
$posts = $posts->slice($pagination->offset(), $pagination->limit());
Then continue like in the example I linked to.