Анонимные функции, также известные как closures
, позволяют создавать функции без определенного имени. Они наиболее полезны в качестве значений вызываемых параметров, но у них есть много других применений.
Анонимные функции реализованы с помощью. Класс закрытия .
Пример #1 Пример анонимной функции
<?php
echo preg_replace_callback('~-([a-z])~', function ($match) {
return strtoupper($match[1]);
}, 'hello-world');
// outputs helloWorld
?>
Замыкания также могут использоваться как значения переменных; PHP автоматически преобразует такие выражения в экземпляры внутреннего класса Closure . Присваивание замыкания переменной использует тот же синтаксис, что и любое другое присваивание, включая точку с запятой в конце:
Пример #2 Пример назначения переменной анонимной функции
<?php
$greet = function($name)
{
printf("Hello %s\r\n", $name);
};
$greet('World');
$greet('PHP');
?>
Замыкания также могут наследовать переменные из родительской области. Любые такие переменные должны быть переданы в use
языковую конструкцию. Начиная с PHP 7.1, эти переменные не должны включать суперглобальные значения , $this или переменные с тем же именем, что и параметр. Объявление типа возвращаемого значения функции должно быть помещено после предложения use
.
Пример #3 Наследование переменных из родительской области видимости
<?php
$message = 'hello';
// No "use"
$example = function () {
var_dump($message);
};
$example();
// Inherit $message
$example = function () use ($message) {
var_dump($message);
};
$example();
// Inherited variable's value is from when the function
// is defined, not when called
$message = 'world';
$example();
// Reset message
$message = 'hello';
// Inherit by-reference
$example = function () use (&$message) {
var_dump($message);
};
$example();
// The changed value in the parent scope
// is reflected inside the function call
$message = 'world';
$example();
// Closures can also accept regular arguments
$example = function ($arg) use ($message) {
var_dump($arg . ' ' . $message);
};
$example("hello");
// Return type declaration comes after the use clause
$example = function () use ($message): string {
return "hello $message";
};
var_dump($example());
?>
Приведенный выше пример выведет что-то похожее на:
Примечание: Неопределенная переменная: сообщение в /example.php в строке 6
НУЛЕВОЙ
строка(5) "привет"
строка(5) "привет"
строка(5) "привет"
строка(5) "мир"
строка (11) "привет, мир"
строка (11) "привет, мир"
Начиная с PHP 8.0.0, список переменных, унаследованных от области видимости, может включать запятую в конце, которая будет игнорироваться.
Наследование переменных из родительской области — это не то же самое, что использование глобальных переменных. Глобальные переменные существуют в глобальной области видимости, которая не зависит от выполняемой функции. Родительская область замыкания — это функция, в которой было объявлено замыкание (не обязательно функция, из которой оно было вызвано). См. следующий пример:
Пример #4 Замыкания и область видимости
<?php
// A basic shopping cart which contains a list of added products
// and the quantity of each product. Includes a method which
// calculates the total price of the items in the cart using a
// closure as a callback.
class Cart
{
const PRICE_BUTTER = 1.00;
const PRICE_MILK = 3.00;
const PRICE_EGGS = 6.95;
protected $products = array();
public function add($product, $quantity)
{
$this->products[$product] = $quantity;
}
public function getQuantity($product)
{
return isset($this->products[$product]) ? $this->products[$product] :
FALSE;
}
public function getTotal($tax)
{
$total = 0.00;
$callback =
function ($quantity, $product) use ($tax, &$total)
{
$pricePerItem = constant(__CLASS__ . "::PRICE_" .
strtoupper($product));
$total += ($pricePerItem * $quantity) * ($tax + 1.0);
};
array_walk($this->products, $callback);
return round($total, 2);
}
}
$my_cart = new Cart;
// Add some items to the cart
$my_cart->add('butter', 1);
$my_cart->add('milk', 3);
$my_cart->add('eggs', 6);
// Print the total with a 5% sales tax.
print $my_cart->getTotal(0.05) . "\n";
// The result is 54.29
?>
Пример #5 Автоматическая привязка$this
<?php
class Test
{
public function testing()
{
return function() {
var_dump($this);
};
}
}
$object = new Test;
$function = $object->testing();
$function();
?>
Приведенный выше пример выведет:
объект(Тест)#1 (0) {
}
При объявлении в контексте класса текущий класс автоматически привязывается к нему, делая его $this
доступным внутри области видимости функции. Если эта автоматическая привязка текущего класса не нужна, вместо нее можно использовать статические анонимные функции .
Статические анонимные функции
Анонимные функции могут быть объявлены статически. Это предотвращает автоматическую привязку к ним текущего класса. Объекты также могут быть не привязаны к ним во время выполнения.
Пример #6 Попытка использования $this
внутри статической анонимной функции
<?php
class Foo
{
function __construct()
{
$func = static function() {
var_dump($this);
};
$func();
}
};
new Foo();
?>
Приведенный выше пример выведет:
Примечание: Неопределенная переменная: это в %s в строке %d
НУЛЕВОЙ
Пример #7 Попытка привязать объект к статической анонимной функции
<?php
$func = static function() {
// function body
};
$func = $func->bindTo(new StdClass);
$func();
?>
Приведенный выше пример выведет:
Предупреждение: невозможно привязать экземпляр к статическому замыканию в %s в строке %d.
0 комментариев