A php if statement with one equal sign...? What does this mean? - php

I'm attempting to troubleshoot a problem, and need to understand what this if statement is saying:
if ($confirmation = $payment_modules->confirmation()) {
All the resources I can find only show if statements with double equal signs, not single. Is this one of the shorthand forms of a php if? What is it doing?
(If it's actually wrong syntax, changing it to a double equal sign doesn't resolve the problem. As-is, in some scenarios it does return true. In the scenario I'm troubleshooting, it doesn't return true until after I refresh the browser.)
Any help is greatly appreciated!!!

It's a form of shorthand, which is exactly equivalent to this:
$confirmation = $payment_modules->confirmation();
if ($confirmation) {
}

This will first assign the value of $payment_modules->confirmation() to $confirmation. The = operator will evaluate to the new value of $confirmation.
This has the same effect as writing:
$confirmation = $payment_modules->confirmation();
if ($confirmation) {
// this will get executed if $confirmation is not false, null, or zero
}

The code works because an assignment returns the value assigned, so if $payment_modules->confirmation() is true, $confirmation will be set to true, and then the assignment will return true. Same thing for false.
That's why you can use a command to assign to many variables, as in a = b = 0. Assigns zero to b and returns that zero. Therefore, it becomes a = 0. And a receives zero and it will return that zero, which can or can not be used.

Sometimes people like to do an assignment and then check if the assignment went through okay. Pair this up with functions that return false (or equivalent) on failure, and you can do an assignment and a check at the same time.
In order to understand this, remember that assignments are a kind of expression, and so (like all expressions) have a return value. That return value is equal to whatever got put into the variable. That is why you can do something like
a = b = c = 0;
to assign all of those variables at the same time.

= means assignment ( $a = 1 ), == is for comparison ( true == false is false ). I think in your example it should use = because it assigns it to the return value of confirmation, which should be something that evaluates to true.
Try doing a var_dump:
var_dump( $payment_modules->confirmation() );
See what boolean it evaluates to, and from there you can troubleshoot. Post more code if you want more help.
class test() {
public function confirmation() { return true; }
}
$boolean = test::confirmation();
var_dump( $boolean );
Will equate to true

Related

Is it correct way to return value in PHP

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...

Is this a bug or am I wrong?

/**
* Returns nodes found by xpath expression
*
* #param string $xpath
* #return array
*/
public function getXpath($xpath)
{
if (empty($this->_xml)) {
return false;
}
if (!$result = #$this->_xml->xpath($xpath)) {
return false;
}
return $result;
}
This code is taken from Magento. You can checkout the specific file in their public svn:
http://svn.magentocommerce.com/source/branches/1.5/lib/Varien/Simplexml/Config.php
Now I think that (!$result = #$this->_xml->xpath($xpath)) can never ever evaluate to true and thus the return false statement can never happen.
Because the assignment of the return value of xpath, regardless of whether it is true or false to the variable $result always returns true and negated always returns false.
So this is a bug or a completely redundant code, or am i wrong?
FYI: I am currently debugging a problem where some config elements get "lost" and I assume the error is somewhere in there.
This is a weird way of building a condition like that, but I think it makes sense.
$result = will assign the result of the xpath operation to $result.
If that result is false (a value which xpath() will return in case of an error), the condition will match and the function will return false.
"Because the assignment of the return value of xpath to the variable $result always returns true" this statement is wrong and I have no idea why did you make this conclusion. Value of assignment operator is always equal to value that was assigned, so it can easily be false or true (($x = false) == false )
You can test that with
var_dump(!$result = FALSE); // TRUE
var_dump(!$result = array()); // TRUE
var_dump(!$result = array(1)); // FALSE
So if SimpleXml::xpath returns an empty array or FALSE, the Magento function will return FALSE. Negating an array will typecast it to boolean first. Empty Arrays typecasted to Boolean will be FALSE. Which means, when your XPath is syntactically correct, but did not find any results, Magento will return FALSE.
I find it helps to parenthesise the inner assignment like this:
if (! ($result = #$this->_xml->xpath($xpath)) ) {
Visually the assignment is now a sub-task and must be executed before being inverted. Without the extra parentheses it performs exactly the same, this just helps your own code reading.
Any assignment command returns the value being returned. This lets you do things like:
$a = $b = $c = $d = $e = 'A made-up value';
The new value of $e is being returned to $d, which is being returned to $c, and so on...

Using 'or die()' to stop on errors in PHP

Often in PHP, I see:
$result = mysql_query($query) or die();
Coming from python, I know why this should work, because or returns the first value if it is true in a boolean context, and the second value otherwise (see this).
But when I try the above technique in PHP in another context, for example something like:
$name = "John Doe";
echo $name or "Anonymous";
The or doesn't return the first value ("John Doe"), it returns 1.
Why does this work in the mysql_query() result case, but not in other cases? Is it bad to use in a mysql_query() case (ignore the fact that I am not returning a useful error to the user)?
In PHP, variable assignment (the equals sign) and functions both take precedence over the or operator. That means a function gets executed first, then the return value of the function is used in the or comparison. In turn when you use two values/variables together with an or operator, it compares the two values first then returns a Boolean value.
Therefore, the order of evaluation in this example is:
$result = mysql_query($query) or die();
mysql_query($query)
Returns either a result set for DQL queries such as SELECT, or a Boolean value for DDL, DML or DCL queries such as CREATE, DROP, INSERT, UPDATE, DELETE and ALTER.
$result = mysql_query($query)
The result of this query execution is assigned to the variable $result.
$result /* = ... */ or die();
If it's either a result set or true, it's considered true (aka "truthy") so the or condition is satisfied and the statement ends here. Otherwise the script would die() instead.
echo is a language construct and therefore doesn't actually return a value, so it doesn't run like a function before the or comparison is made.
As $name or "Anonymous" is always true because the string "Anonymous" is non-empty and therefore truthy, the echo implicitly converts true to 1, hence that output.
The order of evaluation in this example is:
$name = "John Doe";
echo $name or "Anonymous";
$name = "John Doe";
Pretty straightforward — assigns the string John Doe to $name.
$name or "Anonymous"
PHP discovers that $name contains the string John Doe, so what ends up being evaluated is the following:
"John Doe" or "Anonymous"
Since at least one string is non-empty here, it's considered truthy and the condition is satisfied. This evaluation then returns true.
echo true /* $name or... */;
Converts true to 1 and prints the number 1.
Why should or return anything? or is a normal boolean operator. $a or $b is true if either $a or $b evaluates to true and false otherwise.
The difference between || and or is, that or has a lower operator precedance, even lower than =. This is why
$result = mysql_query($query) or die();
is same as
($result = mysql_query($query)) or (die());
whereas
$result = mysql_query($query) || die();
is same as
$result = (mysql_query($query) || die());
In your case
echo $name or "Anonymous";
gets
(echo $name) or ("Anonymous");
What you are looking for probably is the ternary operator:
echo $name ?: 'Anonymous';
The above will work as of PHP 5.3, if you have only PHP 5.2 use:
echo $name ? $name : 'Anonymous';
The reason actually occurred to me shortly after asking the question. It's about operator precedence. The = happens before the or, so:
$result = mysql_query($query) or die();
is equivalent to:
($result = mysql_query($query)) or die();
not:
$result = (mysql_query($query) or die());
as it would be in Python. So this:
$a = false or true;
will set $a to false, not true, which is bound to catch me out at some point in the future.
PHP does something often called "type juggling". In other words: PHP transforms the type of any value for the current use case. Since Strings will be transformed to "true" values, your expression returns true. But echo wants to print an string expression and transforms "true" to 1. Kinda annoying in some cases, but if you know it, you also know how to handle ;)
Check this out, by the way: http://php.net/manual/en/types.comparisons.php
the or clause is evaluated first and returns a boolean which the echo outputs. If you want to output text you need a if/else construct like:
echo ($name ? $name : 'Anonymous');
That is because echo is not a function, it's a language construct. It mimicks to be a function, but it really isn't :)
I would never use die() like this, it's kind of rough. You should handle your errors appropriately, don't just bail out.
If you wanted to replicate that behavior AND output to the screen/browser, you need a function that will return something other than TRUE. printf() can do that for you.
echo microtime."<br>";<
$str = "";
printf("%s",$str) or die();
echo "<br>".microtime();
If $str is empty, null, or false the die() will be called, otherwise, the script will finish executing.

Test for NULL value in a variable that may not be set

Considering that:
The isset() construct returns TRUE if a variable is set and not NULL
The is_null() function throws a warning if the variable is not set
Is there a way to test whether a variable exists, no matter it's NULL or not, without using the # operator to suppress the notice?
EDIT
Together with your first replies, I've been thinking about this and I'm getting the conclusion that inspecting get_defined_vars() is the only way to distinguish between a variable set to NULL and an unset variable. PHP seems to make little distinctions:
<?php
$exists_and_is_null = NULL;
// All these are TRUE
#var_dump(is_null($exists_and_is_null));
#var_dump(is_null($does_not_exist));
#var_dump($exists_and_is_null===NULL);
#var_dump($does_not_exist===NULL);
#var_dump(gettype($exists_and_is_null)=='NULL');
#var_dump(gettype($does_not_exist)=='NULL');
?>
$result = array_key_exists('varname', get_defined_vars());
As you already found out, you cannot :
rely on isset, as it return false for a variable that's null.
use $not_exists===null, as it'll raise a notice.
But you could be able to use a combinaison of :
get_defined_vars to get the list of existing variables, including those which are null,
and array_key_exists to find out if an entry exists in that list.
For instance :
$exists_and_null = null;
$exists_and_not_null = 10;
$defined_vars = get_defined_vars();
// true
var_dump(array_key_exists('exists_and_null', $defined_vars)
&& $defined_vars['exists_and_null']===null);
// false
var_dump(array_key_exists('exists_and_not_null', $defined_vars)
&& $defined_vars['exists_and_not_null']===null);
// false
var_dump(array_key_exists('not_exists', $defined_vars)
&& $defined_vars['not_exists']===null);
A couple of notes :
In the first case, the variable exists => there is an entry in the list returned by get_defined_vars, so the second part of the condition is evaluated
and both parts of the condition are true
In the second case, the variable exists too, but is null
which means the first part of the condition is true, but the second one is false,
so the whole expression is false.
In the third case, the variable doesn't exist,
which means the first part of the condition is false,
and the second part of the condition is not evaluated -- which means it doesn't raise a notice.
But note this is probably not that a good idea, if you care about performances : isset is a language construct, and is fast -- while calling get_defined_vars is probably much slower ^^
I would argue here that any code requiring such a comparison would have gotten its semantics wrong; NULL is an unset value in a language that has no straightforward way of distinguishing between the two.
I used a self created function to check this easily, keep in mind it will fire off a PHP warning (I only monitor E_ERROR when I develop).
function isNullOrEmpty( $arg )
{
if ( !is_array( $arg ) )
{
$arg = array( $arg );
}
foreach ( $arg as $key => $value )
{
if( $value == null || trim($value) == "" )
{
return true;
}
}
return false;
}
if (isset($var) && (is_null($var)) {
print "\$var is null";
}
This should do the trick.

problem with if statement used to determine function return

Im using an if statement to determine what to return in a function, but it seems to be not working the way i want it to.
function DoThis($dogs, $cats){
// do something with dogs, pet them perhaps.
$reg = $dogs[0];
$nate = $dogs[1];
if($cats = "dave"){return $reg;}
if($cats = "tom"){return $nate;}
}
$cats is a string (if that helps), and when entered it doesn't yield any return.
If i manually set a return, that works, but the above doesnt for some reason.
To test for equality, use the == (double equals) operator instead of the = (single equals) operator.
For example:
if("dave" == $cats){return $reg;}
if("tom" == $cats){return $nate;}
You're using the assignment operator instead of the comparison operator. Try the following instead.
$cats == "dave"
$cats == "tom"
When you say
if($cats = "dave") { ... }
you're really saying
Assign the value "dave" to the variable $cats
If the variable $cats is true after assignment, return true. Otherwise, return false
It's a common mistake, and something tha plagues old hands and new hands alike.
You need to use == to compare.
= is an assignment, so it has the effect of setting $cats to "dave" and then (because the expression evaluates to "dave", which is non-empty) it treats the if statement as being "if (true) ..." and executes the contained code.

Categories