Does PHP have short-circuit evaluation?

PhpIf StatementShort Circuiting

Php Problem Overview


Given the following code:

if (is_valid($string) && up_to_length($string) && file_exists($file)) 
{
    ......
}

If is_valid($string) returns false, does the php interpreter still check later conditions, like up_to_length($string)?
If so, then why does it do extra work when it doesn't have to?

Php Solutions


Solution 1 - Php

Yes, the PHP interpreter is "lazy", meaning it will do the minimum number of comparisons possible to evaluate conditions.

If you want to verify that, try this:

function saySomething()
{
    echo 'hi!';
    return true;
}

if (false && saySomething())
{
    echo 'statement evaluated to true';
}

Solution 2 - Php

Yes, it does. Here's a little trick that relies on short-circuit evaluation. Sometimes you might have a small if statement that you'd prefer to write as a ternary, e.g.:

    if ($confirmed) {
        $answer = 'Yes';
    } else {
        $answer = 'No';
    }

Can be re-written as:

   $answer = $confirmed ? 'Yes' : 'No';

But then what if the yes block also required some function to be run?

    if ($confirmed) {
        do_something();
        
        $answer = 'Yes';
    } else {
        $answer = 'No';
    }

Well, rewriting as ternary is still possible, because of short-circuit evaluation:

    $answer = $confirmed && (do_something() || true) ? 'Yes' : 'No';

In this case the expression (do_something() || true) does nothing to alter the overall outcome of the ternary, but ensures that the ternary condition stays true, ignoring the return value of do_something().

Solution 3 - Php

Bitwise operators are & and |. They always evaluate both operands.

Logical operators are AND, OR, &&, and ||.

  • All four operators only evaluate the right side if they need to.
  • AND and OR have lower precedence than && and ||. See example below.

 

From the PHP manual:

// The result of the expression (false || true) is assigned to $e
// Acts like: ($e = (false || true))
$e = false || true;

// The constant false is assigned to $f before the "or" operation occurs
// Acts like: (($f = false) or true)
$f = false or true;

In this example, e will be true and f will be false.

Solution 4 - Php

Based on my research now, PHP doesn't seem to have the same && short circuit operator as JavaScript.

I ran this test:

$one = true;

$two = 'Cabbage';

$test = $one && $two;

echo $test;

and PHP 7.0.8 returned 1, not Cabbage.

Solution 5 - Php

No, it doesn't anymore check the other conditions if the first condition isn't satisfied.

Solution 6 - Php

I've create my own short-circuit evaluation logic, unfortunately it's nothing like javascripts quick syntax, but perhaps this is a solution you might find useful:

$short_circuit_isset = function($var, $default_value = NULL) {
	return	(isset($var)) ? : $default_value;
};

$return_title = $short_circuit_isset( $_GET['returntitle'], 'God');

// Should return type 'String' value 'God', if get param is not set

I can not recall where I got the following logic from, but if you do the following;

(isset($var)) ? : $default_value;

You can skip having to write the true condition variable again, after the question mark, e.g:

(isset($super_long_var_name)) ? $super_long_var_name : $default_value;

As very important observation, when using the Ternary Operator this way, you'll notice that if a comparison is made it will just pass the value of that comparison, since there isn't just a single variable. E.g:

$num = 1;
$num2 = 2;
var_dump( ($num < $num2) ? : 'oh snap' );
// outputs bool 'true'

Solution 7 - Php

My choice: do not trust Short Circuit evaluation in PHP...

function saySomething()
{
    print ('hi!');
    return true;
}

if (1 || saySomething())
{
    print('statement evaluated to true');
}

The second part in the condition 1 || saySomething() is irrelevant, because this will always return true. Unfortunately saySomething() is evaluated & executed.

Maybe I'm misunderstood the exact logic of short-circuiting expressions, but this doesn't look like "it will do the minimum number of comparisons possible" to me.

Moreover, it's not only a performance concern, if you do assignments inside comparisons or if you do something that makes a difference, other than just comparing stuff, you could end with different results.

Anyway... be careful.

Solution 8 - Php

Side note: If you want to avoid the lazy check and run every part of the condition, in that case you need to use the logical AND like this:

if (condition1 & condition2) {
 echo "both true";
}
else {
 echo "one or both false";
}

This is useful when you need for example call two functions even if the first one returned false.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMuntasirView Question on Stackoverflow
Solution 1 - PhpZach RattnerView Answer on Stackoverflow
Solution 2 - PhpRobertView Answer on Stackoverflow
Solution 3 - PhpSteve DouglasView Answer on Stackoverflow
Solution 4 - Phpagm1984View Answer on Stackoverflow
Solution 5 - PhpObayView Answer on Stackoverflow
Solution 6 - PhpPerspectiveView Answer on Stackoverflow
Solution 7 - PhpBeto AveigaView Answer on Stackoverflow
Solution 8 - PhpPatricio RossiView Answer on Stackoverflow