callable php что такое

Замыкания в PHP

или в PHP — это обычные функции, но без имени. Давайте рассмотрим пример такой функции:

В этом примере есть анонимная функция, но нет никакого смысла. Возникает вопрос — как использовать такие функции? Следующий пример поможет разобраться в этом:

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

Как на практике используются замыкания

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

Давайте ещё усложним наш пример.

Функция is_callable()

Анонимные функции в PHP реализованы с помощью встроенного класса Closure (PHP 5 >= 5.3.0, PHP 7). То есть каждая анонимная функция является объектом этого класса.

Конструкция use

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

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

Аргументы в анонимных функциях

В анонимную функцию можно передать аргументы. Давайте для примера передадим один аргумент в нашу функцию.

С аргументами всё очень просто, тут анонимные функции ничем не отличаются от обычных.

Функция preg_replace_callback

Я обещал несколько встроенных в PHP функций, которые принимают в качестве аргумента замыкание, вот одна из них: preg_replace_callback

preg_replace_callback — выполняет поиск по регулярному выражению и замену с использованием callback-функции (замыкания).

Это краткий синтаксис, подробнее про возможности этой функции можно почитать на сайте мануала по PHP.

Функция call_user_func

Функция call_user_func — вызывает пользовательскую функцию, указанную в первом параметре. Возвращает результат функции, или FALSE в случае ошибки.

Примеры использования call_user_func :

Пример использования call_user_func в ООП.

Класс Closure

Также отмечу, что при вызове объекта как функции, вызывается магический метод __invoke (начиная с PHP5.3).

Источник

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

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

Источник

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

Дата публикации: 2014-02-12

От автора: в данном уроке я хотел бы поговорить о приеме, который достаточно редко используется в создании скриптов на языке PHP, особенно на ранних этапах изучения языка. Речь идет о функциях быстрого вызова. Поэтому в данном уроке мы разберем, что это такое и каких видов они бывают.

1. Постановка задачи

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

Читайте также:  что находится под мамаевым курганом

Бесплатный курс по PHP программированию

Освойте курс и узнайте, как создать динамичный сайт на PHP и MySQL с полного нуля, используя модель MVC

В курсе 39 уроков | 15 часов видео | исходники для каждого урока

Для чтения этих файлов предусмотрен специальный класс, следующего содержания:

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

2. Модернизация класса

Прямой вызов функции: function(). Функции обратного вызова обычно передаются как параметр для другой функции. И при этом мы передаем указатель (ссылку) на функцию. Сейчас давайте изменим код метода get_numbers(), следующим образом:

Источник

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:

?>

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 для этого нужно было использовать различные обходные пути.

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

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

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

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

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

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

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

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

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

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

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

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

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

Источник

Образовательный портал