PHP: Nested for loops with if statement inside not executing - php

I have the following PHP code that gives a "Fatal error: Maximum execution time of 30 seconds exceeded" message whenever it runs. If I remove the "if()" statement inside the second for loop the code runs without any problems. I cannot figure out why the "if()" statement would cause this error.
for ($i=1;$i<=$nParam;$i++){
for($j=0;$j<=$nParam-1;$j++){
if ($j=$i-1){
//do something
}
}
}

You are assigning a value, not comparing.
Use:
if ($j === $i-1){

You need to use == for your if statement. The way you have it at the moment is continuously resetting the value of $j to 0, which is making it loop for ever.

Change ($j=$i-1) it to
if ($j == $i-1){
//do something
}
== is for comparison
= is for assignment
hope this help.

You have a typo. You are using the assignment = operator instead of the comparison == operator:
if ($j=$i-1){ // <-- HERE
change it to
if ($j==$i-1){

Related

how to rewrite this php "if" statement without the deprecated "each" function?

How can I rewrite this piece of php script to not use the deprecated function 'each' anymore in the 'if' statement ?
if (list($_basic_auth_realm, $_basic_auth_header) = each($_auth_creds))
{
...
}
Many thx in adv. for you input !
V.
[EDIT]. This if statement is not in a loop. It's part of an larger block:
if (!empty($_basic_auth_header))
{
....
}
else if (!empty($_basic_auth_realm) && isset($_auth_creds[$_basic_auth_realm]))
{
....
}
else if (list($_basic_auth_realm, $_basic_auth_header) = each($_auth_creds))
{
....
}
$_basic_auth_realm, $_basic_auth_header are strings
$_auth_creds is an array
I don't really understand how this 'if' statement works. I only attempt to update the script which returns warnings when executed. It is used as a php proxy on my NAS as was written by Abdullah Arif: https://github.com/emersion/phproxy
Use your own variable to keep track of the current index in the array, rather than depending on the internal state of the array.
$auth_creds_index = 0;
...
else if (list($_basic_auth_realm, $_basic_auth_header) = $_auth_creds[$auth_creds_index++])
Each place where you currently use each($_auth_creds) should use $_auth_creds[$auth_creds_index++], they'll get successive elements of the array.
If you reassign the variable with a new array, you need to reset the variable back to 0.
You could also define a class wrapper for the array that automates all this.

While loop: only Variables can be passed by reference error

I am running into a "Only variables should be passed by reference" error, because on the code I am using there is a line that does not put the explode() result into a variable. As required when using strict PHP standards.
However because the explode() function is used in a While loop I can't think of a appropriate solution.
My code looks like
function user_exists($username) {
rewind($this->fp);
while(!feof($this->fp) && trim($lusername = array_shift(explode(":",$line = rtrim(fgets($this->fp)))))) {
if($lusername == $username)
return 1;
}
return 0;
}
Any suggestions on how to solve this?
I think maybe you need to sit back and break your code apart a bit and take a look at what is happening.
First, condition is while !feof($this->fp)
From the manual:
feof — Tests for end-of-file on a file pointer
One thing you will notice here is that feof() is only a test which returns true or false. It does not advance the pointer position while looping over, so while using this function, somewhere else in your while loop there needs to be something that advances the pointer or else you will have an infinite loop.
Second condition is:
trim($lusername = array_shift(explode(":",$line = rtrim(fgets($this->fp)))))
First function from left to right is trim(), which returns a string. From our handy dandy comparison table we see that when doing if ((String) $var) it evaluates to false if and only if the string is empty ("") or the number zero as a string ("0"), otherwise it returns true. Personally I tend to really hate using if ((String) $var) (first because it's slightly unclear to newbies unless you know your comparison table well and second because 99% of the time people are doing that they are actually checking for string length, in which case I would want it to return true for the string "0"). So assuming that you don't need it to return false for "0" we could change this to strlen($var) > 0 and then manipulate the variable within the loop. That should greatly simplify things here.
So now we have:
while (!feof($this->fp) && strlen($var) > 0) { /*...*/ }
This will loop over until either we are at the end of the file or $var is an empty line. Everything else can be offloaded into the body of the while loop, so it is much easier to break apart.
So this is what we have now:
$line = rtrim(fgets($this->fp));
$lusername = array_shift(explode(":",$line)));
Uh-oh! There's that "nasty" error:
Strict Standards: Only variables should be passed by reference in /path/to/file.php on line x.
So we can see from here, the part producing the error is not explode(), but array_shift(). See also: Strict Standards: Only variables should be passed by reference
What this means is that since array_shift() modifies the array, it requires it to be by reference. Since you are not passing an actual variable but instead the result of a function, PHP is unable to modify it. It's similar to doing something like function($var) = 3;. Of course you can't do that. Instead you need to save the value to a temporary variable. So now we have:
$line = rtrim(fgets($this->fp));
$split = explode(":",$line);
$lusername = array_shift($split);
Woo hoo! No more warning message.
So putting this together, we now have:
while (!feof($this->fp) && strlen($lusername) > 0) {
$line = rtrim(fgets($this->fp));
$split = explode(":",$line);
$lusername = array_shift($split);
if($lusername == $username) {
return 1;
}
}
Also, as mentioned earlier, the fgets() will advance the pointer, which allows the !feof($this->fp) part in the while statement to vary.

For-loop conditions checking PHP

I am writing PHP code with a for-loop:
for($i=1;$i<=count($ArrayData);$i++){
//some code that changes the size of $ArrayData
}
Does the program check the loop condition ($i<=count($ArrayData)) every time or only once?
Thanks
Every time.
From the PHP manual:
for (expr1; expr2; expr3)
...
In the beginning of each iteration, expr2 is evaluated. If it evaluates to TRUE, the loop continues and the nested statement(s) are executed. If it evaluates to FALSE, the execution of the loop ends.
This can also be verified by using a snippet like:
<?php
function compare($i)
{
echo 'called'.PHP_EOL;
return $i < 5;
}
for($i = 0; compare($i); $i++) {}
which should print:
called
called
called
called
called
called
(Note that the 6th time compare is called, it returns FALSE, but still prints called.)
[ Demo ]
It is checking it every iteration, for example:
for($i=1;$i<count($ArrayData);$i++){
$ArrayData[]=1;
}
will last until memory is exhausted, it will yield for example:
Fatal error: Allowed memory size of 536870912 bytes exhausted
To change it to checking only once once, use this:
for($i=1,$c =count($ArrayData); $i<=$c;$i++){
$ArrayData[]=1;
}
As $i is incremented in every iteration. Condition is also checked in every iteration against new value of $i as long as loop is running.

Why 'break' is not working in array_walk php

Please see my code, i am almost stuck in this, Why the break inside the array_walk not breaking...
$bool=array_walk($_POST, 'check_empty');
function check_empty($item, $key)
{
$bool=(isset($item) && $item != "") ? 1: 0 ;
if(!$bool)
{
//return 0;
break;
}
return $bool;
}
It's not at all clear what you're trying to do, but break is a control structure that exits only true loops (for, foreach, while and do-while) and switch structures.
array_walk is iterative but not a loop in the true sense.
You can't 'break' (to use the terminology) from an array walk callback; it is invoked on each element of the array as a means to update or otherwise modify each element, and I can't imagine a use case where you'd want to terminate this during it.
What are you trying to do? Your break is not working, because you're returning a value right before it - so the line with break is never executed.
If you're trying to remove all empty values from the array, try array_filter($array).

What is the "for(;;)" syntax in this code?

for(;;)
{
if(!$monitor->Throttle($cause))
die('Fatal error: '.$monitor->error);
if($cause == THROTTLE_CAUSE_NONE)
break;
sleep(60);
}
i'm a beginner php developer. So how do you read the "for" syntax in previous code. is it valid ?
i got them from http://www.phpclasses.org/blog/post/132-Accelerate-Page-Accesses-Throttling-Background-Tasks-Unusual-Site-Speedup-Techniques-Part-2.html
for(;;) is a C idiom which means "do forever", an infinite loop. This loop will only exit when either the die statement fires (violently) , or the cause is set to THROTTLE_CAUSE_NONE (not so violently).
It's a for loop with no pre-setup, no condition and not post-iteration commands, effectively the same as while true (pseudo-code).
That's a forever-loop.
for(;;) is basically an infinite loop, nothing more :)
Ugh.
It is valid syntax, it creates an infinite loop. But it's ugly.
A much more beautiful way to do this would be
while ($cause = $monitor->Throttle($cause) != THROTTLE_CAUSE_NONE)
{
if(!$cause)
die('Fatal error: '.$monitor->error);
sleep(60);
}
It is valid. It creates an infinite loop, which in this case will be broken out of when/if the break statement executes, i.e. if($cause == THROTTLE_CAUSE_NONE)
The for loop has four parts:
for(initialization; exit condition; step) { body; }
Your loop has none of them, so without an exit condition it will just run forever until it hits the 'break' sentence:
if($cause == THROTTLE_CAUSE_NONE)
break;
An equivalent would be:
while(True) { ... }

Categories