What's better, isset or not? - php

Is there any speed difference between
if (isset($_POST['var']))
or
if ($_POST['var'])
And which is better or are they the same?

It is a good practice to use isset for the following reasons:
If $_POST['var'] is an empty string or "0", isset will still detect that the variable exists.
Not using isset will generate a notice.

They aren't the same. Consider a notional array:
$arr = array(
'a' => false,
'b' => 0,
'c' => '',
'd' => array(),
'e' => null,
'f' => 0.0,
);
Assuming $x is one of those keys ('a' to 'f') and the key 'g' which isn't there it works like this:
$arr[$x] is false for all keys a to g;
isset($arr[$x]) is true for keys a, b, c, d and f but false for e and g; and
array_key_exists($x, $arr) is true for all keys a to f, false for g.
I suggest you look at PHP's type juggling, specifically conversion to booleans.
Lastly, what you're doing is called micro-optimization. Never choose which one of those by whichever is perceived to be faster. Whichever is faster is so negligible in difference that it should never be a factor even if you could reliably determine which is faster (which I'm not sure you could to any statistically significant level).

isset tests that the variable has any value, while the if tests the value of the variable.
For example:
// $_POST['var'] == 'false' (the string false)
if (isset($_POST['var'])) {
// Will enter this if
}
if ($_POST['var']) {
// Won't enter this one
}
The big problem is that the equivalency of the two expressions depends on the value of the variable you are checking, so you can't make assumptions.

In strict PHP, you need to check if a variable is set before using it.
error_reporting(E_ALL | E_STRICT);
What you are doing here
if($var)
Isn't checking if the value is set. So Strict PHP will generate a notice for unset variables. (this happens a lot with arrays)
Also in strict PHP (just an FYI for you or others), using an unset var as an argument in a function will throw a notice and you can't check isset() within the function to avoid that.

Just repeating what others said, if you execute:
if($variable)
and $variable is not set, you'll get a notice error. Plus..
$var = 0;
if($variable) {
//This code will never run, because $var is false
}
but using isset would return true in this case.

Related

Why empty('0') = true; empty('00') = false;

I eval $var using
if(empty($_GET['var'])){
...
}
I take TRUE from
https://myweb.com/?var=0
I take FALSE from
https://myweb.com/?var=00
The empty pseudo-function shares its logic with casting to boolean - if something is equivalent to "false", it is considered "empty".
The list of values which are considered "empty" is intended to be helpful, but is occasionally confusing, because there isn't really one perfect answer. Starting off with integers, it seems reasonable that 0 is "empty", but for instance 1 is not. Because user input almost always comes in the form of strings (particularly on the web, where PHP is most at home), it's also useful for the string "0" to behave the same as the integer 0.
On the face of it, "00" should also be equivalent to 0, and therefore "empty", but now things start getting messy: if you convert the string "hello" to an integer, that is also 0, so is "hello" also empty? That wouldn't be very useful.
The truth is, casts such as this can only really work one of two ways:
Throw an error on any conversion which is not 100% unambiguous.
Pick a set of compromises which is mostly useful, but not entirely consistent.
PHP picked the second route, and the difference between empty("0") and empty("00") is one of the side effects of the particular compromise chosen. Other languages which took a similar route (e.g. Perl, JavaScript) have different compromises, with different surprising outcomes.
See also my answer to a similar question here.
Because 0 gives empty in PHP if you check without type, but I think 00 type-cast to a string value and thus it's not empty.
You can strict check with type via the operator ===
I think it's probably because you are receiving the 00 as string value in your code. Because 0 and 00 are both considered as empty by the empty function in PHP. Try executing the code below in one of your PHP's to understand better. You can even check out the sandbox link.
<?php
$a = 0;
$b = 00;
$c = '00';
if(empty($a)) echo 'empty a';
if(empty($b)) echo 'empty b';
if(empty($c)) echo 'empty c';
?>
Check the documentation of empty() function, there are a list of values that are considered as empty by it.
The empty() function checks whether a variable is empty or not.
This function returns false if the variable exists and is not empty,
otherwise it returns true.
The following values evaluates to empty:
0
0.0
"0"
""
NULL
FALSE
array()
Additionally, when you are dealing with numeric check, you should always typecast the value to integer and then compare if it's 0 or not. This would be the ideal approach.
<?php
$a = 0;
$b = '0';
$c = '00';
$d = 1;
$e = '1';
if(!intval($a)) echo 'empty a ';
if(!intval($b)) echo 'empty b ';
if(!intval($c)) echo 'empty c ';
if(!intval($d)) echo 'empty d ';
if(!intval($e)) echo 'empty e ';
?>

