PHP conditional statement using $_SESSION assigns value, but why? - php

I actually found out how to solve this particular problem on my own, but it's still driving me crazy wondering why the problem came about to begin with. I had a conditional statement:
if($_SESSION['authenticated'] = 1) {
DOSTUFF;
}
Now prior to this if statement I know that $_SESSION['authenticated'] is empty by using print_r(). However, after executing this code block this conditional statement assigns 1 to $_SESSION['authenticated'], which makes the if statement evaluate to true no matter what! I found a way around this using isset(), but I still have no clue why a conditional statement would assign a value to a variable in the first place when it should only evaluate whether or not the condition is true or false.

Because = is assignment. You want == or === which test for equality. === checks that the operands are both equal and of the same type. == only checks for equality.

You have a semantic (or syntactic) (or typing) error. You should use double equal sign for equality comparison like this:
if($_SESSION['authenticated'] == 1) {
DOSTUFF;
}
If you use single equality sing, that means assignment, and the assigned value gets evaluated in the if statement.

Related

Will an If Statement Stop Checking if the first OR condition is met in PHP?

I want to try and make my code as efficient as possible and from what ive read
if($process == true)
Will process faster than something that calls a function. I.e
if(count($total) == 100)
So if i had an OR inside my if and the first condition was a simple boolean check and it turned out to be true would the second part of the condition still be checked anyway?
For example
$process = true;
if($process == true || count($total) == 100)
Would the count function still be called even though process is true and that is enough the make the condition pass.
PHP has indeed a mechanic named short-circuit:
http://php.net/manual/en/language.operators.logical.php#example-140
If the first operand of a logical OR is true, then the second part isn't evaluated, and the function isn't called.
Since comparing a variable to a boolean is faster than calling a function in PHP, this mechanic can help you to optimize, but never forget that premature optimisation is the root of all evil.
It will work same as exactly logical operator works. For example foo() will never get called.
if (false && foo()) {
}
if (true || foo()) {
}
In case of OR once it found a true statement it wont check further conditions,
In case of AND once it found a false statement it wont check further conditions.
its known as lazy evaluation.
illustration:
<?php
$var=0;
if($var++ || $var++){//Since 0 means false in Php both conditions will be checked
//Do nothing
}
echo $var;//output :2
if we change condition to if(++$var || $var++) the first condition will return true hence next condition will not be checked thus it will print output as 1;
If any statement inside a or is true other statements will not be checked and the if will be evaluated to true.
If you are checking a and statement all statements needs to evaluate to true and if any of them is false the stamen check will stop because the if is already false.
Just another important detail is that a function inside a if does not slow down the if check, what will slow down is what the function is doing and if it needs a lot of processing of course will be slower than just check a boolean but do not get afraid of use functions because they are very important in any system.
(I remember this from C# but I'm quite sure it's the same in php)
This depends if you use the single | or double || I think if you used the single ones it would still go do the other one ( usefull for when theres a function like loggin behind it ) if you use double and the first one is true it'll skip the second condition.
(This could be the other way around, so best bet is to try it using Javascript eg. create 2 function each returning true after alerting something, and thest these with either 1 line or 2)

Multiple IF statement conditions

I have a PHP script that runs through an array of values through my own custom function that uses the PHP function preg_match. It's looking for a match with my regular expression being $valueA, and my string to search being $valueB, and if it finds a match, it returns it to $match, otherwise I don't want my IF statement to run.
Now, I'm having no problem with this IF statement running if the function finds a match (in other words, is TRUE);
if ($match = match_this($valueA, $valueB))
{
//do this
}
HOWEVER, if I wanted to compare an additional condition to check if it is also TRUE, and only run the IF statement when both are TRUE, I run into problems;
if ($match = match_this($valueA, $valueB) && $x == 'x')
{
//do this
}
Instead of the statement running as normal when both conditions are TRUE, I end up outputting a 1 from $match instead of what my $match value should be.
I can sort of see what's happening. My IF statement is just returning a literal boolean TRUE into $match, instead of my value returned from match_this();
Is this because I can only return one sense of TRUE?
I can get around the problem by having two nested IF statements, but for the sake of clean code I'd like to be able to compare multiple conditions in my IFs which includes functions that return values.
Are there different kinds of TRUE? If so, how do I compare them in this way? Or is there an easier method? I suppose I could just put a second IF statement inside my function and pass my second condition through the function, but then my function wouldn't be very clearly defined in terms of its purpose.
I've ran into this problem before and didn't quite know what I was looking for. Hope someone can help.
if (($match = match_this($valueA, $valueB)) && $x == 'x')
^ ^
You missed an extra set of brackets.
Without the extra set of brackets around $match = match_this($valueA, $valueB), the evaluation of the && is performed first and finally result is assigned to $match.
Alternatively, you could use and (which has lower precedence than assignment =) instead of &&
PHP Operator Precedence
if ($match = match_this($valueA, $valueB))
^---wrong operator
You should be using == for equality tests. Right now you're just assigning the return values of match_this. Ditto for your other if()
as per the comments below, if you actually ARE wanting to do assignments within the if() structure, then you should slap a very-large-blinking-neon-bright comment/warning above the code to say that this is intended behavior. In most any language and most any other person looking at this code later on will assume it's a typo and change the assignment to an equality test.

Question with setting variables in if statements

Here is the sample:
if(($test = array('key'=>true)) && $test['key']){
// works
}
if($test = array('key'=>true) && $test['key']){
// does not work
}
Why is the parenthesis required? My understanding is that it computes the first conditional then the second no matter what.
And is it "safe" to do an assignment like this?
It's a matter of operator precedence in the language. In your second statement, you're essentially writing this to be evaluated:
$test = array('key'=>true) && $test['key'];
Just about any language is going to take that to mean this:
$test = (array('key'=>true) && $test['key']);
It's assigning to $test the value of the evaluation of the logical && between the two other values. So $test will be either true or false when evaluated.
i don't think the parens are required in PHP. they are in JS.
depends what you mean by "safe". it works. but some would argue that this is bad style and makes for less understandable and less maintainable code. otoh, K&R positively recommended it. it doesn't worry me and sometimes makes for tidier code.
It's because it's forcing the interpreter to perform the assignment before it attempts to evaluate any of conditions within the if.
Without the parenthesis, you're simply assigning the results of array('key'=>true) && $test['key'] to $test.
It is safe to use, but in this case the parenthesis are required for disambiguation. The operator precedence rules of PHP mean that the second line will be executed as:
if ($test = (array('key' => true) && $test['key'])) { .. }
So test will not be an array but a bool.
The practice of doing assignment in if statements itself is not really encouraging readability though, so you probably want to avoid doing this too much.
In PHP, the assignment operator = has lower precedence that most other operators. (For more information, see the documentation). Furthermore, the result of an expression using the assignment operator is the value of the assignment. With this in mind, consider the expressions you posted:
First example:
($test = array('key'=>true)) && $test['key']
The first part of this expression, ($test = array('key'=>true)) evaluates to array('key'=>true) (by the rule above), and the second part evaluates to true since the key was just set. Thus the whole expression evaluates to true.
Second example:
$test = array('key'=>true) && $test['key'] By the rules of operator precedence, $test is going to get assigned the value of the expression array('key'=>true) && $test['key']. The first half of this is true, but $test['key'] hasn't been set yet, so true && false is false, so $test takes the value false, which is also the result of the if condition.

Strange variable assignment

I was studying some code I found on the web recently, and came across this php syntax:
<?php $framecharset && $frame['charset'] = $framecharset; ?>
Can someone explain what is going on in this line of code?
What variable(s) are being assigned what value(s), and what is the purpose of the && operator, in that location of the statement?
Thanks!
Pat
Ah, I just wrote a blog post about this idiom in javascript:
http://www.mcphersonindustries.com/
Basically it's testing to see that $framecharset exists, and then tries to assign it to $frame['charset'] if it is non-null.
The way it works is that interpreters are lazy. Both sides of an && statement need to be true to continue. When it encounters a false value followed by &&, it stops. It doesn't continue evaluating (so in this case the assignment won't occur if $framecharset is false or null).
Some people will even put the more "expensive" half of a boolean expression after the &&, so that if the first condition isn't true, then the expensive bit won't ever be processed. It's arguable how much this actually might save, but it uses the same principle.
&& in PHP is short-circuited, which means the RHS will not be evaluated if the LHS evaluates to be false, because the result will always be false.
Your code:
$framecharset && $frame['charset'] = $framecharset;
is equivalent to :
if($framecharset) {
$frame['charset'] = $framecharset;
}
Which assigns the value of $framecharset as value to the array key charset only if the value evaluates to be true and in PHP
All strings are true except for two: a string containing nothing at all and a string containing only the character 0

