Simplifing PHP or statements - php

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.

Related

Is there a compelling reason to use PHP's operator === in comparison operations, over ==?

Say I have this code:
$str = '5';
$int = 5;
For comparison, is there any reason to use something like this (with conversion):
if ($int === intval($str)) //...
or do I just use native PHP facilities?
if ($int == $str) //...
To me, == looks simpler, perhaps at the expense of having PHP do the extra work for me.
Using '==' tends to lead to subtle bugs - eg if two strings look like numbers, PHP does not compare them as strings, which can give unexpected results - the most common/scary example is:
<?php
$actual_password = '240610708';
$provided_password = 'QNKCDZO';
// These would presumably be stored in your database
$stored_password_md5 = md5($actual_password); //0e462097431906509019562988736854;
$stored_password_hash = password_hash($actual_password, PASSWORD_DEFAULT);
$computed_password_md5 = md5($provided_password); //0e830400451993494058024219903391
var_dump($stored_password_md5 == $computed_password_md5); // bool(true) - BAD! NO!
var_dump($stored_password_md5 === $computed_password_md5); // bool(false) - Better, but still no. Vulnerable to timing attacks
var_dump(hash_equals($stored_password_md5, $computed_password_md5)); // bool(false) getting somewhere
var_dump(password_verify($provided_password, $stored_password_hash)); // bool(false) best
While in your specific example, this problem doesn't occur, the possible problems lead to a lot of people recommending to /always/ use ===, so you don't have to remember when == is safe and when it isn't.
Depends on what you are trying to do. Some functions might return false or 0 or a positive integer, like strpos(). 0 means the string was found at position 0 so == false would not work as === false.
In your scenario it is fine to use == as this is common when getting values from a DB or $_POST and $_GET, they will always be strings.
Thanks to the comment from Fred Emmott: Be careful, the following return true:
var_dump('0xa' == '10'); // 0xa hex 10 in decimal
var_dump('10pigs' == 10); // pigs truncated
See String conversion to numbers
The == operator just checks to see if the left and right values are equal. But, the === operator (note the extra “=”) actually checks to see if the left and right values are equal, and also checks to see if they are of the same variable type (like whether they are both booleans, ints, etc.).

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.

Is this Valid PHP? Complex If statement

can I do something like
if($x != (y&&z&&r&&w))
Or do I have to write it like this
if($x!=y && $x!=z && $x!=r && x!=w)
Just wondering because I have lots of variables to compare and just wanted a more elegant solution.
You might have a more elegant solution anyway. Here's what I'm trying to do.
foreach($_POST as $key => $value){
if($key != 'category_id'){
$cp[$key] = $value;
}
}
And I have about 6 more variables to compare in my $_POST statement and I would like to make the code pretty. It's basically a huge form that needs to format into a specific array ($cp[]) with specific keys to use my MySQL insert statement.
Any fancy ideas?
Your first portion of code :
if($x != (y&&z&&r&&w))
will evaluate the constants y, z, r and w (strings 'y', 'z', 'r' and 'w', if those constants don't exist) ; doing a AND between each one of those.
And, then, the result of this AND will be compared to $x -- which will be considered as a boolean.
So, no, it's not quite doing what you hoped for ; you must use your second portion of code :
if($x!=y && $x!=z && $x!=r && x!=w)
Note that here, too, it'll search for constants called y, z, r and w (or strings, if those constants still don't exist) -- you should probably put some $ in front of those, if you expect them to be treated as variables.
If you want to test if a variable has one of several values, a possible solution is to put those values into an array, and, then, use the in_array() function :
if (in_array($x, array(10, 20, 30) )) {
// $x is one of those values : 10, 20, 30
}
Some think it's easier to understand this way than writing several comparisons -- I sometimes use this myself, and kind of like it.
You'll have to write the long form or use in_array and an array containing your values.
You you can not do it like this:
if($x != (y&&z&&r&&w))
They have to be separated out in to 4 comparisons.
Alternatively, what you can do is stick the values in an array and have only 1 comparison:
$skip_keys = array('a', 'b', 'c', 'd');
foreach ($_POST AS $key => $value) {
if ( ! in_array($key, $skip_keys)) {
// Continue
}
}
You can't say
if ($x != (1&&2&&3))
like that
I also was wondering in my early years whether we can do
if (1 < $x < 5)
and the answer is no too. But you can use in_array() to test if something in an array for you to check several values at once:
http://php.net/manual/en/function.in-array.php
My recommendation, if you're doing this comparions multiple times, is to write a function that validates your requirements for it. So you'll pass in your '$x' and can compare that to everything you need, and will get a boolean result. The function can be structured nicely with ifs and elseifs and you'll keep your code cleaner.
So, example...
<?php
// random, bad logic, but you get the idea
function validateThisThing($x) {
$toReturn = false;
if ($x == 'this') {
$toReturn = true;
} elseif ($x == 'that') {
$toReturn = true;
}
return $toReturn;
}
Then you can just use that function as needed and keep your checks cleaner and more structured as your function name will bring context into what's being checked.

