What do PHP closures return in IF statements?

两盒软妹~` 提交于 2019-12-23 08:29:10

问题


My goal is to put some complex logic in an if() statement. Let's say I have an array of values and I'm going to execute a bit of code if everything in my array is nonzero. Normally, I could say, $valid = true, foreach my array, and set $valid = false when a zero is found. Then I'd run my code if ($valid). Alternatively, I could put my loop into a function and put the function intop my if().

But I'm lazy, so I'd rather not muck about with a bunch of "valid" flags, and I'd rather not write a whole new function that's only being used in one place.

So let's say I have this:

if ($q = function() { return 'foo'; }) {
  echo $q;
}
else {
  echo 'false';
}

I was expecting that the if gets 'foo', which evaluates to true. My closure is committed to $q and the statement executes. $q returns string foo, and 'foo' is printed.

Instead, I get the error Object of class Closure could not be converted to string.

So let's try this instead:

if (function() { return false; }) {
  echo 'foo';
}
else {
  echo 'true';
}

I was expecting that my function would return false and 'true' would be printed. Instead, 'foo' is printed.

What is wrong about the way that I'm going about this? It seems like it's saying, "Yep, that sure is a function!" instead of "No, because the function evaluated to false." Is there a way to do what I'm trying to do?


回答1:


function() { return false; } creates an object of type Closure, similar to new with other class-types, compare the following code:

$func = function() { return false; };

$func now is an object. Each object returns true in an if clause. So

if ($func)
{
  # true
} else {
  # will never go here.
}

You might want to do this instead:

if ($func())
{
  # true
} else {
  # false
}

which will invoke the Closure object $func and give it's return value.




回答2:


Both of those evaluate to true.

You need to make the function execute to use it in the if statement.

Try this:

$q = function() { return false; };
if ($q()) { //should not go here.
  echo $q();
}
else {
  echo 'false';
}

Demo: http://codepad.viper-7.com/Osym1s




回答3:


PHP's closures are implemented as a hack - objects of type Closure. Your code is actually instantiating an object of this class, and assigning it to $q. In PHP, the result of assignment is the value being assigned, so in effect you code boils down to

if (new Closure()) { ... }



回答4:


You're not executing the closure when you call echo, thus it's trying to print out the closure, not the result of the closure:

echo $q();



回答5:


You are creating an anonymous function, but never executing it. When you test $q = function() { return 'foo'; }, what you're saying is "Assign a reference to this anonymous function to $q, and pass this test if $q is not null" (isn't PHP fun?)

You need to invoke the closure and assign its result to $q before testing and echoing $q.



来源:https://stackoverflow.com/questions/8040067/what-do-php-closures-return-in-if-statements

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!