A stocking full of $pages updates

ProcessWire 3.0.46

Christmas stockings are where you find the small gifts, while the big stuff goes wrapped up under the tree. Yet, looking back, it often seems like some of the most useful stuff ends up in those stockings… Swiss army knifes, digital tire gauges, flash drives, and so on. This week, the big stuff is between you and Santa, but what we do have are lots of useful stocking stuffers for you to enjoy in ProcessWire 3.0.46!

New $pages API finding method

This method works just like $pages->find() except that it simply returns an array of matching page IDs. If there are situations where that's all you need, this method is a whole lot faster than $pages->find(). Read more

New $pages API manipulation methods

The following new $pages API methods are useful for manually sorted pages.

$pages->sort($page, $n)
This method sets and saves the sort value of $page to integer $n (0 based), and then also adjusts the sort values of all sibling pages as needed to ensure consistent order.

$pages->sort($page, true)
This is an alternate use of the sort() method that makes it re-build the sort values for all children of $page. In doing this, it removes any gaps or collisions in the sort values.

One nice thing about the sort() method is that it doesn't actually load any pages to do its job. It handles it all at the database level, so it can do it's job quickly regardless of scale.

I'm not sure how often this might be needed by others, but we needed it for certain instances in the core, and there was also a request for something like it, so we made it part of the advanced $pages API group.

Read more about the sort method

$pages->insertAfter($page, $afterPage)
This method inserts $page after the given $afterPage and commits it to the database. Internally it uses the above $pages->sort() method, so the sort values of siblings are adjusted as needed to achieve the correct placement in a manner that's efficient.

The $afterPage argument can either have the same parent as $page or a different parent. If the parent is different then the given $page goes through a $pages->save() as well (along with all related hooks) to update the parent.

$pages->insertBefore($page, $beforePage)
This works exactly like the insertAfter() method except that it inserts $page before the given $beforePage instead.

These new insert before/after methods work consistently with those you may already be familiar with in WireArray types or InputfieldWrapper types.

Support for negative “limit” and “start” values in selectors

If you've used limit=n in a selector before, you know that it is how we typically do pagination. For instance, if we wanted to get the first 10 children of $page (or the current pagination), we would do something like $page->children("limit=10"), or something similar with a $pages->find() call.

Now you can also specify negative numbers for that limit. For instance, if you specified limit=-10, it will pull the last 10 items rather than the first 10.

// get the last 10 children
$lastChildren = $page->children("limit=-10");

// get the last child
$lastChild = $page->child("limit=-1");

// last 3 items
$pages->find("template=basic-page, limit=-3"); 

While less commonly used, there's also the "start" property in selectors that typically goes along as an optional extra with the "limit", and specifies which index the results should start from (zero-based). This too can now accept negative values as well. For instance, if you wanted the 2nd to the last child:

$child = $page->child("start=-2"); 

Or maybe the 2nd to the last pagination of 10 pages:

$items = $page->children("start=-20, limit=10");  

I'm using the Page children() and child() methods in most of the examples above, but should note that this capability exists anywhere that you would use a page matching selector in ProcessWire, whether from a $pages API call, a $page traversal call, or any kind of WireArray or PageArray find/filter call. Meaning they are supported by both database and in-memory selector operations.

New “index=n” available in selectors

This new selector property lets you specify the zero-based index of the item you want to retrieve. Think of it like an nth-child() CSS selector, or a jQuery eq() method. It's similar to using a start=n, limit=1 selector, and like them, also accepts negative values to reference the end rather than the beginning. Essentially, it provides a shorter or more clear syntax for instances where you want to pluck an item at a specific index. Here's a few examples:

// get the 10th match
$pages->find("index=9, foo=bar");

// get the 10th last match
$pages->find("index=-10, bar=baz");

// get the 2nd child

The index property also accepts the keywords "first" and "last", which refer to "0" or "-1", but might provide more readable syntax for some cases:

$pages->find("index=first, foo=bar");
$pages->find("index=last, bar=baz"); 

Like the start and limit updates, the index property can be used in all database and in-memory selectors.

ProDrafts updates

