callable php что такое

Callbacks / Callables

Callbacks can be denoted by callable type hint as of PHP 5.4. This documentation used callback type information for the same purpose.

Some functions like call_user_func() or usort() accept user-defined callback functions as a parameter. Callback functions can not only be simple functions, but also object methods, including static class methods.

Passing

A method of an instantiated object is passed as an array containing an object at index 0 and the method name at index 1. Accessing protected and private methods from within a class is allowed.

Static class methods can also be passed without instantiating an object of that class by passing the class name instead of an object at index 0. As of PHP 5.2.3, it is also possible to pass ‘ClassName::methodName’.

Apart from common user-defined function, anonymous functions can also be passed to a callback parameter.

Пример #1 Callback function examples

// An example callback function
function my_callback_function () <
echo ‘hello world!’ ;
>

// An example callback method
class MyClass <
static function myCallbackMethod () <
echo ‘Hello World!’ ;
>
>

// Type 1: Simple callback
call_user_func ( ‘my_callback_function’ );

// Type 4: Static class method call (As of PHP 5.2.3)
call_user_func ( ‘MyClass::myCallbackMethod’ );

// Type 5: Relative static class method call (As of PHP 5.3.0)
class A <
public static function who () <
echo «A\n» ;
>
>

class B extends A <
public static function who () <
echo «B\n» ;
>
>

Пример #2 Callback example using a Closure

Результат выполнения данного примера:

Источник

Callable php что такое

Передача

Метод созданного объекта ( object ) передаётся как массив, содержащий объект по индексу 0 и имя метода по индексу 1. Доступ к закрытым и защищённым методам разрешён изнутри класса.

Помимо обычных пользовательских функций, в качестве callback-функции можно передавать анонимные функции и стрелочные функции.

Как правило, любой объект, реализующий __invoke(), также может быть передан в параметр callback.

Пример #1 Пример callback-функции

// Пример callback-функции
function my_callback_function () <
echo ‘Привет, мир!’ ;
>

// Пример callback-метода
class MyClass <
static function myCallbackMethod () <
echo ‘Привет, мир!’ ;
>
>

// Тип 1: Простой callback
call_user_func ( ‘my_callback_function’ );

// Тип 4: Вызов статического метода класса
call_user_func ( ‘MyClass::myCallbackMethod’ );

// Тип 5: Вызов относительного статического метода
class A <
public static function who () <
echo «A\n» ;
>
>

class B extends A <
public static function who () <
echo «B\n» ;
>
>

Пример #2 Пример callback-функции с использованием замыкания

Результат выполнения данного примера:

User Contributed Notes 17 notes

When specifying a call back in array notation (ie. array($this, «myfunc») ) the method can be private if called from inside the class, but if you call it from outside you’ll get a warning:

Warning: array_walk() expects parameter 2 to be a valid callback, cannot access private method mc::walkIt() in /in/tfh7f on line 22

— Using the name of a function as string has worked since at least 4.3.0
— Calling anonymous functions and invokable objects has worked since 5.3.0
— Using the array structure [$object, ‘method’] has worked since 5.4.0

Note, however, that the following are not supported when calling callbacks as variable functions, even though they are supported by call_user_func():

— Calling static class methods via strings such as ‘foo::doStuff’
— Calling parent method using the [$object, ‘parent::method’] array structure

All of these cases are correctly recognized as callbacks by the ‘callable’ type hint, however. Thus, the following code will produce an error «Fatal error: Call to undefined function foo::doStuff() in /tmp/code.php on line 4»:

static function doStuff () <
echo «Hello World!» ;
>
>

foo :: callIt ( ‘foo::doStuff’ );
?>

The code would work fine, if we replaced the ‘$callback()’ with ‘call_user_func($callback)’ or if we used the array [‘foo’, ‘doStuff’] as the callback instead.

You can use ‘self::methodName’ as a callable, but this is dangerous. Consider this example:

