php is_function(), чтобы определить, является ли переменная функцией

Я был очень взволнован, прочитав об анонимных функциях в php, которые позволяют вам объявить переменная, которая является функцией проще, чем вы могли бы сделать с create_function. Теперь мне интересно, есть ли у меня функция, которой передается переменная, как я могу проверить ее, чтобы определить, является ли она функцией? Пока нет функции is_function(), и когда я делаю var_dump переменной, которая является функцией::

$func = function(){
    echo 'asdf';
};
var_dump($func);

Я получаю это:

object(Closure)#8 (0) { } 

Любые мысли о том, как проверить, является ли это функцией?


person Jage    schedule 14.05.2010    source источник


Ответы (5)


Используйте is_callable, чтобы определить, является ли данная переменная функцией. Например:

$func = function()
{  
    echo 'asdf';  
};

if( is_callable( $func ) )
{
    // Will be true.
}
person Jon Benedicto    schedule 14.05.2010
comment
is_callable() будет отлично работать, если вы передаете анонимную функцию, имя функции в виде строки или допустимый массив обратного вызова PHP. Если вы специально хотите проверять только анонимные функции, вам нужно что-то вроде того, что сказал Гамбо: убедитесь, что параметр является объектом, и убедитесь, что он является экземпляром Closure. - person Lane; 03.11.2011
comment
Что, если я хочу проверить, является ли это вызовом или строкой, и сделать для них разные вещи. Я не хочу, чтобы строковое значение было случайно принято в качестве обратного вызова. - person Gherman; 19.08.2014
comment
@German Просто сначала проверьте, если is_string($func), а затем вторую проверку с помощью is_callable($func) - person Heroselohim; 09.01.2015
comment
Фрагмент кода выше доставил мне неприятности. Я имел в виду строку с надписью Date, а затем она была обработана как закрытие и выполнена. Правильный способ: if (($variable instanceof Closure) && is_callable($variable)) {...} - person Basil Musa; 18.12.2015
comment
@BasilMusa это потому, что Date (date(...)) действительно можно вызывать, в этом нет ничего плохого, AFAICS. - person Sz.; 24.11.2016
comment
Спасибо за ошибки. is_callable возвращает true для строк, которые являются именами функций - person Farzher; 12.01.2017
comment
Для методов также есть method_exists(). - person StanE; 18.09.2017
comment
Почему экземпляр закрытия AND вызывается. Когда замыкание не вызывается? Не удивлюсь, если будет время, но мне любопытно, зачем нам оба чека. - person Joel M; 01.01.2020
comment
это неверно, если вы сделаете что-то столь же простое, как is_callabale('array_slice'), он вернет true, и переменная явно НЕ является функцией. - person Rob; 20.03.2020

Вы можете использовать function_exists, чтобы проверить, существует ли функция с заданным именем. И чтобы объединить это с анонимными функциями, попробуйте следующее:

function is_function($f) {
    return (is_string($f) && function_exists($f)) || (is_object($f) && ($f instanceof Closure));
}
person Gumbo    schedule 14.05.2010
comment
Спасибо за это! Мое приложение позволяет пользователям указывать свою собственную хеш-функцию или альтернативно предоставлять аргумент для hash(). Но некоторые из действительных алгоритмов хеширования также являются встроенными в PHP и, следовательно, могут вызываться (например, «md5», «sha1»). is_object() и instanceof Closure — гораздо более надежный способ проверить это! - person njbair; 22.12.2012
comment
Удалите вызовы is_string и function_exists, и это функция, которую вы хотите использовать для обнаружения лямбда-функций. Благодарю вас! - person jack; 10.09.2013
comment
@njbair Я уверен, что вы думали об этом, но что, если кто-то укажет что-то вредоносное в своей собственной хеш-функции? - person Enigma Plus; 11.03.2021
comment
@EnigmaPlus Честно говоря, я понятия не имею, над чем я работал в то время, но я понимаю, что работал над библиотекой, а не над приложением, и что хэш-функция будет указана в коде, а не через внешний интерфейс. пользователь. - person njbair; 12.03.2021

Если вы хотите только проверить, является ли переменная анонимной функцией, а не вызываемой строкой или массивом, используйте instanceof.

$func = function()
{  
    echo 'asdf';  
};

if($func instanceof Closure)
{
    // Will be true.
}

Анонимные функции (такие, которые были добавлены в PHP 5.3) всегда являются экземплярами класса Closure, а каждый экземпляр класса Closure является анонимной функцией.

В PHP есть еще один тип вещей, которые, возможно, можно считать функцией, и это объекты, которые реализуют магический метод __invoke. Если вы хотите включить их (исключая при этом строки и массивы), используйте method_exists($func, '__invoke'). Это по-прежнему будет включать замыкания, поскольку замыкания реализуют __invoke для согласованности.

person Brilliand    schedule 12.12.2014
comment
Это особенно полезно, потому что is_callable() попытается найти метод для вызова на основе переданной строки или массива, который может автоматически загружать классы и может не соответствовать тому поведению, которое вы ожидаете/требуете. - person spikyjt; 16.02.2015

В php допустимыми вызываемыми объектами могут быть функции, имена функций (строки) и массивы форм ['className', 'staticMethod'] или [$object, 'method'], поэтому для обнаружения только функций необходимо исключить строки и массивы:

function isFunction($callable) {
    return $callable && !is_string($callable) && !is_array($callable) && is_callable($callable);
}
person Andrey Izman    schedule 27.02.2020

person    schedule
comment
В будущем PHP может изменить gettype() с Object на Callable, как это уже делают другие языки. Итак, этот ответ, вероятно, лучший путь. Но это можно оптимизировать следующим образом: return !is_string($f) && !is_array($f) && is_callable($f). - person Alexandre T.; 26.12.2019