Hi all
I’ve created a blog, and used the same method as with tags, to filter by category. I have it working okay but now I would like to create a route to remove the /category; from the url. Sonja has helped me with a route the other day, and it works but for a totally different way of filtering. Now I’ve filtered in a new way and would like to create a new route.
I’ve looked at the documentation and really can’t get it working…
my url looks like this site.com/magazin/category:Sport I would like it to say site.com/magazin/sport
I’ve tried this code but that only removes the ‘magazin’ part out…
return [
'routes' => [
[
'pattern' => '(:any)',
'action' => function($uid) {
$page = page($uid);
if(!$page) $page = page('blog/' . $uid);
if(!$page) $page = site()->errorPage();
return site()->visit($page);
}
],
[
'pattern' => 'blog/(:any)',
'action' => function($uid) {
go($uid);
}
]
]
];
Any help please?
texnixe
December 30, 2022, 8:14am
2
Why does your route use blog
instead of magazin? You should have a route called
'magazin/(:any)'
And apart from that, it should be like described here:
1 Like
So this is my new route
'routes' => [
[
'pattern' => 'magazin/(:any)',
'action' => function ($category) {
if ($page = page('magazin/' . $category)) {
return $page;
} else {
return page('magazin')->render([
'category' => $category
]);
}
}
]
]
When I manually type in magazin/sport - magazin opens up but it’s not filtered by sport category. However if I use the link and open up magazin/category;Sport then it filters…
texnixe
December 30, 2022, 10:48am
4
I assume you didn’t follow the recipe properly, because you cannot filter by param anymore if you don’t use params.
So I should try to use the filtering method presented in the recipe which is this?
<?php
return function ($page, $tag) {
$articles = $page->children()->listed();
if ($tag) {
$articles = $articles->filterBy('tags', $tag, ',');
}
return [
'articles' => $articles
];
};
texnixe
December 30, 2022, 8:18pm
6
Yes, of course. You cannot just use half of the recipe, it works all together. But you have to change the field name, because you want to filter by category, right?
1 Like
Okay I got it working… Only other thing I haven’t done is the lower case category in the url. Any suggestions with that?
This would work if the field contains a single value (i.e. select field, not multiselect or tags):
$articles = $articles->filter(fn ($article) => $article->category()->lower() === $category);
With this - what should my link look like?
This is what it currently looks like.
<a href="<?= page('magazin')->url() .'/'. esc($category, 'url') ?>"> <?= $category ?></a>
Okay so that works, however the filter doesn’t seem to work. I’m not getting any results now…
What is actually stored in your category field? Only one value or a comma separated list of values?
It’s always only one value.
texnixe
January 3, 2023, 12:36pm
14
Ok, can you give me an example of the value stored in the content file, an example url that doesn’t work and the final filtering code?
example value
----
Category: Sport
----
But I also have examples where Category is such as ‘Priča Se’.
Url
http://localhost:8888/magazin/sport
Filter
if ($category) {
$articles = $articles->filter(fn ($article) => $article->category()->lower() === $category);;
}
texnixe
January 3, 2023, 11:21pm
16
I know what the issue is.
$article->category()->lower()
doesn’t return a string but a field object, so we need to get the value
$articles = $articles->filter(fn ($article) => $article->category()->lower()->value() === $category);
That just goes to the 404 error page.
I think I would need to see your project, we are going in circles, it seems.
texnixe:
project
Okay
How do I show you my project?
texnixe
January 7, 2023, 11:35pm
20
The reason why you are getting the error is that you added a second routes
key in your config instead of adding the new route to the first array, thus overwriting the original route.
'routes' => [
[
'pattern' => 'magazin/(:any)',
'action' => function ($category) {
if ($page = page('magazin/' . $category)) {
return $page;
} else {
return page('magazin')->render([
'category' => $category,
]);
}
},
],
[
'pattern' => 'logout',
'action' => function () {
if ($user = kirby()->user()) {
$user->logout();
}
go('login');
},
],
],
Secondly, you need to urlencode/decode your tags.
In the template:
<a href="<?= page('magazin')->url() .'/'. urlencode(Str::lower($category)) ?>" class="button btn-small btn-red rounded text-normal ms-1"> <?= $category ?> <span class="ms-2 badge text-bg-light"><?= $page->children()->filterBy('category', $category)->count() ?></span></a>
In the controller:
if ($category) {
$articles = $articles->filter(fn ($article) => $article->category()->lower()->value() === urldecode($category));
}