PHP While loop never finishes Amazon Product API / APAIO? - php

I've got the following code:
$counter = 0;
while($currentPage <= $pages) {
sleep(0.1);
flush();
$browseNodeLookup->setPage($currentPage);
try {
$xml = $apaiIO->runOperation($browseNodeLookup);
} catch(Exception $e1) {
if($counter == 20) {
break;
}
}
if($xml) {
$all_elements = iq_parse_data($xml, $itemcount, $all_elements);
$currentPage++;
} else {
if($counter == 20) {
break;
}
}
$counter++;
}
By now it looks a little bit weird already, because I just can't get that while loop to break. The problem is, my website suddenly(without any change by myself) crashed. What I did was to just remove the while loop and the website worked again. Now the problem is, sometimes the page loads, and sometimes it doesn't.
When it doesn't the script continues for so long, that with multiple clients, the server crashes and I have to manually restart apache.
Is there anything wrong with this while loop? Did I miss something?
EDIT:
I found out the mistake, it wasn't even about my while loop(allthough the fix with counter <= 20 is also true). It was about guzzle, which makes the request behind "runOperation". I had to define a timeout, because I don't know why, but it seems that something with Amazon Product API changed, so that there could be an infinite loop in guzzle.
The fix was this:
$client = new \GuzzleHttp\Client(['timeout' => 2.0]);
I should provide the whole code next time, maybe someone would have spotted this. Thank you guys.

The most likely explanation is that your code is not actually hitting your break, because the counter gets incremented every iteration, but you are only checking for exactly 20 when it's not an actual page
The following code should be changed to change this issue:
if($counter >= 20) {
break;
}

Currently your code looks a little complicated. You can simplify it in this way:
while($currentPage <= $pages) {
sleep(0.1);
flush();
$browseNodeLookup->setPage($currentPage);
try {
$xml = $apaiIO->runOperation($browseNodeLookup);
$all_elements = iq_parse_data($xml, $itemcount, $all_elements);
} finally {
$currentPage++;
}
}

From the looks of it, you're only breaking when ($counter == 20 && !$xml). You're never advancing $currentPage if that condition isn't true, so the loop will be stuck forever.
Edit for clarity:
It's likely that $counter has passed 20 by the time that $xml is falsy, which means $currentPage isn't advancing (so your while condition is still true) but because $counter is greater than 20, your break does not get hit. Change $counter == 20 to $counter >= 20.
Also if you're trying to just advance until you either hit 20 or $totalPages, whichever is lower, your code could be simplified to something like
$pages = min(20, $pages);
while ($currentPage <= $pages) {
sleep(0.1);
flush();
$browseNodeLookup->setPage($currentPage);
try {
$xml = $apaiIO->runOperation($browseNodeLookup);
$all_elements = iq_parse_data($xml, $itemcount, $all_elements);
} catch (Exception $e1) {
// Any error handling you want to do
}
$currentPage++;
}

Related

PHP - counter error using $_SESSION

The $count++; does not working while i am using if(!isset($_SESSION["rand"]))...
I am building a number guessing game.
$numOfGess=4;
$min=1;
$max=10;
if(!isset($_SESSION["rand"])){
$_SESSION["rand"] = rand($min, $max);
$count=0;
}
if(isset($_POST["numGuess"])){
$numGuess = $_REQUEST["numGuess"];
if($numGuess != $_SESSION["rand"]) {
//Validation
if($numGuess < $min || $numGuess > $max) {
echo"Your number must be between 1 to 10 !";
}
//Number is Small
if($numGuess < $_SESSION["rand"]) {
echo "too small...";
$count++;
}
//Number is Big
if($numGuess > $_SESSION["rand"]) {
echo "too big...";
$count++;
}
if($count==$numOfGess) {
echo"Game Over!";
unset($_SESSION["rand"]);
}
}
else {
echo"You got it! (in your last chance)";
unset($_SESSION["rand"]);
}
}
You should store the count variable as a session variable as well, otherwise it gets reset with every request. So, just replace $count with $_SESSION['count'] and it should work.
Store count in your session variable. What happens if $_SESSION['rand'] is set? How does it know what the previous count was?
Your forgetting
Session_start()
to start/resume the session

PHP continue if conditions are ok

Is there something in php that can halt or let the script proceed if things are ok?
In my current scripts I do like this (for this example):
$fetch = false;
if($i == 10){
echo 'I is clear'
$fetch = true;
}
if($fetch){
//Do database work here
}
echo 'This should be seen no matter what the above';
Instead of the $fetch in there, can I do something else? I don't want to stop the entire script after that like what die() or exit does.
Here's an example that should help you:
<?php
function doLoop() {
for($i=0;$i<100;$i++) {
if($i != 50) {
continue; //It's not 50, skip it
}
//Otherwise
printf("Loop: $i");
}
}
function doBreak() {
for($i=0;$i<100;$i++) {
if($i != 49) {
continue; //It's not 49 yet, continue
} //Otherwise, break
printf("Loop: $i");
break;
}
}
doLoop();
doBreak();
?>
break; can be used to end a loop when a condition is met, while continue; can also be used to skip a certain value if a condition is not met. Using die(); would stop your whole script from executing, preventing it to call anything that comes after the die(); statement because that's how the execution of the scripts pretty much go, from the top to the end.

php continue - alternative way?

