What is this syntax structure and how does it work? - php

I'm not sure how the comparison operation of the array node works in relation to the assignment of 'true' to the same array node. Is this some alternate usage of the Ternary syntax? Either an explanation or a link to the PHP reference (I don't even know how to search for this) would be helpful. Thanks in advance.
// RESOLVE myvar TO BOOLEAN
$atts['myvar'] = 'true' == $atts['myvar'];

You should read this like that:
$atts['myvar'] = ('true' == $atts['myvar']);
(saving on brackets is never worth a penny). When run, it will compare actual content of $atts['myvar'] with string true (4 letters) and then overwrite $atts['myvar'] with result of the comparison, which will be boolean by then. If it equals to string "true" then result is boolean true, for anything else it will become boolean false. In other words, it converts "string boolean" to regular boolean.

Related

for loop with isset() != null - why?

for($i=0; isset($_POST['key_str'][$i]) != null; $i++)
{
// some php here
}
I've inherited some legacy code at work and I've found above for() loop in several places. I've been writing PHP, Javascript and Python for years now and have never seen anything like this. My gut tells me this is the person who wrote this legacy code came from a different language. And may have not been very experienced.
Questions:
1) Does isset($_POST['key_str'][$i]) perform better than count($_POST['key_str'])?
2) Does this resemble syntax that you'd typically find in another language? If so, which language?
Inside isset, $i (which is incremented in the loop) is used in this expression. $_POST['key_str'][$i], which is part of the check.
So basically, $_POST['key_str'] is expected to be an array, and this loop will loop over all items in that array.
If you like, you could use count(), or replace the whole thing with a foreach loop, although that may result in a warning if $_POST['key_str'] is not set at all or is not an array. isset is a very easy way to get around that, because it handles all those situations and will return false, so the loop will simply not be entered in that scenario.
isset() is a language construct that returns a boolean, thus it can never be null. However, the comparison uses the equal operator (==) rather than the identical operator (===) thus type juggling applies:
Type of Operand 1 Type of Operand 2 Result
bool or null anything Convert both sides to bool
… and null casts to boolean false so:
true != null → true != false → true
false != null → false != false → false
Thus the loop is equivalent to:
for($i=0; isset($_POST['key_str'][$i]); $i++){}
In other words, != null is redundant and harms readability.
Now, square brackets are used to read an array element by key or a string byte by offset. Since $_POST is an external variable the loop can actually do both—I presume the former was intended. Without further context it's impossible to say what it's meant to accomplish or how to rewrite it but I suspect it's a convoluted alternative to foreach().
So to answer your questions:
It's irrelevant. They do entirely different things.
This is opinion-based (to me, it's the syntax of someone who's not familiar with programming in general.)

Several PHP type-juggling comparisons, such as empty string and an empty array, return unexpected results

