&& and || conditions in single IF Condition in PHP - php

I want to check whether the length of $a is 0 or if the length is not 0 then check if it is a numeric value in single IF statement in PHP. I tried this but not working
$a = '23bc';
if((strlen($a)===0 || (strlen($a)>0 && ctype_digit($a))) )
{
echo 'Good to Go';
}
else
{
echo 'Bad to Go';
}
I do not want to apply nested conditions here. Is it possible to do it in single IF statement?
I found this question here but this does not answers what I am asking for && (AND) and || (OR) in IF statements

It would be nice to know what your script is trying to achieve beyond using a one-liner in an if conditional concerning an empty string or a numeric string. With cytpe_digit() every character must evaluate as a number to qualify as a numeric string. You get a false result with '23bc' because of the 'bc' portion.
One of the problematic aspects with the script is that one don't know which condition results in a true. One or the other conditions could be true or they could both be false.
See demo: http://3v4l.org/8Pchk.
You could rewrite the code making use of a ternary expression to have a one liner which eliminates the if-else construct, as follows:
<?php
$a = '23bc';
if( strlen( $a ) != 0) {
echo ctype_digit( $a )? "Good to Go\n" : "Bad to Go\n";
}
The following may be more in line with what you're asking. Here's the ultimate one-liner:
<?php
echo ( !strlen($a) || ctype_digit($a) )? "Good to Go\n" : "Bad to Go\n";
Because of the strictness of the identity operator === if $a is null, then you you'll see "Bad to Go. You may either test for equality strlen($a) == 0 or you can be more succinct by using the ! operator (boolean NOT). See demo: http://3v4l.org/7cfV0

Related

Unexpected behaviour of "!print("1") || 1" in php

Example1:
if(!print("1") || 1){
echo "a";
}else{
echo "b";
}
Output
1b
The Example 1 is printing "1b" instead of "1a". According to me, inside if the final condition should be if(0 || 1) after solving !print("1").
But the Example 2 is printing "1a".
Example 2:
if((!print("1")) || 1){
echo "a";
}else{
echo "b";
}
Output
1a
Can you elaborate, why the or condition in the first statement didn't work.
The key thing here is to realise that print is not a function, and doesn't take arguments in parentheses - the parentheses aren't optional, they're just not part of the syntax at all.
When you write print("1"); the print statement has a single argument, the expression ("1"). That is if course just another way of writing "1" - you could add any number of parentheses and it wouldn't change the value.
So when you write print("1") || 1 the argument to print is the expression ("1") || 1. That expression is evaluated using PHP's type juggling rules as true || true which is true. Then it's passed to print and - completely coincidentally to what you were trying to print - is type juggled to the string "1".
The print statement is then treated as an expression returning true, and the ! makes it false, so the if statement doesn't run.
This is a good reason not to use parentheses next to keywords like print, require, and include - they give the mistaken impression of "attaching" an argument to the keyword.

how ordering makes a difference within an expression for an if statement

I have an array ...
$a= array(1,2,3,4);
if (expr)
{ echo "if";
}
else
{ echo 'else';
}
When expr is ( $a = '' || $a == 'false') , output is "if" ,
but when expr is ( $a == 'false' || $a = '' ) , output is "else"
Can anyone explain why & how ordering makes a difference ??
Edit : I understand that I am assigning '' to $a. That is not the problem. The real question is : What does the expression $a = '' return? And why does reversing the order of the 2 situations switch us from the IF section to the ELSE section?
AGAIN : I UNDERSTAND I AM ASSIGNING NOT COMPARING. PLEASE ANSWER THE QUESTION AS IS.
First, never use = as a comparison operator. It is an assignment operator.
The difference is that false (as a boolean) is not the same as 'false' as a string.
Certain expressions are type juggled by PHP to evaluate somewhat differently to how you would expect.
false==""
// TRUE.
false=="false"
// FALSE.
Additionally, when you try to compare numbers to strings, PHP will try to juggle the data so that a comparison will be performed. There is a lot to it (much more than I will post here) but you would do well to investigate type juggling and various operators. The docs are a great start for this. You should also have a read of the comparison operators which go into a lot of detail about how various comparisons will work (depending on whether you use == or === for example).
With $a = '' you are setting $a to an empty string. This is the same as:
$a = '';
if($a){
echo 'if';
}
The || operator checks if the first condition is true and if it is, it continues with the code in the brackets. In PHP, if $a is set to anything, it will return true. In the second case $a does not equal the string 'false' (you are not comparing it to a boolean false even!), so it executes the code in the else part.
And Fluffeh is not entirely correct. You can use the assignment operator in an if condition very effectively, you just have to be smart about it.
$a = '' is an assignment: you have, in error, used = in place of ==. Assignment is an expression which has the value of the thing your assigning.
A single equals sign = is the assignment opporator, so $a = '' is assigning an empty string to $a not checking if it is equal to.
In your 1st example you set the value of $a to an empty string, then check if it is false. An empty tring evalutes to false in php, so the conditional is true.
In your second example, you check if $a equals false 1st (when the value of $a is an array), so the conditional is false

