PHP >! operator isn't legit but works - php

So I used >! comparison operator in PHP 5.6 and it works. It doesn't appear on any operators documentation and I'm confused why does it work and why PHPStorm doesn't complain about it? Even if !($foo > $bar) would be the correct syntax..

Your >! operator is in fact two operators: > and !. ! is applied to second argument:
var_dump(!4); // `false`
var_dump(3 >! 4); // `true`
How come that last case it true:
var_dump(3 >! 4) is same as var_dump(3 >(! 4)) because of operators precedence
first, applying ! to 4 gives you false
second, comparing 3 and false gives you true, because 3 is truthy value which is always greater than any falsy/false value.
As a practice you can understand this tricky cases:
var_dump(0 > !0); // false
var_dump(-3 > !0); // false

It does not seems to work for me, as a variable comparison operator. In php 5.6, results are inconsistent:
$a = 10;
$b = 5;
var_dump($a >! $b);
returns true
but
$a = 10;
$b = 11;
var_dump($a >! $b);
returns true again
As others have stated, your variable is being evaluated as false, which make the if statement to returns true in the code above

Related

type casting and equal operator precedence in php

Why do these 2 statements not output the same result?
The only reason I can imagine is operator precedence which appears to the same for == and ===.
$a = (bool) 4 == 4;
$b = (bool) 4 === 4;
var_dump($a); // bool(true)
var_dump($b); // bool(false)
Yes, operator precedence is the same for == and ===. Clearly the difference here is the operator itself.
First we have to acknowledge that type casting has a higher precedence than these two comparison operators. So, in reality, you're doing:
$a = (TRUE == 4);
$b = (TRUE === 4);
When you do a == you're simply trying to see if the values are equal. Only values of the same type can be compared. Since you start with a boolean, the number 4 will therefore also be turned into a boolean. This is called type juggling. We already know that (bool)4 is TRUE. So $a must be TRUE.
However, when you do a === there is no type juggling, instead it will only return TRUE if the two operands have the same value and type. Since a boolean isn't the same type as an integer $b must be FALSE.

PHP xor returns wrong value

Using php 7.1.0 I'm running this little test:
<?php
$a = true;
$b = true;
$value = $a xor $b;
if ($value == true) {
print "bad!\n";
} else {
print "good\n";
}
and it's coming back and saying bad. Why? An xor of two true values should be FALSE, not true.
The problem is operator precedence. The xor operator has lower precedence than =, so your statement is equivalent to:
($value = $a) xor $b;
You need to write:
$value = ($a xor $b);
or
$value = $a ^ $b;
The ^ operator is bit-wise XOR, not boolean. But true and false will be converted to 1 and 0, and the bit-wise results will be equivalent to the boolean results. But this won't work if the original values of the variables could be numbers -- all non-zero numbers are truthy, but when you perform bit-wise XOR with them you'll get a truthy result for any two numbers that are different.
See the PHP Operator Precedence Table
See the related Assignment in PHP with bool expression: strange behaviour

PHP if execution

In PHP if you have the following code does $b get evaluated since $a will cause the if statement to return false?
$a = false;
$b = true;
if ($a && $b) {
// more code here
}
also if $b does get evaluated are there ever circumstances where a portion of an if statement may not be evaluated as the processor already knows that the value to be false?
Evaluation of && is stopped as soon as it hits the false condition.
These (&&) are short-circuit operators, so they don't go to check second condition if the first one true (in case of OR) or false(in case of AND).
Reference: http://php.net/manual/en/language.operators.logical.php
From documentation:
<?php
// --------------------
// foo() will never get called as those operators are short-circuit
$a = (false && foo());
$b = (true || foo());
$c = (false and foo());
$d = (true or foo());
Evaluation of logical expressions is stopped as soon as the result is known.
If $a is false, $b will not get evaluated, as it won't change the ($a && $b) result.
A consequence of that is that if the evaluation of $b requires more ressources than the evaluation of $a, starts your test condition with $a.
But be aware that:
PHP does not (in the general case) specify in which order an expression is evaluated and code that assumes a specific order of evaluation should be avoided, because the behavior can change between versions of PHP or depending on the surrounding code. (Source php docs)
So you should not assume $b is never evaluated if $a is false, as it may change in the future (says php docs).

Does PHP support conjunction and disjunction natively?

