limit and offset foreach loops - php

Say i want to loop through XML nodes but i want to ignore the first 10 and then limit the number i grab to 10.
$limit=10; //define results limit
$o=20; //define offset
$i=0; //start line counter
foreach($xml->id AS $key => $value){
$i++;
if($i > $o){
//if line number is less than offset, do nothing.
}else{
if($i == "$limit"){break;} //if line is over limit, break out of loop
//do stuff here
}
}
So in this example, id want to start on result 20, and only show 10 results, then break out of the loop. Its not working though. Any thoughts?

There are multiple bugs in there. It should be
foreach (...
if ($i++ < $o) continue;
if ($i > $o + $limit) break;
// do your stuff here
}

The answer from soulmerge will go through the loop one too many times. It should be:
foreach (...
if ($i++ < $o) continue;
if ($i >= $o + $limit) break;
// do your stuff here
}

You can use next() function for the yours array of elements:
$limit=10; //define results limit
$o=20; //define offset
$i=0; //start line counter
for ($j = 0; $j < $o; $j++) {
next($xml->id);
}
foreach($xml->id AS $key => $value){
$i++;
if($i > $o){
//if line number is less than offset, do nothing.
}else{
if($i == "$limit"){break;} //if line is over limit, break out of loop
//do stuff here
}
}
More information about next() function: http://php.net/manual/en/function.next.php

if($i == $limit+$o){break;}
you should use that cause $limit is reached before $o

Related

forloop continue again after end of the iteration

I used function with same logic given below
Given below code is sample of same logic i used, i need to continue the for loop after end of the iteration, i assign 0 to the variable $j at end so forloop need to continue, why its closed the process.
for($i=$j;$i<7;$i++){
echo "<br/>".$i;
if($i == 6){$j=0;continue;}
}
Actual Output
1
2
3
4
5
6
Expected output
1
2
3
4
5
6
1
2
3
4
5
6
.....etc
My Original code sample is
foreach($Qry_Rst as $key=>$Rst_Val){
for($j=$ItrDt;$j<7;$j++){
$ItrDate = date('Y-m-d', mktime(0, 0, 0, $month, $day + $j, $year));
if($ItrDate == $Rst_Val['sloat_day']){
$TimeTableAry[$loop_itr] = $Rst_Val;
break
}
}
}
The doc says
The first expression (expr1) is evaluated (executed) once unconditionally at the beginning of the loop.
So instead of $j just use $i to reset the loop. As this (demo)
$j = 1;
$current = 0;
for ($i=$j; $i<4; $i++) {
printf("i: %d, j: %d\n", $i, $j);
if ($i==3 && $current < 5) {
$i = -1;
$j = mt_rand(0,3);
$current++;
continue;
}
}
shows, you actually need to reset $i = -1; so it will be 0 after $i++ will be evaluated.
But with this you'll have an if in every iteration of the loop although you only need it for one. Basically you don't need it for the iteration itself but only to start a next one, so there must be something else here.
function doFor($data, $callback) {
$dataLength = count($data);
for ($i=0; $i<$dataLength; $i++) {
call_user_func($callback, $data[$i]);
}
return $data;
}
Isolating the loop into its own function will allow for one line that will execute the wanted callback allowing your main code to be something like (demo)
$data = array(array("foo","bar"),array("hello"),array("world","!"));
function justDump($obj) {
var_dump($obj);
};
$i = 0;
do {
$data = doFor($data, 'justDump');
print "<br>";
$i++;
} while($i<5);
You can also try the way you originally wanted (only slightly edited):
//counter to avoid infinite loop
$counter = 0;
for($i=$i;$i<7;$i++){
echo "<br/>".$i;
if($i == 6){
$i=0;
$counter++;
continue;
}
if($counter == 5){break;}
}
1
2
3
4
5
6
1
2
3
...

How can I loop through an array, starting at an offset and looping round again?

