PHP If Statement not working correctly, not null - php

I'm struggling to understand why my if statement below always results in false. I am creating a function which will test incoming connections to a script which will reject connections made by certain bots.
In my test below, on applying the if logic, I'm expecting a TRUE as both the array $value and $test value should match... resulting in a NOT NULL?
$bots = array(0 => "PaperLiBot", 1 => "TweetmemeBot", 2 => "Appsfirebot", 3 => "PycURL", 4 => "JS-Kit", 5 => "Python-urllib");
$test = strtolower("PaperLiBot");
foreach($bots as $value)
{
$i = strtolower(strpos($value, $test));
if ($i != NULL)
{
echo "Bot is found";
exit;
}else
{
echo "not found";
}
}

I think you are trying to accomplish this
foreach($bots as $value)
{
$i = strpos(strtolower($value), $test);
if ($i !== false){
echo "Bot is found";
exit;
}else{
echo "not found";
}
}

you want to write:
if(stristr($value, $test)){
// found
}else{
// not found
}

null in PHP is mutually type-castable to '0', '', ' ', etc... You need to use the strict comparisons to check for a 0-based array index:
if ($i !== NULL) {
...
}
note the extra = in the inequality operator. It forces PHP to compare type AND value, not just value. When comparing value, PHP will typecast however it wants to in order to make the test work, which means null == 0 is true, but null === 0 is false.

the correct way to check if a variable is set to NULL is:
if(!is_null($var)){
[my code]
}
the strpos returns a boolean, not a NULL value.
if you are unsure of the content of a variable, you can always debug it with a simple
var_dump($var);

Related

Boolean from MySQL to PHP - Conversion to tinyint and comparing

My database has multiple boolean values. After I saved the database, the booleans got converted into tinyint(1). I think this is because it just needs to save 1 or 0.
However, I now have a problem comparing the value in PHP. I saved the tinyint into an array without any code-wise conversion. The array has multiple entries that are text and date and multiple entries with booleans, for example:
array[0] is '09:45:00'
array[1] is '10:45:00'
array[2] is 1
array[3] is 0
array[4] is 0
array[5] is 1
array[6] is 'active'
Now if I loop through the array I want to check if the value is a time, a text, or true/false.
Checking if the entry is true will always return true, because no entry is empty. Checking if the entry is 1 or 0 works for the boolean, but when I check if 'active' == 0 it is returning true. Why is this the case and how can I get a false if I compare a string with a tinyint?
Comparing with === does not work in any case.
I think u can do this with some nested if-else statements. But I'm pretty sure there is a better-looking solution too. :)
$a=array('09:45:00','10:45:00',1,0,0,1,'active',3.12);
foreach ($a as $value) {
$type= gettype($value);
if ($type == "string") {
if(strtotime ($value)){
echo "$value is 'Time' \n";
}
else{
echo "$value is 'String' \n";
}
} elseif ($type == "integer") {
if($value == 0 || $value == 1){
echo "$value is 'Boolean' \n";
}
else{
echo "$value is 'Integer' \n";
}
} else{
echo "$value is ($type)!";
}
}

filter_input with 0 returns false

I'm using filter_input now and I want it to return true on every number (0-9) and false on non-numbers (a-z, A-Z etc..)
Now, I use this script (just an example script but the idea is the same):
<?php
$i = filter_input(INPUT_GET, 'i', FILTER_SANITIZE_NUMBER_INT);
if ($i)
{
echo 'good';
}
else
{
echo 'bad';
}
If I use 1-9 as GET variable (so like test.php?i=1), it shows good.
If I use a-Z as GET variable (so like test.php?i=a), it shows bad. So far so good.
But if I use 0 as GET variable, it shows bad as well. The variable can be 0 and should be true when the GET variable is 0.
Can anybody explain me why 0 returns false? I mean the GET variable is set and 0 is a number. Is it just because 0 is a falsey value?
0 is a falsey value in PHP. if (0) is false.
Further, you're using the sanitisation filter, which will basically never fail. You want to use FILTER_VALIDATE_INT to validate whether the input is an integer.
Further, filter_input returns either false, null or 0 here. They're all equally falsey, meaning == false. You need to explicitly distinguish between them:
$i = filter_input(INPUT_GET, 'i', FILTER_VALIDATE_INT);
if ($i === null) {
echo 'value not provided';
} else if ($i === false) {
echo 'invalid value';
} else {
echo 'good';
}

How to check if an associative array has an empty or null value

