Compound boolean expressions in C/PHP and variable assignment - php

Forgive me if the title doesn't exactly match what I'm asking, I'm having a tough time describing the question exactly.
Consider the following PHP code:
#!/usr/bin/php
<?php
class foo{
function bar()
{
return true;
}
}
if (true && $a = new foo() && $a->bar()) {
echo "true";
} else {
echo "false";
}
It gives
Fatal error: Call to a member function bar() on a non-object
for the $a->bar(); expression.
Consider the following C code:
int main(void)
{
int i = 0;
if (i += 1 && printf("%d\n", i))
{
printf("Done: %d.\n", i);
}
}
It outputs :
0
Done: 1.
Why is this? Since C and PHP claim to short-circuit these expressions and evaluate left to right, I expect a value set in expressions to the left to be used in expressions to the right. Is there something I'm missing?

Your problem right now is with operator precedence. PHP currently evaluates your PHP statement as such:
if (true && $a = ( new foo() && $a->bar() ) )
In which case $a is not defined by the time you try calling $a->bar().
What you really want is this:
if (true && ( $a = new foo() ) && $a->bar())
Using brackets in complex conditions will prevent those kinds of errors from happening.
EDIT: Proof
if(true && $a = true && false) { }
var_dump($a); // bool(false)
if(true && ( $b = true ) && false) { }
var_dump($b); // bool(true)

Related

difficulty to understand a PHP syntax

Suppose we have this method in a class :
public static function example($s, $f = false)
{
(static::$i['s'] === null or $f) and static::$i['s'] = $s;
return new static;
}
would you please give me any hint what is the meaning of this line of code?
(static::$i['s'] === null or $f) and static::$i['s'] = $s;
is it a conditional statement? or something like a ternary operator?
Thanks
They are trying to be clever by using the short circuiting that happens when dealing with logical operators like this. This is what they are doing:
if ((static::$info['syntax'] === null) || $force) {
static::$info['syntax'] = $syntax;
}
If you want to see how this short circuiting works with the &&/and operator:
$a = 'something';
false && $a = 'else';
echo $a;
// output: something
Since the first part is false, it never even runs the statement on the other side since this logical operation already evaluates to false.

Is it ok to use a 'boolean operator' to evaluate null in PHP

Is it ok to use a 'boolean operator' to evaluate null? ie
function a(bool $z): ?int
{
return ($z) ? 1 : null;
}
if (!$b = a(false)) {
...
} else {
...
}
It seems ok since $b will evaluate false if a returns null but it also seems wonky and like a potential source of errors. Is there a cleaner way to do it?
Use triple equal (===) to compare value and type.
if(0 == null) { /* pass */ }
if(0 === null) { /* no pass */ }
Btw, did you intentionally assign $b's value in the if condition?
Assuming you did not, the following if condition will distinguish null:
$b = a(false);
if($b === null) { ... } else { ... }
You could use is_null
Here is the test case :
<?php
use PHPUnit\Framework\TestCase;
class BooleanTest extends TestCase
{
public function booleanProvider()
{
return [
'boolean null' => [null, 'this is null boolean'],
'boolean 0' => [0, 0],
'boolean 1' => [1, 1],
];
}
/**
* #dataProvider booleanProvider
*/
public function testNullBoolean($value, $expected) {
$actual = is_null($value) ? 'this is null boolean' : $value;
$this->assertSame($actual, $expected);
}
}
I think the best way to find out if your code contains any potential error is to write the unit test for it, you could see many input and output for your code and find out where the errors could be.
Here is the phpUnit link PhpUnit document
You can use the PHP built in empty() method:
Returns FALSE if var exists and has a non-empty, non-zero value. Otherwise returns TRUE.
The following values are considered to be empty:
"" (an empty string)
0 (0 as an integer)
0.0 (0 as a float)
"0" (0 as a string)
NULL
FALSE
array() (an empty array)
You can find more on the empty() method here: http://php.net/manual/en/function.empty.php
So you could then write your function like this:
function a($var)
{
return empty($var);
}
if( $b = a(false) )
{
echo 'it is empty';
}
else
{
echo 'it is not';
}
will output:
it is empty
I remembered what I was looking for:
if (null === $b = a(false)) { ... }
It's a strange but elegant construct. Sorry if the intent wasn't clear from the question.

is it possible to simplify isset?

I have a lot of functions with parameter that can be either bool or null. If we simplify my functions I have somethings like this:
funtion ($param) {
if ($param) {
//true
} else {
//false
}
}
However, when I call function(null); it obviously goes into else part of condition. So I have to do
funtion ($param) {
if (isset($param)) {
if ($param) {
//true
} else {
//false
}
}
}
for every similar if condition, which is sort of annoying.
So my question is this:
Is there a possibility to do this type of condition with this type of parameter faster and/or without additional function?
To only validate on true and false, use strict type comparison (===):
function check($param)
{
if ($param === true) {
// It's true. :)
} else if ($param === false) {
// It's false.. :o
}
}
This will ignore it if it is null.
Please read the bottom code for the most useful (but least explanative) function.
The below function solves your dilemma. If $param is true or false then the return gives back the boolean version of the $param (useful for such instances as if $param is a sting or an integer etc).
else, nothing is returned by the function which is defined as a NULL value.
example with type clarity texts:
<?php
//Enter your code here, enjoy!
$test[] = NULL;
$test[] = true;
$test[] = false;
$test[] = "string";
$test[] = 45;
function tester($param) {
if(!is_null($param)){
return (boolean)$param?"true":"false";
}
return "null";
}
foreach($test as $row){
print $row . " :: ". tester($row)."\n";
}
Exampled Output:
:: null 1 :: true :: false string :: true 45 ::
true
If you want to return the actual type rather than the textual representation this can be easily achieved with a slimmed down version:
Solution:
function ($param) {
if(!is_null($param)){
return (boolean)$param;
}
// not required but useful to keep for code clarity.
//return null;
}
Possible results:
1 (true) 0 (false) null

