Short-circuit evaluation via the AND operator in PHP - php

I'm trying to improve my coding ninja h4x skills, and I'm currently looking at different frameworks, and I have found sample code that's pretty hard to google.
I am looking at the FUEL framework used in a project.
The sample I don't understand is
$data and $this->template->set_global($data);
What is the and keyword doing in this line of code? It is used many places in the framework and it's the first that I have found that uses it.

This is a type of "short circuit evaluation". The and/&& implies that both sides of the comparison must evaluate to TRUE.
The item on the left of the and/&& is evaluated to TRUE/FALSE and if TRUE, the item on the right is executed and evaluated. If the left item is FALSE, execution halts and the right side isn't evaluated.
$data = FALSE;
// $this->template->set_global($data) doesn't get evaluated!
$data and $this->template->set_global($data);
$data = TRUE;
// $this->template->set_global($data) gets evaluated
$data and $this->template->set_global($data);
Note these don't have to be actual boolean TRUE/FALSE, but can also be truthy/falsy values according to PHP's evaluation rules. See the PHP boolean docs for more info on evaluation rules.

When you use logical operators, operands (the value on the left and the value on the right) are evaluated as boolean, so basically that code will do this, in a shorter way:
$o1 = (Bool)$data; // cast to bool
if($o1)
$o2 = (Bool)$this->template->set_global($data); // cast to bool
Edit:
Some additional information:
$a = 33;
isset($a) && print($a) || print("not set");
echo "<br>";
isset($a) AND print($a) OR print("not set");
echo "<br>";
Try to comment/decomment $a = 33;. This is the difference between && and AND, and between || and OR (print returns true that is casted to "1" when converted to string).

It is a valid statement and works like this:
If $data is valid (is not '', 0 or NULL) then run $this->template->set_global($data)
It's a quick way of saying:
if ($data)
{
$this->template->set_global($data);
}
Btw you can also use && instead of and

PHP supports both && and and for the logical AND operation, and they generally work identically, except and has a slightly lower operator precedence than &&: http://php.net/manual/en/language.operators.precedence.php

It's a boolean operator which means it takes two operands and returns a boolean value-- true or false. If both operands evaluate to true (anything but and empty string, zero or null in PHP) it will return true, otherwise the result will be false.
Here's PHP's official docs on the and operator: http://www.php.net/manual/en/language.operators.logical.php
<?php
$a = true and false; # FALSE
$b = true and 5; # TRUE
$c = '' and 0; # FALSE
$d = null and true; # FALSE
?>

Related

strpos function error. I'm trying to parse MRZ from string [duplicate]