class Foo <
public static function doAwesomeThings () <
FunctionCaller :: callIt ( ‘self::someAwesomeMethod’ );
>

public static function someAwesomeMethod () <
// fantastic code goes here.
>
>

Foo :: doAwesomeThings ();
?>

This results in an error:
Warning: class ‘FunctionCaller’ does not have a method ‘someAwesomeMethod’.

For this reason you should always use the full class name:
:: callIt ( ‘Foo::someAwesomeMethod’ );
?>

I believe this is because there is no way for FunctionCaller to know that the string ‘self’ at one point referred to to `Foo`.

> As of PHP 5.2.3, it is also possible to pass ‘ClassName::methodName’

You can also use ‘self::methodName’. This works in PHP 5.2.12 for me.

If you pass a callable method to a function with a callable type declaration, the error message is misleading:

class X <
protected function foo (): void <>
>

I needed a function that would determine the type of callable being passed, and, eventually,
normalized it to some extent. Here’s what I came up with:

Читайте также:  card2card visa direct rus пришли деньги на карту что это

?>

Hope someone else finds it useful.

Источник

Применение замыканий в PHP

Введение в PHP 5.3 замыканий — одно из главных его новшеств и хотя после релиза прошло уже несколько лет, до сих пор не сложилось стандартной практики использования этой возможности языка. В этой статье я попробовал собрать все наиболее интересные возможности по применению замыканий в PHP.

Для начала рассмотрим, что же это такое — замыкание и в чем его особенности в PHP.

Как видим, замыкание как и лямбда-функция представляют собой объект класса Closure, коорый хранит переданные параметры. Для того, чтобы вызывать объект как функцию, в PHP5.3 ввели магический метод __invoke.

Используя конструкцию use мы наследуем переменную из родительской области видимости в локальную область видимости ламбда-функции.
Ситаксис прост и понятен. Не совсем понятно применение такого функционала в разработке web-приложений. Я просмотрел код нескольких совеременных фреймворков, использующих новые возможности языка и попытался собрать вместе их различные применения.

Функции обратного вызова

Самое очевидное применение анонимных функций — использование их в качестве функций обратного вызова (callbacks). В PHP имеется множество стандартных функций, принимающих на вход тип callback или его синоним callable введенный в PHP 5.4. Самые популярные из них array_filter, array_map, array_reduce. Функция array_map служит для итеративной обработки элементов массива. Callback-функция применяется к каждому элементу массива и в качестве результата выдается обработанный массив. У меня сразу возникло желание сравнить производительность обычной обработки массива в цикле с применением встроенной функции. Давайте поэкспериментируем.

Как видно, накладные расходы на большое количество вызовов функций дают ощутимый спад в производительности, чего и следовало ожидать. Хотя тест синтетический, задача обработки больших массивов возникает часто, и в данном случае применение функций обработки данных может стать тем местом, которе будет существенно тормозить ваше приложение. Будьте осторожны. Тем не менее в современных приложениях такой подход используется очень часто. Он позволяет делать код более лаконичным, особенно, если обработчик объявляется где-то в другом месте, а не при вызове.

По сути в данном контексте применение анонимных функций ничем не отличается от старого способа передачи строкового имени функции или callback-массива за исключением одной особенности — теперь мы можем использовать замыкания, то есть сохранять переменные из области видимости при создании функции. Рассмотрим пример обработки массива данных перед добавлением их в базу данных.

Очень удобно применять анонимные функции и для фильтрации

События.

Замыкания идеально подходят в качестве обработчиков событий. Например

Вынос логики в обработчики событий с одной стороны делает код более чистым, с другой стороны — усложняет поиск ошибок — поведение системы иногда становится неожиданным для человека, который не знает, какие обработчики навешаны в данный момент.

Валидация

Замыкания по сути сохраняют некоторую логику в переменной, которая может быть выполнена или не выполнена в по ходу работы скрипта. Это то, что нужно для реализации валидаторов:

