daniel-not-dan Posted April 6, 2013 Share Posted April 6, 2013 Hi everyone! Got a puzzle here for you, and if you're able to solve it - I'm all ears! I'm trying to create a grid using PHP that looks roughly like this: <div class = "row"> <div class = "6-columns"> <div>Product</div> </div> <div class = "6-columns"> <div>Product</div> </div> </div> <div class = "row"> <div class = "6-columns"> <div>Product</div> </div> <div class = "6-columns"> <div>Product</div> </div> </div> The Products here are being collected from a group of pages. I'm able to get them to display, but here's the problem... I need to Loop thru them two-at-a-time so I can add a new "row" before each new group of two 6-column divs. Here's what I have so far (in overly-simplified form): echo "<div class = 'row'>"; foreach ($productList as $product) { echo "<div class = '6-columns'><div>$product</div></div>"; } echo "</div>" See my issue? The output from this is something like: <div class = "row"> <div class = "6-columns"> <div>Product</div> </div> <div class = "6-columns"> <div>Product</div> </div> <div class = "6-columns"> <div>Product</div> </div> <div class = "6-columns"> <div>Product</div> </div> </div> I'm sure I need some kind of do while loop or something in there, but I can't seem to get the sequence right of what should go where so I can do ONE row, then TWO products, then ONE row, then TWO products, etc. So, no, this is not really a PW issue, but I thought someone here might like a crack at helping me solve this! All the best,Daniel Link to comment Share on other sites More sharing options...
diogo Posted April 6, 2013 Share Posted April 6, 2013 I'm on mobile, so i will try to help without code. In your example, inside the foreach, check if the item is even (%=0) and not the last. If true, echo a closing row div and open a new one. For checking this you can use a counter or the api. Look on he cheatsheet for the array methods getItemKey() and last(). Link to comment Share on other sites More sharing options...
daniel-not-dan Posted April 6, 2013 Author Share Posted April 6, 2013 Awesome. I'm a PHP noob, so some of that made sense... enough of it so that I was able to get it to work anyway! Here's the basic outline of it: $lastProduct = $productList->last(); $counter = 1; foreach ($productList as $product) { if($counter % 2 != 0) { echo "<div class = 'row'>"; //item is odd, so open the div.row } //echo the product echo "<div class = '6-columns'>"; echo "<div>$product</div>"; echo "</div>"; if($counter % 2 == 0) || $product == $lastProduct { echo "</div>" ; //item is even (or list is complete), so close the div.row } $counter = $count + 1; } I wasn't sure how to use the getItemKey() method, so if anyone feels like elaborating on that, I'm once again all ears! Thanks so much, diogo! Link to comment Share on other sites More sharing options...
diogo Posted April 6, 2013 Share Posted April 6, 2013 You could use getItemKey() like this: if($a->getItemKey($i) % 2 != 0) But thinking better, this does the same and it's simpler: foreach ($productList as $key => $product){ if($key % 2 != 0) { // echo } ... 1 Link to comment Share on other sites More sharing options...
daniel-not-dan Posted April 6, 2013 Author Share Posted April 6, 2013 That worked, too - and yes, it's simpler. So, the $key is basically just a counter? I had it print the $key for each product next to the title and it just looked like sequential integers going up from 0. Is that the basic idea? Link to comment Share on other sites More sharing options...
Wanze Posted April 6, 2013 Share Posted April 6, 2013 That worked, too - and yes, it's simpler. So, the $key is basically just a counter? I had it print the $key for each product next to the title and it just looked like sequential integers going up from 0. Is that the basic idea? Yes - in this example the key acts like a counter. However, this depends on your array. In PHP, you can have arrays with numbers and strings as keys in any order - then the counter wouldn't work anymore. Some examples of arrays and keys: //Array without keys (indexes are given implicit started by 0) $array1 = array('hi', 'how', 'are', 'you?'); //Array with defined integer keys $array2 = array(0 => 'good', 245 => 'thanks'); //Associative array $array3 = array( 'firstKey' => 'firstValue', 'secondKey' => 'secondValue', ); //Now the loops foreach ($array1 as $k => $v) { echo $k; //Prints 0, 1, 2, 3 } foreach ($array2 as $k => $v) { echo $k; //Prints 0, 245 } foreach ($array3 as $k => $v) { echo $k; //Prints firstKey, secondKey } Link to comment Share on other sites More sharing options...
Macrura Posted April 6, 2013 Share Posted April 6, 2013 <?php $lastProduct = $productList->last(); $counter = 1; foreach ($productList as $product) { if(!$counter % 2) echo "<div class = 'row'>"; //item is odd, so open the div.row echo "<div class = '6-columns'> <div>$product</div> </div> "; if ( $counter % 2 || $product == $lastProduct ) echo "</div>" ; //item is even (or list is complete), so close the div.row $counter++; } ?> Link to comment Share on other sites More sharing options...
diogo Posted April 7, 2013 Share Posted April 7, 2013 Like Wanze said, in this case it can be used as a counter. Strangely the same doesn't happen with multiple image fields, where the key returns the name of the image. Ryan, if you are reading this, why is it? Link to comment Share on other sites More sharing options...
daniel-not-dan Posted April 7, 2013 Author Share Posted April 7, 2013 So after everyone's help on this, I wanted to go a little further and make the number of columns within the div.row variable to some degree. I'd like the option to display the products either two-across (which we've already accomplished) or three-across, which hurt my brain as soon as I tried to tackle it using the method above. So instead, here's what I came up with which should work for any number of columns across a 12-column grid setup. $numColumns = "4-columns"; // For a 3-across layout, given a 12-column grid. $magicNumber = 12 / $numColumns; //This will be the magic number at which the row closes itself. $lastProduct = $productList->last(); $counter = 1 foreach ($productList as $product) { if ($counter == 1) { echo "<div class = 'row'>"; //This is the first one, so open the div.row } echo "<div class = '$numColumns'>$product</div>"; if ($counter == $magicNumber || $product == $lastProduct) { echo "</div>" //This is the last one in the row, so close the div.row $counter = 0 //Reset to 0, knowing the next step will set it back to 1, so that the new row will open. } $counter++; } This allows me to pass in a variable ($numColumns) that says "I want these products to display thismany across." For my money, this seems like the simplest solution. Anyone think of any improvements? Link to comment Share on other sites More sharing options...
diogo Posted April 7, 2013 Share Posted April 7, 2013 You should change this: if ($counter == $magicNumber || $product == $lastProduct) to this: if ($counter % $magicNumber == 0 || $product == $lastProduct) Link to comment Share on other sites More sharing options...
ryan Posted April 7, 2013 Share Posted April 7, 2013 Like Wanze said, in this case it can be used as a counter. Strangely the same doesn't happen with multiple image fields, where the key returns the name of the image. Ryan, if you are reading this, why is it? On a file system, you can't have two of the same filename in the same directory. Filenames as keys ensure that same remains true in memory. 1 Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now