Моя цель – поставить сложную логику в оператор if (). Предположим, у меня есть массив значений, и я собираюсь выполнить немного кода, если все в моем массиве отличное от нуля. Обычно я могу сказать: $valid = true
, foreach
my array и set $valid = false
когда найден нуль. Тогда я запустил бы свой код, if ($valid)
. В качестве альтернативы, я мог бы включить мой цикл в функцию и поместить функцию intop my if()
.
Но я ленив, поэтому я бы предпочел не гадать с кучей «правильных» флагов, и я бы предпочел написать совершенно новую функцию, которая используется только в одном месте.
Итак, скажем, у меня есть это:
if ($q = function() { return 'foo'; }) { echo $q; } else { echo 'false'; }
Я ожидал, что if
получит 'foo'
, который оценивается как true. Мое закрытие привязано к $q
и оператор выполняется. $q
возвращает строку foo
, и 'foo' печатается.
Вместо этого я получаю ошибку. Object of class Closure could not be converted to string
.
Итак, давайте попробуем это:
if (function() { return false; }) { echo 'foo'; } else { echo 'true'; }
Я ожидал, что моя функция вернет false, и «true» будет напечатано. Вместо этого печатается «foo».
Что не так в том, как я это делаю? Похоже, он говорит: «Да, это определенно функция!» вместо «Нет, потому что функция вычисляется как false». Есть ли способ сделать то, что я пытаюсь сделать?
function() { return false; }
function() { return false; }
создает объект типа Closure
, аналогичный new
с другими типами классов, сравнивает следующий код:
$func = function() { return false; };
$func
теперь является объектом. Каждый объект возвращает true в if
. Так
if ($func) { # true } else { # will never go here. }
Возможно, вы захотите сделать это:
if ($func()) { # true } else { # false }
который вызовет объект Closure $func
и даст его возвращаемое значение.
Оба они оценивают истину.
Вы должны заставить функцию выполнить ее использовать в инструкции if.
Попробуй это:
$q = function() { return false; }; if ($q()) { //should not go here. echo $q(); } else { echo 'false'; }
Закрытия PHP реализованы как хак-объекты типа Closure
. Ваш код фактически создает экземпляр объекта этого класса и присваивает его $ q. В PHP результат присваивания – это назначаемое значение, поэтому, по сути, код сводится к
if (new Closure()) { ... }
Вы не выполняете закрытие, когда вы вызываете echo
, поэтому он пытается распечатать закрытие, а не результат закрытия:
echo $q();
Вы создаете анонимную функцию, но не выполняете ее. Когда вы проверяете $q = function() { return 'foo'; }
$q = function() { return 'foo'; }
, вы говорите: «Назначьте ссылку на эту анонимную функцию на $ q и передайте этот тест, если $ q не является нулевым» (не PHP весело?)
Вы должны вызвать закрытие и назначить его результат до $q
перед тестированием и повторить $q
.