Hi,
I need to filter a pages section to only show pages that have the current user selected in a users field on that page.
I have found this post on the forum:
Is the method shown here (a custom page method) still the best approach?
Thanks!
Hi,
I need to filter a pages section to only show pages that have the current user selected in a users field on that page.
I have found this post on the forum:
Is the method shown here (a custom page method) still the best approach?
Thanks!
Does your users field store one or multiple users?
Note that a pages section is not filterable, you need the pagesdisplay plugin
Or a page model, depends on whether the method is needed for one or more page types.
The field stores a single user, and I only need to apply the filter to a single page type. I plan on showing it as part of site.yml
, so users can see pages that have been linked to them
The adding the method to a page model instead will be fine. The filter can be shortened a bit using an arrow function
public function getUserPages(string $fieldName)
{
return $this->children()->filter(fn ($child) => $child->{$fieldName}()?->toUser()?->is(kirby()->user()));
}
This method requires a fieldname as input, but you remove the parameter and hard-code a field name instead.
Thank you @texnixe I will be working on this next week and this is a great starting point
I have got the pagesdisplay plugin installed, and tested it with some of the example queries. All working great.
I am going with a page method, as I will probably need to use this elsewhere. I have this in my blueprint as my section:
primarySchools:
headline: Primary schools
type: pagesdisplay
query: site.currentUser
status: all
create: false
templates: school
image: false
And this in site/plugins/page-methods/index.php
:
<?php
Kirby::plugin('mhd/page-methods', [
'pageMethods' => [
'currentUser' => function () {
return $this->children()->filter(function($child) {
return $child->mentor()->toUser() === kirby()->user();
});
}
]
]);
But am getting the following error:
The section “primarySchools” could not be loaded: Query result must be of type “Kirby\Cms\Pages”, “Kirby\Cms\Field” given
The pages I am filtering are all top level, and I need to do an additional filter on them as well (site.index.filterBy('schoolType', '==', 'primary')
, which I have tried and works well), but it would be good to get the user filtering working.
This is in a user-specific blueprint using the method here: Different site blueprint depending on user - if that makes any difference, but I don’t think it would
=======================
UPDATE
I have tried this as my query (the first part works great):
query: site.index.filterBy('schoolType', '==', 'primary').currentUser
And this as the method:
Kirby::plugin('mhd/page-methods', [
'pageMethods' => [
'currentUser' => function () {
return $this->mentor() == kirby()->user();
}
]
]);
But then get this error:
**The section "primarySchools" could not be loaded:** Query result must be of type "Kirby\Cms\Pages", "null" given
You are defining a page method, but calling site.currentuser
in your blueprint. A site object is not the same as a page object.
Thanks for the pointer, that makes sense. I think I would like it to be a page method, so it is more reusable.
I have updated my query to be:
query: page.index.filterBy('schoolType', '==', 'primary').currentUser
If I remove the .currentUser
I get the pages listed correctly.
My currentUser
method is:
Kirby::plugin('mhd/page-methods', [
'pageMethods' => [
'currentUser' => function () {
return $this->mentor()->toUser() === kirby()->user();
}
]
]);
Which throws the error:
The section “primarySchools” could not be loaded: Query result must be of type “Kirby\Cms\Pages”, “null” given
I am at the edge of my understanding with this at the moment, so any help would be great.
This will return a boolean, not a collection.
Here you are trying to run your page method on a pages collection. But for a pages collection, you would need a pages
method, not a page method. Please read up about object types and return values (the new docs intro, chapter about return types might be helpful: About the docs | Kirby CMS).
Thank you for your patience, I appreciate it. I have taken a look at your suggested sections of the docs, and understand a bit more about return values (and that I need a pages one in this instance).
I am trying out a new approach to achieve this, using a user model. This was suggested on Discord, and probably makes more sense as I only need to do this for this type of user. I now have the following query:
query: kirby.user.schools
And a new schools.php
collection:
return function ($site) {
return $site->index()->filterBy('template','school');
};
And have set up this user model at plugins/user-models/index.php
:
<?php
class MentorUser extends User
{
public function schools() {
return kirby.collection('schools').filterBy('schoolType', '==', 'primary').filter(function ($school) {
return $school->mentor()->toUser() === kirby()->user();
});
}
}
Kirby::plugin('users/plugin', [
'userModels' => [
'mentor' => 'MentorUser'
],
]);
And am getting the error:
The section “primarySchools” could not be loaded: Query result must be of type “Kirby\Cms\Pages”, “Kirby\Cms\Field” given
Having looked at the docs I understand this means that the returned object is not correct. However kirby.collection('schools')
should return a pages object, I think?
The problem with this user model approach is that if a user with another role than mentor is logged in, you get this error result, because then the method is not defined. If you want a user method, then use a normal user method, not a user model method.
Note that I’m not following along the discussions on Discord. Official support = forum
Absolutely, I was just seeing if I could get some help without bothering you too much!
I have started back with the page method approach as I understand this the best. Method now looks like:
<?php
Kirby::plugin('mhd/page-methods', [
'pageMethods' => [
'currentUser' => function () {
if($this->mentor()->isNotEmpty()){
return $this->mentor()->toUser() == kirby()->user();
}
else {
return false;
}
}
]
]);
As some schools don’t have mentors. The query now looks like:
query: kirby.collection('schools').filterBy('schoolType', '==', 'primary').filterBy('currentUser')
So I can use my page
method. Unfortunately it is showing an empty section (‘No pages yet’) but at least I am not getting an error . So I think something must be up with my comparison in the middle of the method. Does that sound right?
It doesn’t even work if I hard-code the value for kirby()->user(), like this:
return $this->mentor()->toUser() === 'KP87ZUaa';
Almost, but there is a comparison value missing:
query: kirby.collection('schools').filterBy('schoolType', '==', 'primary').filterBy('currentUser', true)
And you can improve your method a little:
Kirby::plugin('mhd/page-methods', [
'pageMethods' => [
'currentUser' => function () {
// comparing these two values will return either true or false
return $this->mentor()->toUser() === kirby()->user();
}
]
]);
No need for if else… it doesn’t matter if the field is empty. If it is empty, toUser()
will return null and null is not the same as the current user.
Amazing! That is working.
Thanks for your help and patience - miraculously, I actually also understand the solution now.