что такое анонимная функция php

Анонимные функции в PHP: сеанс чёрной магии с разоблачением

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

Дабы не быть голословным:

Забегая вперёд, скажу, что на самом деле это не совсем обычный объект. Давайте разберёмся.

Например, такой код

компилируется в такой набор опкодов:

Блок с описанием тела функции нам не особо интересен, а вот в первом блоке присутствуют два интересных нам опкода: DECLARE_LAMBDA_FUNCTION и INIT_DYNAMIC_CALL. Начнём со второго.

INIT_DYNAMIC_CALL

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

В случае замыкания нас интересует вызов на переменной с объектом, что логично.
Углубляясь в код VM, обрабатывающий этот опкод, мы дойдём до функции zend_init_dynamic_call_object, в которой увидим следующее (нарезка):

Забавно, что привычный всем вызов метода __invoke в терминах VM является попыткой вызова замыкания — get_closure.

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

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

И это таки правда. Функция get_closure для замыкания возвращает не __invoke, а вашу функцию, из которой создавалось замыкание.

Более подробно можете изучить исходники сами — файл zend_closure.c, а мы перейдём к следующему опкоду.

DECLARE_LAMBDA_FUNCTION

И вот на этом месте начинаются не очень приятные новости.

Так что же не так с анонимными функциями?

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

Чтобы понять, где именно поджидают проблемы, разберём случаи, когда происходит создание замыкания.
Замыкание создаётся заново:
а) при каждой обработке опкода DECLARE_LAMBDA_FUNCTION.
Интуитивно — ровно тот кейс, где замыкание смотрится хорошо, но на самом деле новый объект замыкания будет создаваться на каждой итерации цикла.

б) при каждом вызове методов bind и bindTo:
Тут замыкание будет создаваться заново также на каждой итерации.

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

Читайте также:  что значит нубка в wot blitz

Выводы

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

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

Источник

Что такое анонимная функция php

Пример #1 Пример анонимной функции

Замыкания также могут быть использованы в качестве значений переменных; PHP автоматически преобразует такие выражения в экземпляры внутреннего класса Closure. Присвоение замыкания переменной использует тот же синтаксис, что и для любого другого присвоения, включая завершающую точку с запятой:

Пример #2 Пример присвоения анонимной функции переменной

Пример #3 Наследование переменных из родительской области видимости

// Значение унаследованной переменной задано там, где функция определена,
// но не там, где вызвана
$message = ‘мир’ ;
$example ();

// Сбросим message
$message = ‘привет’ ;

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

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

Пример #4 Замыкания и область видимости

// Базовая корзина покупок, содержащая список добавленных
// продуктов и количество каждого продукта. Включает метод,
// вычисляющий общую цену элементов корзины с помощью
// callback-замыкания.
class Cart
<
const PRICE_BUTTER = 1.00 ;
const PRICE_MILK = 3.00 ;
const PRICE_EGGS = 6.95 ;

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

Статические анонимные функции

Анонимные функции могут быть объявлены статически. Это предотвратит их автоматическое связывание с текущим классом. Объекты также не будут с ними связаны во время выполнения.

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

Пример #7 Попытка связать объект со статической анонимной функцией

Источник

Что такое анонимная функция php

В этом разделе помещены уроки по PHP скриптам, которые Вы сможете использовать на своих ресурсах.

Фильтрация данных с помощью zend-filter

Когда речь идёт о безопасности веб-сайта, то фраза «фильтруйте всё, экранируйте всё» всегда будет актуальна. Сегодня поговорим о фильтрации данных.

Контекстное экранирование с помощью zend-escaper

Обеспечение безопасности веб-сайта — это не только защита от SQL инъекций, но и протекция от межсайтового скриптинга (XSS), межсайтовой подделки запросов (CSRF) и от других видов атак. В частности, вам нужно очень осторожно подходить к формированию HTML, CSS и JavaScript кода.

Подключение Zend модулей к Expressive

Expressive 2 поддерживает возможность подключения других ZF компонент по специальной схеме. Не всем нравится данное решение. В этой статье мы расскажем как улучшили процесс подключение нескольких модулей.

Совет: отправка информации в Google Analytics через API

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

Подборка PHP песочниц

Подборка из нескольких видов PHP песочниц. На некоторых вы в режиме online сможете потестить свой код, но есть так же решения, которые можно внедрить на свой сайт.

Читайте также:  что значит дорама с корейского на русский

Совет: активация отображения всех ошибок в PHP

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

Агент

PHP парсер юзер агента с поддержкой Laravel, работающий на базе библиотеки Mobile Detect.

Источник

Замыкания в 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).

Источник

Что такое анонимная функция php

So you will need to explicitly pass them in by reference if your closure cares about their contents over time:

//set up variable in advance
$myInstance = null ;

//$myInstance might be instantiated, might not be
if( SomeBusinessLogic :: worked () == true )
<
$myInstance = new myClass ();
>

Every instance of a lambda has own instance of static variables. This provides for great event handlers, accumulators, etc., etc.

Читайте также:  что значит фонарный столб на руке

In case you were wondering (cause i was), anonymous functions can return references just like named functions can. Simply use the & the same way you would for a named function. right after the `function` keyword (and right before the nonexistent name).

As of PHP 7.0, you can use IIFE(Immediately-invoked function expression) by wrapping your anonymous function with ().

PERFORMANCE BENCHMARK 2017!

I decided to compare a single, saved closure against constantly creating the same anonymous closure on every loop iteration. And I tried 10 million loop iterations, in PHP 7.0.14 from Dec 2016. Result:

a single saved closure kept in a variable and re-used (10000000 iterations): 1.3874590396881 seconds

new anonymous closure created each time (10000000 iterations): 2.8460240364075 seconds

In other words, over the course of 10 million iterations, creating the closure again during every iteration only added a total of «1.459 seconds» to the runtime. So that means that every creation of a new anonymous closure takes about 146 nanoseconds on my 7 years old dual-core laptop. I guess PHP keeps a cached «template» for the anonymous function and therefore doesn’t need much time to create a new instance of the closure!

So you do NOT have to worry about constantly re-creating your anonymous closures over and over again in tight loops! At least not as of PHP 7! There is absolutely NO need to save an instance in a variable and re-use it. And not being restricted by that is a great thing, because it means you can feel free to use anonymous functions exactly where they matter, as opposed to defining them somewhere else in the code. 🙂

public function __destruct ()
<
echo «destructed\n» ;
>
>

new Test ;
echo «finished\n» ;

public static function createClosure ()
<
return function () <
>;
>

When using anonymous functions as properties in Classes, note that there are three name scopes: one for constants, one for properties and one for methods. That means, you can use the same name for a constant, for a property and for a method at a time.

Since a property can be also an anonymous function as of PHP 5.3.0, an oddity arises when they share the same name, not meaning that there would be any conflict.

Consider the following example:

class MyClass <
const member = 1 ;

public function member () <
return «method ‘member'» ;
>

header ( «Content-Type: text/plain» );

$myObj = new MyClass ();

/*
* Establish mock authorisation, call the service; should get
* ‘Service returns: test 1’.
*/
$_SESSION [ ‘is_authorised’ ] = true ;
$service ( ‘test 1’ );

/*
* Remove mock authorisation, call the service; should get ‘Access Denied’.
*/
$_SESSION [ ‘is_authorised’ ] = false ;
$service ( ‘test 2’ );

Источник

Строительный портал