if(strpos("http://www.example.com","http://www.")==0){ // do work}
I'd expect this to resolve as true, which it does. But what happens when I do
if(strpos("abcdefghijklmnop","http://www.")==0){// do work}
This also passes on php 5 because as far as I can work out the strpos returns false which translates as 0.
Is this correct thinking/behaviour? If so what is the workaround for testing for that a substring is at the beginning of another string?
Yes, this is correct / expected behavior :
strpos can return 0 when there is a match at the beginning of the string
and it will return false when there is no match
The thing is you should not use == to compare 0 and false ; you should use ===, like this :
if(strpos("abcdefghijklmnop","http://www.") === 0) {
}
Or :
if(strpos("abcdefghijklmnop","http://www.") === false) {
}
For more informations, see Comparison Operators :
$a == $b will be TRUE if $a is equal to $b.
$a === $b will be TRUE if $a is equal to $b, and they are of the same type.
And, quoting the manual page of strpos :
This function may return Boolean
FALSE, but may also return a
non-Boolean value which evaluates to
FALSE, such as 0 or "". Please
read the section on Booleans for
more information. Use the ===
operator for testing the return
value of this function.
=== and !== compare type and value as shown below:
if (strpos("abcdefghijklmnop", "http://www.") !== false) {
// do work
}
strpos returns an int or boolean false. the == operator also evaluates 0 to mean false, you want to use the === operator (three equals signs) that also checks that the types being compared are the same instead of just seeing if they can be evaluated to mean the same.
so
if (strpos($hastack, $needle) === 0)
{
// the $needle is found at position 0 in the $haystack
}
0 is a possible return value from strpos when it finds a match at the very beginning. In case if the match is not found it returns false(boolean). So you need to check the return value of strpos using the === operator which check the value and the type rather than using == which just checks value.
I personally tend to use this way :
if(!strpos($v,'ttp:'))$v='http://'.$v;
or
if(strpos(' '.$v,'http'))
to avoid the "0" position then always make it a number more than 0
cheers

PDO fetchAll returns number 1 without any rows [duplicate]

What does the double not operator do in PHP?
For example:
return !! $row;
What would the code above do?
It's not the "double not operator", it's the not operator applied twice. The right ! will result in a boolean, regardless of the operand. Then the left ! will negate that boolean.
This means that for any true value (numbers other than zero, non-empty strings and arrays, etc.) you will get the boolean value TRUE, and for any false value (0, 0.0, NULL, empty strings or empty arrays) you will get the boolean value FALSE.
It is functionally equivalent to a cast to boolean:
return (bool)$row;
It's the same (or almost the same - there might be some corner case) as casting to bool. If $row would cast to true, then !! $row is also true.
But if you want to achieve (bool) $row, you should probably use just that - and not some "interesting" expressions ;)
It means if $row has a truthy value, it will return true, otherwise false, converting to a boolean value.
Here is example expressions to boolean conversion from php docs.
Expression Boolean
$x = ""; FALSE
$x = null; FALSE
var $x; FALSE
$x is undefined FALSE
$x = array(); FALSE
$x = array('a', 'b'); TRUE
$x = false; FALSE
$x = true; TRUE
$x = 1; TRUE
$x = 42; TRUE
$x = 0; FALSE
$x = -1; TRUE
$x = "1"; TRUE
$x = "0"; FALSE
$x = "-1"; TRUE
$x = "php"; TRUE
$x = "true"; TRUE
$x = "false"; TRUE
"not not" is a convenient way in many languages for understanding what truth value the language assigns to the result of any expression. For example, in Python:
>>> not not []
False
>>> not not [False]
True
It can be convenient in places where you want to reduce a complex value down to something like "is there a value at all?".
Another more human, maybe simpler, way to 'read' the not not:
The first '!' does 2 things: 'convert' the value to boolean, then output its opposite. So it will give true if the value is a 'falsy' one.
The second '!' is just to output the opposite of the first.
So, basically, the input value can be anything, maybe a string, but you want a boolean output, so use the first '!'. At this point, if you want TRUE when the input value is 'falsy', then stop here and just use a single '!'; otherwise if you want TRUE when the input value is 'truthy', then add another '!'.
Lets look at
!$a;
Rather than interpreting the ! operator as as taking the
Boolean opposite of the value to its right
read
take the Boolean opposite of the expression to its right
In this case
$a;
could be an expression
so to is
!$a;
so is
!!$a;
and
!!!$a;
and so on, as each of these is a valid expression, the ! operator can be prepended to each of them.

how ordering makes a difference within an expression for an if statement

I have an array ...
$a= array(1,2,3,4);
if (expr)
{ echo "if";
}
else
{ echo 'else';
}
When expr is ( $a = '' || $a == 'false') , output is "if" ,
but when expr is ( $a == 'false' || $a = '' ) , output is "else"
Can anyone explain why & how ordering makes a difference ??
Edit : I understand that I am assigning '' to $a. That is not the problem. The real question is : What does the expression $a = '' return? And why does reversing the order of the 2 situations switch us from the IF section to the ELSE section?
AGAIN : I UNDERSTAND I AM ASSIGNING NOT COMPARING. PLEASE ANSWER THE QUESTION AS IS.
First, never use = as a comparison operator. It is an assignment operator.
The difference is that false (as a boolean) is not the same as 'false' as a string.
Certain expressions are type juggled by PHP to evaluate somewhat differently to how you would expect.
false==""
// TRUE.
false=="false"
// FALSE.
Additionally, when you try to compare numbers to strings, PHP will try to juggle the data so that a comparison will be performed. There is a lot to it (much more than I will post here) but you would do well to investigate type juggling and various operators. The docs are a great start for this. You should also have a read of the comparison operators which go into a lot of detail about how various comparisons will work (depending on whether you use == or === for example).
With $a = '' you are setting $a to an empty string. This is the same as:
$a = '';
if($a){
echo 'if';
}
The || operator checks if the first condition is true and if it is, it continues with the code in the brackets. In PHP, if $a is set to anything, it will return true. In the second case $a does not equal the string 'false' (you are not comparing it to a boolean false even!), so it executes the code in the else part.
And Fluffeh is not entirely correct. You can use the assignment operator in an if condition very effectively, you just have to be smart about it.
$a = '' is an assignment: you have, in error, used = in place of ==. Assignment is an expression which has the value of the thing your assigning.
A single equals sign = is the assignment opporator, so $a = '' is assigning an empty string to $a not checking if it is equal to.
In your 1st example you set the value of $a to an empty string, then check if it is false. An empty tring evalutes to false in php, so the conditional is true.
In your second example, you check if $a equals false 1st (when the value of $a is an array), so the conditional is false

'AND' vs '&&' as operator

I have a codebase where developers decided to use AND and OR instead of && and ||.
I know that there is a difference in operators' precedence (&& goes before and), but with the given framework (PrestaShop to be precise) it is clearly not a reason.
Which version are you using? Is and more readable than &&? Or is there no difference?
If you use AND and OR, you'll eventually get tripped up by something like this:
$this_one = true;
$that = false;
$truthiness = $this_one and $that;
Want to guess what $truthiness equals?
If you said false... bzzzt, sorry, wrong!
$truthiness above has the value true. Why? = has a higher precedence than and. The addition of parentheses to show the implicit order makes this clearer:
($truthiness = $this_one) and $that
If you used && instead of and in the first code example, it would work as expected and be false.
As discussed in the comments below, this also works to get the correct value, as parentheses have higher precedence than =:
$truthiness = ($this_one and $that)
Depending on how it's being used, it might be necessary and even handy.
http://php.net/manual/en/language.operators.logical.php
// "||" has a greater precedence than "or"
// 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 and then true is ignored
// Acts like: (($f = false) or true)
$f = false or true;
But in most cases it seems like more of a developer taste thing, like every occurrence of this that I've seen in CodeIgniter framework like #Sarfraz has mentioned.
Since and has lower precedence than = you can use it in condition assignment:
if ($var = true && false) // Compare true with false and assign to $var
if ($var = true and false) // Assign true to $var and compare $var to false
For safety, I always parenthesise my comparisons and space them out. That way, I don't have to rely on operator precedence:
if(
((i==0) && (b==2))
||
((c==3) && !(f==5))
)
Precedence differs between && and and (&& has higher precedence than and), something that causes confusion when combined with a ternary operator. For instance,
$predA && $predB ? "foo" : "bar"
will return a string whereas
$predA and $predB ? "foo" : "bar"
will return a boolean.
Let me explain the difference between β€œand” - β€œ&&” - "&".
"&&" and "and" both are logical AND operations and they do the same thing, but the operator precedence is different.
The precedence (priority) of an operator specifies how "tightly" it binds two expressions together. For example, in the expression 1 + 5 * 3, the answer is 16 and not 18 because the multiplication ("*") operator has a higher precedence than the addition ("+") operator.
Mixing them together in single operation, could give you unexpected results in some cases
I recommend always using &&, but that's your choice.
On the other hand "&" is a bitwise AND operation. It's used for the evaluation and manipulation of specific bits within the integer value.
Example if you do (14 & 7) the result would be 6.
7 = 0111
14 = 1110
------------
= 0110 == 6
which version are you using?
If the coding standards for the particular codebase I am writing code for specifies which operator should be used, I'll definitely use that. If not, and the code dictates which should be used (not often, can be easily worked around) then I'll use that. Otherwise, probably &&.
Is 'and' more readable than '&&'?
Is it more readable to you. The answer is yes and no depending on many factors including the code around the operator and indeed the person reading it!
|| there is ~ difference?
Yes. See logical operators for || and bitwise operators for ~.
Another nice example using if statements without = assignment operations.
if (true || true && false); // is the same as:
if (true || (true && false)); // TRUE
and
if (true || true AND false); // is the same as:
if ((true || true) && false); // FALSE
because AND has a lower precedence and thus || a higher precedence.
These are different in the cases of true, false, false and true, true, false.
See https://ideone.com/lsqovs for en elaborate example.
I guess it's a matter of taste, although (mistakenly) mixing them up might cause some undesired behaviors:
true && false || false; // returns false
true and false || false; // returns true
Hence, using && and || is safer for they have the highest precedence. In what regards to readability, I'd say these operators are universal enough.
UPDATE: About the comments saying that both operations return false ... well, in fact the code above does not return anything, I'm sorry for the ambiguity. To clarify: the behavior in the second case depends on how the result of the operation is used. Observe how the precedence of operators comes into play here:
var_dump(true and false || false); // bool(false)
$a = true and false || false; var_dump($a); // bool(true)
The reason why $a === true is because the assignment operator has precedence over any logical operator, as already very well explained in other answers.
Here's a little counter example:
$a = true;
$b = true;
$c = $a & $b;
var_dump(true === $c);
output:
bool(false)
I'd say this kind of typo is far more likely to cause insidious problems (in much the same way as = vs ==) and is far less likely to be noticed than adn/ro typos which will flag as syntax errors. I also find and/or is much easier to read. FWIW, most PHP frameworks that express a preference (most don't) specify and/or. I've also never run into a real, non-contrived case where it would have mattered.

