Jump to content

Selecting by a page field


ferahl
 Share

Recommended Posts

Hi,

I have created a post-like structure like this:

Page: Posts

Page: Category

Posts has a field called "category" which is derived from the Category page's children - these children simply have a title field e.g. ("Events", "News" etc)

I would like to filter the children of Posts based on this field, something like this:

$posts = $pages->get('/posts/')->children("category=events");

However category is a number, in my case Events is the number 1014. Obviously I want to filter by a string instead. How can I do this?

Thanks in advance for your help!

///////////////////////////////////////

Apologies, after I wrote this I saw a related page at the bottom. Here is the solution for completeness:

http://processwire.c...a-selector-tag/

$category = $pages->get("/category/events/");

$posts = $pages->get('/posts/')->children("category=$category");

Nice and easy :)

  • Like 1
Link to comment
Share on other sites

To make it even shorter, you can also do this (specify path to category):

$posts = $pages->find("parent=/posts/, category=/category/events/"); 

Or this (specify title of category):

$posts = $pages->find("parent=/posts/, category.title=Events");

To take it further, you could replace "title" above with any field present on the category template and match based on that. But I think 'title' or 'name' are probably the most common ones.

If your 'category' field only exists on your posts, then technically, you could leave out the "parent=" part. Though a more specific selector tends to scale better than a less specific one (like if you re-use your category field in another template). So I do think it's worthwhile to keep it, or use $pages->get('/posts/')->children('...') like in your example.

In PW 2.3 (dev branch), you can now do this as well, which would be the shortest possible alternative:

$posts = $pages->find("category=events"); 

The above is matching the page's name field. Since there is no slash in the value "events", it assumes you are talking about the page's name rather than path or ID.

  • Like 4
Link to comment
Share on other sites

  • 7 months later...
Same situation here:
 
I have built a structure with language trees.
 
home/de/page1/page2
home/en/page1/page3
 
 
I am almost always selecting from the, what I call - local_index page, like /de/ to find pages in the same language tree.
 
$local_lang_url = "/de/"; // (example)

//search 1 (works, 2 searches):
$blocks = $pages->get($local_lang_url)->find('page_key=block_m-help-legal');
//search 2 (does not work): 
$blocks = $pages->get($local_lang_url)->children('page_key=block_m-help-legal');
//search 3 (does not work) 
$blocks = $pages->get("has_parent=" . $local_lang_url . " , page_key=block_m-help-legal");
//search 4 (works best): 
$blocks = $pages->find("has_parent=" . $local_lang_url . ", page_key=block_m-help-legal");
 
For my curiosity, I wonder what is wrong with search 2 and 3:
What is the problem with children() and get() in this context?
 
And how it is with the speed if I do a get(), narrowing the search with a find()
- instead of using find() with an AND selector?
 
And my last question is, whether there is a better way to declare the
local_index file as homepage and root for searches?
 
At the moment I stick with search 4, although I thought, find() is slow.
Link to comment
Share on other sites

For my curiosity, I wonder what is wrong with search 2 and 3:
What is the problem with children() and get() in this context?
//search 2 (does not work): 
$blocks = $pages->get($local_lang_url)->children('page_key=block_m-help-legal');

I don't see anything wrong with #2, other than that I'm wondering if your $pages->get($local_lang_url); really makes more sense to be a $page->rootParent call instead? But if your current one isn't working, I would suggest that the /de/ page does not have any visible or viewable children that have a field 'page_key' with the value 'block_m-help-legal'. Are you sure you didn't intend for your children() to instead be a find()? Example:

$blocks = $page->rootParent->find("page_key=block_m-help-legal"); 
//search 3 (does not work) 
$blocks = $pages->get("has_parent=" . $local_lang_url . " , page_key=block_m-help-legal");

The problem with #3 is that it looks like you are expecting a PageArray, but getting a Page. If you simply changed your get() to a find(), I believe it would do what you are expecting. And it should return the same exact results as the example above I posted. 

And how it is with the speed if I do a get(), narrowing the search with a find()
- instead of using find() with an AND selector?

If you can achieve the same thing with one find() that you could with a combined get() and find(), then the single find() will likely be faster. For all practical purposes, it probably doesn't matter much though. 

And my last question is, whether there is a better way to declare the
local_index file as homepage and root for searches?

