Recursion infinite loop? - php

So I am running into an issue that I figured out how to fix, but I am very curious as to why. So here is a block of code
<?php
function test($attempt=1){
if ($attempt == 5){
echo "Done!";
}else{
echo 'recursion!';
test($attempt++);
}
}
$test = test();
Now this code should run the first time, check, go into the else statement then run test again but this time with $attempt++ until eventually it is == to 5 and then it will echo done and complete. However this does not work and it loops forever. However it can be fixed by assigning the variable to another variable immediately after entering the function like so
<?php
function test($attempt=1){
$nextAttempt = $attempt+1;
if ($attempt == 5){
echo "Done!";
}else{
echo 'recursion!';
test($nextAttempt);
}
}
$test = test();
Any ideas as to why this is?

You want pre-increment instead of post-increment of the variable. This will increment the variable $attempt before passing it as an argument to the function instead of after.
So basically you want test(++$attempt); instead of test($attempt++);.
Sandbox with working example: http://sandbox.onlinephpfunctions.com/code/c50731815588d55bd079e701f1c5dde9e7148696
http://php.net/manual/en/language.operators.increment.php

The operator ++ executes after the evaluation of the sentence, so you are executing the call to the function with the same value ever.
test($attempt++);
is the same than:
test($attempt);
$attempt = $attempt + 1

Related

Php recursion issue not sending back values

Here is the code that I am going to use for solving my complicated issue, that I posted earlier.
Logic behind that is - on every iteration of the recursion, function should decrease $wa for $amount, that has been already proceeded, and calculate new $wa, to find new $amount, until system could not find the $amount in table that will be bigger then resulted $wa, and proceed it as last iteration.
Code is returning nothing, when trying to devel it, no errors, no echo. What am I doing wrong?
$wa = 0.001;
$address = $address;
function recursion($wa)
{
$resulte = db_select ('Credit_user','c')
->fields ('c')
->range(0,1)
->orderby('cr_ts', 'ASC')
->condition('c.affected','0','=')
->condition('c.amount','0','!=')
->execute();
foreach($resulte as $item) {
$code = $item->redeem_code;
global $code;
$amounte = $item->amount;
global $amounte;
$wai = $wa - $amounte;
global $wai;
if ($wai < 0){
echo "production code that should operate with different
variations of $amounte and $redeem on last iteration";
return;
}
elseif ($wai >= 0){ echo "production code
that should operate with different variations
of $amounte and $redeem on each iteration";
return;
} else {
function recursion($wa){
}
}
}}
echo $amounte;
echo "<br>";
Well at least this part is wrong
} else {
function recursion($wa){
}
Should be
} else {
return recursion($wa);
}
But the rest of this code is pretty messy, so....
For example, this logic
if ($wai < 0){
//...
}elseif ($wai >= 0){
//...
}else{
//not reachable
return recursion($wa);
}
is quite flawed. Because the else block is not reachable. In otherwords nothing satisfies the else condition because most values goes though the elseif which has 1 and 0 in it's range, and many things in PHP evaluate out to 1{true} or 0{false} because of PHP's loose typing.
UPDATE
You can test this condition for yourself
$tests = [
false,
-10,
1,
0,
[], ''
];
foreach($tests as $wai){
if ($wai < 0){
echo "1";
}elseif ($wai >= 0){
echo "2";
}else{
echo "3";
}
echo "\n";
}
Outputs
2
1
2
2
2
2
As you can see there is no #3 which comes from the else block which as I said is impossible to reach. Thus this function does no recursion, and therefor can return nothing from said non-existant recursion.
Test it online
Additionally:
$wai = $wa - $amounte;
global $wai;
Global must be declared first.
global $wai;
$wai = $wa - $amounte;
We can test this, by setting up a function scope.
function foo(){
$wai = 50;
global $wai;
echo $wai;
}
global $wai;
$wai = 100;
foo();
Now one would expect this to print 50, however it prints 100. It executes this way:
PHP parses and interprets the code
We declare global$wai outside the function
We set $wai to = 100 (assignment)
We call function foo
We set the local variable $wai = 50;
We then declare $wai as a global, and it inherits the value of the global $wai from the global scope (outside the function scope), which is a value of 100
Then we echo that value.
This is a very close approximation of your code, it's functionally equivalent Check it yourself
Now if you change the order
function foo(){
global $wai;
$wai = 50;
echo $wai;
}
global $wai;
$wai = 100;
foo();
It outputs 50 test this
Let's see, the echo functions need to be changed to return. Assuming the recursion worked, but it doesn't. One has to assume that at some point it goes thought one of the other 2 parts of that if condition that I pointed out. If it didn't do that we would have infinite recursion until PHP runs out of memory and crashes or the max execution time is hit. So we're agreed it has to go though those. Now how can it return anything from
return recursion($wa);
If both of the other returns are just return; or return null. By it's very nature if the next iteration of the function returns null back to our return from calling said function recursively, then that call must also return null.
echo "production code that should operate with different variations of $amounte and $redeem on last iteration";
return;
So
return "production code that should operate with different variations of $amounte and $redeem on last iteration";
In other words, it's pretty much all broken. Please don't take this the wrong way, I'm just pointing out what I see wrong. Everyone has to start somewhere learning to code, I have almost 8 years professional web design and PHP programing experience. But, I still remember what it was like learning and I still make plenty of mistakes.
I've pointed out fixes for what I could, but for things like the if logic there is no way for me to figure out what that logic was supposed to be. I can only point out where it falls apart.