Double not (!!) operator in PHP

What does the double not operator do in PHP?
For example:
return !! $row;
What would the code above do?
It's not the "double not operator", it's the not operator applied twice. The right ! will result in a boolean, regardless of the operand. Then the left ! will negate that boolean.
This means that for any true value (numbers other than zero, non-empty strings and arrays, etc.) you will get the boolean value TRUE, and for any false value (0, 0.0, NULL, empty strings or empty arrays) you will get the boolean value FALSE.
It is functionally equivalent to a cast to boolean:
return (bool)$row;
It's the same (or almost the same - there might be some corner case) as casting to bool. If $row would cast to true, then !! $row is also true.
But if you want to achieve (bool) $row, you should probably use just that - and not some "interesting" expressions ;)
It means if $row has a truthy value, it will return true, otherwise false, converting to a boolean value.
Here is example expressions to boolean conversion from php docs.
Expression Boolean
$x = ""; FALSE
$x = null; FALSE
var $x; FALSE
$x is undefined FALSE
$x = array(); FALSE
$x = array('a', 'b'); TRUE
$x = false; FALSE
$x = true; TRUE
$x = 1; TRUE
$x = 42; TRUE
$x = 0; FALSE
$x = -1; TRUE
$x = "1"; TRUE
$x = "0"; FALSE
$x = "-1"; TRUE
$x = "php"; TRUE
$x = "true"; TRUE
$x = "false"; TRUE
"not not" is a convenient way in many languages for understanding what truth value the language assigns to the result of any expression. For example, in Python:
>>> not not []
False
>>> not not [False]
True
It can be convenient in places where you want to reduce a complex value down to something like "is there a value at all?".
Another more human, maybe simpler, way to 'read' the not not:
The first '!' does 2 things: 'convert' the value to boolean, then output its opposite. So it will give true if the value is a 'falsy' one.
The second '!' is just to output the opposite of the first.
So, basically, the input value can be anything, maybe a string, but you want a boolean output, so use the first '!'. At this point, if you want TRUE when the input value is 'falsy', then stop here and just use a single '!'; otherwise if you want TRUE when the input value is 'truthy', then add another '!'.
Lets look at
!$a;
Rather than interpreting the ! operator as as taking the
Boolean opposite of the value to its right
read
take the Boolean opposite of the expression to its right
In this case
$a;
could be an expression
so to is
!$a;
so is
!!$a;
and
!!!$a;
and so on, as each of these is a valid expression, the ! operator can be prepended to each of them.

Categories