Muntasir
Muntasir

Reputation: 1140

Does PHP have short-circuit evaluation?

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?

Upvotes: 86

Views: 37072

Answers (10)

Zach Rattner
Zach Rattner

Reputation: 21353

Yes, it's short-circuit. The PHP interpreter does "lazy" evaluation of boolean operators, 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';
}

Upvotes: 114

Obay
Obay

Reputation: 3205

No, PHP doesn't perform any more evaluations or execute subsequent expressions in the remaining condition statement after a condition isn't satisfied.

Upvotes: 3

Nate Symer
Nate Symer

Reputation: 2293

PHP short circuits || & &&.

Here's a little test:

function retfalse() { echo "FALSE\n"; return false; }
function rettrue() { echo "TRUE\n"; return true; }

$a = retfalse() || rettrue();
$b = rettrue() || retfalse();

Should print:

FALSE
TRUE
TRUE

Upvotes: 0

Tony Patrinos
Tony Patrinos

Reputation: 11

In this example I expected according to the precedence rules at https://www.php.net/manual/en/language.operators.precedence.php for $a to be equivalent to $b. However, because of short circuiting, $a is true and $b is false.

<?php

 $a = 1 || 0 && 0;
 $b = (1 || 0) && 0;
 

Upvotes: 0

Steve Douglas
Steve Douglas

Reputation: 195

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.

Upvotes: 11

agm1984
agm1984

Reputation: 17132

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.

Upvotes: 7

Robert
Robert

Reputation: 669

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().

Upvotes: 12

Perspective
Perspective

Reputation: 632

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'

Upvotes: 1

Patricio Rossi
Patricio Rossi

Reputation: 163

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.

Upvotes: -8

Beto Aveiga
Beto Aveiga

Reputation: 3670

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.

Upvotes: -6

Related Questions