ProcessWire 3.0.25 and 2.8.25
This week we've got a pretty major upgrade to our page finding selectors that we think you will find useful in a lot of cases! Now you can accomplish much more with less, and this really brings our selectors to the next level.
Introduction
In ProcessWire, the most basic representation of an item within a selector string follows the format field=value
(see Selectors documentation). We use these throughout ProcessWire, but most commonly for finding pages via API calls like $pages->find("selector").
Within that context, you've been able to specify not only field=value
, but also field.property=value
, where "property" can be any property of the field. This enables you to match values from field types that might have multiple properties. Page fields are the most common case here.
Going forward in this post, we'll refer to field.property
as a.b
.
What you haven't been able to do is to go beyond that 2-part a.b
syntax for the field/property portion of the selector. Meaning you've not been able to do things like a.b.c=value
or a.b.c.d=value
, when it comes to matching pages.
Syntax and examples
For example, lets say you wanted to find all pages using template "building" that have architects located in the city of Chicago. For our example, we're assuming that both "city" and "architects" are Page fields in ProcessWire. You may have done something like this – find the architects in one operation, and the buildings in another:
$architects = $pages->find("template=architect, city.title=Chicago");
$buildings = $pages->find("architect=$architects");
That's easy enough, but wouldn't it be nicer if you could just do this?
$buildings = $pages->find("architect.city.title=Chicago");
As of ProcessWire 3.0.25 (and 2.8.25) now you can! We'll refer to the above 3-part field as a.b.c
. You can nest those properties as deep as you want to, for instance a.b.c.d
or a.b.c.d.e
(if you find the need).
Lets say that we wanted to broaden our query to include buildings designed by all architects in the state of Illinois. We'll assume that "state" is a Page field attached to template used by "city" pages, and we'll assume "abbr" is a text field used to hold the state abbreviation:
$buildings = $pages->find("architect.city.state.abbr=IL");
Broadening further, perhaps we want buildings from all architects in the USA:
$buildings = $pages->find("architect.city.state.country.abbr=USA");
Or perhaps both USA and Canada:
$buildings = $pages->find("architect.city.state.country.abbr=USA|CA");
The point to get across here is that you can get a lot more granular with your matching than previously. While you could have also accomplished this with nested sub-selectors, the syntax may have kept you from pursuing it, even when you could. This new syntax provides a more clear and readable alternative that should help you to accomplish more with less.
Details and usage
This syntax is primarily useful when dealing with Page fields, as they form the basis of cross references between pages in ProcessWire. So the a
part of a.b.c
should always be the name of a Page field, or something else that references a Page. For instance parent
and children
keywords may be used here to reference the family hierarchy the page(s) to be matched might live within.
In addition to Page fields, and the "parent" and "children" keywords, support has also been built in for Repeater, RepeaterMatrix, and PageTable fields. Meaning, any of these can represent the "a", "b", or "c" portion of the field.
The last two components of the "field" (i.e. "b.c") do not necessarily have to reference any of the above. They can be any field that has a property to match. For instance, if we wanted to find all buildings where the architect also had one or more images:
$buildings = $pages->find("architect.images.count>0");
Basically, the syntax should work just about anywhere you would expect to. Though there are a couple of limitations, mentioned below.
Limitations
While you can use OR conditions in the value portion of the selector, you can't with the field portion. Meaning, you can do a.b.c
but cannot do a.b.c|d.e.f
.
As this syntax is brand new, you might also find it may not work in some of the more complex usages of OR-groups, sub-selectors and such. So for the short term, try not to combine this syntax with those more complex selector features. Or if you do, verify your results before assuming it works – we'll be slowly introducing support for more complex usages as time goes on.
The last limitation to mention here is that this "a.b.c" syntax is implemented for database-driven page finding operations (powered by our PageFinder class), and not currently implemented for in-memory matching. Though it's unlikely you would need this syntax for pages/assets that are already in memory, but wanted to mention it just in case. Of course, the vast majority of API functions you supply selector strings to are database-driven page finding operations, so this new usage is supported by most API calls you are likely to use.
Conclusion
We hope you enjoy these enhancements to page-finding selectors in ProcessWire 3.0.25 and 2.8.25! Please let us know how they work for you, and likewise if you run into any issues while using them.
Read the ProcessWire Weekly
Comments
Szabesz
Wow! Thank you so much!
Reply
ryan
In this case, it would only be the "building" template that is using the field "architect" so it wouldn't be necessary to specify a template or parent, etc. It also helps us keep the code examples above shorter, less line-wrapping. :)
Reply
Marcello Bacos
- 8 years ago
- 01
★★★★★Amazing feature ! I'm just confused about "retrieve buildings". In examples you haven't specified "buildings template" anywhere. I'm wondering that field architects is inside buildings template, so this could be implicit! But, if another template also use architects field, how will be the result ?
Thank you for the Amazing PW !
Reply
Fantomas
Is this the answer to my question regarding the field dependencies? Please have a look at: https://processwire.com/talk/topic/4323-field-dependencies/?do=findComment&comment=129384
Reply