array_chunk support

Recommended Posts

While ProcessWire and WireArray does not have support for array_chunk, there is a simple way to achieve this.

With array_chunk() you can easily add DIVs to a foreach loop, without having to set up counters when using general PHP (hat-tip to Laurance over at StackOverflow). The idea in a ProcessWire context is to use array_chunk() to split an array into chunks - and use eq() when looping page results.

Simple example that will split a WireArray into three columns. Before we begin, you should know the array_chunk syntax: array_chunk($array, $chunk_size, $preserve_keys=true|false).

$p = $pages->get('/news')->children('limit=15, template=article, sort=-sort');
<div class="row">
	<?php foreach (array_chunk(range(0,14),5) as $chunk): ?>
	<div class="col">
		<?php foreach ($chunk as $i): ?>
			<h5><a href="<?=$p->eq($i)->url?>"><?=$p->eq($i)->title?></a></h5>
		<?php endforeach; ?>
	<?php endforeach; ?>

A more realistic example:

$p = $pages->get('/news');
$pp = $p->children('limit=15, template=article, sort=-sort');
<h2><a href="<?=$p->url?>"><?=$p->title?></a></h2>
<div class="row">
	<?php foreach (array_chunk(range(0,14),5) as $chunk): ?>
	<div class="col">
		<?php foreach ($chunk as $i): ?>
				<a href="<?=$pp->eq($i)->url?>"><?=$pp->eq($i)->title?></a>
		<?php endforeach; ?>
	<?php endforeach; ?>
  • Like 2

Share this post

Link to post
Share on other sites

Although your approach would be a bit faster (less function calls overall), it can be turned into a hook and be called on any class that extends WireArray, basically any collection returned by ProcessWire API

// /site/ready.php

wire()->addHookMethod('WireArray::chunk', function (HookEvent $e) {
    $chunkSize = (int)$e->arguments(0) ?? 1;
    $e->return = array_chunk($e->object->getArray(), $chunkSize);

A common use case is to build grids

<?php $myPages = $pages('template=my-template'); ?>
<div class="grid">
<?php foreach ($myPages->chunk(5) as $chunk): ?>
    <div class="row">
        <?php foreach ($chunk as $item): ?>
            <div class="col"><?= $item->title ?></div>
        <?php endforeach; ?>
<?php endforeach; ?>


  • Like 3

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.

  • Similar Content

    • By modifiedcontent
      Another dumb question:
      Is there a field type for a text-based array?
      In my case I need to store an array of RSS feeds for SimplePie. Storing that list of links in a textarea - text formatted to look like an array - doesn't work with the script. It works with one link.
      The images field is an array. I assumed there would be an equivalent for URLs or text in general.
      Or is there another approach for these cases?
      I guess using the optional (module) Repeater field type is the best solution in this case? I have now a working solution based on that. Still curious about other ideas.
    • By celfred
      Still in my 'teaching game'. Here's my problem : I 'find' all players with a request like

      $allPlayers = $pages->find("template=player"); [/code Then, I limit to players belonging to the team of the logged in player with [code] $teamPlayers = $allPlayers->find("team=$loggedPlayer->team");
      No problem so far. But my scoreboards rely on either :


      to find the logged player's position in the charts.
      On the 'global' newboard with scoreboards based upon $allPlayers, everything works as expected.
      BUT on my 'team' newsboard, even though I'm using $teamPlayers, the returned indexes are based upon $allPlayers. Am I clear ? In other words, I have a total of 125 players, and my logged player is 61 out of 125 regarding the number of places he freed. But in his particular team of 25 players, he sould be 15 whereas he's still 61
      I'd like to reset my indexes (and start back from 0), but I can't find my way out of this...
      If someone has a hint to help, I'd appreciate.
      I have a second part in my worry : I had a way around it by simply making another 'raw' request :

      $teamPlayers = $pages->find("team=$loggedPlayer->team");
      Then my team indexes were right, but I faced another issue : Reordering my wirearray according to the scoreboard I want usually worked fine (simple sort() based upon an integer field, for example, player's coins, player's karma...) and indexes were updated BUT resorting with places.count ('places' field is a pageArray) doesn't update the indexes returned by getItemKey and my logged player is always at the position he was when I first did my initial $pages->find() query  
      So my way around found its limit and that's why I'm posting here, after struggling with this for a couple of hours...
      Thanks in advance for the help. 
    • By louisstephens
      I believe I have hit a roadblock on this one. I am trying to pass an array to a "cc" in wiremail (using wiremailsmpt to extend). Everything else is working, but I am getting an "invalid email address" for $cc_recipient[0]. I looked in wiremail, and it is checking to see if it is a valid email address before sending (which my variable is not). Is there a way around this by chance?
    • By thmsnhl
      Hi everyone,
      I've recently hired at a new company and here I am evaluating the abilities of ProcessWire for our projects.
      I was able to meet almost every requirement so far, but there is one point I couldn't find an adequate solution for: outputting data to json.
      I am aware of modules like https://modules.processwire.com/modules/pages2-json/ (which does not seem to work for me) but I thought with a function like wireEncodeJSON this should be much cleaner. What I would like to achieve is outputting pages with according field values into an array to use this within javascript.
      My first attempt on this was:
      $jsontestOne = $pages->find(1001)->children(); echo wireEncodeJSON($jsontestOne); which outputs 
      [{}] and afterwards I tried that one:
      $jsontest = $pages->find("template=basic-page")->getArray(); echo wireEncodeJSON($jsontest); which outputs 
      [{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},...] Maybe you can point out where my mistake is.
      Thanks in advance!
    • By modifiedcontent
      I am trying to integrate another script, Questions2Answer, with Processwire user management. The script needs an array with key/value pairs for user->name => user->id 
      The script provides an array $userids with active user->ids that looks like this var_dumped for a page with two users:
      array(2) { [0]=> int(1107) [1]=> int(41) } How can I take $userids, find the corresponding $user->names in Processwire as values and then return that to Q2A as a clean key/value array?
      This is probably basic PHP, but I have tried so many variations that I now completely lost the plot. Any pointers appreciated.