匿名函數(Anonymous functions),也稱作閉包函數(closures),它允許臨時創建一個沒有指定名稱的函數。最經常用作回調函數 callable參數的值。當然,也有其它應用的情況。
<?php
// 使用回調執行正則表達式搜索和替換
echo preg_replace_callback('~-([a-z])~', function ($match) {
return strtoupper($match[1]); // 將所選的變成大寫,從index: 1開始過濾掉原先"-"
}, 'hello-world');
// 输出 helloWorld
?>
閉包函數也可以作為變量的值來使用。 PHP 會自動把此種表達式轉換成內置類 Closure 的對象實例。把一個 closure 對象賦值給一個變量的方式與普通變量賦值的語法是一樣的,最後也要加上分號 ;
<?php
$sayHi = function($name)
{
echo "Hello $name";
}; // 記得加上分號
$sayHi('joe');
$sayHi('cherry');
?>
閉包可以從父作用域中繼承變量。任何此類變量都應該用 use 語言結構傳遞進去。
PHP 7.1 起,不能傳入此類變量: superglobals(超全局便量)、 $this 或者和參數重名。
從 PHP 8.0.0 開始,作用域繼承的變量列表可能包含一個尾部的逗號,這個逗號將被忽略
<?php
$message = 'hello';
// 没有 "use" php會不知道這變數從哪來
$example = function () {
var_dump($message);
};
$example();
// 繼承父作用域 $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(); // 不會受到改變因為已經在上面先調用了(14行)
// 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");
?>
// outputs
// Notice: Undefined variable: ...
// NULL
// string(5) "hello"
// string(5) "hello"
// string(5) "hello"
// string(5) "world"
// string(11) "hello world"
箭頭函數是更簡潔的匿名函數,都是屬於Closure類(閉包)的實現
箭頭函數的語法為 fn (argument_list) => expr。
箭頭函數支持與 匿名函數 相同的功能,只是其父作用域的變量總是自動的。 當表達式中使用的變量是在父作用域中定義的,它將被隱式地按值捕獲。
在下面的例子中,函數 $fn1 和 $fn2 的行為是一樣的
<?php
$y = 1;
$fn1 = fn($x) => $x + $y;
// 相當於 using $y by value:
$fn2 = function ($x) use ($y) {
return $x + $y;
};
// var_export -- 輸出或返回一個變量的字串表示
var_export($fn1(3)); // 4
?>
通常在A程序執行中,尚未結束前又開始執行B程序,B程序結束後,繼續執行A程序,就稱為嵌套。
<?php
$z = 1;
$fn = fn($x) => fn($y) => $x * $y + $z;
// 輸出 21
var_export($fn(5)(4));
?>
和匿名函數一樣,箭頭函數語法同樣允許標準的函數聲明,包括參數和返回類型、缺省值、變量,以及通過引用傳遞和返回。以下都是箭頭函數的有效例子。
<?php
fn(array $x) => $x;
static fn(): int => $x;
fn($x = 42) => $x;
fn(&$x) => $x;
fn&($x) => $x;
fn($x, ...$rest) => $rest;
?>
箭頭函數會自動綁定上下文變量,這相當於對箭頭函數內部使用的每一個變量 $x 執行了一個 use($x)。這意味著不可能修改外部作用域的任何值,若要實現對值的修改,可以使用 匿名函數 來替代。
<?php
$x = 1;
$fn = fn() => $x++; // 不會影響 x 的值
$fn();
var_export($x); // 輸出 1
?>
資料來源: https://www.php.net/