I just started learning php and I have to do something like this which I got it working but I just have a few questions I want to ask for alternate way of doing but eh first of all the br/ is suppose to be with <> but somehow if i do that the coding at the bottom will see it as a line break.
Anyways if questions are...
With the coding below the outcome will be 0-9 (without 5) but I have to set $zero=-1 if I put $zero=0 then the outcome would be 1-9 (without 5) is there a way I don't have to make $zero=-1 and still have the outcome of 0-9 (without 5)?
I realized I have to put $zero++ before the if and continue statement if I put it at the end of the script after echo "$zero" . "br/"; the script won't run as wanted. Is this how it is suppose to be or I just don't know the other way of doing it.
Thanks in advance for people replying ^_^
$squared = pow(3,2);
echo "\"3 squared is $squared:";
echo "br/";
$zero = -1;
while ($squared > $zero)
{
$zero++;
if ($zero == 5)
{
continue;
}
else if ($squared == $zero)
{
echo "$squared\"";
}
else
{
echo "$zero" . "br/";
}
}
Here it is (you were almost there :P )
$nr = 0;
while ($squared > $nr) {
if (5 == $nr) {
$nr++; // add this
continue;
} else if ($squared == $nr) {
echo "$squared\"";
} else {
echo "$nr" . "<br/>";
}
$nr++; // move to the bottom
}
PS: You're welcome #clement
Change your while loop to while ($squared >= $zero) and then set $zero = 0;
Should work!

stop script or loop after first match without using exit;

no idea how to ask this question... the problem is that I need to stop the loop from runing if if ($current[$id][$i]['item'] == '') is true, so whatever the script needs to do or in this case echo, don't get repeated 15 times.
If using exit; the whole page will stop to render, so, any ideas ?
Thanks in advance.
If the question is not clear enough don't hesitate to ask using the comments, I will more than happy to clarify any doubts.
$i=1;
while($i<=15) {
if ($current[$id][$i]['item'] == '') {
echo 'Done!.';
//do something
}
$a++;
}
use break
$i=1;
while($i<=15) {
if ($current[$id][$i]['item'] == '') {
echo 'Done!.';
break;
}
$i++; //<- that should probably be $i instead of $a?
}
How about using the break control structure?
You need to break. Also, your current loop is endless and will therefore time-out. Presumably you meant to increment $i, not $a.
$i=1;
while($i<=15) {
if ($current[$id][$i]['item'] == '') {
echo 'Done!.';
break; //<-- terminate loop
}
$a++; //<-- shouldn't this be $i++?
}
There is only 2 ways to break a loop... using exit; and break;....
break; is what you want it will exit the loop and continue execution, exit will end the script.
$i=1;
while($i<=15) {
if ($current[$id][$i]['item'] == '') {
echo 'Done!.';
break; // or you can make value of $i = 20;
}
$a++;
}

How do I save the original argument in a recursive function in PHP?

I'm in PHP working on an Euler problem. I have this function so far:
<?php
$biggest = 0;
$counter = 1;
function test($i){
global $biggest;
global $counter;
if ($i == 1) {
echo "I'm done! Took me $biggest steps";
}
else {
if ($i%2 == 0) {
$counter = $counter + 1;
if ($counter>$biggest) {
$biggest = $counter;
}
test($i/2);
}
else {
$counter = $counter + 1;
if ($counter>$biggest) {
$biggest = $counter;
}
test(3*$i+1);
}
}
}
test(13);
?>
I have the problem mostly licked, but I can't seem to get back at the original input. The question is "When you have a number, if odd get 3n+1, when even, get n/2, do until returns 1. What starting value yields the most "steps" before you get to one?" I currently am returning the number of steps, but I keep resetting $i as I recurse, so I can't record what starting # yielded my $biggest number of steps.
How can I keep track of that number, but also not have it destroyed at the next instance of the loop? (I'll eventually wrap this in a for ($i=1, $i<1000000, $i++) loop)
Thanks!
A common approach is to pass the original argument through each time, so that when eventually you get to your base case, you still have it available. A primitive (and almost entirely unrelated example):
<?php
function fact($n) {
if($n == 1) return 1;
else return $n * fact($n - 1);
}
?>
This is an extremely basic implementation of the factorial function in PHP. Now say you wanted for whatever reason to have the initial value available in the final step: you'd build a wrapper function fact($n) that would call something like memory_fact($n, $initial):
<?php
function fact($n) {
return memory_fact($n, $n);
}
function memory_fact($n, $initial) {
if($n == 1) return 1;
else return $n * memory_fact($n - 1, $initial);
}
?>
This way, memory_fact always knows where it started.
It's easy, just pass it around as a parameter! Here's some python-ish pseudocode:
def func(start, arg):
if foo(arg):
return func(start, arg+1)
else:
return [start, arg]
You don't need the globals; globals are evil. Try returning something useful from test(). Also, you'll find the test() above wastes many cycles. Try using memoization.
Here's a memoization example for calculating Fibonacci numbers:
function fib($n) {
static $data = array(1, 1);
if (!isset($data[$n])) {
$data[$n] = fib($n-1) + fib($n-2);
}
return $data[$n];
}
Note that there are other time-efficent constant-space approaches to handle Fibonacci numbers (including one in O(log n) time), but the Collatz conjecture is a little trickier.

Categories