Jump to content


Photo

Multiple lists and loops into dynamic reusable piece of code

lists loops foreach php

  • Please log in to reply
8 replies to this topic

#1 arjen

arjen

    Sr. Member

  • Members
  • PipPipPipPip
  • 340 posts
  • 126

  • LocationHoogeveen, The Netherlands

Posted 02 April 2012 - 01:06 PM

$jurisdictionsPageChildren = $pages->get(1011)->children();

// Check whether there are any children before attempting to split them
if($jurisdictionsPageChildren > 0) {

// Some general vars
$rows = 2;
$totalCount = count($jurisdictionsPageChildren);
$rowCount = $totalCount / $rows;
// Creating the seperate list (there has to be an easier way to do this)
$firstList = $jurisdictionsPageChildren->slice(0, $rowCount);
$secondList = $jurisdictionsPageChildren->slice($rowCount, $totalCount)
  
$mainContent .= "<div class='row jurisdictions-list'>";
  
// First list of elements
$mainContent .= "<div class='columns six alpha'>";
foreach($firstList as $child) {	
	 $mainContent .= "<h2><a$class href='{$child->url}' title='{$child->title}'>{$child->title}</a></h2>";
}
$mainContent .= "</div>";
  
// Second list of elements
$mainContent .= "<div class='columns six omega'>";
foreach($secondList as $child) {	
	 $mainContent .= "<h2><a$class href='{$child->url}' title='{$child->title}'>{$child->title}</a></h2>";
}
$mainContent .= "</div>";
  
$mainContent .= "</div>"; // Close the row class
	  
}

Okay, here is the deal. I have one list ($jurisdictionsPageChildren) which I want to split into multiple blocks/columns. I would like to adjust this code so I can set the $rows variable to some number.

The condition is that the first block (regardless of the number of blocks) has to have a class 'alpha' and that every last block has to have a class 'omega'.

I was thinking to put a foreach in a foreach, but somewhere things got messed up. If this was JSP it would do it like this:

<c:set var="splittedListHere" value="$(rpfn:splitListFunction(listHere, 2))" />
<c:forEach items="splittedListHere" var="list" varStatus="i">
  <div class="block$(i.first ? ' alpha' :'')$(i.last ? ' omega')">
	more foreach stuff
  </div>
</c:forEach>

Any thoughts to make this prettier for a PHP noob are very welcome.
work will always be the curse of the drinking classes...

#2 arjen

arjen

    Sr. Member

  • Members
  • PipPipPipPip
  • 340 posts
  • 126

  • LocationHoogeveen, The Netherlands

Posted 03 April 2012 - 03:48 AM

Sorry, it was late and perhaps I didn't explain myself correctly. I re-edited the post to be more precise.

$jurisdictionsPageChildren = $pages->get(1011)->children();

Gives as a result: 1012,1013,1014,1015,1016,1017,101,1018,1019,1020,1021,1022,1023,1024

I would like to split those into a x amount of columns. For example: if I would set the following variable:

$columnCount = 4;

For example I would like to have 4 columns/blocks.

Column 1: 1012,1013,1014,1015
Column 2: 1016,1017,1018
Column 3: 1019,1020,1021
Column 4: 1022,1023,1024

In this case column 1 (the first) should have an extra class 'alpha' and column 4 (the last) should have an extra class 'omega'.

I already found out that I can slice arrays by using the $a->slice($n, $limit), but I have trouble understanding to iterate over those loops.

I've also tried to use a while loop for the first loop and a foreach inside the while, but I am having trouble to define $n and $limit. As you can see I can set them by hand, but I thought it would be nice to create a function that sorts things out dynamicly.

Can anyone point me in the right direction?
work will always be the curse of the drinking classes...

#3 diogo

diogo

    Hero Member

  • Moderators
  • 2,014 posts
  • 1098

  • LocationPorto, Portugal

Posted 03 April 2012 - 06:37 AM

I don't know how to help you here. But somehow, this should work more or less the same way as pagination does. I wonder if looking into that the module we could find something...

EDIT:
Ok, this as nothing to do with what i said above. I wrote this code on the browser, and didn't test it. So, take it as a proof of concept.
EDIT2: I simplified the code, since the only difference you want is in the class
EDIT3: corrected some more code
$rows = 4;
$totalCount = count($jurisdictionsPageChildren);
$rowCount = $totalCount / $rows;
$firstInRow = 0;
$i = 1;
while ($i <= $rows){
   $mainContent .= "<div class='columns six";
   if($i == 1) $mainContent .= " alpha";
   if($i == $rows) $mainContent .= " omega";
   $mainContent .= "'>";
   $sliced = $jurisdictionsPageChildren->slice($firstInRow, $rowCount);
   $firstInRow+=$rowCount;
   foreach($sliced as $p){
	  $mainContent .= "<h2><a$class href='{$p->url}' title='{$p->title}'>{$p->title}</a></h2>";
   }
   $mainContent .= "</div>";
   $i++;
}

