Robin S

Adding array_chunk support to WireArray

Recommended Posts

PHP has a useful array_chunk function: it is used to split an array into a number of smaller arrays ('chunks') of a size you specify, which are returned to you in a new array (i.e. an array of arrays).

ProcessWire doesn't provide a method for WireArrays that is the equivalent of array_chunk, but we can add a new method for this in hook. In /site/init.php...

// Add a new 'chunk' method to WireArray, the equivalent of PHP's array_chunk
$wire->addHookMethod('WireArray::chunk', function($event) {
    $wire_array = $event->object;
    $size = $event->arguments[0];
    if( !((int) $size > 0) ) throw new WireException('WireArray::chunk requires an integer $size argument greater than zero');
    $array = array();
    $count = count($wire_array);
    for($n = 0; $n < $count; $n += $size) {
        $array[] = $wire_array->slice($n, $size);
    }
    $event->return = $array;
});

 

Now we can use this new chunk() method on any WireArray to return an array of smaller WireArrays. Remember that many array-like objects in PW are WireArrays, including PageArrays, Pageimages and Pagefiles.

An example using a PageArray of 'workshop' pages. We are running a series of workshops and there is only time for four workshops per day, so we want to divide the workshops into groups of no more than four and put each group under a heading...

// Get all workshop pages
$workshops = $pages->find("template=workshop"); // say this returns 12 pages

// Split the workshops into PageArrays of no more than 4 pages each
$chunked_workshops = $workshops->chunk(4); // an array of 3 PageArrays of 4 pages each

foreach($chunked_workshops as $key => $chunk) {

    // $key is the zero-based index of the array
    $num = $key + 1;

    // Output a heading followed by the workshop links
    echo "<h3>Day $num</h3>";
    echo $chunk->each("<p><a href='{url}'>{title}</a></p>"); // $chunk is a PageArray
    
}

 

Another example, this time using images. Say we want to divide the images into groups of three or less - maybe they are to be arranged into rows or we are giving the groups some special styling.

// Say this page's 'images' field holds 8 images
// Split the images into Pageimages objects of no more than 3 images each
// 8 does not divide evenly by 3 so the last Pagesimages object will contain only 2 images
$chunked_images = $page->images->chunk(3);

foreach($chunked_images as $chunk) {
    echo "<div class='image-group'>";

    // $chunk is a Pageimages object
    foreach($chunk as $image) {
        echo "<img src='{$image->size(300, 300)->url}'>";
    }

    echo "</div>";
}

 

  • Like 10

Share this post


Link to post
Share on other sites

For sure it would be a great addition to WireArray API.

Share this post


Link to post
Share on other sites
On 2017-5-7 at 9:47 AM, Zeka said:

For sure it would be a great addition to WireArray API.

I do not think too many functions/methods should be implemented in the core, especially this unique one, although I get the usefulness of it as a shortcut.

BTW, here's the docs of $wire->addHookMethod with another example

https://processwire.com/api/ref/wire/add-hook-method/

And for those who want to get more OOP:

https://processwire.com/docs/tutorials/using-custom-page-types-in-processwire/

Share this post


Link to post
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

  • Recently Browsing   0 members

    No registered users viewing this page.