The triple equal I think everyone understands; my doubts are about the double equal. Please read the code below.
<?php
//function to improve readability
function compare($a,$b,$rep)
{
if($a == $b)
echo "$rep is true<br>";
else
echo "$rep is false<br>";
}
echo "this makes sense to me<br>";
compare(NULL,0,'NULL==0');
compare(NULL,"",'NULL==""');
compare(NULL,[],'NULL==[]');
compare(0,"",'0==""');
echo "now this is what I don't understand<br>";
compare("",[],'""==[]');
compare(0,[],'0==[]');
compare(0,"foo",'0=="foo"');
echo "if I cast to boolean then it makes sense again<br>";
compare("",(bool)[],'""==(bool)[]');
compare(0,(bool)[],'0==(bool)[]');
?>
Output:
this makes sense to me
NULL==0 is true
NULL=="" is true
NULL==[] is true
0=="" is true
now this is what I don't understand
""==[] is false
0==[] is false
0=="foo" is true
if I cast to boolean then it makes sense again
""==(bool)[] is true
0==(bool)[] is true
I would expect an empty array to be "equal" to an empty string or to the integer 0. And I wouldn't expect that the integer 0 would be "equal" to the string "foo". To be honest, I am not really understanding what PHP is doing behind the scenes. Can someone please explain to me what is going on here?
The simple answer is that this is the way php has been designed to work.
The outcomes are well defined in the docs comparison operators and comparison tables.
A == comparison between an array (your first two queries) and a string always results in false.
In a == comparison between a number and a string (your third query) the string is converted to a number and then a numeric comparison made. In the case of 0=='foo' the string 'foo' evaluates numerically to 0 and the test becomes 0==0 and returns true. If the string had been 'numeric' e.g. "3" then the result in your case would be false (0 not equal to 3).
Whether the design is "correct" (whatever that may mean) is arguable. It is certainly not always immediately obvious. An illustrative example of the potential fury of the debate can be found in Bug#54547 where the devs argue strongly that the design is rooted in php's history as a web language where everything is a string and should be left alone, and others argue php "violates the principle of least surprise".
To avoid uncertainty use === wherever possible, with the added benefit of potentially showing up assumptions in your code that may not be valid.
As someone has already said, the PHP automatic casting rules can be quite tricky, and it is worth using === unless you know both sides will be of the same type. However I believe I can explain this one:
""==[] (returns false)
The initial string "" indicates the comparison will be a string one, and thus [] is cast to a string. When that happens, the right hand side of the comparison will be set to the word Array. You are therefore doing this comparison:
"" == "Array" (returns false)
and thus false is the correct result.
Edit: a helpful comment below casts doubt on my answer via this live code example. I should be interested to see what other answers are supplied.

Changing database value to false doesn't change result