Can I check and echo get_post_meta() without running the function twice?

Is there a way to reduce the amount of times get_post_meta() is called, whilst still performing a conditional check to see if the value exists before retrieving it?
if(get_post_meta(get_the_ID(), 'staffQualifications', true)) {
echo get_post_meta(get_the_ID(), 'staffQualifications', true);
}
This is running the function twice obviously. Is there a way to only run it once and save resources and memory, whilst still only returning the value if it exists?
What about this ? assign to variable and print when condition is true.
One Single query to check and print if has value
if($qualification = get_post_meta(get_the_ID(), 'staffQualifications', true)) {
echo $qualification;
}
Test scenario, below code will output var_dump if it has value, else nothing will be output.
$a = '';
if($a){
var_dump($a);
}

Recursion function's variable value not changing in PHP

I want to print 1 to 10 numbers using recursion but its not working.
CODE
function table($num1) {
if( $num1 <= 10 ) {
echo $num1;
echo "<br>";
table($num1++);
}
}
$num = 1;
table($num);
Here's the error
Fatal error: Maximum function nesting level of '256' reached,
aborting!
But when I am declaring $num1 as global its working fine. Please anyone tell me the reason behind it.
table($num1++) means please pass $num1 to table(), and then increase it by one. So this is not what you want.
You have to write table(++$num1) instead. It means increase $num1 first, then pass it to table().
Because you are passing a variable in copy. So the first variable has still 1 for value, and you are calling infinitely your function "table".
By default, for all variables (with the exception of objects) PHP makes a copy when passing it to a function/method. If you want to pass the same "in-memory" variable, you have to do it by reference.
$myVar=1;
myFunction($myVar);
Before, you declared your function like this:
function myFunction(&myVar) { ...}
Regards
function table($num) {
if( $num <= 10 ) {
echo $num;
echo "<br>";
table(++ $num);
}
}
$num = 1;
table($num);
table(++ $num) means increase $num first then pass to table function
Try:
function table($value) {
echo $value;
echo "<br>";
$num1=$value+1;
if($num1<=10){
table($num1);
}
}
$num = 1;
table($num);

does static var get automatic 0 values PHP?

I understand the use of static inside of a function.
But what I don't understand in the next example, why the variable $x can be incremented (like it was initialized to zero):
function print_conditional() {
static $x;
if($x++ == 1) {
echo "things";
} else {
echo "good ";
}
}
print_conditional();
print_conditional();
echo PHP_EOL;
This will output "good things"
So, the first time the function is called, the variable $x with no value doesn't match in the if, but the second time, look likes it was incremented to 1 and match, how is that possible?
Decrementing NULL values has no effect, but incrementing them results in 1.
Source

PHP - Could this if statement EVER return true?

I'm trying to edit my co-worker's code (he's on vacation and out of reach) and there is this if statement:
if($this->carrier() == 1 and $this->carrier() == 2) {
return 'V';
}
My hope is that he accidentally put "and" instead of "or" which could explain a bug I'm getting, but he knows much more about PHP than I do and I want to be sure that this is wrong instead of just counter intuitive.
Yes, since it's a function with potential side effects, it might be true.
For example:
function carrier() {
return $someValue++;
}
Yes. The carrier() method could increment whatever value it returns each time you call it.
There's a small chance it could, yes.
He's calling a function twice, and you've not included the text of that function. So that could be doing something we can't see, like counting the number of times it's been called by this process.
On the other hand, it's much more likely that it is indeed a typo.
It is possible. Here is a working example you can run.
class program
{
private $i = 1;
function carrier()
{
$this->i=$this->i+1;
return $this->i-1;
}
function run()
{
if ($this->carrier()==1 && $this->carrier()==2)
{
echo "works";
}
else
{
echo "doesnt work" . $i;
}
}
}
$prog = new Program();
$prog->run();

Categories