Let's say I have a variable that will always be a string.
Now take the code below:
if($myVar === "teststring")
Note: $myVar will always be a string, so my questions is
Which is quicker/best, using === (indentity) or the == (equality)?
Testing for identity is always faster, because PHP does not have to Type Juggle to evaluate the comparison. However, I'd say the speed difference is in the realms of nanoseconds and totally neglectable.
Related reading:
PHP type comparison tables
Type Juggling
=== will be slightly faster, but more importantly, It enforces that $myVar will be a string so you don't have to worry about the possible effects of it being some other type.
In general when I code, I use == over ===, however, using the identity is more precise, and also, slightly faster (difference is minimal).
The difference between the two is likely irrelevant for whatever you need.
Related
I'm new to PHP and I just ran across a day-wasting bug because I didn't realize that the PHP == operator does type coercion similar to Javascript.
I know that Douglas Crockford recommends never using the == operator with Javascript, and to always use the === operator.
If I code in a manner that never assumes type coercion, can I use the same advice in PHP, and never use the == operator? is it safe to always use the === operator, or are there gotchas that I need to be aware of?
You should use === by default (to avoid the problems you just encountered) and use == when needed, as a convenience.
For instance, you may be taking parameters from $_GET or similar, and a parameter might be the string true or false, vs the boolean true or false. Personally, I check everything, but there can be legitimate use cases for == if you are conscious of it, and careful with use.
== and ===, exist for specific reasons. As you've already mentioned in your post, == does type coercion.
I come from a strongly typed programming background, and thus never require type coercion, quite like you. In this case, it is safe to always use ===.
Of course, when you do require coercion, use ==.
In case of inputs you have no control over (GET/POST parameters, API responses) you could either use == or use casting.
var_dump('1' == 1); return bool(true) and var_dump('1' === 1); return bool(false) because they have the same value but different types. One is string and other is int.
Only use === if you know the type you are checking.
I've always came away from stackoverflow answers and any reading I've done that "===" is superior to "==" because uses a more strict comparison, and you do not waste resources converting value types in order to check for a match.
I may be coming at this with the wrong assumption, so I assume part of this question is, "is my assumption true?"
Secondly,
I'm dealing specifically with a situation where I'm getting data from a database in the form of a string "100".
The code I am comparing is this...
if ($this->the_user->group == 100) //admin
{
Response::redirect('admin/home');
}
else // other
{
Response::redirect('user/home');
}
vs.
if ( (int) $this->the_user->group === 100) //admin
{
Response::redirect('admin/home');
}
else // other
{
Response::redirect('user/home');
}
or even
if (intval($this->the_user->group) === 100) //admin
{
Response::redirect('admin/home');
}
else // other
{
Response::redirect('user/home');
}
is any integrity (or performance) gained by manually casting or converting simply so you can use the identity ('===') comparison?
In your particular case == is the better option. As you (as can be seen in your code) have probably already found out many database functions will always return strings, even if you fetch an integer. So type strict comparison really only bloats your code.
Furthermore you are adding a potential (let's call it theoretic) security risk. E.g. (int) '100AB2' would yield 100. In your case this probably can't happen, but in others it may.
So: Don't overuse strict comparison, it's not always good. You mainly need it only in ambiguous cases, like the return value of strpos.
There is a performance difference between == and === - latter will be even twice as fast, see Equal vs identical comparison operator.
The difference, however is too small to be bothered with - unless the code is executed millions of times.
That's a really tiny optimization you're doing there. Personally, I don't think it's really worth it.
Any boost you gain from not casting the value when using === is lost when you explicitly cast the value. In your case, since the type is not important to you, you should just do == and be done with it.
My recommendation would be to keep === for when you need to check type as well - e.g. 0 evaluating to false and so on.
Any performance gains will be microscopically small, unless you're performing literally billions and trillions of these comparisons for days/months/years on-end. The strict comparison does have its uses, but it also is somewhat of anomally in PHP. PHP's a weakly typed language, and (usually) does the right thing for auto-converting/casting values to be the right thing. Most times, it's not necessary to do a strict comparison, as PHP will do the right thing.
But there are cases, such as when using strpos, where the auto-conversion will fail. strpos will return '0' if the needle you're searching is right at the start of the haystack, which would get treated as FALSE, which is wrong. The only way to handle this is via the strict comparison.
PHP has some WTF loose comparisons that return TRUE like:
array() == NULL
0 == 'Non-numeric string'
Always use strict comparison between a variable and a string
$var === 'string'
Often when I am writing PHP I construct conditionals like this:
if(1 === $var1
and 2 === $var2
or 1 == $var3) {
// do something here maybe
}
I think it makes them easier and more natural to read. I know this is probably laughable when I am using Yodas though.
The reason I have each condition on its own line prefaced by and or or is because it makes it easier to comment part of the statement out when debugging.
Is there any disadvantage to doing this compared with the "usual" || and &&?
or and and do not have the same operator precedence as || and &&. This means that in for certain values of expressions[a] and [b], [a] and [b] != [a] && [b]. This may create non-obvious bugs.
Note that one is higher precedence than assignment, while the other is not. This is a subtle difference, and even if you understand it, other developers reading your code may not. As a result, I personally recommend using only && and ||
Ruby's operators are similar to PHP's in this regard. Jay Fields published a simple example of the difference.
There's no significant functional difference in PHP between and and &&, nor betweeen or and ||.
The only difference between them is that they are considered as different operators, and have different positions in the order of operator precedence. This can have a big impact on the results of complex operations if you neglect to wrap things in brackets.
For this reason, it is generally a good idea to use one or other style of operators, and stick with it, rather than mixing between the two in the same code base (this is also a good idea for readability). But the choice if which pair of operators to use is fairly immaterial.
Other than that, they are basically the same thing.
See here for the PHP operator precedence: http://php.net/manual/en/language.operators.precedence.php
(note the different positions in the table of the and and or vs && and ||)
I know that for instance, using:
if (in_array('...'), array('.', '..', '...') === true)
Over:
if (in_array('...'), array('.', '..', '...') == true)
Can increase performance and avoid some common mistakes (such as 1 == true), however I'm wondering if there is a reason to use strict comparisons on strings, such as:
if ('...' === '...')
Seems to do the exactly same thing as:
if ('...' == '...')
If someone can bring some light to this subject I appreciate it.
If you know both of the values are guaranteed to be strings, then == and === are identical since the only difference between the two is that === checks to see if the types are the same, not just the effective values.
However, in some cases you don't know for sure that a value is going to be a string - for example, with things like the $_GET and $_POST variables. Consider the following:
$_GET['foo'] == ""
The above expression will evaluate to true if foo was passed in as a blank string, but it will also evaluate to true if no value was passed in for foo at all. In contrast,
$_GET['foo'] === ""
will only evaluate to true if a blank string was explicitly passed in - otherwise the value of $_GET['foo'] might be equivalent to a blank string, but the type would not be since it would actually be an empty value for that index, not a string.
When you can use one or the other choose the strict comparison because:
It has better performance
It prevents unexpected results
When comparing strings you can still have unexpected results because a string could be empty or a variable you think is a string actually is not.
You would never use the comparison of two string literals because it can always be reduced to TRUE or FALSE. For example:
if ('...' === '...')
is the same as
if (TRUE)
So since you will always be comparing at least one variable you must assume that you can have unexpected results.
You can see benchmark results of various strict vs. loose comparisons at http://net-beta.net/ubench/. I have also ran my own tests and found the same results.
This is a micro optimization, which means you shouldn't go changing existing code because it isn't going to make a noticeable difference, but if you are writing new code you might as well practice using the most efficient techniques.
I have an interesting question about the way PHP evaluates boolean expressions. When you have, for example,
$expression = $expression1 and $expression2;
or
if ($expression1 and $expression2)
PHP first checks if $expression1 evaluates to true. If this is not the case, then $expression2 is simply skipped to avoid unnecessary calculations. In a script I am writing, I have:
if ($validator->valid("title") and $validator->valid("text"))
I need to have the second statement ($validator->valid("text")) evaluated even if the first one evaluates to false. I would like to ask you whether there is some easy way to force PHP to always evaluate both statements. Thank you!
$isValidTitle = $validator->valid("title");
$isValidText = $validator->valid("text");
if($isValidTitle && $isValidText)
{
...
}
Will that suit?
This is known as short circuit evaluation, and to avoid it you need to do this, using a single &:
if($validator->valid("title") & $validator->valid("text")) {
}
Note that this is not using logical operators but actually bitwise operators:
They're operators that act on the binary representations of numbers. They do not take logical values (i.e., "true" or "false") as arguments without first converting them to the numbers 1 and 0 respectively. Nor do they return logical values, but numbers. Sure, you can later treat those numbers as though they were logical values (in which case 0 is cast to "false" and anything else is cast to "true"), but that's a consequence of PHP's type casting rules, and nothing to do with the behavior of the operators.
As such, there is some debate as to whether it is good practice to use this side effect to circumvent short-circuit evaluation. I would personally at least put a comment that the & is intentional, but if you want to be as pure as possible you should evaluate whether they are valid first and then do the if.
try to evaluate each term separately:
$term1 = $validator->valid("title");
$term2 = $validator->valid("text");
if($term1 && $term2) {
//things to do
}
This might not be the best implementation, but you could always do:
$a=$validator->valid("title");
$b=$validator->valid("text");
if($a && $b) {...}
You can define a function like:
function logical_and($x,$y) {return ($x && $y);}
Since PHP uses call-by-value, this works.
Alternatively, if you can modify the class $validator instantiates, you could make the valid method accept a string or an array. If it's an array, it runs the code that already exists on each item and only returns TRUE if all items are "valid".