Enhanced page finding selectors

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

    Szabesz

    • 4 years ago
    • 90
    Wow! Thank you so much!
  • ryan

    ryan

    • 4 years ago
    • 21
    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. :)
  • Marcello Bacos

    Marcello Bacos

    • 4 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 !
    • Fantomas

      Fantomas

      • 4 years ago
      • 00
      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
     

    Twitter updates

    • This week a 2nd new module for processing Stripe payments has been added to FormBuilder. Unlike our other Stripe Inputfield, this new one supports 3D Secure (SCA) payments. We’ll take a closer look at it in this post, plus a live demo— More
      16 October 2020
    • Quick weekly update covering this week's commits for the upcoming 3.0.167 ProcessWire core version— More
      18 September 2020
    • This week ProcessWire version 3.0.166 is released on the dev branch. In this post we’ll cover all that’s new relative to the previous version, 3.0.165. Plus we’ll check out the latest new versions of ProCache and FormBuilder— More
      11 September 2020

    Latest news

    • ProcessWire Weekly #335
      In the 335th issue of ProcessWire Weekly we walk you through the latest core updates, introduce a couple of handy little tips and tricks that have surfaced from this week's support forum posts, and more. Read on!
      Weekly.pw / 10 October 2020
    • Stripe Payment Processor for FormBuilder
      This week a second new module for processing Stripe payments has been added to FormBuilder. We’ll take a closer look at it in this blog post, plus we’ve got a demo of it here too.
      Blog / 16 October 2020
    • Subscribe to weekly ProcessWire news

    “We were really happy to build our new portfolio website on ProcessWire! We wanted something that gave us plenty of control on the back-end, without any bloat on the front end - just a nice, easy to access API for all our content that left us free to design and build however we liked.” —Castus, web design agency in Sheffield, UK