So I have created tag filtering (in it’s simplest form) and I am getting the correct URLS (I believe) but when I visit one of those URLs I still just get the full list of things. I am obviously expecting just a list that contains only that one tag, not all of them.
Controller
<?php
return function ($page) {
$gallery = $page->images()->sortBy("sort");
$tags = $page->tags();
if($tag = param('tag')) {
$tags = $page->filterBy('tags', $tag, ',');
}
return [
'gallery' => $gallery,
'tag' => $tag,
'tags' => $tags
];
};
Template
<?php if ($tags->isNotEmpty()): ?>
<?php foreach($tags->split() as $tag): ?>
<a href="<?= url('photography', ['params' => ['tag' => urlencode($tag)]]) ?>">
<p><?= $tag ?></p>
</a>
<?php endforeach ?>
<?php endif ?>
Returning
http://localhost:8888/plainkit/photography/tag:fiat
So from this I am getting the correct URL (I think) - but why is the display of this URL still show all albums and not just the ones containing the tag fiat?
You cannot filter a single page, you probably want to filter the children:
<?php
return function ($page) {
$albums = $page->children()->listed();
$gallery = $page->images()->sortBy("sort");
$tags = $page->tags();
if($tag = param('tag')) {
$albums = $albums->filterBy('tags', $tag, ',');
}
return [
'gallery' => $gallery,
'tag' => $tag,
'tags' => $tags,
'albums' => $albums
];
};
Then in your template
<?php foreach ($albums as $album): ?>
<!-- your code here -->
<?php endforeach ?>
1 Like
Ah, OK. I guess I will need to move the controller up a level to the albums list rather than the individual album. Thanks for pointing me in the right direction.
Quick question - how would I link from the individual album then?
With the code you already posted above, but a bit modified:
<?php $tags = $page->tags()->split(','); ?>
<?php if (count($tags)): ?>
<?php foreach($tags as $tag): ?>
<a href="<?= url('photography', ['params' => ['tag' => urlencode($tag)]]) ?>">
<p><?= $tag ?></p>
</a>
<?php endforeach ?>
<?php endif ?>
And if you urlencode()
, you have to urldecode()
again in the controller.
if($tag = urldecode(param('tag'))) {
Last one, can you point me in the right direction to always show all tags. Currently going to tag:books for example, will only show the tags that those articles have and not all of them.
All Tags = Books, Life, Colors
tag:books = Books, Life
tag:colors = Life, Colors
This will fetch all unique tags of all children into an array:
$tags = $page->children()->listed()->pluck('tags', ',', true);
Yeah, I already have that which is why I asked.
I can’t point to parent because blog is the parent of all blog articles.
This is now the updated code
<?php
return function ($page) {
$notes = $page->children()->listed();
$tagurl = $page->url();
if($tag = urldecode(param('tag'))) {
$notes = $notes->filterBy('tags', $tag, ',');
}
$tags = $notes->pluck('tags', ',', true);
sort($tags);
return [
'notes' => $notes,
'tags' => $tags,
'tagurl' => $tagurl
];
};
Then this is the template
<ul class="c-tags">
<li class="c-tags__item"><a href="<?= $page->url() ?>" class="c-tags__link">All</a></li>
<?php foreach ($tags as $tag): ?>
<li class="c-tags__item">
<a href="<?= url($tagurl, ['params' => ['tag' => urlencode($tag)]]) ?>" class="c-tags__link">
<?= $tag ?>
</a>
</li>
<?php endforeach ?>
</ul>
Hm, maybe I’m missing something, but if you place your $tags
definition after the filter code, you will only get the filtered tags when the URL contains a parameter, not all tags. If you want to always have all tags, the order should be like this:
$notes = $page->children()->listed();
$tags = $notes->pluck('tags', ',', true);
$tagurl = $page->url();
if($tag = urldecode(param('tag'))) {
$notes = $notes->filterBy('tags', $tag, ',');
}
1 Like
Ah I see. OK. Many thanks.