In the following associative array
$array = array(
[0] => 0
[1] => 1
[2] =>
[3] => 2
[4] =>
)
how can you determine if a given key has an empty (or null) value? I used
if(empty($array[$value]))
and
if(isset($array[$value])) && $array[$value] !=='')
When using empty I also get false for the first array value which is zero and isset doesn't seem to do the trick.
use array_key_exists() and is_null() for that. It will return TRUE if the key exists and has a value far from NULL
Difference:
$arr = array('a' => NULL);
var_dump(array_key_exists('a', $arr)); // --> TRUE
var_dump(isset($arr['a'])); // --> FALSE
So you should check:
if(array_key_exists($key, $array) && is_null($array[$key])) {
echo "key exists with a value of NULL";
}
Looked at all the answers and I don't like them. Isn't this much simpler and better? It's what I am using:
if (in_array(null, $array, true) || in_array('', $array, true)) {
// There are null (or empty) values.
}
Note that setting the third parameter as true means strict comparison, this means 0 will not equal null - however, neither will empty strings ('') - this is why we have two conditions. Unfortunately the first parameter in in_array has to be a string and cannot be an array of values.
PHP empty return values states:
Returns FALSE if var exists and has a non-empty, non-zero value. Otherwise returns TRUE.
The following things are considered to be empty:
"" (an empty string)
0 (0 as an integer)
0.0 (0 as a float)
"0" (0 as a string)
NULL
FALSE
array() (an empty array)
$var; (a variable declared, but without a value)
From your array example I take it as you want to exclude the 0 as an integer. If that's the case this would do the trick:
<?php
$array = array(0, 1, '', 2, '');
foreach ($array as $value) {
echo (empty($value) && 0 !== $value) ? "true\n" : "false\n";
}
If you want to exclude other conditions that empty considers just negate them in that condition. Take in account that this might not be the optimal solution if you want to check other values.
if ( !isset($array[$key]) || $array[$key] == "" || is_null($array[$key]) )
{
//given key does not exist or it has "" or NULL value
}
foreach($array as $i => $v) {
if(null === $v) {
// this item ($array[$i]) is null
}
}
...or, for a given key:
if(null === $array[2]) {
// this item ($array[2]) is null
}
Potentially this could be cleaner if I knew how the array was constructed, but, having the assumption that you can have both empty strings, or nulls in the array, and you want to account for values of 0 --> here's what I'd do:
if (is_null($array[$key]) || (string)$array[$key] == '')
Here's a little bit of test code showing it in action with an array that has both 0, null, an empty string, and non-zero integers...
$array = array(0,1,null,2,'');
print_r($array);
foreach ($array as $key => $val) {
if (is_null($array[$key]) || (string)$array[$key] == '') {
echo $key.", true\n";
}
}
As for using isset() -- an empty string is consider to be set. Which may be what you're running into (aside from 0 being considered empty) Compare with this usage:
$foo = array(0,1,null,2,'');
print_r($foo);
foreach ($foo as $key => $val) {
if (isset($foo[$key])) {
echo $key.", true\n";
}
}
function is_empty($data){
$is_empty = true;
foreach ($data as $val){
if(is_array($val)){
$is_empty = is_empty($val);
}else{
if(!empty($val)){
$is_empty = false;
break;
}
}
}
return $is_empty;
}

Check if all values in array are the same