Is this an OK test to see if a variable is set

Yesterday, I posted an answer to a question that included several (unknown to me at the time) very bad code examples. Since then, I've been looking at my fundamental knowledge of PHP that allowed me to think that such code is possible. This brings me to a question that I can't seem to find an answer to:
If I want to check for whether or not a variable has anything set, is it a valid practice to not use isset() or another helper function? here's a "for instance":
if($not_set){
//do something
} else {
//do something else
}
Rather than...
if(isset($not_set)){
//do something
} else {
//do something else
}
From the name of the variable, you can see that this variable is not set. Therefore the conditional would be false and the else portion would run. Up until now I have been using this practice, but after the posts yesterday, I now have an inkling that this is wrong.
Here's why I thought that it would be an ok practice to leave out the isset() function above. From PHP manual:
The if construct is one of the most
important features of many languages,
PHP included. It allows for
conditional execution of code
fragments. PHP features an if
structure that is similar to that of
C:
if (expr) statement
As described in the section about
expressions, expression is evaluated
to its Boolean value. If expression
evaluates to TRUE, PHP will execute
statement, and if it evaluates to
FALSE - it'll ignore it. More
information about what values evaluate
to FALSE can be found in the
'Converting to boolean' section.
And from the 'Converting to boolean section':
When converting to boolean
, the following values are considered
FALSE:
...
* the special type NULL (including unset variables)
Why would the manual go out of its way to state that unset variables are included if this is a bad practice? If it's unset, it gets converted to NULL and therefore is evaluated properly by the conditional. Using isset() will find the same result, but will take extra cycles to do so.
Have I been wrong this whole time, and if so, why? (And just how bad it is, maybe?)
If the variable is not set you get a Notice. If you use isset() you don't get a notice. So from an error reporting point of view, using isset() is better :)
Example:
error_reporting(E_ALL);
if($a) {
echo 'foo';
}
gives
Notice: Undefined variable: a in /Users/kling/test on line 5
whereas
error_reporting(E_ALL);
if(isset($a)) {
echo 'foo';
}
does not output anything.
The bottom line: If code quality is important to you, use isset().
It's okay but not good practice to use if to check for a set variable. Two reasons off the top of my head:
Using isset makes the intent clear - that you're checking whether the variable is set, and not instead checking whether a condition is true.
if ($not_set) will evaluate to false when $not_set is actually set but is equal to boolean false.
You will run in to problems if your variable is set, but evaluates to FALSE, like the following:
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
Taken from the PHP manual.
Basically, using isset() is showing that you are explicitly checking if a variable exists and is not NULL, while the structure of your if statement only checks if the variable is true. It is more clear and less error-prone.
It is a common practise, but is not good -- you should always use isset!
If your $not_set is set, and is a bool with the value false, your "test" will fail!
isset works as a guard preventing you from using variables that do not actually exist.
if (isset($foo)) and if ($foo) do not mean the same thing. isset just tells you if the variable actually exists and if it's okay to use it, it does not evaluate the value of the variable itself*.
Hence, you should usually use one of these two patterns:
If the variable is sure to exist and you just want to check its value:
if ($foo == 'bar')
If the variable may or may not exist, and you want to check its value:
if (isset($foo) && $foo == 'bar')
If you're just interested that a variable is set and evaluates to true, i.e. if ($foo), you can use empty:
if (isset($foo) && $foo)
// is the same as
if (!empty($foo))
* it does check for null, where null is as good as not being set at all

Categories