Newb question: I'm using a foreach loop to get items from an array.
I need to start looping at an offset number- (I'm using a $i variable to do this, no problem).
But when my foreach reaches the end of the array I want it to start going through the array again until it reaches the offset number.
I need to do this so I can have a user open any image in an artist's portfolio and have this image used as the first image presented in a grid of thumbnail icons , with all the other images subsequently populating the rest of the grid.
Any ideas?
Please bear in mind I'm new to PHP! :)
See below for an example of my current code...
$i=0;
$limit=50;// install this in the if conditional with the offset in it (below) to limit the number of thumbnails added to the page.
$offset=$any_arbitrary_link_dependant_integer;
foreach($portfolio_image_array as $k=>$image_obj){//$k = an integer counter, $image_obj = one of the many stored imageObject arrays.
$i++;
if ($i > $offset && $i < $limit) {// ignore all portfolio_array items below the offset number.
if ($img_obj->boolean_test_thing===true) {// OK as a way to test equivalency?
// do something
} else if ($img_obj->boolean_test_thing===false) { // Now add all the non-see_more small thumbnails:
// do something else
} else {
// error handler will go here.
}
} // end of offset conditional
}// end of add boolean_test_thing thumbnails foreach loop.
};// end of add thumbnails loop.
$i = 0;
$limit = 50;
$offset = $any_arbitrary_link_dependant_integer;
$count = count($portfolio_image_array);
foreach($portfolio_image_array as $k=>$image_obj){//$k = an integer counter, $image_obj = one of the many stored imageObject arrays.
$i++;
if ($i > $offset && $i < $limit && $i < ($count - $offset)) {// ignore all portfolio_array items below the offset number.
if ($img_obj->boolean_test_thing===true) {// OK as a way to test equivalency?
// do something
} else if ($img_obj->boolean_test_thing===false) { // Now add all the non-see_more small thumbnails:
// do something else
} else {
// error handler will go here.
}
} // end of offset conditional
}// end of add boolean_test_thing thumbnails foreach loop.
};
Only thing I added was a $count variable.
Edit: If your array starts at 0 I would suggest you put the $i++; at the end of your foreach loop.
A simple method is to use two separate numeric for loops, the first going from offset to end, and the second going from beginning to offset.
<?php
// Create an example array - ignore this line
$example = array(1,2,3,4,5,6);
$offset = 3;
// Standard loop stuff
$count = count($example);
for($i = $offset; $i < $count; $i++)
{
echo $example[$i]."<br />";
}
for($i = 0; $i < $offset; $i++)
{
echo $example[$i]."<br />";
}
?>
This is also almost certainly cheaper than doing multiple checks on every single element in the array, and it expresses exactly what you are trying to do to other programmers who look at this code - including yourself in 2 weeks time.
Edit: depending on the nature of the array, in order to use numeric keys you may first need to do $example = array_values($portfolio_image_array);.
Using Answer Question to force StackOverflow to let me post a decent length of text!
OK #Mark Walet et al, not sure how to post correctly on this forum yet but here goes. I got the issue sorted as follows:
$i=0;
$offset=$image_to_display_number;
$array_length = count($portfolio_image_array);
// FIRST HALF LOOP:
foreach($portfolio_image_array as $k=>$img_obj){// go through array from offset (chosen image) to end.
if ($i >= $offset && $i <= $array_length) {
echo write_thumbnails_fun($type_of_thumbnail, $image_path, $k, $i, $portfolio_image_array, $title, $image_original);
$t_total++;// update thumbnail total count.
}
$i++;
}// end of foreach loop 1.
$looped=true;// Just FYI.
$i=0;// Reset.
// SECOND HALF LOOP:
foreach($portfolio_image_array as $k=>$img_obj){// go through array from beginning to offset.
if ($i < $offset) {
echo write_thumbnails_fun($type_of_thumbnail, $image_path, $k, $i, $portfolio_image_array, $title, $image_original);
}
$i++;
}// end of foreach loop 2.
Thankyou so much for all the help!
:)
as #arkascha suggested use modulo operator
<?php
$example = array(1,2,3,4,5,6);
$count = count($example);
$offset = 3;
for($i = 0; $i < $count; $i++) {
$idx = ($offset + $i) % count
echo $example[$idx]."<br />";
}
?>

Step inside foreach

How to do something every 5 (for example) cycles inside foreach?
I'm add $i++ How to check it by step?
Use modulo to determine offset.
$i = 0;
foreach ($array as $a) {
$i++;
if ($i % 5 == 0) {
// your code for every 5th item
}
// your inside loop code
}
Unless you're doing something separately in each iteration, don't.
Use a for loop and increment the counter by 5 each time:
$collectionLength = count($collection);
for($i = 0; $i < $collectionLength; i+=5)
{
// Do something
}
Otherwise, you can use the modulo operator to determine if you're on one of the fifth iterations:
if(($i + 1) % 5 == 0) // assuming i starts at 0
{
// Do something special this time
}
for($i = 0; $i < $items; $i++){
//for every 5th item, assuming i starts at 0 (skip)
if($i % 5 == 0 && $i != 0){
//execute your code
}
}

