foreach( $tabs2 as $tab2 => $name ){
$class = ( $tab2 == $current ) ? ' current' : '';
echo("<li class='posts'><a href='?page=pigg&tab=help&tab2=$tab2' class='$class'>$name");
echo(' |'); // If array last then do not display
echo('</a></li>');
}
I'm using a foreach loop to create a navigation for a WordPress plugin I'm working on, but I don't want the ' |' to be displayed for the last element, the code above is what I've got so far, I was thinking of using an if statement on the commented line, but not sure what the best approach would be, any ideas? Thanks!
The end() function is what you need:
if(end($tabs2) !== $name){
echo ' |'; // not the last element
}
I find it easier to check for first, rather than last. So I'd do it this way instead.
$first = true;
foreach( $tabs2 as $tab2 => $name ){
if ($first) {
$first = false;
} else {
echo(' | ');
}
$class = ( $tab2 == $current ) ? ' current' : '';
echo("<li class='posts'><a href='?page=pigg&tab=help&tab2=$tab2' class='$class'>$name</a></li>");
}
I also combined the last two echos together.
First thing you need to find out what is the last key of the array, and doing so by finding the array length, using the count() function.
Afterwords we gonna create a counter and add +1 on every loop.
If the counter and the last key are equal then it is the last key.
$last = count($array);
$counter = 1;
foreach ($array as $key => $val){
if ($counter != $last){
// all keys but the last one
// do something
$counter++; // add one to counter count
}
else {
// this is for the last key
}// end else
}// end foreach
I would do this way:
$arrLi = array();
foreach( $tabs2 as $tab2 => $name ){
$class = ( $tab2 == $current ) ? ' current' : '';
$arrLi[] = "<li class='posts'><a href='?page=pigg&tab=help&tab2=$tab2' class='$class'>$name</a></li>";
}
echo implode('|', $arrLi);
end() is good function to use
foreach( $tabs2 as $tab2 => $name ){
if(end($tabs2)== $name)
echo "|";
}
or you can do it manually for more understanding
$copyofarry = $tabs2;
$last = array_pop($copyofarry);
foreach( $tabs2 as $tab2 => $name ){
if($last == $name)
echo "|";
}
Something like this is possible:
$size = count($tabs2);
$counter = 0;
foreach( $tabs2 as $tab2 => $name ){
$class = ( $tab2 == $current ) ? ' current' : '';
echo("<li class='posts'><a href='?page=pigg&tab=help&tab2=$tab2' class='$class'>$name");
if ( ++$counter < $size ){
echo(' |'); // If array last then do not display
}
echo('</a></li>');
}
Why not pop the last element first? So you do not need to check if the current element is the last element in each iteration.
The function array_pop(&$array) returns the last element and removes it from the array.
<div id="breadcrumb">
<?php
$lastBreadcrumb = array_pop($breadcrumb);
foreach ($breadcrumb as $crumb){ ?>
<?php echo $crumb; ?>
<?php } ?><span><?php echo $lastBreadcrumb?></span>
</div>
Related
I have this code using an api , the first iteration is showing everything right , but at the second iteration is showing the items from the first iteration + the items from the second iteration , and the same thing at the third iteration.
I dont want that , how can i fix that problem ?
$g=0;
foreach ($matches as $match) {
$inside = $api->getMatch('123');
$pp = $api->getMatchTimeline('123');
foreach ($inside->participants as $partId) {
if ($partId->championId == $match->champion) {
$participant_id[] = $partId->participantId;
$participant_idS = $partId->stats->participantId;
foreach ($pp->frames as $p) {
foreach ($p->events as $t) {
if ($t->type == "ITEM_PURCHASED" and $t->participantId == $participant_idS) {
$item_id = $t->itemId;
$d = $api->getStaticItem($item_id);
if($d->depth == 2 or $d->depth == 3){
$itemsMade[] = $d->id;
}
}
}
}
}
}
$dt = [['match_ids' => $part, "champion" => $soloq->champion, "timestamp" => $match->timestamp, "participantId" => $participant_id[$g++], "itens" => json_encode($itemsMade)]
];
echo ' <pre>';
var_dump($dt);
echo '</pre>';
}
You need to set that array to be empty at the start of your loop. Otherwise you just keep adding to it as you see in your output.
foreach ($inside->participants as $partId) {
$itemsMade = [];
I have an array like this:
$aMyArray = array(
"bmw"=>"user1",
"audi"=>"user2",
"mercedes"=>"user3"
);
And I only want to show the first two elements bmw=>user1 and audi=>user2.
But I want it by using a foreach loop.
If you want the first 2 by name:
Using in_array (documentation) is what you looking for:
$aMyArray = array("bmw"=>"user1", "audi"=>"user2", "mercedes"=>"user3");
$valuesToPrint = array("bmw", "audi");
foreach($aMyArray as $key => $val) {
if (in_array($key, $valuesToPrint))
echo "Found: $key => $val" . PHP_EOL;
}
If you want the first 2 by index use:
init index at 0 and increment in each iteration as:
$aMyArray = array("bmw"=>"user1", "audi"=>"user2", "mercedes"=>"user3");
$i = 0;
foreach($aMyArray as $key => $val) {
echo "Found: $key => $val" . PHP_EOL;
if (++$i > 1)
break;
}
$counter = 1;
$max = 2;
foreach ($aMyArray as $key => $value) {
echo $key, "=>", $value;
$counter++;
if ($counter === $max) {
break;
}
}
It is important to break execution to avoid arrays of any size looping until the end for no reason.
<?php
$aMyArray = array(
"bmw"=>"user1",
"audi"=>"user2",
"mercedes"=>"user3"
);
reset($aMyArray);
echo key($aMyArray).' = '.current($aMyArray)."\n";
next($aMyArray);
echo key($aMyArray).' = '.current($aMyArray)."\n";
Easiest way:
$aMyArray=array("bmw"=>"user1","audi"=>"user2","mercedes"=>"user3");
$i=0;
foreach ($aMyArray as $key => $value) {
if($i<2)
{
echo $key . 'and' . $value;
}
$i++;
}
I know you're asking how to do it in a foreach, but another option is using array travelling functions current and next.
$aMyArray = array(
"bmw"=>"user1",
"audi"=>"user2",
"mercedes"=>"user3"
);
$keys = array_keys($aMyArray);
//current($array) will return the value of the current record in the array. At this point that will be the first record
$first = sprintf('%s - %s', current($keys), current($aMyArray)); //bmw - user1
//move the pointer to the next record in both $keys and $aMyArray
next($aMyArray);
next($keys);
//current($array) will now return the contents of the second element.
$second = sprintf('%s - %s', current($keys), current($aMyArray)); //audi - user2
You are looking for something like this
$aMyArray = array(
"bmw"=>"user1",
"audi"=>"user2",
"mercedes"=>"user3"
);
foreach($aMyArray as $k=>$v){
echo $v;
if($k=='audi'){
break;
}
}
i can loop through 2 elements in an array , but here im having trouble looping through 3 elements .
this is my example :
$y = array('cod=>102,subcod=>10201,name=>"blabla"',
'cod=>103,subcod=>10202,name=>"blibli"',
'cod=>103,subcod=>10202,name=>"bblubl"')
my desire result is how to get the value of cod and subcod and name of every line .
I tried this :
foreach ($y as $v) {
echo $v['cod'] ;
echo $v['subcod'];
echo $v['name'] ;
}
but didnt work , im getting this error : Warning: Illegal string offset 'cod' and same error for every offset .
any help would be much apreciated.
If you can't change you're array
Then you need to format that and then use the loop and get the value.
function format_my_array($arg) {
$new = array();
foreach( $arg as $n => $v ) {
// splitting string like
// 'cod=>102,subcod=>10201,name=>"blabla"'
// by comma
$parts = explode(',', $v);
$new[$n] = array();
foreach( $parts as $p ) {
// splittin again by '=>' to get key/value pair
$p = explode('=>', trim($p));
$new[$n][$p[0]] = $p[1];
}
}
return $new;
}
$new_y = format_my_array($y);
foreach( $new_y as $v ) {
echo $v['cod'];
echo $v['subcod'];
echo $v['name'];
}
In the code below I want to apply the object "$activeclass" as a DIV class. I thought the end pointer I included would apply this only to the last iteration of the array, but instead it is applying the class to all iterations.
<div id="right_bottom">
<?
$content = is_array($pagedata->content) ? $pagedata->content : array($pagedata->content);
foreach($content as $item){
$activeclass = end($content) ? 'active' : ' ';
?>
<div id="right_side">
<div id="<?=$item->id?>" class="side_items <?=$activeclass?>">
<a class="content" href="<?=$item->id?>"><img src="<?=PROTOCOL?>//<?=DOMAIN?>/img/content/<?=$item->image?>"><br />
<strong><?=$item->title?></strong></a><br />
<h2><?=date('F j, Y', strtotime($item->published))?></h2><br />
</div>
</div>
<?
}
?>
</div>
Any ideas where I am making a mistake? How can I apply the class $activeclass only to the last iteration of my "foreach" statement?
The simplest way is to keep a count:
$i = 0; $size = count( $content);
foreach( $content as $item) {
$i++;
$activeclass = ( $i < $size) ? '' : 'active';
}
Alternatively, you can compare the last element with the current element (if your array is consecutively numerically indexed starting with 0 [Thanks to webbiedave for pointing out the assumptions made by this method]):
$last = count( $content) - 1;
foreach( $content as $item) {
$activeclass = ( $content[$last] === $item) ? 'active' : '';
}
Note that this approach will not work if your array has duplicate items.
Finally, you can compare indexes in the following way:
// Numerical or associative
$keys = array_keys($content);
$key = array_pop($keys); // Assigned to variables thanks to webbiedave
// Consecutive numerically indexed
$key = count( $content) - 1;
foreach( $content as $current_key => $item) {
$activeclass = ( $current_key === $key) ? 'active' : '';
}
$activeclass = end($content) ? 'active' : ' ';
The end() function returns the last element in the array, so you're basically checking to see if the array has a last element (which it always will, unless it's empty).
This is an explanation of what you're doing wrong - nick has the answer for how to fix it by using a counter.
Try this approach from the following link http://blog.actsmedia.com/2009/09/php-foreach-last-item-last-loop/
$last_item = end($array);
$last_item = each($array);
reset($array);
foreach($array as $key => $value)
{
// code executed during standard iteration
if($value == $last_item['value'] && $key == $last_item['key'])
{
// code executed on the
// last iteration of the foreach loop
}
}
Suppose I have a multi-dimensional array of the form:
array
(
array('Set_ID' => 1, 'Item_ID' => 17, 'Item_Name' = 'Whatever'),
array('Set_ID' => 1, 'Item_ID' => 18, 'Item_Name' = 'Blah'),
array('Set_ID' => 2, 'Item_ID' => 19, 'Item_Name' = 'Yo')
)
The array has more sub-arrays, but that's the basic form-- Items in Sets.
How can I loop through this array so that I can echo the number of items in each set along with the all the items like so:
Set 1 has 2 Items: 17: Whatever and 18: Blah
Set 2 has 1 Items: 19: Yo
I'm aware that this could be done with two loops-- one to build an array, and another to loop through that array. However, I'd like to do this all with only one loop.
In your answer, you should assume that there are two display functions
display_set($id, $count) //echo's "Set $id has $count Items"
display_item($id, $name) //echo's "$id: $name"
UPDATE: Forgot to mention that the data is sorted by Set_ID because its from SQL
Right, all the examples below rely on an ordered set, the OP states it is ordered initially, but if needed a sort function could be:
// Sort set in to order
usort($displaySet,
create_function('$a,$b',
'return ($a['Set_ID'] == $b['Set_ID']
? ($a['Set_ID'] == $b['Item_ID']
? 0
: ($a['Item_ID'] < $b['Item_ID']
? -1
: 1))
: ($a['Set_ID'] < $b['Set_ID'] ? -1 : 1));'));
Straight example using a single loop:
// Initialise for the first set
$cSetID = $displaySet[0]['Set_ID'];
$cSetEntries = array();
foreach ($displaySet as $cItem) {
if ($cSetID !== $cItem['Set_ID']) {
// A new set has been seen, display old set
display_set($cSetID, count($cSetEntries));
echo ": " . implode(" and ", $cSetEntries) . "\n";
$cSetID = $cItem['Set_ID'];
$cSetEntries = array();
}
// Store item display for later
ob_start();
display_item($cItem['Item_ID'], $cItem['Item_Name');
$cSetEntries[] = ob_get_clean();
}
// Perform last set display
display_set($cSetID, count($cSetEntries));
echo ": " . implode(" and ", $cSetEntries) . "\n";
Using a recursive function it could be something like this:
// Define recursive display function
function displayItemList($itemList) {
if (!empty($itemList)) {
$cItem = array_shift($itemList);
display_item($cItem['Item_ID'], $cItem['Item_Name');
if (!empty($itemList)) {
echo " and ";
}
}
displayItemList($itemList);
}
// Initialise for the first set
$cSetID = $displaySet[0]['Set_ID'];
$cSetEntries = array();
foreach ($displaySet as $cItem) {
if ($cSetID !== $cItem['Set_ID']) {
// A new set has been seen, display old set
display_set($cSetID, count($cSetEntries));
echo ": ";
displayItemList($cSetEntries);
echo "\n";
$cSetID = $cItem['Set_ID'];
$cSetEntries = array();
}
// Store item for later
$cSetEntries[] = $cItem;
}
// Perform last set display
display_set($cSetID, count($cSetEntries));
echo ": ";
displayItemList($cSetEntries);
echo "\n";
Amusingly, it can be one single recursive function:
function displaySetList($setList, $itemList = NULL) {
// First call, start process
if ($itemList === NULL) {
$itemList = array(array_shift($setList));
displaySetList($setList, $itemList);
return;
}
// Check for display item list mode
if ($setList === false) {
// Output first entry in the list
$cItem = array_shift($itemList);
display_item($cItem['Item_ID'], $cItem['Item_Name']);
if (!empty($itemList)) {
// Output the next
echo " and ";
displaySetList(false, $itemList);
} else {
echo "\n";
}
return;
}
if (empty($setList) || $setList[0]['Set_ID'] != $itemList[0]['Set_ID']) {
// New Set detected, output set
display_set($itemList[0]['Set_ID'], count($itemList));
echo ": ";
displaySetList(false, $itemList);
$itemList = array();
}
// Add next item and carry on
$itemList[] = array_shift($setList);
displaySetList($setList, $itemList);
}
// Execute the function
displaySetList($displaySet);
Note that the recursive example here is grossly inefficient, a double loop is by far the quickest.
<?php
$sets = array();
foreach ($items as $item)
{
if (!array_key_exists($item['Set_ID'], $sets))
{
$sets[$item['Set_ID']] = array();
}
$sets[$item['Set_ID']][] = $item;
}
foreach ($sets as $setID => $items)
{
echo 'Set ' . $setID . ' has ' . count($items) . ' Items: ';
foreach ($items as $item)
{
echo $item['Item_ID'] . ' ' . $item['Item_Name'];
}
}
?>
Something like this i guess?
EDIT:
After i posted this i saw the display functions where added. But you get the point.
The need to not print out any items until we know how many there are in the set makes this difficult. At some point, we'll need to doing some buffering, or else backtracking. However, if I'm allowed internal loops, and sets are contiguous in the "master" array, then with some hacking around:
$set = 0;
$items;
foreach ($arr as $a) {
if ($a['Set_ID'] != $set) {
if ($set != 0) {
display_set($set, count($items));
foreach ($items as $i)
display_item($i)
}
$set = $a['Set_ID'];
$items = array();
}
$items[] = $a;
}
How about this:
$previous_set = false;
$items = '';
$item_count = 0;
foreach ($rows as $row)
{
if ($row['Set_ID'] != $previous_set)
{
if ($previous_set)
{
echo display_set($row['Set_ID'], $item_count);
echo $items;
}
$previous_class = $row['Set_ID'];
$item_count = 0;
$items = '';
}
$items .= display_item($row['Item_ID'], $row['Title']);
$item_count++;
}
echo display_set($row['Set_ID'], $item_count);
echo $items;