В последнем случае мы применяем функцию высшего порядка, которая возвращает другую функцию — валидатор с предустановленными границами значений. Применять валидаторы можно, например, так.

Использование в формах классический пример. Также валидация может использоваться в сеттерах и геттерах обычных классов, моделях и т.д. Хорошим тоном, правда, считается декларативная валидация, когда правила описаны не в форме функций, а в форме правил при конфигурации, тем не менее, иногда такой подход очень кстати.

Выражения

В Symfony встречается очень интересное применение замыканий. Класс ExprBuilder опеделяет сущность, которая позволяет строить выражения вида

В Symfony как я понял это внутренний класс, который используется для создания обработки вложенных конфигурационных массивов (поправьте меня, если не прав). Интересна идея реализации выражений в виде цепочек. В принципе вполне можно реализовать класс, который бы описывал выражения в таком виде:

Применение, конечно, экспериментально. По сути — это запись некоторого алгоритма. Реализация такого функционала достаточно сложна — выражение в идеальном случае должно хранить дерево операций. Инетересна концепция, может быть где-то такая конструкция будет полезна.

Роутинг

Во многих мини-фреймворках роутинг сейчас работает на анонимных функциях.

Достаточно удобно и лаконично.

Кеширование

На хабре это уже обсуждалось, тем не менее.

Здесь метод get проверяет валидность кеша по ключу ‘users.list’ и если он не валиден, то обращается к функции за данными. Третий параметр определяет длительность хранения данных.

Инициализация по требованию

Допустим, у нас есть сервис Mailer, который мы вызываем в некоторых методах. Перед использованием он должен быть сконфигурирован. Чтобы не инициализировать его каждый раз, будем использовать ленивое создание объекта.

Инициализация объекта произойдет только перед самым первым использованием.

Изменение поведения объектов

Иногда бывает полезно переопределить поведение объектов в процессе выполнения скрипта — добавить метод, переопределить старый, и т.д. Замыкание поможет нам и здесь. В PHP5.3 для этого нужно было использовать различные обходные пути.

Читайте также:  cpl что это такое фильтр

В принципе можно и переопределять старый метод, однако только в случае если он был определен подобным путем. Не совсем удобно. Поэтому в PHP 5.4 появилось возможность связать замыкание с объектом.

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

Передача как параметры по умолчанию в методы доступа к данным

Пример получения значения из массива GET. В случае его отсутствия значение будет получено путем вызова функции.

Функции высшего порядка

Здесь уже был пример создания валидатора. Приведу пример из фреймворка lithium

Метод возвращает замыкание, которое может быть использовано потом для записи сообщения в кеш.

Передача в шаблоны

Иногда в шаблон удобно передавать не просто данные, а, например, сконфигурированную функцию, которую можно вызвать из кода шаблона для получения каких либо значений.

В данном случае в шаблоне генерировалось несколько ссылок на сущности пользователя и в адресах этих ссылок фигурировал его логин.

Рекурсивное определение замыкания

Напоследок о том, как можно задавать рекурсивные замыкания. Для этого нужно передавать в use ссылку на замыкание, и вызывать ее в коде. Не забывайте об условии прекращения рекурсии

Многие из примеров выглядят натянуто. Сколько лет жили без них — и ничего. Тем не менее иногда применение замыкания достаточно естественно и для PHP. Умелое использование этой возможности позволит сделать код более читаемым и увеличить эффективность работы программиста. Просто нужно немного подстроить свое мышление под новую парадигму и все станет на свои места. А вообще рекомендую сравнить, как используются такие вещи в других языках типа Python. Надеюсь, что кто-нибудь нашел для себя здесь что-то новое. И конечно, если кто-то знает еще какие-нибудь интересные применения замыканий, то очень жду ваши комментарии. Спасибо!

Источник

is_callable

(PHP 4 >= 4.0.6, PHP 5, PHP 7, PHP 8)