Insert line break after every two rows of database

I have a little script that prints a certain amount of rows in a mysql database.
Is there any way to make it so that after every second row it prints, there is a line break inserted?
Adding a line break after every row is simple, but I don't know how to add one after every other row. Is that possible?
You write "script" but in tags you have PHP, so I suppose you need PHP code:
foreach ($rows as $row) {
if ($i++ % 2) {
// this code will only run for every even row
}
...
}
$i=1;
while ($row = mysql_fetch_array($query))
{
//your code
if ($i % 2 == 0)
echo '<br>';
$i++;
}
add new variable before the loop
$i = 0;
then in your loop add
if ($i != 0 && $i%2 == 0)
echo '<br/>';
Depending on the language, something like this should do it: (in php) (where $arr is an array of results)
$str = '';
$i = 0;
for ($i=0; $i<count( $arr ); $i++)
{
if ( ( $i + 1 ) % 2 === 0 )
{
$str .= $arr[$i] . '<br />';
}
else
{
$str .= $arr[$i];
}
}
echo $str;
Use php and modulo.
such as
if($i % 3)
{
echo '<br />'..
If you need to do this inside the query for some reason, you could use something like
SELECT
<your fields>,
IF (((#rn:=#rn+1) % 3)=0,'<br>','') as brornot
FROM
<your tables and joins>,
(#rn:=0)

Continue in while with mysql_fetch_assoc

I have a few lines of code, but can't find the right way to use it properly.
$cc = 0;
$tt = 50;
while ($row = mysql_fetch_assoc($result)) {
//building array with values from DB.
if (++$cc < $tt)
continue;
for ($i = 0; $i < $tt; $i++) {
//Work with the array
}
}
Let's say I have 133 results in DB. It'll get first 50 - do something in the for loop, then 50 more, will go thru the for loop again and will stop.
The last 33 results will be untouched.
It'll get them, but cause can't reach 50 will stop and they won't go through the for loop.
My problems is how to "send" them in the loop down there?
Move the for loop in a function and call it after the while loop:
$cc = 0;
$tt = 50;
while ($row = mysql_fetch_assoc($result)) {
//building array with values from DB.
if (++$cc < $tt) continue;
work_with_array($array);
}
if($cc) work_with_array($array);
function work_with_array($array) {
for ($i = 0; $i < count($array); $i++) {
//Work with the array
}
}
Try this:
$i = 0
while ($row = mysql_fetch_assoc($result)):
if($i < 50):
//Code when $i is less than 50
//Insert code here
elseif($i > 50 && $i < 100):
//Code when $i is more than 50 but less than 100
//Insert code here
elseif($i > 100):
//Code when $i is more than 100
//Insert code here
endif;
$i++;
endwhile;
So all results are going through this loop. If $i is less than 50 (or if the result is less than 50) then some code is executed, or if $i is more than 50 but less than 100 then some different code is executed. Finally if $i is more than 100 then some other code is executed.
Do you understand?
You could try:
$i = 0
while ($row = mysql_fetch_assoc($result) && $i < 100):
if($i < 50):
//Code when $i is less than 50
else:
//Code more than or equal to 50
endif;
$i++;
endwhile;
All the continues inside the loop seem unneccesary. If you're simply trying to process the entire result set and do something in chunks, you can do this
$cc = 0;
$tt = 50;
$result_array = array();
// this will chunk your array into blocks
while ($row = mysql_fetch_assoc($result)) {
//building array with values from DB.
$result_array[intval($cc++/$tt)] = $row;
}
// at this point you should have result_array with indexes:0,1,2 and have subarrays with 50, 50, 33 entries each.
foreach ($result_array as $k=>$sub_array) {
//Work with your sub array
foreach ($sub_array as $one_row)
{
// do something with the row
}
}
I do agree with #Col.Shrapnel though. Why are you creating another array inside the while loop just to go through that array one row at a time to do something? It would've made sense if you send out a batch of data at once (like bulk insert into db, sure) but to loop through again seems odd. Why can't you do the same right in the while loop

Categories