Javascript employs the conjunction and disjunction operators.
The left–operand is returned if it can be evaluated as: false, in the case of conjunction (a && b), or true, in the case of disjunction (a || b); otherwise the right–operand is returned.
Do equivalent operators exist in PHP?
PHP supports short-circuit evaluation, a little different from JavaScript's conjunction. We often see the example (even if it isn't good practice) of using short-circuit evaluation to test the result of a MySQL query in PHP:
// mysql_query() returns false, so the OR condition (die()) is executed.
$result = mysql_query("some faulty query") || die("Error");
Note that short-circuit evaluation works when in PHP when there is an expression to be evaluated on either side of the boolean operator, which would produce a return value. It then executes the right side only if the left side is false. This is different from JavaScript:
Simply doing:
$a || $b
would return a boolean value TRUE or FALSE if either is truthy or both are falsy. It would NOT return the value of $b if $a was falsy:
$a = FALSE;
$b = "I'm b";
echo $a || $b;
// Prints "1", not "I'm b"
So to answer the question, PHP will do a boolean comparison of the two values and return the result. It will not return the first truthy value of the two.
More idiomatically in PHP (if there is such a thing as idiomatic PHP) would be to use a ternary operation:
$c = $a ? $a : $b;
// PHP 5.3 and later supports
$c = $a ?: $b;
echo $a ?: $b;
// "I'm b"
Update for PHP 7
PHP 7 introduces the ?? null coalescing operator which can act as a closer approximation to conjunction. It's especially helpful because it doesn't require you to check isset() on the left operand's array keys.
$a = null;
$b = 123;
$c = $a ?? $b;
// $c is 123;

PHP considers null is equal to zero

In PHP, ($myvariable==0)
When $myvariable is zero, the value of the expression is true; when $myvariable is null, the value of this expression is also true. How can I exclude the second case? I mean I want the expression to be true only when $myvariable is zero. Of course I can write
($myvariable != null && $myvariable == 0)
But is there other elegant way to do this?
$myvariable === 0
read more about comparison operators.
You hint at a deep question: when should an expression be true?
Below, I will explain why what you are doing isn't working and how to fix it.
In many languages null, 0, and the empty string ("") all evaluate to false, this can make if statements quite succinct and intuitive, but null, 0, and "" are also all of different types. How should they be compared?
This page tells us that if we have two variables being compared, then the variables are converted as follows (exiting the table at the first match)
Type of First Type of Second Then
null/string string Convert NULL to "", numerical/lexical comparison
bool/null anything Convert to bool, FALSE < TRUE
So you are comparing a null versus a number. Therefore, both the null and the number are converted to boolean. This page tells us that in such a conversion both null and 0 are considered FALSE.
Your expression now reads, false==false, which, of course, is true.
But not what you want.
This page provides a list of PHP's comparison operators.
Example Name Result
$a == $b Equal TRUE if $a equals $b after type juggling.
$a === $b Identical TRUE if $a equals $b, AND they are of the same type.
$a != $b Not equal TRUE if $a not equals $b after type juggling.
$a <> $b Not equal TRUE if $a not equals $b after type juggling.
$a !== $b Not identical TRUE if $a not equals $b, or they are not of the same type.
$a < $b Less than TRUE if $a is strictly less than $b.
$a > $b Greater than TRUE if $a is strictly greater than $b.
$a <= $b Less than/equal TRUE if $a is less than or equal to $b.
$a >= $b Greater than/equal TRUE if $a is greater than or equal to $b.
The first comparator is the comparison you are using now. Note that it performs the conversions I mentioned earlier.
Using the second comparator will fix your problem. Since a null and a number are not of the same type, the === comparison will return false, rather than performing type conversion as the == operator would.
Hope this helps.
To identify as null or zero by:
is_int($var) if a variable is a number or a numeric string. To identify Zero, use is_numeric($var) is also the solution or use $var === 0
is_null($var) if a variable is NULL
Try ($myvariable === 0) which will not perform type coercion.
Use the php function is_null( ) function along with the === operator. !== also works the way you'd expect.
The second solution wouldn't work either. The === operator is the solution to your problem.
If your zero could be a string, you should also considere checking the "zero string"
($myvariable === 0 || $myvariable === '0')
I hade faced a similar issue in one of my projects, with a minor difference that I was also using the values ZERO as a valid value for my condition. here's how I solved it using simple logic to separate NULL from zero and other values.
if (gettype($company_id) === 'NULL') {
$company = Company::where('id', Auth::user()->company_id)->first();
} else {
$company = Company::where('id', $company_id)->first();
}
$myvariable===0
$a === $b
Identical TRUE if $a is equal to $b, and they are of the same type
There's an is_null function, but this will just replace your $myvariable!=null
For my case i found this soulution and it works for me :
if ($myvariable === NULL) {
codehere...
}

Categories