I need to check if all values in an array equal the same thing.
For example:
$allValues = array(
'true',
'true',
'true',
);
If every value in the array equals 'true' then I want to echo 'all true'. If any value in the array equals 'false' then I want to echo 'some false'
Any idea on how I can do this?
All values equal the test value:
// note, "count(array_flip($allvalues))" is a tricky but very fast way to count the unique values.
// "end($allvalues)" is a way to get an arbitrary value from an array without needing to know a valid array key. For example, assuming $allvalues[0] exists may not be true.
if (count(array_flip($allvalues)) === 1 && end($allvalues) === 'true') {
}
or just test for the existence of the thing you don't want:
if (in_array('false', $allvalues, true)) {
}
Prefer the latter method if you're sure that there's only 2 possible values that could be in the array, as it's much more efficient. But if in doubt, a slow program is better than an incorrect program, so use the first method.
If you can't use the second method, your array is very large, and the contents of the array is likely to have more than 1 value (especially if the 2nd value is likely to occur near the beginning of the array), it may be much faster to do the following:
/**
* Checks if an array contains at most 1 distinct value.
* Optionally, restrict what the 1 distinct value is permitted to be via
* a user supplied testValue.
*
* #param array $arr - Array to check
* #param null $testValue - Optional value to restrict which distinct value the array is permitted to contain.
* #return bool - false if the array contains more than 1 distinct value, or contains a value other than your supplied testValue.
* #assert isHomogenous([]) === true
* #assert isHomogenous([], 2) === true
* #assert isHomogenous([2]) === true
* #assert isHomogenous([2, 3]) === false
* #assert isHomogenous([2, 2]) === true
* #assert isHomogenous([2, 2], 2) === true
* #assert isHomogenous([2, 2], 3) === false
* #assert isHomogenous([2, 3], 3) === false
* #assert isHomogenous([null, null], null) === true
*/
function isHomogenous(array $arr, $testValue = null) {
// If they did not pass the 2nd func argument, then we will use an arbitrary value in the $arr (that happens to be the first value).
// By using func_num_args() to test for this, we can properly support testing for an array filled with nulls, if desired.
// ie isHomogenous([null, null], null) === true
$testValue = func_num_args() > 1 ? $testValue : reset($arr);
foreach ($arr as $val) {
if ($testValue !== $val) {
return false;
}
}
return true;
}
Note: Some answers interpret the original question as (1) how to check if all values are the same, while others interpreted it as (2) how to check if all values are the same and make sure that value equals the test value. The solution you choose should be mindful of that detail.
My first 2 solutions answered #2. My isHomogenous() function answers #1, or #2 if you pass it the 2nd arg.
Why not just compare count after calling array_unique()?
To check if all elements in an array are the same, should be as simple as:
$allValuesAreTheSame = (count(array_unique($allValues, SORT_REGULAR)) === 1);
This should work regardless of the type of values in the array.
Update: Added the SORT_REGULAR flag to avoid implicit type-casting as pointed out by Yann Chabot
Also, you can condense goat's answer in the event it's not a binary:
if (count(array_unique($allvalues)) === 1 && end($allvalues) === 'true') {
// ...
}
to
if (array_unique($allvalues) === array('foobar')) {
// all values in array are "foobar"
}
If your array contains actual booleans (or ints) instead of strings, you could use array_sum:
$allvalues = array(TRUE, TRUE, TRUE);
if(array_sum($allvalues) == count($allvalues)) {
echo 'all true';
} else {
echo 'some false';
}
http://codepad.org/FIgomd9X
This works because TRUE will be evaluated as 1, and FALSE as 0.
You can compare min and max... not the fastest way ;p
$homogenous = ( min($array) === max($array) );
$alltrue = 1;
foreach($array as $item) {
if($item!='true') { $alltrue = 0; }
}
if($alltrue) { echo("all true."); }
else { echo("some false."); }
Technically this doesn't test for "some false," it tests for "not all true." But it sounds like you're pretty sure that the only values you'll get are 'true' and 'false'.
Another option:
function same($arr) {
return $arr === array_filter($arr, function ($element) use ($arr) {
return ($element === $arr[0]);
});
}
Usage:
same(array(true, true, true)); // => true
Answering my method for people searching in 2023.
$arr = [5,5,5,5,5];
$flag = 0;
$firstElement = $arr[0];
foreach($arr as $val){
// CHECK IF THE FIRST ELEMENT DIFFERS FROM ANY OTHER ELEMENT IN THE ARRAY
if($firstElement != $val){
// FIRST MISMATCH FOUND. UPDATE FLAG VALUE AND BREAK OUT OF THE LOOP.
$flag = 1;
break;
}
}
if($flag == 0){
// ALL THE ELEMENTS ARE SAME... DO SOMETHING
}else{
// ALL THE ELEMENTS ARE NOT SAME... DO SOMETHING
}
In an array where all elements are same, it should always be true that all the elements MUST match with the first element of the array. Keeping this logic in mind, we can get the first element of the array and iterate through each element in the array to check for that first element in the loop which does not match with the first element in the array. If found, we will change the flag value and break out of the loop immediately. Else, the loop will continue till it reaches the end. Later, outside the loop, we can use this flag value to determine if all the elements in the array are same or not.
This solution is good for arrays with definite limit of elements (small array). However, I am not sure how good this solution would be for arrays with very large number of elements present considering that we are looping through each and every element to check for the first break even point. Please use this solution at your own convenience and judgement.
$x = 0;
foreach ($allvalues as $a) {
if ($a != $checkvalue) {
$x = 1;
}
}
//then check against $x
if ($x != 0) {
//not all values are the same
}

php, mysql, arrays - if( x == 0 ) { }

I have the following code
while($row = $usafisRSP->fetch_assoc())
{
$hidden_keys = array('Applicantid', 'unique_num', 'regs_time' ....);
$hidden_fields = array_intersect_key($row, array_fill_keys($hidden_keys, NULL));
$hidden_values = array();
foreach ($hidden_fields as $key => $value) {
// fill the values array using the values from fields array
$hidden_values[$value] = "$key = ".base64_decode($value)."";
if(base64_decode($value)== 0)
{
$hidden_values[$value] = "";
}
echo $hidden_values[$value];
The question is about "if($hidden_values[$value] == 0)" ... Basically I want to do not display/echo the $hidden_values[$value] if it's value of $value is 0. Sometimes $value is 0 or some words like (23 avenue).
I think you ran into three catches with PHP type comparisons and equalities:
Any string not beginning with a number will always loosely equal 0. So basically, if(base64_decode($value)== 0) will likely always resolve to true, even if decoded $value is "Adam".
Return value of base64_decode is a string, so if 0 is the result, it will be string 0, not integer 0. This means if(base64_decode($value) === 0) wouldn't even work if decoded $value is "0". Another catch is base64_decode may return false on errors, again failing this strict equality check.
A non-empty string (other than "0") will always loosely equal true. So this is the only comparison you really need for your case.
I think this is what you want, replacing the last 5 lines...
if(base64_decode($value)) echo $hidden_values[$value];
else $hidden_values[$value] = "";
} // closing your for loop
Is this what you're looking for?
foreach( $hidden_values as $value ) {
if( $value !== 0 ) {
echo $value;
}
}

Categories