1

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

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

0 : string

0 : string

0 : string

for the code above. If comment out the inner for loop like so

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

I get the contents of "mystring" which is

a non empty string

and if I then change mystring to an empty string like so

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

I get

couldn't find something valuable

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

2
  • please fix your code formatting. function test() { and } test() is unformatted. Commented May 14, 2015 at 10:48
  • @noc2spamツ thanks. fixed it just before I read your comment.XD Commented May 14, 2015 at 13:02

2 Answers 2

2

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"));
Sign up to request clarification or add additional context in comments.

6 Comments

Ok. but i did get it to work temporarily at one point by putting brackets around it. why could that be?
I really do not know, it just couldn't be as far as I know.
I meant reproduce the result I got when using ||. but thanks. found that method with @KyleK in his comment section. it does allow the same logic though
Only the inside parenthesis is needed in the nested ternary expression, assignation has not the precedence. See php.net/manual/en/language.operators.precedence.php
|
1

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');

5 Comments

you say empty() gets more explicit code. like the kind of output you would get form var_dump() or json_encode()? <-(more descriptive easier to read)
I tried $out = $output? $output : $mystring ? $mystring : 'couldnt find something valuable'; just before I read your post. I like the newer php version you have enlightened me to. I got the content of $mystring though(a non empty string) instead of the content of $output. not sure why
Just add the parentheses: $out = $output ? $output : ($mystring ? $mystring : 'couldnt find something valuable'); and I do not understand your first comment.
about my first comment : sorry was just asking if what the output of empty() looks like but I will look it up
Done, for functions please see the doc, empty return true or false, it why it is more explicit to use it in a condition.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.