difference between $a==5 and 5==$a in php

Today I have faced a question, I was unable to answer it,
I have tried by making a php program but was unable to find out the exact reason for it
if $a=5 then both($a==5 and 5==$a) are giving me output as boolean true and,
if $a != 5 then both ($a==5 and 5==$a ) are giving me output as boolean false
Can anyone tell me what is the difference between $a==5 and 5==$a from any language point of view.
**Program**
$a = 3;
var_dump( 5==$a );
var_dump( $a==5 );
$a = 5;
var_dump( 5==$a );
var_dump( $a==5 );
**Output**
boolean false
boolean false
boolean true
boolean true
Comparisons like that are not affected by which value you write first. However, it is best practice to put the literal first, e.g. 5 == $x because if you mess up and only enter one equals sign, you'll get an error instead of an accidental value assignment, which is far easier to debug.
No difference
but 5 == $a prevents some error if you forgot one '='.
For example $a = 1
if you write if ($a = 5) - $a value becomes 5
if you write if (5 = $a) - you got error
It's just a technique, that prevents you from accidentally using assignment instead of comparison. The if operator happily accepts $a = 5, while 5 = $a throws an error, preventing you from creating a nasty bug.
5 == $a is logically the same as $a == 5
This format, commonly referred to as yoda conditions and does not affect the logical comparison.
https://en.wikipedia.org/wiki/Yoda_conditions
It is preferred, commonly in PHP, to prevent accidental assignment in conditions, which will always evaluate as either truthy or falsy, but will not actually perform the indented condition check:
if ($a = 5) {
// always run... oops
} else {
// never run
}
The WordPress PHP Coding Standards have a good explanation of this as well

Using Eval to perform if comparison of strings in PHP

I have some code that looks like this.
eval('$ruleTrue = '."{$value} {$operator} {$value2};");
I am pulling mostly numeric values from a database and comparing them with other numeric values. The operator comes from a database as well. Possible operators are <,>,==.
Well when comparing ints and floats this works perfectly. BUT when comparing strings it breaks. For instance..
WORKS:
5 > 4
$ruleTrue = true
Doesn't Work Right:
John-Adams == Alice
$ruleTrue = true <--- WHY? Because John is not == to Alice.
For some reason my $ruleTrue variable is being returned as true when comparing strings.
You're trying to evaluate this code:
$ruleTrue = John == Alice;
John and Alice aren't strings, they're undefined constants. You want to put quotes around them. But be careful, because if your users are able to edit those fields in your database, they could find a way of unquoting the strings and executing their own php code, which could be disastrous. Eval is very unsecure that way, and you probably shouldn't be using it.
The expression John-Adams == Alice parses somewhat like (John - Adams) == Alice. The left side is trying to subtract two strings (undefined constants are considered 'barewords', and are equal to a stringification of their names; John === 'John', for example), and in order to make sense of such an odd operation, PHP turns both strings into numbers. As integers, both strings have a value of 0, so the left side equates to 0.
An int.
Now, when PHP wants to compare with ==, it wants to coerce both sides into the same type. In this case, it's converting to int. Alice also converts to 0. Both sides being 0, they're "obviously" equal.
In order to prevent this from happening, you should probably put quotes around your values. You might also consider using the strict equals operator (===), unless you really want that type coercion magic.
Alternatively, if you have a known set of operators, you can eliminate eval and make this safer and more robust all around, by making a comparison function that has sub-functions for the operators. Like so:
function compare($value1, $op, $value2) {
static $known_ops = array(
'==' => function($a, $b) { return $a == $b; },
'!=' => function($a, $b) { return $a != $b; },
...
# you can even make up your own operators. For example, Perl's 'eq':
'eq' => function($a, $b) { return "$a" === "$b"; }
...
);
$func = $known_ops[$op];
return $func($value1, $value2);
}
...
$ruleTrue = compare($value, $operator, $value2);
Now you don't have to worry about your values. You do have to worry about $operator, but that's only an issue if you let a user input it without you validating it. In which case, you may want to throw an exception or something if $op wasn't in $known_ops, cause if you leave PHP to handle it, you'll likely get a fatal error when it tries to call null.
Make sure, if the value are strings, they are surrounded with "quotes"