Does PHP have short-circuit evaluation?

Given the following code:
if (is_valid($string) && up_to_length($string) && file_exists($file))
{
......
}
If is_valid($string) returns false, does the php interpreter still check later conditions, like up_to_length($string)?
If so, then why does it do extra work when it doesn't have to?
Yes, the PHP interpreter is "lazy", meaning it will do the minimum number of comparisons possible to evaluate conditions.
If you want to verify that, try this:
function saySomething()
{
echo 'hi!';
return true;
}
if (false && saySomething())
{
echo 'statement evaluated to true';
}
Yes, it does. Here's a little trick that relies on short-circuit evaluation. Sometimes you might have a small if statement that you'd prefer to write as a ternary, e.g.:
if ($confirmed) {
$answer = 'Yes';
} else {
$answer = 'No';
}
Can be re-written as:
$answer = $confirmed ? 'Yes' : 'No';
But then what if the yes block also required some function to be run?
if ($confirmed) {
do_something();
$answer = 'Yes';
} else {
$answer = 'No';
}
Well, rewriting as ternary is still possible, because of short-circuit evaluation:
$answer = $confirmed && (do_something() || true) ? 'Yes' : 'No';
In this case the expression (do_something() || true) does nothing to alter the overall outcome of the ternary, but ensures that the ternary condition stays true, ignoring the return value of do_something().
Bitwise operators are & and |.
They always evaluate both operands.
Logical operators are AND, OR, &&, and ||.
All four operators only evaluate the right side if they need to.
AND and OR have lower precedence than && and ||. See example below.
From the PHP manual:
// The result of the expression (false || true) is assigned to $e
// Acts like: ($e = (false || true))
$e = false || true;
// The constant false is assigned to $f before the "or" operation occurs
// Acts like: (($f = false) or true)
$f = false or true;
In this example, e will be true and f will be false.
Based on my research now, PHP doesn't seem to have the same && short circuit operator as JavaScript.
I ran this test:
$one = true;
$two = 'Cabbage';
$test = $one && $two;
echo $test;
and PHP 7.0.8 returned 1, not Cabbage.
No, it doesn't anymore check the other conditions if the first condition isn't satisfied.
I've create my own short-circuit evaluation logic, unfortunately it's nothing like javascripts quick syntax, but perhaps this is a solution you might find useful:
$short_circuit_isset = function($var, $default_value = NULL) {
return (isset($var)) ? : $default_value;
};
$return_title = $short_circuit_isset( $_GET['returntitle'], 'God');
// Should return type 'String' value 'God', if get param is not set
I can not recall where I got the following logic from, but if you do the following;
(isset($var)) ? : $default_value;
You can skip having to write the true condition variable again, after the question mark, e.g:
(isset($super_long_var_name)) ? $super_long_var_name : $default_value;
As very important observation, when using the Ternary Operator this way, you'll notice that if a comparison is made it will just pass the value of that comparison, since there isn't just a single variable. E.g:
$num = 1;
$num2 = 2;
var_dump( ($num < $num2) ? : 'oh snap' );
// outputs bool 'true'
My choice: do not trust Short Circuit evaluation in PHP...
function saySomething()
{
print ('hi!');
return true;
}
if (1 || saySomething())
{
print('statement evaluated to true');
}
The second part in the condition 1 || saySomething() is irrelevant, because this will always return true. Unfortunately saySomething() is evaluated & executed.
Maybe I'm misunderstood the exact logic of short-circuiting expressions, but this doesn't look like "it will do the minimum number of comparisons possible" to me.
Moreover, it's not only a performance concern, if you do assignments inside comparisons or if you do something that makes a difference, other than just comparing stuff, you could end with different results.
Anyway... be careful.
Side note: If you want to avoid the lazy check and run every part of the condition, in that case you need to use the logical AND like this:
if (condition1 & condition2) {
echo "both true";
}
else {
echo "one or both false";
}
This is useful when you need for example call two functions even if the first one returned false.

String comparison using '==' or '===' vs. 'strcmp()'

