Can someone explain this line of code please? (Logic & Assignment operators) - php

I've seen the following lines of code and I know what they do, but I don't know how the second line works (and hence how to apply it to another situation).
$user = User::model()->findByPk(123);
empty($user->profile) and $user->profile = new Profile();
The code tries to look up the User from the database, and if there isn't a profile, creates a new for use later on.
I have also seen code before that goes something like the following:
$variable1 = $variable2 = $variable3;
It did something a bit more complex than simple assigning three things to be the same, but I'm finding it impossible to search for this type of thing to find out any information about it, let alone find the original code that I came across. I think it originally had an 'and' in there somewhere. Does anyone know how to search for code that has more than one equals sign in it that wasn't just an if statement?
Sorry for the two questions in one (and vague at that) and the terrible title (I'll fix it up when I know what the names are, if it's anything like a tenary statement)).

Using Logical Operators to Skip Code:
As php evaluates a line with the AND operator, if the fist part is false, the second part is not evaluated since it would not change the result.
So in this case, if empty() returns true, then php evaluates the right side. If empty() returns false, no more evaluation is done and the profile is not effected.
The php manual logical operators page has some illustrations of this.
Multiple Assignment Operators: The assignment operator assigns the right expression to the variable on the left.
$variable1 = $variable2 = $variable3;
In this case $variable2 is set to the value of $variable3 then $variable1 is set to the value of $variable2. The php manual assignment operators page covers this.

empty($user->profile) and $user->profile = new Profile();
in and statement, first element is evaluated first; if it's true, then second statement is evaluated, simple assignment should always evaluate to true, I presume. if the first element was false, second element is not evaluated.
You can read more about operator precedence in php docs.

It's basically the same as
if (empty($user->profile))
$user->profile = new Profile();
Weird syntax indeed...

What you're seeing is used in many languages. Here is an article for using it in JavaScript... but it explains the concept well.
http://css.dzone.com/articles/guard-and-default-operators-ja

This is a fairly bizarre way to write this. With a PHP expression, if the first part evaluates false, the expression will stop rendering.
Like if I write:
if (x == 5 and y == 2)
that will test if x==5, then if it does, it will test if y==2. If x != 5, it will never test the y == 2. So the code above is using that fact to test whether $user->profile is empty. Then if it is, it runs the next part of the expression, which is the assignment of $user->profile = new Profile(); Basically the same as:
if (empty($user->profile))
$user->profile = new Profile();
or
empty($user->profile) ? $user->profile = new Profile();
As far as your second question, the operator = is just an assignment, so it means that the value of $variable1 will be set to the value of $variable2, which will be set to the value of $variable3.
PHP does some very nice things with expressions, which are really helpful to learn. Check out this link for more info:
http://us.php.net/manual/en/language.expressions.php

$variable1 = $variable2 = $variable3;
Assignment (via the equal sign) in PHP has right to left precedence. Every expression in PHP has a return value. So the return value of the expression $variable3 is assigned to $variable2. Then the reurn value of the expression $variable2 = $variable3 is assigned to $variable1.

Related

Odd and confusing PHP syntax

I am taking over the maintenance of an old web site and came across this confusing syntax for processing a form that I have never seen before, and I am not exactly certain what it does:
foreach (array('address','comments','country','email','mail_content','name','title') as $vuln)
{
isset($_REQUEST[$vuln]) and $_REQUEST[$vuln] = htmlentities($_REQUEST[$vuln]);
isset($_GET[$vuln]) and $_GET[$vuln] = htmlentities($_GET[$vuln]);
isset($_POST[$vuln]) and $_POST[$vuln] = htmlentities($_POST[$vuln]);
isset($$vuln) and $$vuln = htmlentities($$vuln);
}
It's the "and" that is throwing me - I read it as "if variable is set convert it to htmlentities, but why is there an "and" in there?
Finally what does the last line do?
isset($$vuln) and $$vuln = htmlentities($$vuln);
It's using the operator precedence rules of PHP in an unusual way.
If you have an and statement, PHP will stop processing it if the left side is false - there's no need to check the right hand side, because it won't make a difference to the end result. (The converse is also true for an or statement if the left hand side is true.)
So the coder that wrote this is using it as a shorthand for:
if (isset($_REQUEST[$vuln])) {
$_REQUEST[$vuln] = htmlentities($_REQUEST[$vuln]);
}
They've save a small amount of typing, at the cost of making the code slightly harder to read. It's good practice to use isset to make sure that your array values are set before you use them, which is why the check is there.
As to the last line; logically, it's doing the same as the above, but with a variable variable. The first time through, $vuln will be set to the first item in your array, which is address - the final line of code is checking to see if there's a variable called $address, and if so, set its value to htmlentities($address).
That's what the code is doing. Why it's checking REQUEST, GET, and POST is beyond me.
Hi These are the nothing but the shortend form.
isset($_REQUEST[$vuln]) and $_REQUEST[$vuln] = htmlentities($_REQUEST[$vuln]);
above line means
if(isset($_REQUEST[$vuln])){
$_REQUEST[$vuln] = htmlentities($_REQUEST[$vuln]);
}
Also the $$vuln is a reference variable its checking the same that if reference variable is set then assign it value
isset($var) and <statement goes here that uses $var>;
This basically only executes the <statement ...> if the statement preceding and (in this case isset($var)) evaluates to true. This happens because if anything is false before a and, there's no need to evaluate (or execute) the rest. This works similarly to:
if (false && condition) { ... }
The condition will never be evaluated, since no matter what its value evaluates to, the if condition will always evaluate to false.
A more readable alternative for the first example:
if (isset($var)) {
<statement goes here that uses $var>;
}
As pointed out in the comments by #chris85, see $$variable.
An example of a variable variable:
$vuln = 'abc'; /* Regular variable assignment */
$$vuln = 'def'; /* This is "equivalent" to $abc = 'def'
* because $$vuln expands to $<contents of $vuln>,
* therefore $abc is assigned with 'def'.
*/
/* $abc is now a variable with 'def' as its value */
It might be easier to comprehend as the following, for the first iteration through the array:
<?php
if(isset($_REQUEST['address'])) {
$_REQUEST['address'] = htmlentities($_REQUEST['address']);
}
if(isset($_GET['address'])) {
$_GET['address'] = htmlentities($_GET['address']);
}
if(isset($_POST['address'])) {
$_POST['address'] = htmlentities($_POST['address']);
}
if(isset($address)) {
$address = htmlentities($address);
}
It looks to me like legacy code that probably was a replacement for (or perhaps in addition to) 'magic quoting' when 'register globals' was turned on. Probably so they could do some pseudo escaping of variables before database inserts and or page echos.