I have this code
if (true == $run_user['online'] {
$result = 'Online now!';
} else {
$date = $run_user['lastloggedin'];
$result = Agotime($date);
}
$run_user is to check the database by the way
So whenever I change the value in the database to false, it will still just result "Online Now!" Instead of saying what it's supposed to say, which is for example 1 hour ago.
#John Conde had it right, but I can expound on what is actually happening.
In PHP there are certain things that will be left for interpretation. Boolean checks are one of those things. Here is a couple lists of things that will be interpreted in a Boolean check:
These will be interpreted as TRUE
Boolean true, of course
Non-empty strings
Any non-zero integer
A function, object or array
These will be interpreted as FALSE
Boolean false
The integer 0
An empty string
null
The not (!) character followed by an interpreted true or Boolean true
These might be confusing at times, but the best thing to do for checking is to make sure you know what type of variables you are passing into the conditional. Sometimes it may be useful to use a strict comparator like so:
if(true === $variable){ ... }
The third equal sign will tell PHP to only interpret this as true/false if it is EXACTLY what I am comparing it to. So $variable = true; would work, but $variable = 1; would not. Without the strict comparator, both versions would work. This issue comes into play a lot when you are working with integers where 0 needs to be interpreted as true and null should be false.

Which one is the right and better way of setting a True value as a function argument

Following are two line of code, please observe them.
$client->setWatermarkInBackground('True');
$client->setWatermarkInBackground(True);
From the code lines you might have an idea that I want to send a value True as an argument.
But I'm not getting the difference between above two statements. Can anyone explain me the difference between two statements and which one is correct or wrong? If both the ways are correct then which statement is better to use? etc. Please explain me. Thanks in advance.
$client->setWatermarkInBackground('True');
You're setting the value true as a string and not the correct Boolean.
You should set it like this (2nd method) as to set boolean ( 0/1 ).
$client->setWatermarkInBackground(True);
Allowing you to do something like:
if($client->setWatermarkInBackground()) {
// is true do whatever you need?
}
There is no difference, since PHP promotes the undefined name True to the string "True". You should instead be using the lowercase literal true
'True' is the string True, in english.
True is the boolean value that means true for the computer.
Although PHP is very good and understands both as the computer value, there are some differences:
When using the test if ($client->getWatermarkInBackground() === true), the first line will return false, because the triple = means "Same value and same type", which is not the case, a string doesn't equal a boolean.
When displaying it with echo $client->getWatermarkInBackground(), the second line will return 1, because it's how the computer understands the value true.
Which one to choose? Well, speak to the computer in its language, it's better, mostly for the programmer who will look at your code (or yourself): if you use 'True', I understand you want to display the string, if you use true, I understand you want to use it in some test later on.
Most functions you will see in PHP are smart enough to parse strings; therefore, when you pass "True" to a function, it will parse it and evaluate it as a boolean value, true.
However, this is bad practice and can cause some errors.
If you want to be correct in all cases, do not use any quotes.
true --> boolean value
"true" --> string
Edit
According to php.net,
var_dump((bool) "false"); // bool(true)
Casting from "false" to a boolean value will give you a true boolean value, therefore, you must be very careful; remember that the only thing that will cast to a boolean value false is the number 0 or an empty object.
Therefore, in all cases where possible, you should use true, with no quotes.
Any string will always evaluate to true (i.e. a string is a non zero value). Therefore "false" is also true, strictly speaking. Essentially, by using "true", you are evaluating to true almost by luck.
Stick with
function(true) and function(false)
Instead of
function("true") and function("false")

if($val) vs. if($val != "") vs. if(!empty($val)) -- which one?

I see a lot of people using a variety of different methods to check whether of a variable is empty, there really seems to be no consensus. I've heard that if($foo) is exactly the same as if(!empty($foo)) or if($foo != ""). Is this true?
I realize it's a really simple question, but I'd really like to know. Are there any differences? Which method should I use?
Difference between bare test and comparison to empty string
if($foo != "") is equivalent to if($foo) most of the time, but not always.
To see where the differences are, consider the comparison operator behavior along with the conversion to string rules for the first case, and the conversion to boolean rules for the second case.
What I found out is that:
if $foo === array(), the if($foo != "") test will succeed (arrays are "greater than" strings), but the if($foo) test will fail (empty arrays convert to boolean false)
if $foo === "0" (a string), the if($foo != "") test will again succeed (obviously), but the if($foo) test will fail (the string "0" converts to boolean false)
if $foo is a SimpleXML object created from an empty tag, the if($foo != "") test will again succeed (objects are "greater than" strings), but the if($foo) test will fail (such objects convert to boolean false)
See the differences in action.
The better way to test
The preferred method to test is if(!empty($foo)), which is not exactly equal to the above in that:
It does not suffer from the inconsistencies of if($foo != "") (which IMHO is simply horrible).
It will not generate an E_NOTICE if $foo is not present in the current scope, which is its main advantage over if($foo).
There's a caveat here though: if $foo === '0' (a string of length 1) then empty($foo) will return true, which usually is (but may not always be) what you want. This is also the case with if($foo) though.
Sometimes you need to test with the identical operator
Finally, an exception to the above must be made when there is a specific type of value you want to test for. As an example, strpos might return 0 and also might return false. Both of these values will fail the if(strpos(...)) test, but they have totally different meanings. In these cases, a test with the identical operator is in order: if(strpos() === false).
No it's not always true. When you do if($foo) PHP casts the variable to Boolean. An empty string, a Zero integer or an empty array will then be false. Sometimes this can be an issue.
You should always try to use the most specific comparison as possible, if you're expecting a string which could be empty use if($foo==='') (note the three equal signs). If you're expecting either (boolean) false or a resource (from a DB query for instance) use if($foo===false){...} else {...}
You may read the documentation about casting to boolean to find the answer to this question. There's a list in there with which values are converted to true and false, respectively.
Note that empty also checks if the variable is set, which regular comparison does not. An unset variable will trigger an error of type E_NOTICE during comparison, but not when using empty. You can work around this using the isset call before your comparison, like this:
if(isset($foo) && $foo != '')
if() "converts" the statement given to a bool, so taking a look at the documentation for boolean seems to be what you're looking for. in general:
empty strings (""), empty arrays (array()), zero (0) and boolean false (false) are treated as false
everything else ("foo", 1, array('foo'), true, ...) is treated as true
EDIT :
for more information, you could also check the type comparison tables.
empty($foo) should return true in all of these cases: 0,"", NULL.
For a more complete list check this page: http://php.net/manual/en/function.empty.php
No, it's not equal. When variable is not defined, expression without empty will generate notice about non-defined variable.

Categories