EDIT4: Tested the code above and it's working :)
I had to round up the $roundCount because i wasn't getting the last row with less pages. I used ceil() for that. So, final code would be:
$rows = 4;
$totalCount = count($jurisdictionsPageChildren);
$rowCount = ceil($totalCount / $rows); // <- this is what changed
$firstInRow = 0;
$i = 1;
while ($i <= $rows){
   $mainContent .= "<div class='columns six";
   if($i == 1) $mainContent .= " alpha";
   if($i == $rows) $mainContent .= " omega";
   $mainContent .= "'>";
   $sliced = $jurisdictionsPageChildren->slice($firstInRow, $rowCount);
   $firstInRow+=$rowCount;
   foreach($sliced as $p){
	  $mainContent .= "<h2><a$class href='{$p->url}' title='{$p->title}'>{$p->title}</a></h2>";
   }
   $mainContent .= "</div>";
   $i++;
}

Attached Thumbnails

  • 3rows.png
  • 4rows.png
  • 8rows.png


#4 diogo

diogo

    Hero Member

  • Moderators
  • 2,014 posts
  • 1098

  • LocationPorto, Portugal

Posted 03 April 2012 - 11:19 AM

Another edit deserves a new post... I noticed that the previous approach didn't work in some situations where last row wouldn't have any page to populate it (on the first screenshot there is an example with 7 rows and 23 pages). I'm not very good at maths, but I thought that, knowing the mod we could distribute the pages in another way. So, here is the new code with the changes commented:

$rows = 7;
$totalCount = count($jurisdictionsPageChildren);
$rowCount = ceil($totalCount / $rows);
$mod = $totalCount % $rows; // this will tell us how many rows will have more pages than the others
$firstInRow = 0;
$i = 1;
while ($i <= $rows){
   $mainContent .= "<div class='columns six";
   if($i == 1) $mainContent .= " alpha";
   if($i == $rows) $mainContent .= " omega";
   $mainContent .= "'>";
   if($i <= $mod){ // do this when we want one more page on the row
      $sliced = $jurisdictionsPageChildren->slice($firstInRow, $rowCount);
      $firstInRow += $rowCount;
   }else{ // do this when we want one less page on the row
      $sliced = $jurisdictionsPageChildren->slice($firstInRow, $rowCount-1);
      $firstInRow += $rowCount-1;
   }
   foreach($sliced as $p){
      $mainContent .= "<h2><a$class href='{$p->url}' title='{$p->title}'>{$p->title}</a></h2>";
   }
   $mainContent .= "</div>";
   $i++;
}
and on the other screenshots, the working version

Attached Thumbnails

  • 7rows_bad.png
  • 7rows_good.png
  • 5rows_good.png


#5 arjen

arjen

    Sr. Member

  • Members
  • PipPipPipPip
  • 340 posts
  • 126

  • LocationHoogeveen, The Netherlands

Posted 04 April 2012 - 05:00 AM

Check, check, check. You're better at math than me. :D Very clear code. This makes a lot of sense. I will use this.

Thanks diogo!
work will always be the curse of the drinking classes...

#6 diogo

diogo

    Hero Member

  • Moderators
  • 2,014 posts
  • 1098

  • LocationPorto, Portugal

Posted 04 April 2012 - 05:08 AM

i worked on it more than i thought i would, but it was fun and i learned with it ;)
glad it helped!

#7 arjen

arjen

    Sr. Member

  • Members
  • PipPipPipPip
  • 340 posts
  • 126

  • LocationHoogeveen, The Netherlands

Posted 04 April 2012 - 01:37 PM

Glad you liked it. I think i'm going to try to make this a module. I got some more ideas like sorting the elements in a horizontal way. I use a lot lists and this seems very reusable. Got to finish this project and then I think I have some spare time to try this.
work will always be the curse of the drinking classes...

#8 diogo

diogo

    Hero Member

  • Moderators
  • 2,014 posts
  • 1098

  • LocationPorto, Portugal

Posted 04 April 2012 - 01:56 PM

At some point we will have a library of reusable snippets on the website (something like this http://symphony-cms....xslt-utilities/). I think these kind of things are even better as snippets/functions than as modules, but ya, would also be a nice module :)

#9 arjen

arjen

    Sr. Member

  • Members
  • PipPipPipPip
  • 340 posts
  • 126

  • LocationHoogeveen, The Netherlands

Posted 05 April 2012 - 02:48 AM

I've heard of the library before. Is this work in progress or just an idea yet? I think it would be a great idea.
work will always be the curse of the drinking classes...





Also tagged with one or more of these keywords: lists, loops, foreach, php

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users