It seems that PHP's === operator is case sensitive. So is there a reason to use strcmp()?
Is it safe to do something like the following?
if ($password === $password2) { ... }
The reason to use it is because strcmp
returns < 0 if str1 is less than str2; > 0 if str1 is greater than str2, and 0 if they are equal.
=== only returns true or false, it doesn't tell you which is the "greater" string.
You should never use == for string comparison. === is OK.
$something = 0;
echo ('password123' == $something) ? 'true' : 'false';
Just run the above code and you'll see why.
$something = 0;
echo ('password123' === $something) ? 'true' : 'false';
Now, that's a little better.
Don't use == in PHP. It will not do what you expect. Even if you are comparing strings to strings, PHP will implicitly cast them to floats and do a numerical comparison if they appear numerical.
For example '1e3' == '1000' returns true. You should use === instead.
Well...according to this PHP bug report, you can even get 0wned.
<?php
$pass = isset($_GET['pass']) ? $_GET['pass'] : '';
// Query /?pass[]= will authorize user
//strcmp and strcasecmp both are prone to this hack
if ( strcasecmp( $pass, '123456' ) == 0 ){
echo 'You successfully logged in.';
}
?>
It gives you a warning, but still bypass the comparison.
You should be doing === as #postfuturist suggested.
Always remember, when comparing strings, you should use the === operator (strict comparison) and not == operator (loose comparison).
Summing up all answers:
== is a bad idea for string comparisons.
It will give you "surprising" results in many cases. Don't trust it.
=== is fine, and will give you the best performance.
strcmp() should be used if you need to determine which string is "greater", typically for sorting operations.
Using == might be dangerous.
Note, that it would cast the variable to another data type if the two differs.
Examples:
echo (1 == '1') ? 'true' : 'false';
echo (1 == true) ? 'true' : 'false';
As you can see, these two are from different types, but the result is true, which might not be what your code will expect.
Using ===, however, is recommended as test shows that it's a bit faster than strcmp() and its case-insensitive alternative strcasecmp().
Quick googling yells this speed comparison: http://snipplr.com/view/758/
strcmp() and === are both case sensitive, but === is much faster.
Sample code: Speed Test: strcmp vs ===
strcmp will return different values based on the environment it is running in (Linux/Windows)!
The reason is the that it has a bug as the bug report says - Bug #53999strcmp() doesn't always return -1, 0, or 1
You can use strcmp() if you wish to order/compare strings lexicographically. If you just wish to check for equality then == is just fine.
Also, the function can help in sorting. To be more clear about sorting. strcmp() returns less than 0 if string1 sorts before string2, greater than 0 if string2 sorts before string1 or 0 if they are the same. For example
$first_string = "aabo";
$second_string = "aaao";
echo $n = strcmp($first_string, $second_string);
The function will return greater than zero, as aaao is sorting before aabo.
if ($password === $password2) { ... } is not a safe thing to do when comparing passwords or password hashes where one of the inputs is user controlled.
In that case it creates a timing oracle allowing an attacker to derive the actual password hash from execution time differences.
Use if (hash_equals($password, $password2)) { ... } instead, because hash_equals performs "timing attack safe string comparison".
In PHP, instead of using alphabetical sorting, use the ASCII value of the character to make the comparison.
Lowercase letters have a higher ASCII value than capitals. It's better to use the identity operator === to make this sort of comparison. strcmp() is a function to perform binary safe string comparisons. It takes two strings as arguments and returns < 0 if str1 is less than str2; > 0 if str1 is greater than str2, and 0 if they are equal. There is also a case-insensitive version named strcasecmp() that first converts strings to lowercase and then compares them.

does the condition after && always get evaluated

I have this if statement that tests for the 2 conditions below. The second one is a function goodToGo() so I want to call it unless the first condition is already true
$value = 2239;
if ($value < 2000 && goodToGo($value)){
//do stuff
}
function goodToGo($value){
$ret = //some processing of the value
return $ret;
}
My question is about the 2 if conditions $value < 2000 && goodToGo($value). Do they both get evaluated or does the second one only get evaluated when the first one is true?
In other words, are the following 2 blocks the same?
if($value < 2000 && goodToGo($value)) {
//stuff to do
}
if($value < 2000) {
if (goodToGo($value)){
//stuff to do
}
}
No--the second condition won't always be executed (which makes your examples equivalent).
PHP's &&, ||, and, and or operators are implemented as "short-circuit" operators. As soon as a condition is found that forces the result for the overall conditional, evaluation of subsequent conditions stops.
From http://www.php.net/manual/en/language.operators.logical.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());
Yes. The two blocks are the same. PHP, like most (but not all) languages, uses short-circuit evaluation for && and ||.
The two blocks ARE same.
PHP logical operators are "lazy", they are evaluated only if they are needed.
The following code prints "Hello, world!":
<?php
$a = 10;
isset($a) || die ("variable \$a does not exist.");
print "Hello, world!"
?>
Other logical operators includes &&, and, or.
<?php
perform_action() or die ('failed to perform the action');
?>
is a popular idiom.
the second condition will only be checked if and only if first one is true, hence both statements are equivalent.
Yes, the 2 code blocks you gave are equivalent. PHP has short-circuiting, so when you use
|| and &&, any statement after the first only gets evaluated when necessary.
Always corelate your technical Language with your own language, Likewise here, If I say you in verbal conversation, its just like :You are asking= "if I am hungry '&&' I am eating Pizza" is similar to "If I am hungry then only i am eating Pizza"?
So here you can see that later phrase says that untill i am not hungry i am not eating pizza, and the former says I am humgry and I am eating pizza.
:-)

Categories