TAGS :Viewed: 11 - Published at: a few seconds ago

[ php "||" assignment logic compared to Javascript ]

I was testing Heredoc and || functionality

function test()
{
    $obj = [(object)['col1'=>'val1'],
            (object)['col2'=>'val2'],
            (object)['col3'=>'val3']];
    $output = '';
$mystring = <<<EOT
a non empty string
EOT;

    foreach($obj as $prop)
    {
        foreach($prop as $i)
        {
            $output .= <<<EOT
            <div style='background-color:lightblue'> 
            \$head  : {gettype($i)} 
            </div>
EOT;
        }
    }
    $out =  $output || $mystring || 'couldn\'t find something valuable';
    echo $out;
}
test();

I get the output of

1

which represents a Boolean true. I had it output the contents of $mystring at one point by putting the logic in brackets eg

echo ($output || $mystring);

and it used to output:

a non empty string

It stopped working straight after and I am not sure what change broke it.

In javascript:

    function test()
    {

    var obj = [{'col1':'val1'},
            {'col2':'val2'},
            {'col3':'val3'}];
    var output = '';
    var mystring ="a non empty string";

    for(var prop in obj)
    {
        for(var i in prop)
        {
            output += 
            "<div style='background-color:lightblue'>" +
                i + " : " + typeof prop[i] +
                "</div>";
        }
    }
    out =  output || mystring || 'couldn\'t find something valuable';
    document.write(out);
    console.log("outputting \n\t" + out);
}
test();
</div>
</div>
</p>

<p>It is slightly different from the php in terms of logic but the || during assignment works as expected. I get </p>

<blockquote>
  <p>0 : string</p>

  <p>0 : string</p>

  <p>0 : string</p>
</blockquote>

<p>for the code above. If comment out the inner for loop like so</p>

for(var prop in obj) { /for(var i in prop) { output += "<div style='background-color:lightblue'>" + i + " : " + typeof prop[i] + "</div>"; }/ }

<p>I get the contents of "mystring" which is</p>

<blockquote>
  <p>a non empty string</p>
</blockquote>

<p>and if I then change mystring to an empty string like so</p>

mystring = ""; //"a non empty string";

```

I get

couldn't find something valuable

How does php's "||" during assignment work ? Can someone explain it?

Answer 1


If you assign a conditional expression in php you always get a boolean (that is, strictly true or false), it does not work as in javascript where the "truthy" value gets assigned, so in PHP

$a = "";
$b = 42;
$c = ($a || $b); // == true

While in javascript

var a = "";
var b = 42;
var c = (a || b); // == 42

and this is, sadly, by language design.

As @billyonecas reports, it is also in the comments to the docs: http://php.net/manual/en/language.operators.logical.php#77411

To obtain a similar behaviour in PHP, we must do something like:

$a = "";
$b = 42;
$c = ($a ?: $b); // newer php version
$c = ($a ? $a : $b); // older php version

if you need to concatenate expression, use parethesis:

$c = ($a ? $a : ($b ? $b : "not found"));

Answer 2


With PHP, you can use ?:

$out =  $output ?: $mystring;

Or in older versions of PHP:

$out =  $output ? $output : $mystring;

You can also use empty() to get a more explicit code:

$out =  empty($output) ? $mystring : $output;

http://php.net/manual/en/function.empty.php

Note: these ternary expressions are equivalent to if-else:

if(empty($output))
{
    $out = $mystring;
}
else
{
    $out = $output;
}

With nested ternary, add parentheses, as the default precedence is:

$out =  $output ? $output : $mystring ? $mystring : 'default';

This is:

$out =  ($output ? $output : $mystring) ? $mystring : 'default';

So you must do:

$out =  $output ? $output : ($mystring ? $mystring : 'default');