We're nearing the 1-year anniversary of ProDrafts in a couple of months, and have a lot of nice upgrades on the way to celebrate. Here's a summary of what's in store for our January update:

  • When a user doesn't have permission to publish a draft, they now have the option to "submit it for approval". This places it in a pending review queue for users that have permission to publish it. Editors can also make updates to their draft or withdraw it from the approval queue.

  • When editing a draft that's been submitted for approval, users with publish permission to the page can now click "Approve" or "Reject". If they click Approve, the page is published. If they Reject, the page is removed from the pending queue and sent back to the editor for further changes.

  • Notification emails accompany the workflow so that publishers know when drafts are pending and editors know when their drafts are approved or rejected. Publishers and editors can subscribe to email notifications by checking a box in their user profile.

  • The drafts list screen (ProcessProDrafts) now uses tabs to isolate drafts awaiting approval from the main list of drafts.

Lastly, I wanted to mention that I'm also currently working on repeater support for drafts as well. This part isn't as far along as the workflow processes mentioned above, but since many have asked for it I wanted to let you know it's in our current high priority list of ProDrafts updates and actively being worked on right now and into the holidays.

Other tweaks in 3.0.46

We've made some adjustments to the dropdown submit buttons (like seen in the page editor) so that they should be a little more friendly when using a mouse. When you click to open the dropdown, it no longer disappears immediately if you hover away from it. Now it will stay open for a second or two, to prevent unintentional menu closure.

A debug mode memory leak that occurred even when debug mode was off has been fixed in the $pages->findMany() method. This would not have been an issue except at very large scale, but now not even a small memory leak is possible here. We've also optimized the performance for some usages of $pages->findMany() as well. Thanks to @apeisa and Avoine for helping us to identify these.

Tomorrow, I'll be starting off my Christmas eve with a coffee and the ProcessWire Weekly, and hope to see you there.

Hope that you all have a wonderful Christmas and holiday!


  • 3fingers


    • 7 years ago
    • 60

    Merry Xmas to you and your family too Ryan!
    P.s. = Does every update of this new release apply to the 2.8.x branch too?

  • 3fingers


    • 7 years ago
    • 00

    Merry Xmas to you and your family too Ryan!
    P.s. = Does every update of this new release apply to the 2.8.x branch too?

  • Zahari M

    Zahari M

    • 7 years ago
    • 60

    Merry Xmas Ryan! Thanks so much for such for an amazing ProcessWire year!!! :)

  • Can


    • 7 years ago
    • 20

    marry christmas =)

  • Matjaž Prijatelj

    Matjaž Prijatelj

    • 7 years ago
    • 50

    Thank you Ryan. I wish you and processwire to further evolve and give us php beginners more casestudies to learn on. With pw I've learned more than with every other cms I've used combined.

    And marry christmas to all pw-ers too.


PrevProcessWire 3.0.45 core updates


This latest version on the dev branch includes several tweaks, fixes, upgrades and some nice optimizations. This post covers them all, plus a look at our new Page field configuration. Then we conclude with some fun API tips and tricks. More 

NextProcessWire 2017 Roadmap


Looking back over the last year, it's been a really great year for the project, and wow has it gone fast! In this post we'll look back at some of what we've accomplished over the last year, and–more importantly–introduce and review our 2017 roadmap. More 

Latest news

  • ProcessWire Weekly #490
    In the 490th issue of ProcessWire Weekly we'll check out what's new in the latest core version ProcessWire 3.0.229, introduce a brand-new third party module, and more. Read on!
    Weekly.pw / 30 September 2023
  • ProcessWire 3.0.226 new main/master version
    After 8 months in development we are excited to bring you ProcessWire 3.0.226 main/master. This version has a ton of great new features, improvements and optimizations, plus more than 100 issue fixes. This post takes an in-depth look at highlights from this great new version.
    Blog / 25 August 2023
  • Subscribe to weekly ProcessWire news

“Indeed, if ProcessWire can be considered as a CMS in its own right, it also offers all the advantages of a CMF (Content Management Framework). Unlike other solutions, the programmer is not forced to follow the proposed model and can integrate his/her ways of doing things.” —Guy Verville, Spiria Digital Inc.