If your level-1 pages are language segments, like "/de/" as you mentioned, then $page->rootParent will always refer to the root of your current language. I have a feeling this is what you want to be using rather than detecting it some other way. 

At the moment I stick with search 4, although I thought, find() is slow.

find() is not slow. Every function that returns a Page or PageArray eventually gets routed through find(), so we've really tried to make sure it is fast and optimized. But I still think you probably want a $page->rootParent->find("page_key=..."); rather than a $pages->find("has_parent=..."); 

Link to comment
Share on other sites

Thank you very much for this in-depth explanation.

This hepls a lot.

Maybe I have a problem with the database but this is strange:

Setup:

/de/file   with checkbox menu (autojoin)

/en/file   with checkbox menu (autojoin)

/es/file    with checkbox menu (autojoin)

This is funny, has_parent only works in 1 language, although I am sure, the settings are identical (cloned):

$pages->find('has_parent=/de/, menu=1, include=all) - OK

$pages->find('has_parent=/en/, menu=1, include=all) - no result

$pages->find('has_parent=/es/, menu=1, include=all) - no result

The rootParent way (good to know about the rootParent, I thought this was for something else):

$page->rootParent->find('menu_btn_to_footer2=1'  - OK only for /de/ - same as above.

 

This works (but it is not what I want, because /de/ could be parent or also grand parent.

$pages->find('parent=/de/, menu=1, include=all) - OK

$pages->find('parent=/en/, menu=1, include=all) - OK

$pages->find('parent=/es/, menu=1, include=all) - OK

Can this be stopwords, or is the search string to short for a reliable result?

Or can this be a problem with the database? Everything was cloned from the /de/ tree.

Link to comment
Share on other sites

This works so far, I guess I was mixing here page arrays and single pages and find() returns an array.

$page->rootParent->child("page_key=check-status")->url

(I wished there were more examples in the tutorials)

Link to comment
Share on other sites

It's possible that your index tree needs a refresh. Try dragging the entire /en/ page (tree) below a new parent. Drop it there and let it sit for 5 seconds. Then drag it back to have home as the parent. Now try your query again and see if it's showing up when using has_parent. 

  • Like 1
Link to comment
Share on other sites

  • 4 weeks later...

It's possible that your index tree needs a refresh. Try dragging the entire /en/ page (tree) below a new parent. Drop it there and let it sit for 5 seconds. Then drag it back to have home as the parent. Now try your query again and see if it's showing up when using has_parent. 

Looks like this was the KEY HINT to solving all our mistery bugs for find() and get().

(The most scary bugs are features which work only sometimes, with no reproducible pattern.)

 THIS TIP SHOULD BE THE #1 HINT IN CASE OF TROUBLE. :-X

I know were it came from: We built one language tree first with all its many sub-pages.

Then we duplicated the tree to make that the basis for language translations.

So the clone module might have an issue - or it should just be common practice to 

refresh indexes manually this way after an excessive cloning.

Thank you again for your time and valuable support!

  • Like 1
Link to comment
Share on other sites

  • 1 year later...
$posts = $pages->find("parent=/posts/, category=/category/events/");
$posts = $pages->find("parent=/posts/, category.title=Events");
$posts = $pages->find("category=events");
The above is matching the page's name field. Since there is no slash in the value "events", it assumes you are talking about the page's name rather than path or ID.

I'm currently quite confused.

I set up a Page field (checkbox as inputfield) called "props" (properties) and I'm using it for additional page properties like for my little messaging system "read" for example. So the selectable pages are under /admin/custom-settings/page-properties/.

First none of them were working. After comparing different page fields in backend and then with this little snippet

$props = $fields->get("props");
$FieldtypePage = $modules->get('FieldtypePage');
var_dump($FieldtypePage->getSelectorInfo($props));

Then I realized that the props field for some reason only has count as subfield listed. Checking admin field settings again led me to the point that I haven't specified a template for selectable pages. After doing so it's still not working as expected.

So what I'm actually trying to do is for example finding all unread pages so where props not includes "read"

$unreadMsgs = $pages->find("template=message, recipient=$user, props.name!=read")->count();

which is still not working

The only thing working now is

props.title!=Read

which is fine in this case. But I'm wondering why "props.name!=read" is not working or as you mentioned "props!=read" ?

What am I missing here?

EDIT: forgot to mention that it's working for other fields. I'm using author.name=$urlSegment for example..

Edited by Can
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...