PHP: Faster to check if variable is integer or starts with #

I'm developing a module with some arrays in it.
Now my array contains:
$omearray = array (
'#title' = 'title',
0 = array ( 'another array', '2ndvalue', ),
);
foreach($omearray as $key => $value)
When I load the array to display I want to check whether the $key value is a 0, 1, 2, 3, etc. or a $key value that starts with a #.
Which would be better to use: checking if the value is_int() or a regex that checks whether the first character is a #?
EDIT: checking stringpos 1 is # vs is_int() since regex seems to be slow.
Since if ($key[0]=='#') is faster and is_int() is exhaustive, and || is a short circuit operator with left associativity (evaluates from left to right, see example 1 on http://php.net/manual/en/language.operators.logical.php) I would say:
if ($key[0]=='#' || is_int($val)) /* etc */
Because this way you only need to bother about using the # key naming self made convention with the keys you'll compare so much that you'd benefit from an optimization.
But unless you're making a huge number of evaluations I would stick to just if(is_int($val)), because it's clearer and less messy.
I would check it using if($key[0]=="#")
You can also check if the $value is an array (is_array($value)), in this case you dont need either regex,is_int, and # char.
PS: # character means (somewhere) "I'm a number/ID"
if (is_int($val) || $val{0} == '#') ...
I would go for the is_int(), because you are not dependent on the string. It can be anything and your code will still just take the integer indeices. Looking for # as the first character will prevent that flexibility. But if you are absolutely sure that the string's first character will always be a #, than the $Key[0] == '#' will be the fastest option.
You haven't given much insight into your actual data or reason for choosing this structure, but depending on that info, altering your structure so that you aren't inter-mixing integer indexes with hash keys may be an option:
$omearray = array(
'#title' => 'title',
'foo' => array(
'anotherarray',
'2ndvalue'
)
);
foreach ($omearray as $key => $value) {
if ($key == 'foo') {
// do something with $value, which is the 2nd array, numerically indexed
}
}
Apologies if this solution doesn't suit your needs.
You can check if string is integer
or if it starts with #
or both
or whatever.
It's all makes not a slightest difference.
It is not a part of your code that may affect any performance issue ever.

Simplifing PHP or statements

Okay, I believe that I can simplify this line of code except I can't find anything online. Can anyone help me?
if(empty($action) || $action == "a" || $action == "b" || $action == "c") {
}
Thanks!
You can use in_array() to search an array of possible values for $action:
if (empty($action) || in_array($action, array('a', 'b', 'c'))) {
}
I keep the empty() condition separate because empty() tests true for a number of things besides the empty string ''.
If all you care is to test for the empty string, you can include it in in_array(), and get rid of that empty():
if (in_array($action, array('', 'a', 'b', 'c'))) {
}
Performantly, I think explicitly including empty() is a teeny weeny little bit better, due to short-circuiting.
$options = array("a", "b", "c");
if (empty($action) || in_array($action, $options) ) {
}
I suggest you don't simplify this code because you may gain some kind of readability but you would also increase computation time. And that's a thing I would prefer to improve more than readability (code is executed a lot more often than read in plain text).
Why is that?
An expression like yours consisting only of or conjunctions will end right the moment the first 'true' value is found. So in best case PHP will just evaluate empty($action) with true and leave the if-header without evaluating all the other parts. In worst case it will check every part till the end. So in average - without further knowlege about the data you will check - you are running and computing half of the if-header.
But if you use something like in_array($action, array('a', 'b', 'c')) than you will construct the whole array with all elements and search in it. So your PHP interpreter has to create all the elements and the array just to match one of the first ones. Which is anyway more computation than your current line.
So think twice about readabilty vs. code complexity.
if (empty($action) || preg_match('/^[abc]$/', $action)) { ... }
Edit: empty($action) is needed to allow false, array(), 0, and null to pass which you may not want.

Categories