is_callable — Проверяет, что значение может быть вызвано как функция в текущей области видимости

Описание

Список параметров

Значение для проверки

Получает «вызываемое имя». В примере ниже это «someClass::someMethod». Следует иметь в виду, что хотя запись someClass::SomeMethod() означает вызываемый статический метод, это не так.

Возвращаемые значения

Примеры

Пример #1 Пример использования is_callable()

// Как проверить переменную, чтобы узнать, может ли она быть вызвана
// как функция.

//
// Простая переменная, содержащая имя функции
//

//
// Массив, содержащий метод класса
//

$anObject = new someClass ();

Пример #2 is_callable() и конструкторы

Функция is_callable() не считает конструкторы за callable.

class Foo
<
public function __construct () <>
public function foo () <>
>

Результат выполнения данного примера:

Примечания

Смотрите также

User Contributed Notes 6 notes

If the target class has __call() magic function implemented, then is_callable will ALWAYS return TRUE for whatever method you call it.
is_callable does not evaluate your internal logic inside __call() implementation (and this is for good).
Therefore every method name is callable for such classes.

Hence it is WRONG to say (as someone said):
. is_callable will correctly determine the existence of methods made with __call.

Example:
class TestCallable
<
public function testing ()
<
return «I am called.» ;
>

class Test
<
public function method1 () < >
public static function method2 () < >
>

is_callable generates an [E_STRICT] error if the tested method cannot be called staticly. (and returns the good value)

I used @is_called
i’m using php 5.2.1

The story about __call() is a bit more complicated unfortunately. It will always return true ONLY if you pass an instance of a class, not if you pass the class name itself:

is_callable ([ MyClass ::class, ‘method’ ]); // true
is_callable ([new MyClass (), ‘method’ ]); // true
is_callable ([ MyClass ::class, ‘other’ ]); // false.
is_callable ([new MyClass (), ‘other’ ])); // true

Note that, for the purpose of this function, an abstract method, although necessarily non-callable since it does not have a body, is still considered to be callable:

abstract class Foo <
abstract function bar ();
>

is_callable() does _not_ check wheter this function is disabled by php.ini’s disable_functions

Источник

Готовимся к собеседованию по PHP: псевдотип «callable»

Не секрет, что на собеседованиях любят задавать каверзные вопросы. Не всегда адекватные, не всегда имеющие отношение к реальности, но факт остается фактом — задают. Конечно, вопрос вопросу рознь, и иногда вопрос, на первый взгляд кажущийся вам дурацким, на самом деле направлен на проверку того, насколько хорошо вы знаете язык, на котором пишете.

Вторая часть серии статей посвящена одному из самых сложных и объемных вопросов о современном PHP — что такое «callable»? Я постарался свести в один текст некий минимум знаний об этом вопросе.

Что такое callable?

Callable — это специальный псевдотип данных в PHP, означающий «нечто, что может быть вызвано как функция». Как будет видно ниже, значения этого псевдотипа могут быть самых разных реальных типов, но всегда есть нечто, что их объединяет — это способность быть использованными в качестве функции.

Читайте также:  app service что это пополнение счета тинькофф

А можно пример?

Да легко. Самый часто используемый в современном языке вариант callable — это анонимная функция.

Функция is_callable() как раз проверяет — принадлежит ли переданное ей значение псевдотипу callable. Разумеется, анонимная функция принадлежит этому псевдотипу и is_callable() вернёт true.

Анонимные функции можно присваивать переменным и затем вызывать с помощью этих переменных (что и продемонстрировано в примере). Разумеется, анонимная функция может быть передана в качестве аргумента в другую функцию или быть возвращена функцией с помощью оператора return, что вместе с семейством функций вроде array_map или array_reduce открывает для нас дорогу к функциональному программированию (узкую, надо сказать дорожку, все-таки PHP изначально не функциональный язык).

