- Погружение в Closure и анонимные функции в PHP
- Что такое анонимная функция?
- Что такое замыкание в PHP?
- На пути понимания этого
- Некоторые факты об этом классе
- Небольшое пояснение
- Какая польза?
- Некоторые практические варианты использования
- Заключение
- How to use $this in closure in php
- 1. Use the “use” keyword to import the parent object
- 2. Use object binding to bind the closure to the parent object
- 3. Use anonymous classes to create an object with a method
Погружение в Closure и анонимные функции в PHP
Замыкания и анонимность — это то, что мне было трудно изучить во всей экосистеме PHP, не потому, что я, вероятно, сошел с ума, а потому, что нет хорошего и подробного объяснения того, что именно они собой представляют и как их можно использовать.
Я решил покопаться и посмотреть, смогу ли я понять, что такое замыкания в PHP. Здесь я поделюсь с вами, как я это сделал и что я нашел. Хотя мой метод может показаться некоторым из вас ненаучным, я попробовал личную процедуру, на оттачивание которой у меня не ушло много времени.
Что такое анонимная функция?
Безымянная функция . _ Анонимная функция выглядит так:
В отличие от обычных функций, анонимная функция не имеет имени.
Теперь представьте, если вы хотите использовать анонимную функцию, как вы это сделаете? в основном (можно использовать в функциях первого класса) это невозможно сделать. Итак, чтобы помочь в этом, реализована привязка имени, позволяющая хранить всю анонимную функцию в файле variable . Когда это сделано, это variable становится тем, что называется Closure
Что такое замыкание в PHP?
Класс , который ( тип ) используется для представления анонимной функции . Это может звучать очень странно, в PHP есть встроенный класс Closure . Когда создается анонимная функция, ее тип автоматически равен object(Closure) . Помните о динамической типизации PHP. Вот почему на практике Closure является анонимной функцией .
Чтобы доказать это, попробуйте следующее:
Переменная , содержащая анонимную функцию
Когда анонимная функция связана с переменной, эта переменная становится объектом класса Closure , следовательно, также является функцией Closure/anonymous .
На пути понимания этого
Во-первых, попробуйте создать объект/экземпляр класса Closure .
PHP Catchable fatal error: Instantiation of 'Closure' is not allowed
- Класс Closure не предназначен для создания экземпляров; его конструктор имеет значение private .
- Класс ничего не возвращает и не имеет параметров.
Некоторые факты об этом классе
- У него всего 5 методов: __construct() , __invoke() , bindTo() , call() , bind()
- Метод __construct() существует только для того, чтобы запретить создание экземпляра класса
- Это точно не интерфейс
- Класс является окончательным
Небольшое пояснение
Нам не нужно создавать экземпляр Closure , так как PHP делает это каждый раз, когда функция создается без имени, поэтому теперь я могу сделать:
Проблема как его так использовать??
Решение, создайте переменную и сохраните функцию, затем, используя переменную, мы вызываем функцию:
$closureFunction = function() < return true; >; //never forget this semi-colon
Теперь, поскольку это (выглядит) как переменная, мы должны иметь возможность использовать ее разными способами, например, повторяя ее, используя ее в качестве параметра функции или свойства класса и т. д.
echo $closureFunction; // PHP Catchable fatal error: Object of class Closure could not be converted to string;
— Как функция
echo test($closureFunction); //PHP Catchable fatal error: Object of class Closure could not be converted to string
Независимо от того, где вы пытаетесь echo это сделать, вы всегда будете получать эту ошибку. Чтобы доказать это, давайте var_dump посмотрим, что мы пытаемся повторить:
var_dump($closureFunction); var_dump(test($closureFunction));
object(Closure)#1 (0) < >object(Closure)#1 (0)
Переменная, содержащая нашу nameless функцию, на самом деле содержит объект типа Closure .
Что произошло, как функция превратилась в объект?
Прежде чем я отвечу, давайте копнем дальше, установив параметр функции:
$closureFunction = function($var) < return $var; >; function test($var) < return $var; >var_dump($closureFunction); // object(Closure)#1 (1) < ["parameter"]=>array(1) < ["$var"]=>string(10) "" > > var_dump($closureFunction('ok')); // string(2) "ok" echo($closureFunction('ok')); // ok var_dump(test($closureFunction)); //object(Closure)#1 (1) < ["parameter"]=>array(1) < ["$var"]=>string(10) "" > > var_dump(test($closureFunction('ok'))); // string(2) "ok" var_dump(test($closureFunction($closureFunction))); // object(Closure)#1 (1) < ["parameter"]=>array(1) < ["$var"]=>string(10) "" > >
Отсюда пока:
- функция nameless находится в переменной
- мы можем использовать его где угодно, так как можно использовать переменную, кроме ее повторения
- функция становится объектом класса Closure
Объяснение магии:
- Тот факт, что класс Closure реализует __invoke , означает, что мы можем вызывать его экземпляры как вызов функции, например $var() . Если this: $var = function()<>; является объектом Closure , он позволяет нам использовать его $var с таким параметром, как $var($parameter) . В этом случае класс называется вызываемым .
- Замыкания считаются первоклассными типами значений , как и string or integer . Это на самом деле секрет. Закрытие — это тип, определенный в движке PHP как тип, и вы не видите, когда именно они генерируются.
Какая польза?
Их использование зависит в основном от вашего варианта использования и потребностей. Тем не менее, вы можете использовать их как:
— Callables/Callback работают следующим образом:
$items = [1, 2]; $closure = function($x, $y)< echo __FUNCTION__, " got $x and $y"; >; call_user_func_array ($closure , $items );
— Наследование переменных , подобное этому:
$msg = 'Hello'; $closure = function () use ($msg) < var_dump($msg); >; $closure();
— Присвоение переменной
$eat = function($food)< echo "I am eating some ", $food."
"; >; $eat('Bananas'); $eat('Apples');
— чтобы прикрепить состояние следующим образом:
function brand($name) < return function ($slogan) use ($name)< return sprintf('%s : %s', $name, $slogan); >; > $brand = brand('Dell'); print $brand('The power to do more.');
$recursive = function () use (&$recursive) < return $recursive; >; print_r($recursive());
Некоторые практические варианты использования
- В большинстве современных фреймворков замыкания используются для маршрутизации.
- Закрытие также используется при разработке корзин для покупок.
Заключение
Это было исследование закрытий PHP. Надеюсь, вы были достаточно близки с ними. Анонимные функции всегда сложны для понимания и использования.
Что вы должны знать сейчас, так это то, что каждый раз, когда у вас возникает случай/проблема, просто помните и спрашивайте себя, могут ли замыкания быть очень полезными. Вы будете удивлены, как они облегчат вашу жизнь.
Я также признаю, что не могу сказать/объяснить все. Если у вас есть плюс, пожалуйста, добавьте его под этим уроком в качестве комментария. Спасибо за чтение.
How to use $this in closure in php
In PHP, a closure is a function that can be assigned to a variable and passed around like any other data. When using a closure, the `$this` keyword can be used to reference the current object. However, using `$this` in a closure can be tricky, especially when dealing with inheritance.
Here are some guidelines on how to use `$this` in a closure in PHP:
1. Use the “use” keyword to import the parent object
To use `$this` in a closure, you need to import the parent object into the closure. You can do this using the `use` keyword followed by the parent object.
class MyClass < public function myMethod() < $myVar = "Hello world"; $myClosure = function() use ($myVar) < echo $myVar; echo $this->myOtherMethod(); >; $myClosure(); > public function myOtherMethod() < return "This is another method"; >>
In the example above, the `myClosure` function uses the `use` keyword to import the `$myVar` variable and the parent object `$this`. This allows the closure to access the `myOtherMethod` function using `$this`.
2. Use object binding to bind the closure to the parent object
Another way to use `$this` in a closure is to use object binding. Object binding is a way to bind a closure to a specific object so that `$this` inside the closure refers to that object.
class MyClass < public function myMethod() < $myVar = "Hello world"; $myClosure = function() use ($myVar) < echo $myVar; echo $this->myOtherMethod(); >.bindTo($this); $myClosure(); > public function myOtherMethod() < return "This is another method"; >>
In the example above, the `myClosure` function is bound to the `$this` object using the `bindTo` method. This allows the closure to access the `myOtherMethod` function using `$this`.
3. Use anonymous classes to create an object with a method
If you need to use a closure with `$this` in a class that doesn’t have a method, you can create an anonymous class and define a method inside that class.
class MyClass < public function myMethod() < $myVar = "Hello world"; $myObject = new class() < public function myClosure() use($myVar) < echo $myVar; echo $this->myOtherMethod(); > public function myOtherMethod() < return "This is another method"; >>; $myClosure = $myObject->myClosure->bindTo($this); $myClosure(); > >
In the example above, an anonymous class is created and a method `myClosure` is defined inside that class. The `$myVar` variable and the `$this` object are imported into the method using the `use` keyword. The `myClosure` method is then bound to the `$this` object using the `bindTo` method, and the closure is executed.
Using `$this` in a closure in PHP can be tricky, but with these guidelines, you can write more efficient and organized code.