I can't understand why the last debugbar message is showing. Strangely enough $nest = 1, not true.
$nest = true;
$showcosts = false;
Debugbar::info($nest);
Debugbar::info($showcosts);
Debugbar::info("x" . $nest . "x");
Debugbar::info("x" . $showcosts . "x");
Debugbar::info($nest == true);
Debugbar::info($showcosts);
if ($showcosts && $nest) {
Debugbar::info("this should never show");
}
returns this:
true
false
x1x
xfalsex
true
false
this should never show
I'd like the last debugbar message not to show as only one of the conditions in the if statement is true.
I'm using Laravel 5.4 with PHP 7.
As mentioned in the comment above:
The string value of a boolean true is 1 which is why you get x1x when you concatenate strings. However the string value of a false should be the empty string and not the string false which means you should also see a xx outputed (not xfalsex) .
Make 100% sure that $showcosts is a boolean and not a string that contains the word false because that behaviour is consistent with checking a false string.
In addition as #NinoŠkopac pointed out, the simple if ($variable) check will be true for any value of $variable which is considered "truthy". This includes non-null objects, non-empty arrays, non-zero numbers and non-empty strings as well as the boolean true. In this case the string "false" is a non-empty string and is therefore a "truthy" value.
If you're getting values from a request query string or post (e.g. via $_POST or $_GET) you must keep in mind that all values are strings.
For this purpose PHP has a set of filtering functions that aim to help with this. There's filter_var and filter_input (and others, check the manual for more details).
You can use filter_var on any variable, for example in your case you could do:
$nest = filter_var($nest,FILTER_VALIDATE_BOOLEAN);
$showcosts = filter_var($showcosts ,FILTER_VALIDATE_BOOLEAN);
The FILTER_VALIDATE_BOOLEAN filter:
Returns TRUE for "1", "true", "on" and "yes". Returns FALSE otherwise.
You can also use filter_input to filter input directly.
For example if you have an input entry $_POST["nest"] then you can do:
filter_input(INPUT_POST,"nest",FILTER_VALIDATE_BOOLEAN);
This will also save you from an isset check.
Related
I face a problem like this:
$area="Dhaka";
isset($area); //returns true which is OK
isset($area['division']); //returns true why?
// actually, any array key of area returns true
isset($area['ANY_KEY']);//this is my question 1
isset($area['division']['zilla');//now it returns false.
//as I know it should returns false but why previous one was true.
Now if I do this:
$area['division'] = "Dhaka";
isset($area); // returns true which is OK
isset($area['division']); // returns true it's also OK
isset($area['ANY_KEY']); // returns false. I also expect this
isset($area['division']['ANY_KEY']); // returns true why? question #2
Basically both of my questions are the same.
Can anyone explain this?
As with every programming language in existence, a string is stored as an array of characters.
If I did:
$area = "Dhaka";
echo $area[0];
It would return D.
I could also echo the whole string by doing:
echo $area[0].$area[1].$area[2].$area[3].$area[4];
PHP will also type juggle a string into 0 when passed in a manner that accepts only integers.
So by doing:
echo $area['division'];
You would essentially be doing:
echo $area[0];
and again, getting D.
That's why isset($area['division']) returns a true value.
Why doesn't $area['foo']['bar'] (aka $area[0][0]) work? Because $area is only a single-dimension array.
The best approach to handle this problem when you're working with a variable that could either be a string or an array is to test with is_array() before trying to treat your variable as an array:
is_array($area) && isset($area['division'])
PHP lets you treat a string as an array:
$foo = 'bar';
echo $foo[1]; // outputs 'a'
So
$area['division']
will be parsed/executed as
$area[0];
(the keys cannot be strings, since it's not REALLY an array, so PHP type-converts your division string by its convert-to-int rules, and gives 0), and evaluate to the letter D in Dhaka, which is obviously set.
Okay, here's a solution rather than explaining why isset isn't going to work properly.
You want to check if an array element is set based on it's index string. Here's how I might do it:
function isset_by_strkey($KeyStr,$Ar)
{
if(array_key_exists($KeyStr,$Ar))
{
if(strlen($Ar[$KeyStr]) > 0 || is_numeric($Ar[$KeyStr] !== FALSE)
{
return TRUE;
}
return FALSE;
}
}
isset_by_strkey('ANY_KEY',$area); // will return false if ANY_KEY is not set in $area array and true if it is.
The best way to access a linear array in php is
// string treated as an linear array
$string= "roni" ;
echo $string{0} . $string{1} . $string{2} . $string{3};
// output = roni
It is expected behaviour.
PHP Documentation covers this
You can try empty() instead.
If it is returning true for keys that do not exist there's nothing you can do; however, you can make sure that it doesn't have a negative effect on your code. Just use array_key_exists() and then perform isset() on the array element.
Edit: In fact, using array_key_exists() you shouldn't even need isset if it is misbehaving just use something like strlen() or check the value type if array_key_exists returns true.
The point is, rather than just saying isset($Ar['something']) do:
if(array_key_exists('something',$Ar) )
and if necessary check the value length or type. If you need to check the array exists before that of course use isset() or is_array() on just the array itself.
I have a quick question here. I know that the cakePHP find('first') function returns an array containing the first result if found, false otherwise. My question is this, what if I were to write a check like this:
if(result_is_array) // that means I have data
{
// do something
}
else // that means result is a boolean
{
// do something else
}
Instead of checking whether the result obtained from find('first') is an array or not, can I just say:
$result = $this->MyModel->find('first');
if($result)
{
// do something
}
In order words, if I get an array here, will that evaluate to TRUE in php? Is if(array()) equal to true in php?
YES, you can do
$result = $this->MyModel->find('first');
if($result)
An array with length > 0 returns true
Explanation is here in the docs
When converting to boolean, the following values are considered FALSE
an array with zero elements
Every other value is considered TRUE
A zero value array is false
An array with values in it is true
You can view this table to see what is evaluated as true vs false.
Instead of checking whether the result obtained from find('first') is
an array or not
Yes. Do it the second way:if ($result). If find returns an empty array or boolean false, the branch will not be executed.
The best part about doing it this way is that it makes it clear to the reader that you are checking for a non-empty value.
According to the documentation, if you try to treat an array as a boolean, the array will be considered true precisely when it's not empty.
Use the following if you are looking for a TRUE value:
if ( $result !== false )
{
// do something
}
An empty array will always evaluate to false or if it contain any key/values then it will evaluate to true. if $this->MyModel->find('first'); always returns an array then an empty result will evaluate to false and true other wise. so your code is perfectly valid.
After playing with PHP, I discovered that true is returned as 1 and false as null.
echo (5 == 5) // displays 1
echo (5 == 4) // displays nothing
When writing functions that return true or false, what are the best practices for using them?
For example,
function IsValidInput($input) {
if ($input...) {
return true;
}
else {
return false;
}
}
Is this the best way to use the function?
if (IsValidInput($input)) {
...
}
How would you write the opposite function?
IsBadInput($input) {
return ! IsValidInput($input);
}
When would you use the === operator?
After playing with PHP, I discovered that true is returned as 1 and false as null.
That is not true (no pun intended). PHP, like many other languages, has "truthy" and "falsy" values, which can behave like TRUE or FALSE when compared to other values.
It is so beause PHP uses weak typing (vs. strong typing). It automatically converts different types of values when comparing them, so it can eventually compare two values of the same type. When you echo TRUE; in PHP, echo will always output a string. But you passed it a boolean value, that has to be converted to a string before echo can do its job. So TRUE is automatically converted to the string "1", while FALSE is converted to "".
When would you use the === operator?
This weak, or loose, typing is the reason PHP uses two equality operators, == and ===. You use === when you want to make sure both values you are comparing are not just "equal" (or equivalent), but also of the same type. In practice:
echo 1 == TRUE; // echoes "1", because the number 1 is a truthy value
echo 1 === TRUE; // echoes "", because 1 and TRUE are not the same type (integer and boolean)
When writing functions that return true or false, what are the best practices for using them?
Be precise when you can, returning the actual boolean TRUE or FALSE. Typical cases are functions prefixed by is, like isValidInput. One usually expects such functions to return either TRUE or FALSE.
On the other hand, it's useful to have your function return a "falsy" or "truthy" values in some cases. Take strpos, for example. If it finds the substring in position zero, it returns 0 (int), but if the string is not found, it returns FALSE (bool). So:
$text = "The book is on the table";
echo (strpos($text, "The") == FALSE) ? "Not found" : "Found"; // echoes "Not found"
echo (strpos($text, "The") === FALSE) ? "Not found" : "Found"; // echoes "Found"
function isValidInput($input){
return ($input ...); // if your test returns true/false, just return that result
}
Your last example is missing an argument, otherwise fine:
function isBadInput($input){
return !isValidInput($input);
}
Sure. Unless you need it in a different sort of structure, e.g. a while loop.
You never would. Always invert the normal function directly.
When you need to differentiate false from 0, '', etc.
After playing with PHP, I discovered that true is returned as 1 and false as null.
No.. true and false are returned as boolean true and false. When you echo output it must be cast to a string for display. As per the manual:
A boolean TRUE value is converted to the string "1". Boolean FALSE is converted to "" (the empty string). This allows conversion back and forth between boolean and string value.
As for the rest: that's fine, yes, yes, when you want exact type matches, to avoid type juggling in comparisons, e.g. "1" == true is true but "1" === true is false.
function isValidInput($input) {
return ($input...);
}
if(isValidInput($input))
...
if(!isValidInput($input)) // never rewrite inverse functions
...
if(isValidInput($input) === false) {
// Only run if the function returned a boolean value `false`
// Does the same thing as above, but with strict typing.
}
I have very basic question regarding return value of a function, and checking the variable value.
function test($var1, $var2){
if ($var1 == $var2){
$var3 = "abc";
return $var3;
}
return false
}
$value = test($var1, $var2);
if ($value){
echo "Value is".$value; //should output abc.
} else {
echo "Not equal";
}
Is it ok to either return a value or return false? For example I am not returning TRUE, it is ok?
When i call the function, i store the return value in a variable $value. How can i check the function did return the $var3? Which of the if condition should be used?
if (!empty($value)) or if (isset($value)) or if ($value) or if (value != false)
Yes, it is common practice in PHP to return FALSE as an indicator of an error condition. (What constitutes an error is your own decision and depends on what the function is supposed to do.)
However, since PHP automatically casts values to Boolean that are of another type (like the empty string or 0, which evaluate to FALSE as well), you should do an explicit check for FALSE like this:
if ($value !== FALSE) ...
As Felix Kling notes in the comments, this is called "strict comparison" (or "identity comparison"). It checks if a value is identical to FALSE, where as != FALSE, == FALSE and if ($value) only check if a value could be interpreted as FALSE.
I'm not a PHP developer, but I don't think your first approach works.
There are other things than the boolean value false interpreted as false:
When converting to boolean, the following values are considered FALSE:
* the boolean FALSE itself
* the integer 0 (zero)
* the float 0.0 (zero)
* the empty string, and the string "0"
* an array with zero elements
* an object with zero member variables (PHP 4 only)
* the special type NULL (including unset variables)
* SimpleXML objects created from empty tags
http://php.net/manual/en/language.types.boolean.php
It's perfectly OK to return different data types.
If you want to check against false, use: if ($value !== false). If you get lost which condition to use, this will clarify it: http://www.php.net/manual/en/types.comparisons.php
Your function returns false, so I would go with that check: if ($value != false)
$var3 = "abc";
return $var3;
That's pointless. You're returning a value, not a variable. return "abc"; is perfectly fine.
Is it ok to either return a value or return false?
Yes, that's perfectly fine for a simple case such as this.
How can i check the function did return the $var3?
As said above, the function returns the value "abc", not $var3. You're saving it in a new variable $value. This variable is definitely set (you just created it right there), so there's no need for isset or empty. Just test whether its value is true or false (or whatever else you want to test for). So the way you're doing it in fine.
Yes, you can return pretty much anything from the function, or you can just "return" without returning anything. In your example, you'll get a string or "false" in return.
To check for false you either do if (!$variable) or if ($variable===false). Zero will return true if you do "if ($variable==false)" due to auto casting of zero to false (and any other positive number to true). Three "===" makes sure it really is false and nothing else. The isset($var) checks for existance, not value - and is not applicable to your example since your function will return a value or "false" and thus always exists.
The only right answer here is: it depends.
I always ask myself this question when creating a function like this. To answer it, I analyze what the function does, instead of what it returns.
For instance, if I have a getter, I expect to get a value, or nothing. In this case I often return null when nothing is found/something went wrong.
A test function like yours should return a boolean at all times, in my opinion. Returning a variable when you're checking for something to be true or false is semantically incorrect, I think.
Aside from the semantics: returning 0, false or null does not really matter when you're checking it with if (test($var1, $var2)), since it will all work the same. However, if you want some finer details, you want to do an identity check (===) rather than a equality check. In PHP this is sometimes the case, for instance strpos can return 0 or false, 0 being a match is found, and false is not. Therefore the following would fail:
// returns 0, which is casted to false, so the 'else' part is executed
if (strpos('a', 'abc')) {
// 'abc' contains 'a'
} else {
// 'abc' does not contain 'a'
}
So, long story short: it depends...
EDIT: I believe my confusion is probably created by this code at the top of the page in which I'm testing for the value of the option... This creates a shortcut method to refer to the option without using the get_option('option') method...
global $options;
foreach ($options as $value) {
if (get_settings( $value['id'] ) === FALSE) {
$$value['id'] = $value['std'];
} else {
$$value['id'] = get_settings( $value['id'] );
}
}
And so when I set the value of a variable, $myvar, via a checkbox checked in my theme's options panel and click save, then view my options.php in worpdress, the value of the variable is
true
And when I do a lookup on this variable using
if($myvar == "true")
It passes.
However, when I set the value directly via the update_options() method, like so...
$mvar = true;
update_option('myvar', $myvar);
The value changes from true to 1
And when I do the same comparison as before, if($myvar == "true"), it now fails. It is no longer "true".
What am I missing? (1) why is "true" and 1, not evaluating the same and (2) What is the update_option method doing to the value of myvar to change the value from true to 1?
Try
if($myvar == true)
and
$myvar = true;
TRUE and FALSE are PHP's built in boolean variables which are much more universal than a true string.
About the update_option. It might not be that the option is changing it to 1. Instead it might be that the when it is inserting it into the database, it inserts it as the string "true". Then, when it comes back it is converted to the boolean value true, which when printed is 1
Try
if ($myvar)
Don't test whether things "equal" true, they are either true or they aren't.
You should change your first test to if($myvar == true) or simply if ($myvar). PHP has some strange rules for what is "true"; Generally, strings evaulate to true, except the special cases of "0" and an empty string "", which type-cast to false.
In your specific example, if ($myvar == "true"):
If $myvar contains a boolean, the expression will evaluate as (bool) == (bool)"true", or (bool) == true
If $myvar contains an integer, it's cast to a string and compared against the string "true"; so your test is failing, because "1" != "true".
If $myvar is a string, string comparison takes place and suddenly only the literal string "true" will successfully compare.
I would guess 2nd and 3rd cases are in effect: Wordpress is likely setting $myval to the string "true" when the from is posted back, so your test passes. When you manually specify boolean true, Wordpress must be converting it to an integer, and then integer comparison takes place and fails, because the integer 1 will be cast to string "1" when compared against "true".
You are doing a loose comparison between the integer 1 and the string 'true'. For this PHP will translate the string to a number. 'test' as a number is 0:
var_dump((int) 'true'); // int(0)
And since 0 is not equal to 1, the comparison will return false.
Like some other answers already correctly pointed out, you should test against the boolean literal TRUE or true. If one operator in a equality check is a boolean, PHP will convert the other operator to a boolean too, which, for the number 1, will give
var_dump((bool) 1); // boolean(true)
And then your test will pass, because true is equal to true.
Check out the Type Comparison Table to understand how PHP juggles types when testing for equality.
As for what check_update does to your boolean, check out the function description:
(mixed) (required) The NEW value for this option name. This value can be a string, an array, an object or a serialized value.
So, no boolean allowed. I've tried briefly to find out from the sourcecode where the conversion takes place, but since WP is a mess to me, couldn't find it. Like someone else suggested, it probably happens when storing it to the database and then getting it back.
"true" is a string, and all strings evaulates to the boolean 1 (try casting (bool) $string. true on the other hand, without quotes, is a boolean and will evaluate to 1.