В PHP существует специальный системный класс Closure. Когда вы создаете новую анонимную функцию, по сути вы неявно создаете объект этого класса. Подробнее об этом можно прочитать в мануале: php.net/manual/ru/class.closure.php

Немного путаницы. Авторы версии 5.3, в которой впервые появился современный синтаксис анонимных функций, перепутали два понятия — собственно анонимная функция (лямбда-функция) и замыкание (замыкание переменной на контекст этой анонимной функции). Именно поэтому анонимные функции реализованы в языке с помощью системного класса Closure, а не, к примеру, Lambda, как стоило бы ожидать. Имейте этот факт в виду на собеседовании — многие интервьюеры сами путают понятия «лямбда-функция» и «замыкание». Впрочем, подробный рассказ о том, что такое «замыкание», выходит за рамки этой статьи.

Строка как callable и небольшая историческая справка

Строки в PHP вполне могут быть callable! В этом случае интерпретатор будет искать обычную, неанонимную функцию с именем, совпадающим с данной строкой и, в случае успеха, вызовет такую функцию.

Таким образом можно вызывать как свои функции, так и библиотечные. Есть ряд ограничений — нельзя вызвать isset(), empty() и другие функции, которые фактически являются конструкциями языка.

Стоит заметить, что callable-строка может содержать в себе конструкцию вида ‘ClassName::method’ — это не возбраняется, такие строки тоже будут callable. Обратите внимание на особенность — скобки списка аргументов в таком случае не пишутся!

Вас могут попытаться подловить вопросом — а как давно в PHP появились анонимные функции? Корректный ответ таков: «Современный синтаксис появился в версии 5.3, а ранее, со времен PHP 4, существовал способ создания анонимных функций с помощью функции create_function() Разумеется, сейчас этот способ имеет лишь исторический интерес. И должен у любого уважающего себя программиста вызывать такие же чувства, как оператор goto и функция eval() — желание никогда это не писать.»

Почему я пишу об этом казусе здесь? Дело в том, что на самом деле create_function() не создавала лямбда-функцию в современном понимании, фактически эта функция создавала именованную функцию с именем наподобие «lambda_1» и возвращала ее имя. А дальше работал уже знакомый нам механизм, когда string является callable

Callable массивы

Массивы в PHP тоже могут быть callable! Есть два основных случая, когда это работает. Проще всего показать их на примере:

Итак, массив, в котором нулевой элемент — это имя класса, а первый — имя статического метода, является callable. Ровно также, как и массив, состоящий из объекта и имени его динамического метода.

Callable объекты

Да, в PHP возможно и такое. Объект вполне может быть «функцией», достаточно лишь определить в классе магический метод __invoke():

Метод __invoke() будет автоматически вызван при попытке использования объекта, как функции.

Тайп-хинтинг

В современных версиях PHP, начиная с 5.4, появилась возможность указывать псевдотип callable в качестве хинта типа аргумента функции.

В случае, если переданное значение не будет callable, попытка вызова функции с таким аргументом приведет к фатальной ошибке «Catchable fatal error: Argument 2 passed to filter() must be callable»

Вместо заключения

Callable — одна из самых сложных и запутанных тем при изучении основ PHP. С одной стороны мы имеем современный строгий и чистый синтаксис лямбда-функций и замыканий, прекрасную возможность __invoke(), а с другой стороны — огромное и уже фактически ненужное историческое наследие, которое, видимо, никогда не будет выпилено из языка.

Знать это наследие важно. И не только потому, что в вашей работе с огромной вероятностью придется столкнуться со старым кодом, в котором могут использоваться разные трюки, вроде create_function(). В первую очередь знать такие вещи нужно для собственного самосовершенствования, чтобы понимать все плюсы и минусы разных подходов, конструкций и парадигм, и уметь выбрать нужные в нужный момент времени.

И, разумеется, чтобы не упасть в грязь лицом на собеседовании 🙂

Источник

Сказочный портал