Is =! a declaration and is that why this alternating conditional works?

I have a terrible confession. I've been using variations of the below for ages.
for($x=0;10>$x;++$x){
echo '<li style="color:#'.(($c=!$c)? "fff":"eee").'">example $x</li>";
}
My dilemma is that I don't entirely understand how it works. I know that $c=!$c makes the ternary conditional alternate, but I don't understand how. Googling "php =!" and the likes yields nothing helpful (no surprise given the query).
!= is an operator, but this uses =!
Is this a ternary conditional declaration? If so, how does this one work? I understand the general conditional declarations, but not this one... assuming it even is one.
Any answer or link to documentation would be greatly appreciated.
They are two separate operators. You should read it as
$c = !$c;
In other words, assign the result of the expression !$c back to the variable $c. So indeed, it toggles the value of $c.
Additionally, an assignment like this also returns the assigned value, so you can evaluate it immediately. So in words, the expression ($c=!$c)? "fff":"eee" says:
"Invert the value of $c. If the new value is true, return 'fff', otherwise return 'eee'."
It's not an operator, it just needs better spacing:
$x = !$x;
it's just inverting the value.
=! is not an operator. It is two: = means assignment, and ! means negation.
If $c is true, then !$c is false (and vice versa).
And assignments evaluate to their new value.
You're setting $c to be not itself. So if $c == true you are saying $c = not true, I.e. false which will also count as false for the ternary.
Next iteration you set $c = not false I.e. true and so on.

Assignment statement with AND operator

Can any one explain me following construct.
I do googling for this about 2 hours but can't understand.
public function __construct($load_complex = true)
{
$load_complex and $this->complex = $this->getComplex();
}
See: http://www.php.net/manual/en/language.operators.logical.php
PHP uses intelligent expression evaluation. If any of AND's operands evaluates to false, then there is no reason to evaluate other, because result will be false.
So if $load_complex is false there is no need to evaluate $this->complex = $this->getComplex();
This is some kind of workaround, but I do not suggest to use it, because it makes your code hard to read.
Specifically to your example $this->complex = $this->getComplex() if and only if $load_complex is set to true.
LIVE DEMO
NOTE: If any one of OPERAND result becomes 'false' in short
circuit AND evaluation means, the part of statement will be
OMITTED because there is no need to evaluate it.
Dont code like below line because, you may get probably logical
error while you are putting Expression instead of assigning values
to the variable on LEFT HAND SIDE...
$load_complex and $this->complex = $this->getComplex();
I have modified below with conditinal statement for your needs...
if($load_complex and $this->complex) {
$this->getComplex();
}

Ternary if statement involving php class

Can someone please explain to me the following line of php?
($myobjectfunction = object::function('letsgo')) ? eval($myobjectfunction) : false;
I understand objects and their functions. Is this php saying if $myobjectfunction is defined then eval $myobjectfunction, otherwise do nothing? Because in the code I am reading, object hasn't yet been defined before this line (sometimes).
This line assigns the returned value from the function object::function('letsgo') to the variable $myobjectfunction. If the return was a "truthy" value (evaluates to boolean TRUE), the contents of that variable are then evaluated as PHP code (eval). If the initial return was FALSE, no further action is taken. The false at the end basically does nothing.
This works because PHP will return the value from an assignment, even though it isn't usually used for anything. In the case of your bit of code, however, the return from the assignment is used to determine which branch of the ternary operator to take since it is enclosed in parentheses.
$x = 3;
// returns 3 even if we don't use it...
This is an unusual idiom, because the parentheses are around the initial assignment.
($myobjectfunction = object::function('letsgo')) ? eval($myobjectfunction) : false;
//^^---------------------------------------------^^^
A more typical usage of the ternary operator would assign the output of either side of the ? to the variable on the left, based on the condition to the right of the = like:
$myobjectfunction = object::function('letsgo') ? $someothervalue : false;
It's difficult to tell exactly what's going on here. I'm assuming you have substituted actual values in order to 'simplify' the example, but the use of keywords actually clouds the matter.
The declaration of the class 'object' doesn't need to be before this statement, so long as the object class is defined at some point during the code execution.
This code is equivalent to:
$myobjectfunction = object::function('letsgo');
if( $myobjectfunction ) {
eval( $myobjectfunction );
}
else {
false;
}
In other words, assign the result of object::function( 'letsgo' ) to a variable. If that variable is "truthy" (i.e. not false, null, or 0, or another value that evaluates like false) then eval its contents; otherwise do nothing.
ya you pretty much got it, well its saying IF $myobjectfunction has successfully been returned a positive result (ie: not false, 0, or null) the eval the new variable object, but i probably wouldnt use "false" in the else bit., id probaby use null.
Now for this to do anything, "object" does need to be defined
this is a strange piece of code though, in my own honest opinion

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

Categories