PHP best way to check whether a string is empty or not

I've seen a lot of php code that does the following to check whether a string is valid by doing:
$str is a string variable.
if (!isset($str) || $str !== '') {
// do something
}
I prefer to just do
if (strlen($str) > 0) {
// something
}
Is there any thing that can go wrong with the second method? Are there any casting issues I should be aware of?
Since PHP will treat a string containing a zero ('0') as empty, it makes the empty() function an unsuitable solution.
Instead, test that the variable is explicitly not equal to an empty string:
$stringvar !== ''
As the OP and Gras Double and others have shown, the variable should also be checked for initialization to avoid a warning or error (depending on settings):
isset($stringvar)
This results in the more acceptable:
if (isset($stringvar) && $stringvar !== '') {
}
PHP has a lot of bad conventions. I originally answered this (over 9 years ago) using the empty() function, as seen below. I've long since abandoned PHP, but since this answer attracts downvotes and comments every few years, I've updated it. Should the OP wish to change the accepted answer, please do so.
Original Answer:
if(empty($stringvar))
{
// do something
}
You could also add trim() to eliminate whitespace if that is to be considered.
Edit:
Note that for a string like '0', this will return true, while strlen() will not.
You need isset() in case $str is possibly undefined:
if (isset($str) && $str !== '') {
// variable set, not empty string
}
Using !empty() would have an important caveat: the string '0' evaluates to false.
Also, sometimes one wants to check, in addition, that $str is not something falsy, like false or null[1]. The previous code doesn't handle this. It's one of the rare situations where loose comparison may be useful:
if (isset($str) && $str != '') {
// variable set, not empty string, not falsy
}
The above method is interesting as it remains concise and doesn't filter out '0'. But make sure to document your code if you use it.
Otherwise you can use this equivalent but more verbose version:
if (isset($str) && (string) $str !== '') {
// variable set, not empty string, not falsy
}
Of course, if you are sure $str is defined, you can omit the isset($str) from the above codes.
Finally, considering that '' == false, '0' == false, but '' != '0', you may have guessed it: PHP comparisons aren't transitive (fun graphs included).
[1] Note that isset() already filters out null.
This will safely check for a string containing only whitespace:
// Determines if the supplied string is an empty string.
// Empty is defined as null or containing only whitespace.
// '0' is NOT an empty string!
function isEmptyString($str) {
return !(isset($str) && (strlen(trim($str)) > 0));
}
What about this:
if( !isset($str[0]) )
echo "str is NULL or an empty string";
I found it on PHP manual in a comment by Antone Roundy
I posted it here, because I did some tests and it seems to work well, but I'm wondering if there is some side effect I'm not considering. Any suggestions in comments here would be appreciated.
According to PHP empty() doc (http://ca1.php.net/empty):
Prior to PHP 5.5, empty() only supports variables; anything else will result in a parse error. In other words, the following will not work: empty(trim($name)). Instead, use trim($name) == false.
This simple old question is still tricky.
strlen($var) works perfectly ONLY if you're absolutely sure the $var is a string.
isset($var) and empty($var) result are based on type of the variable, and could be tricky at some cases (like empty string ""). View the table in this page for more details.
UPDATE
There are actually 2 cases for this question:
Case 1: You're sure that your variable is always going to be a "string":
In this case, just test the length:
if(strlen($str) > 0) {
// do something..
}
Case 2: Your variable may and may not be a "string":
In this case, it depends on what you want to do. For me (most of the time), if it's not a string then I validate it as "false". You can do it this way:
if(is_string($var) && $var !== '') {// true only if it's a string AND is not empty
// do something ...
}
And to make it shorter and in 1 condition instead of 2 (specially useful if you're testing more than 1 string in same if condition), I made it into function:
function isNonEmptyString($var) {
return is_string($var) && $var !== '';
}
// Somewhere else..
// Reducing conditions to half
if(isNonEmptyString($var1) && isNonEmptyString($var2) && isNonEmptyString($var3)) {
// do something
}
If your variable $str is not defined then your strlen() method will throw an exception. That is the whole purpose of using isset() first.
trimming the string will also help if there are string with white spaces.
if (isset($str) && trim($str) !== '') {
// code
}
I think not, because strlen (string lenght) returns the lenght (integer) of your $str variable.
So if the variable is empty i would return 0. Is 0 greater then 0. Don't think so.
But i think the first method might be a little more safer. Because it checks if the variable is init, and if its not empty.

What's better, isset or not?

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.

Categories