php is_function (), щоб визначити, чи є змінна функцією


89

Я був дуже радий прочитати про анонімні функції в php, які дозволяють вам оголосити змінну, яка є функцією простіше, ніж ви могли б зробити з create_function . Тепер мені цікаво, чи є у мене функція, яка передає змінну, як я можу перевірити її, щоб визначити, чи є це функцією? Функції is_function () ще немає, і коли я роблю var_dump змінної, яка є функцією ::

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

Я отримую це:

object(Closure)#8 (0) { } 

Будь-які думки про те, як перевірити, чи це функція?

Відповіді:


141

Використовуйте is_callableдля визначення того, чи є дана змінна функцією. Наприклад:

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

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

10
is_callable () буде чудово працювати, незалежно від того, передаєте ви анонімну функцію, ім'я функції як рядок або дійсний масив зворотного виклику PHP. Якщо ви спеціально хочете перевірити лише анонімні функції, то вам потрібно щось на зразок того, що сказав Гамбо: переконайтесь, що параметр є об’єктом, і переконайтеся, що це екземпляр Закриття.
Провулок

2
Що робити, якщо я хочу перевірити, чи є це мозоль чи струна, і зробити для них різні речі. Я не хочу, щоб значення рядка випадково сприймалося як зворотний виклик.
Герман

3
@German Просто спочатку перевірте, якщо is_string ($ func), а потім як другу перевірку за допомогою is_callable ($ func)
Heroselohim

4
Фрагмент коду вгорі викликав у мене проблеми. Я призначив рядок із написом "Дата", а потім оброблявся як закриття та виконувався. Правильний спосіб - якщо (($ змінної instanceof Closure) && is_callable ($ variable)) {...}
Василь Муса

1
Чому екземпляр закриття І можна викликати. Коли закриття не можна викликати? Не здивувався б, якби був час, але мені цікаво, навіщо нам потрібні обидві перевірки.
Джоель М

34

Ви можете використовувати, function_existsщоб перевірити, чи є функція із вказаною назвою. А щоб поєднати це з анонімними функціями, спробуйте наступне:

function is_function($f) {
    return (is_string($f) && function_exists($f)) || (is_object($f) && ($f instanceof Closure));
}

Дякую за це! Мій додаток дозволяє користувачам вказувати власну функцію хешування або по черзі надавати аргумент для hash (). Але деякі допустимі алгоритми хешування також є вбудованими в PHP і, отже, викликаються (наприклад, 'md5', 'sha1'). is_object()і instanceof Closureце набагато надійніший спосіб перевірити це!
njbair

Видаліть виклики is_string і function_exists, і це функція, яку ви хочете використовувати для виявлення лямбда-функцій. Дякую!
Джек

30

Якщо ви хочете лише перевірити, чи є змінна анонімною функцією, а не викликається рядком або масивом, використовуйте instanceof.

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

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

Анонімні функції (типу, додані в PHP 5.3) завжди є екземплярами Closureкласу та кожним екземпляромClosure класу є анонімною функцією.

У PHP є інший тип речей, які можна вважати функцією, і це об’єкти, що реалізують __invokeмагічний метод. Якщо ви хочете включити їх (при цьому виключаючи рядки та масиви), використовуйте method_exists($func, '__invoke'). Це все одно включатиме закриття, оскільки закриття застосовується __invokeдля забезпечення послідовності.


8
Це особливо корисно, оскільки is_callable()спробує знайти метод для виклику на основі переданого рядка або масиву, який може автоматично завантажувати класи та не бути поведінкою, яку ви очікуєте / вимагаєте.
spikyjt

2
function is_function($f) {
    return is_callable($f) && !is_string($f);
}

У майбутньому PHP може змінити gettype () з Object на Callable, як це роблять інші мови. Отже, ця відповідь, мабуть, найкращий шлях. Але це можна оптимізувати як: return! Is_string ($ f) &&! Is_array ($ f) && is_callable ($ f).
Александр Т.

0

У php допустимими викликами можуть бути функції, ім'я функцій (рядки) та масиви форм ['className', 'staticMethod']або [$object, 'method'], тому для виявлення лише функцій потрібно виключити рядки та масиви:

function isFunction($callable) {
    return $callable && !is_string($callable) && !is_array($callable) && is_callable($callable);
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.