PHP foreach loop skip first 3 items - php

I have a list of 6 products that i want to split in 2 lists of 3 products next to each other. The list are made within a foreach loop, the first list stops after the count == 2, so 3 items wil be displayed. The second list should start with the fourth item. How can i achieve this?
This is wat makes the first list of 3 items:
<?php
$_categoryId = explode(' ', $category['id']);
$count = 0;
$_productCollection = Mage::getModel('catalog/category')->load($_categoryId)
->getProductCollection()
->addAttributeToSelect('*')
->setOrder('date_added', 'DESC');
?>
<?php foreach ($_productCollection as $_product): ?>
<li class="category-row-list-item">
<a class="product-name" href="<?php echo $_product->getProductUrl() ?>">
<?php echo $this->htmlEscape($_product->getName()) ?>
</a>
</li>
<?php
if($count == 2) break; // Stop after 3 items
$count++;
?>
<?php endforeach ?>
Best regards,
Robert

For simplicity you could repeat the foreach statement but doing the opposite and continue on the first three items.
<?php foreach ($_productCollection as $_product): ?>
<?php
$count++; // Note that first iteration is $count = 1 not 0 here.
if($count <= 3) continue; // Skip the iteration unless 4th or above.
?>
<li class="category-row-list-item">
<a class="product-name" href="<?php echo $_product->getProductUrl() ?>">
<?php echo $this->htmlEscape($_product->getName()) ?>
</a>
</li>
<?php endforeach ?>
The keyword continue is used in loops to skip the current iteration without exiting the loop, in this case it makes PHP go directly back to the first line of the foreach-statement, thus increasing counter to 4 (since 4th, 5th and 6th is what we're after) before passing the if statement.
Commentary on the approach
I kept it coherent with your existing solution but a more clean way in this case would probably be to use the built in Collection Pagination.
If you use ->setPageSize(3) you can simply iterate the collection to get the first three products and then use ->setCurPage(2) to get the second page of three items.
I'm linking this blog post on the topic here just to give you an example of how it's used but since I don't know your comfort level in working with collections I retain my first answer based on your existing code.

Something like that with modulo function for have new array each 3 items :
$count = 1;
$count_change = 1;
$key = 0;
$yourList = array(
"1",
"2",
"3",
"4",
"5",
"6",
);
foreach ($yourList as $item) {
if (!isset($$new_list)) {
$new_list = "list" . $count_change . "";
$$new_list = array();
}
if ($count % 3 == 0) {
$key = 0;
$count_change++;
$new_list = "list" . $count_change . "";
$$new_list = array();
}
$$new_list[$key] = $item;
$count++;
$key++;
}
Hope this helps.

Related

How to skip the first instance in a foreach loop and limit to 8?

I was wondering if anyone could give me a hand with this...
Basically I am trying to modernize the news system of my site but I can't seem to limit the amount of posts showing in the foreach loop that is on my blog part of the site. I need to skip the first instance as it is already promoted at the top of the page. I've tried various google searches but im getting results for C++ Perl and python, what is really irritating. I just need a simple PHP solution. I'll pop my code below and see if anyone can help. Thanks for any help in-advance. And please remember to leave your responses as an answer so I can mark them up if they helped ;)
<div class="view22 full" style="margin-top:0;">
<h3>Recent News and Announcements</h3>
<?php foreach ($articles as $article) {
?>
<div class="ah7_ clearfix">
<p class="date"><?php echo date('F j', $article['article_timestamp']); ?>, <?php echo date('Y', $article['article_timestamp']); ?></p>
<h3><?php echo $article['article_title']; ?></h3>
</div>
<?php
}
?>
</div>
I assume that the $articles array has keys starting with 0. How about modifying the loop like this:
foreach ($articles as $key => $article)
and checking if $key is 0 at the beginning?
if($key == 0)
continue;
If the array keys are different: Create a new variable $i, set it to 0 and increase the value by 1 in every foreach loop iteration.
$i = 0;
foreach ($articles as $article) {
$i++;
if($i == 1)
continue;
elseif($i > 8)
break;
//the other code goes here
}
In case it is based on a SQL query, using "limit" might help to reduce load!
There are a few things you can do:
If you $articles is an array of array, having continous indexes, use a for loop instead of foreach and do something like
for ($i = 1; $i < 8 : $i++ ) {
// and access it like
$articles[$i]['some_index'] ...
}
If it is not then you can use an external counter
Say
$counter = -1;
foreach ( $articles as $article) {
$counter++;
if (!$counter) continue;
if ($counter > 7 ) break;
...// your code //
}
You can change your Mysql query to give you only the desired data, using LIMIT and OFFSET
To remove the first instance you can manually unset the item ($articles[0]) after making a copy of it or printing it as a featured news.
To limit the number of post you can use the mysql LIMIT Clause;
Or you can do something like this
foreach($articles as $key => $article){
if($key===0)
continue;
if($key===8)
break;
echo $article;// or_do_whatever_youwant_with($article);
}

php foreach even and odd but vice versa after printing 2 rows

In my application I have to loop images with two sizes. Lets call them large and small.. These images are in two columns like below.
large small
large small
large small
I produce the larage/small image by a class by doing this now like this:
<?php $count = 0; ?>
<?php foreach ($posts as $post) : ?>
<div class=" <?=(++$count%2 ? "col-7 pr-10" : "col-5 pl-10");?> mt-15">
<?php endforeach; ?>
What I would like to do here by now is to produce this list;
large small
small large
large small
etc..
In what kind of way can I do this? I guess I have to create a kind of reset after each 2 entries and set odd to eve and vise versa ?
In general if you need A B; B A; A B; etc in consecutive loops, you could do this:
$row = 0;
foreach ($posts as $post) {
if ($row%2) echo "A, B\n"; else echo "B, A\n";
$row++;
}
This looks quite a bit like your code…
If instead you really mean that you need to do
A
B
B
A
(pattern repeating every 4th row, in essence), then a clear and reasonable approach is:
$row = 0;
foreach ($posts as $post) {
$temp = $row%4;
if ($temp == 0 || $temp == 3 ) echo "A\n"; else echo "B\n";
$row++;
}
This can obviously be made more compact - but I usually find that "explicit" is easier to read six months later - and the performance impact is negligible.
Try replacing
<div class=" <?=(++$count%2 ? "col-7 pr-10" : "col-5 pl-10");?> mt-15">
with
<div class=" <?=($count%4 == 1 || ? $count%4 == 2)"col-7 pr-10" : "col-5 pl-10"; $count++;?> mt-15">
<?php $count = 0; $flag = 0;?>
<?php foreach ($posts as $post) : ?>
<?php $flag = $count%2 == 0 ? $flag + 1 : $flag;?>
<div class=" <?=(($count++ +$flag)%2 ? "col-7 pr-10" : "col-5 pl-10");?> mt-15">
<?php endforeach; ?>

Tracking Pixel - PHP Issue

How can i add a statement to this code where it stops if qty = 0.
I got this code from here but it is displaying an additional ITEM after the last one.
for example
https://www.emjcd.com/u?CID=1521607&OID=100000393&TYPE=type&ITEM1=401000305964&AMT1=16.9900&QTY1=1&ITEM2=401000305964&AMT2=0.0000&QTY2=0**&TYPE=347774&CURRENCY=USD&METHOD=IMG
It added ITEM2=401000305964&AMT2=0.0000&QTY2=0
although the database and invoice only have one item
<?php
$_customerId = Mage::getSingleton('customer/session')->getCustomerId();
$lastOrderId = Mage::getSingleton('checkout/session')->getLastOrderId();
$order = Mage::getSingleton('sales/order');
$order->load($lastOrderId);
$_totalData =$order->getData();
$_sub = $_totalData['subtotal'];//USD ==> global_currency_code,base_currency_code order_currency_code
// Incase if it is simple do this ==> https://www.emjcd.com/u?AMOUNT= $_sub;
//print_r($order); print_r($_totalData);
$_order = $this->getOrder();
$allitems = $order->getAllItems();
$index = 1;
$cjData = "";//Needed format ==> &ITEM1=3214sku&AMT1=13.49&QTY1=1&ITEM2=6577sku&AMT2=7.99&QTY2=2&
foreach($allitems as $item)
{
$cjData.="&ITEM".$index."=".$item->getSku()."&AMT".$index."=".$item->getPrice()."&QTY".$index."=".$item->getQtyToShip();
$index++;
}
?>
<div style="display:none;">
<img src="https://www.emjcd.com/u?CID=1&OID=<?php echo $this->getOrderId(); ?>&TYPE=3<?php echo $cjData; ?>&CURRENCY=USD&METHOD=IMG" height="1" width="20">
</div>
You need to set your $index variable to zero (0) before you start the foreach loop.
When you initialize your $index variable to one (1) before you go into the foreach loop, the fact that you have a line which increments the variable by one instantly throws the total item count off by 1, because it will add (a minimum) of 1 to the value (making it 2 the first time through). This is why your value held in $index if off.
What about break; if the qty is 0 just before you append $cjData.
You could use a simple if statement, so the string is only appended if the quantity is not 0.
foreach($allitems as $item)
{
if ($item->getQtyToShip() != 0) {
$cjData.="&ITEM".$index."=".$item->getSku()."&AMT".$index."=".$item->getPrice()."&QTY".$index."=".$item->getQtyToShip();
}
$index++;
}

object foreach loop iterate only even values

Basically I have a set of object values I want render in 2 separate html lists
I figure the simplest way to do this is by displaying evens only in one list, and odd only in the other
Here is the current code for displaying a single list
<ul>
<?php foreach ($values as $value) : ?>
<li><?php echo $value->value; ?></li>
<?php endforeach; ?>
</ul>
Try this:
<ul>
<?php
/* read the index key */
foreach ($values as $key => $value) :
/* skip the current element if it doesn't have an even index */
if($key % 2 == 1) continue;
?>
<li><?php echo $value->value; ?></li>
<?php endforeach; ?>
You didn't specify if the array has integer index. So I use a separate index pivot. This will do.
$v=array();
$index = 1;
foreach ($values as $value){
$v[($index++)%2][]=$value->value;
}
list ($evens, $odds) = $v;
echo "<ul><li>".implode("</li><li>", $odds)."</li></ul>"; // show list of odds
echo "<ul><li>".implode("</li><li>", $evens)."</li></ul>"; // shows list of even

too many rows created in drupal view

I have modified the tpl used for the grid view to show 3 columns of content, my only issue that the code below creates unneeded divs for the view. I have a maximum of 9 items that should be output in 3 rows, 3 per column. What's the best way to modify the code below? to prevent the extra divs from being output.
<?php foreach ($rows as $row_number => $columns): ?>
<div>
<?php foreach ($columns as $column_number => $item): ?>
<?php print $item; ?>
<?php endforeach; ?>
</div>
<?php endforeach; ?>
I would drop that notation of foreach syntax (but I think that's pretty personal :-) )
You could use the modulo to check if you just had 3 columns (if I understood your question).
<?php
// I´m assuming that $column_number is a zero based index
// if thats not the case you should add a counter to keep track of column numbers or if it is in sequence but isn't zero based you could easily update the calculates based in your starting index
foreach ($rows as $row_number => $columns) {
foreach ($columns as $column_number => $item) {
if ($column_number == 0 || $column_number%3 == 0) {
print '<div>';
}
print $item;
if ($column_number == 2 || $column_number%3 == 2) {
print '</div>';
}
}
// prevent open div tags
$total_columns = count($columns);
if ($total_columns > 0 && ($total_columns < 3 || $total_columns%3 != 0)) {
print('<div>');
}
}
I've also dropped all those opening and closing tags of php for readability.

Categories