SwimToWin

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).

<?php
$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; ?>
	</div>
	<?php endforeach; ?>
</div>

A more realistic example:

<?php
$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): ?>
			<h5>
				<a href="<?=$pp->eq($i)->url?>"><?=$pp->eq($i)->title?></a>
			</h5>
		<?php endforeach; ?>
	</div>
	<?php endforeach; ?>
</div>
  • 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; ?>
    </div>
<?php endforeach; ?>
</div>

 

  • 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 celfred
      Hello, 
      I've been struggling for hours with this, and it is driving me crazy. I guess I completely misunderstand basic concepts, but I'm facing a wall here hence this message... Here's what I'm trying to do :
      I have a list of players in $allPlayers (pages) Each player has (among others) 2 pageArray fields : 'group' and 'team'. I'm trying to loop through all the players to build another pageArray (or WireArray or whatever...) to gather the players in groups/teams accordingly and deal with the different info I have on them and calculate a score. My main problem is that some players are in a different team but their group has the same name (and I need to restrict players to their own team mates). Here's my 'code' so far (which doesn't work) :
      // Build group list (for players having a team) $allPlayers->filter("team.name!=no-team")->sort("team.name"); $allGroups = new PageArray(); $uniqueGroups = []; $uGroups = new PageArray(); // This was a test, see below... $already = []; foreach($allPlayers as $p) { // Assign a groupId to each player $groupId = $p->team->id.$p->group->id; $p->groupId = $groupId; if (!in_array($groupId, $already)) { // The following lines were a test but didn't work and I DON'T UNDERSTAND WHY ? // $uG = new Page(); // $uG->of(false); // $uG->template = 'player'; // $uG->name = $groupId; // $uGroups->add($uG); // bd($uGroups->count()); // !! Keeps showing 1 ? My purpose was to be able to use $uGroups->karma, $uGroups->nbBonus... afterwards array_push($uniqueGroups, $groupId); } array_push($already, $groupId); } // Then, I loop through $uniqueGroups, get the players and calulate my score foreach($uniqueGroups as $group) { // Limit to groupId players for group scores $players = $allPlayers->find("groupId=$group"); // Check for group bonus and calculate scores [...] // I cut to simplify my post // But my other problem is storing my score : I can't use $group->karma or $group->nbBonus since $group is a ragular PHP array ? } // Then, I wanted to create a new pageArray (hence my $uGroups above) to be able to sort them with the following $uGroups->sort("-karma"); And I'm stuck... More than 5 hours today already on this, and still blocked
      I've tried playing with WireData, WireArray... but I'm all lost here. You can understand why I'm posting in the 'Getting started' forum !
      For further information, this part of code is embedded in a setScoreboard() function and this is the 'group' part of it.
      If anyone can devote a little time to give me a clue on how to think about this, I'd greatly appreciate !
      Thanks !
      PS : The more I write about this, the more I think I am able to get the group members and scores (with my awkward coding), but then I am unable of simply storing this information before rendering it. Here I'm referring to my comment in my code where I say that TracyDebugger keeps showing me only 1 $uGroups page. I wish I could dynamically build a 'uniqueGroup' page with Pagefields for Group, Team, pageArray for Members, Integer fields for calculated Karma, nbBonus...... sigh......  
    • 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?
      Edit:
      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
      Hello,
      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 :

      $allPlayers->getItemKey($loggedPlayer);
      or

      $teamPlayers->getItemKey($loggedPlayer);
      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!