Why does this code work correctly? - using equal sign inside an if condition

Why does this code work correctly?
function isLoggedIn(){
return false; //or true
}
if($user = isLoggedIn())
{
echo "Hello ".$user['name']; //if isLoggedIn returns true, this prints
} else {
echo "Please login to proceed!";//if isLoggedIn returns false, this prints
}
I always thought assignment operator inside an if() condition will always evaluate to true since it is only evaluating whether the value of right hand side can be assigned to left hand side...
It's evaluating the value of $user after assigning the return of isLoggedIn() to $user. It's the same as:
$user = isLoggedIn();
if($user) {}
It's especially handy in loops:
while($var = someFunction()) {
//do stuff with $var
}
And more expressions:
if($var = someFunction() && $var !== 'bad') {}
if($var = someFunction() && $var === 'good') {}
In PHP, an assignment operation actually has a return value, and it's the value that was assigned. Your if() condition works for the exact same reason that
$x = $y = $z = 42;
works. This statement will assign the value 42 to all three variables, and is functionally the equivalent of
$z = 42;
$y = $z;
$x = $y;
In your case, your isLoggedIn() function call will execute and return a value. That value assigned to $user. Then that value is "returned" to the if() statement itself and is used for the logic test.
If your function had returned boolean false, or a "falsey" value, then the "else" clause would have executed. e.g.
function returns_false() {
return false;
}
if ($foo = returns_false()) {
echo 'if was true';
} else {
echo 'if was false'; // this line will get executed
}
Even though the assignment operation succeeded, it's the value that got assigned that matters, not the success/failure of the operation. so the "it was false" code path gets executed, because the function call returned a false, which propagated up the decision tree.
The condition considers $user after assignment.
Therefore it will be true or false depending on the value returned by isLoggedIn()
There is one note. Code like this will not work as expected:
if($var = someFunction() && $var !== 'bad') {}
if($var = someFunction() && $var === 'good') {}
Because $var will contain not a value returned by someFunction(), but a boolean value of the whole expression, like this:
$var = (someFunction() && $var !== 'bad');
if($var) {}
To get the result you need you should use brackets:
if(($var = someFunction()) && $var !== 'bad') {}
if(($var = someFunction()) && $var === 'good') {}
You can find details on the php.net website.
It works because the IF is TRUE. Oddly enough it will always be TRUE. Because you are assigning the value when you only use one = sign. If you want to check the contents, you have to use ==.
As everyone has already suggested, there are two parts to the statement:
It assigns the value of isLoggedIn() to $user.
It then returns the same value to whichever construct asked for it. In this case, it's
returned to the if () statement.
It is worth noting that although the if () statement expects to receive a boolean value true or false. If the if () receives a value that isn't a boolean, it is still acceptable in PHP (as well as JavaScript). If any operator or statement receives a value of the wrong type, PHP will convert it to boolean=true in most cases.

variable assignment inside 'IF' condition

in php, something like this is fine:
<?php
if ( !$my_epic_variable = my_epic_function() ){
// my epic function returned false
// my epic variable is false
die( "false" );
}
echo $my_epic_variable;
?>
I suppose is a shorter way of doing:
$my_epic_variable = my_epic_function();
if ( !$my_epic_variable ){
die( "false" );
}
Can this be done is javascript? I've tried to no success, wasnt sure if there was some kind of special syntax or something
You can do the same in JavaScript, with one key difference.
You cannot declare a (locally scoped) variable inside the if clause, you may only refer to it.
So, declare it first:
var someVar;
Then use it however you want:
if (!(someVar = someFunction())) { /* do some stuff */ }
Notice that you will also have to wrap negated expressions (!(expression)) with parentheses
This however, will not work:
if (var someVar = someFunction()) { /* NOPE */ }
Yes, that works fine. However, if you're inversing (!), then you need to wrap the assignment in parentheses otherwise you'll get a syntax error.
function myFunc() {
return false;
}
if(!(myVar = myFunc())) {
console.log('true');
}
Working example
It works in JS too:
var foo = null;
if ( foo = 1 ){
// some code
}
alert (foo); // 1
Or assignment even with a function:
var foo = null;
function getFoo(){
return 1;
}
if ( foo = getFoo() ){
// some code
}
alert (foo); // 1
With negation, you need to add braces:
var foo = null;
function getFoo(){
return 1;
}
if (! (foo = getFoo()) ){
// some code
}
alert (foo); // 1
In the last case, it is important to wrap assignment statement in parenthesis because ! is then used to check against the result of that.
This is the preferred method for me (in PHP), because it makes it absolutely clear that you didn't mean to use the == condition but made a mistake.
if ( ($my_epic_variable = my_epic_function()) !== NULL ){
// my epic function returned false
// my epic variable is false
die( "false" );
}
In JavaScript I'd probably do:
function my_epic_function() {
return 5;
}
var my_epic_variable;
if ( (my_epic_variable = my_epic_function()) !== null ){
alert("we're in");
}​

Categories