Suppose we have this method in a class :
public static function example($s, $f = false)
{
(static::$i['s'] === null or $f) and static::$i['s'] = $s;
return new static;
}
would you please give me any hint what is the meaning of this line of code?
(static::$i['s'] === null or $f) and static::$i['s'] = $s;
is it a conditional statement? or something like a ternary operator?
Thanks
They are trying to be clever by using the short circuiting that happens when dealing with logical operators like this. This is what they are doing:
if ((static::$info['syntax'] === null) || $force) {
static::$info['syntax'] = $syntax;
}
If you want to see how this short circuiting works with the &&/and operator:
$a = 'something';
false && $a = 'else';
echo $a;
// output: something
Since the first part is false, it never even runs the statement on the other side since this logical operation already evaluates to false.
Related
I have the following code in numerous places (thousands of places) around my project:
$foo = isset($mixed) ? $mixed : null;
Where $mixed can be anything: array, array element, object, object property, scalar, etc. For example:
$foo = isset($array['element']) ? $array['element'] : null;
$foo = isset($nestedArray['element']['key']) ? $nestedArray['element']['key'] : null;
$foo = isset($object->prop) ? $object->prop : null;
$foo = isset($object->chain->of->props) ? $object->chain->of->props : null;
Is there a way to write this repeated logic as a (simple) function? For example, I tried:
function myIsset($mixed)
{
return isset($mixed) ? $mixed : null;
}
The above function looks like it would work, but it does not in practice. For example, if $object->prop does not exist, and I call myIsset($object->prop)), then I get fatal error: Undefined property: Object::$prop before the function has even been called.
Any ideas on how I would write such a function? Is it even possible?
I realize some solutions were posted here and here, but those solutions are for arrays only.
PHP 7 has a new "Null coalescing operator" which does exactly this. It is a double ?? such as:
$foo = $mixed ?? null;
See http://php.net/manual/en/migration70.new-features.php
I stumbled across the answer to my own question while reading about php references. My solution is as follows:
function issetValueNull(&$mixed)
{
return (isset($mixed)) ? $mixed : null;
}
Calls to this function now look like:
$foo = issetValueNull($array['element']);
$foo = issetValueNull($nestedArray['element']['key']);
$foo = issetValueNull($object->prop);
$foo = issetValueNull($object->chain->of->props);
Hopefully this helps anyone out there looking for a similar solution.
isset is a language construct, not a regular function. Therefore, it can take what would otherwise cause an error, and just return false.
When you call myIsset($object->prop)), the evaluation occurs and you get the error.
See http://php.net/manual/en/function.isset.php
This is the same problem as using typeof nonExistentVariable in JavaScript. typeof is a language construct and will not cause an error.
However, if you try to create a function, you get an error for trying to use an undefined variable.
function isDef(val) {
return typeof val !== 'undefined';
}
console.log( typeof nonExistent !== 'undefined'); // This is OK, returns false
isDef(nonExistent); // Error nonExistent is not defined
You could actually just write it like:
$foo = $mixed?:null;
If you just want to check if it exist do this
function myIsset($mixed)
{
return isset($mixed); // this is a boolean so it will return true or false
}
function f(&$v)
{
$r = null;
if (isset($v)) {
$r = $v;
}
return $r;
}
Why does this code work correctly?
function isLoggedIn(){
return false; //or true
}
if($user = isLoggedIn())
{
echo "Hello ".$user['name']; //if isLoggedIn returns true, this prints
} else {
echo "Please login to proceed!";//if isLoggedIn returns false, this prints
}
I always thought assignment operator inside an if() condition will always evaluate to true since it is only evaluating whether the value of right hand side can be assigned to left hand side...
It's evaluating the value of $user after assigning the return of isLoggedIn() to $user. It's the same as:
$user = isLoggedIn();
if($user) {}
It's especially handy in loops:
while($var = someFunction()) {
//do stuff with $var
}
And more expressions:
if($var = someFunction() && $var !== 'bad') {}
if($var = someFunction() && $var === 'good') {}
In PHP, an assignment operation actually has a return value, and it's the value that was assigned. Your if() condition works for the exact same reason that
$x = $y = $z = 42;
works. This statement will assign the value 42 to all three variables, and is functionally the equivalent of
$z = 42;
$y = $z;
$x = $y;
In your case, your isLoggedIn() function call will execute and return a value. That value assigned to $user. Then that value is "returned" to the if() statement itself and is used for the logic test.
If your function had returned boolean false, or a "falsey" value, then the "else" clause would have executed. e.g.
function returns_false() {
return false;
}
if ($foo = returns_false()) {
echo 'if was true';
} else {
echo 'if was false'; // this line will get executed
}
Even though the assignment operation succeeded, it's the value that got assigned that matters, not the success/failure of the operation. so the "it was false" code path gets executed, because the function call returned a false, which propagated up the decision tree.
The condition considers $user after assignment.
Therefore it will be true or false depending on the value returned by isLoggedIn()
There is one note. Code like this will not work as expected:
if($var = someFunction() && $var !== 'bad') {}
if($var = someFunction() && $var === 'good') {}
Because $var will contain not a value returned by someFunction(), but a boolean value of the whole expression, like this:
$var = (someFunction() && $var !== 'bad');
if($var) {}
To get the result you need you should use brackets:
if(($var = someFunction()) && $var !== 'bad') {}
if(($var = someFunction()) && $var === 'good') {}
You can find details on the php.net website.
It works because the IF is TRUE. Oddly enough it will always be TRUE. Because you are assigning the value when you only use one = sign. If you want to check the contents, you have to use ==.
As everyone has already suggested, there are two parts to the statement:
It assigns the value of isLoggedIn() to $user.
It then returns the same value to whichever construct asked for it. In this case, it's
returned to the if () statement.
It is worth noting that although the if () statement expects to receive a boolean value true or false. If the if () receives a value that isn't a boolean, it is still acceptable in PHP (as well as JavaScript). If any operator or statement receives a value of the wrong type, PHP will convert it to boolean=true in most cases.
Say I have a long(ish) variable, $row['data']['manybullets']['bullets']['bullet'][0], and want to test whether it's set using the ternary operator:
$bulletx =
isset($row['data']['property']['bullets']['bullet'][0]) // condition
? $row['data']['property']['bullets']['bullet'][0] // true
: 'empty'; // false
Is there anyway for me to reference the subject of the expression rather than repeating it. E.g.
$bulletx =
isset($row['data']['property']['bullets']['bullet'][0]) // condition
? SUBJECT // true
: 'empty'; // false
Curious.
PHP supports foo ?: bar but unfortunately this won't work because of the isset() in your condition.
So unfortunately there is no really good way to do this in a shorter way. Besides using another language of course (e.g. foo.get(..., 'empty') in python)
However, if the default value being evaluated in any case is not a problem (e.g. because it's just a static value anyway) you can use a function:
function ifsetor(&$value, $default) {
return isset($value) ? $value : $default;
}
Because of the reference argument this will not throw an E_NOTICE in case of an undefined value.
You can do it like this:
$bulletx = ($r=$row['data']['property']['bullets']['bullet'][0]) ? $r : 'empty';
See working demo
Not really, without triggering an E_NOTICE warning, but if you decide to ignore those you could achieve it like this.
$bulletx =
$row['data']['property']['bullets']['bullet'][0] // true
?: 'empty'; // false
No built-in way, but you can write a wrapper for isset that checks the array keys.
function array_isset(&$array /* ... */) {
$a = $array;
if (! is_array($a)) {
return false;
}
for ($i = 1; $i < func_num_args(); $i++) {
$k = func_get_arg($i);
if (isset($a[$k])) {
$a = $a[$k];
} else {
return false;
}
}
return $a;
}
$bulletx = array_isset($row, 'data', 'property', 'bullets', 'bullet', 0) ?: 'empty';
I like this way, as it keeps the same API as isset() and can make use of the ?: short cut.
First a simple example:
function doReturnSomething()
{
// some logic
if ($resultFromLogic) {
return Default_Model_Something;
}
return false;
}
As you can see, this functions returns a model or false. Now, let's call this function from some place else:
$something = doReturnSomething();
No, I want to put a if-statement to check the variable $something. Let's say:
if (false !== $something) {}
or
if ($something instanceof Default_Model_Something) {}
or
...
Is there a "best practice" for this situation to do? Check for false or use instance of. And are there any consequences for that particular way?
Thank is advance!
Depending on what it is returning, you could just do this:
if(doReturnSomething()) {}
It will return true when an object is returned (Default_Model_Something) and return false when false is returned or a null-value. Just don't use this way when working with numbers because "0" will evaluate to false.
I think that from PHP 5.4 on there is a special notice error for threating a function return in logical statements.
Good pratice is to save result of a function to variable and then use it in any logical statement.
<?php function my($a, $b ,$c){
$total = $a + $b - $c; return $total; }
$myNumber = 0;
echo "Before the function, myNumber = ". $myNumber ."<br />";
$myNumber = my(3, 4, 1); // Store the result of mySum in $myNumber
echo "After the function, myNumber = " . $myNumber ."<br />";
?>
Forgive me if the title doesn't exactly match what I'm asking, I'm having a tough time describing the question exactly.
Consider the following PHP code:
#!/usr/bin/php
<?php
class foo{
function bar()
{
return true;
}
}
if (true && $a = new foo() && $a->bar()) {
echo "true";
} else {
echo "false";
}
It gives
Fatal error: Call to a member function bar() on a non-object
for the $a->bar(); expression.
Consider the following C code:
int main(void)
{
int i = 0;
if (i += 1 && printf("%d\n", i))
{
printf("Done: %d.\n", i);
}
}
It outputs :
0
Done: 1.
Why is this? Since C and PHP claim to short-circuit these expressions and evaluate left to right, I expect a value set in expressions to the left to be used in expressions to the right. Is there something I'm missing?
Your problem right now is with operator precedence. PHP currently evaluates your PHP statement as such:
if (true && $a = ( new foo() && $a->bar() ) )
In which case $a is not defined by the time you try calling $a->bar().
What you really want is this:
if (true && ( $a = new foo() ) && $a->bar())
Using brackets in complex conditions will prevent those kinds of errors from happening.
EDIT: Proof
if(true && $a = true && false) { }
var_dump($a); // bool(false)
if(true && ( $b = true ) && false) { }
var_dump($b); // bool(true)