## 匿名函數
匿名函數(Anonymous functions),也叫閉包函數(*closures*),允許 臨時創建一個沒有指定名稱的函數。最經常用作回調函數([callback](http://php.net/manual/zh/language.pseudo-types.php#language.types.callback))參數的值。當然,也有其它應用的情況。
匿名函數目前是通過 [](http://php.net/manual/zh/class.closure.php)[Closure](http://php.net/manual/zh/class.closure.php) 類來實現的。
**Example #1 匿名函數示例**
```
<?php
echo?preg_replace_callback('~-([a-z])~',?function?($match)?{
????return?strtoupper($match[1]);
},?'hello-world');
//?輸出?helloWorld
?>
```
閉包函數也可以作為變量的值來使用。PHP 會自動把此種表達式轉換成內置類 [Closure](http://php.net/manual/zh/class.closure.php) 的對象實例。把一個 closure 對象賦值給一個變量的方式與普通變量賦值的語法是一樣的,最后也要加上分號:
**Example #2 匿名函數變量賦值示例**
```
<?php
$greet?=?function($name)
{
????printf("Hello?%s\r\n",?$name);
};
$greet('World');
$greet('PHP');
?>
```
閉包可以從父作用域中繼承變量。 任何此類變量都應該用 *use* 語言結構傳遞進去。 PHP 7.1 起,不能傳入此類變量: [superglobals](http://php.net/manual/zh/language.variables.predefined.php)、 $this 或者和參數重名。
**Example #3 從父作用域繼承變量**
```
<?php
$message?=?'hello';
//?沒有?"use"
$example?=?function?()?{
????var_dump($message);
};
echo?$example();
//?繼承?$message
$example?=?function?()?use?($message)?{
????var_dump($message);
};
echo?$example();
//?Inherited?variable's?value?is?from?when?the?function
//?is?defined,?not?when?called
$message?=?'world';
echo?$example();
//?Reset?message
$message?=?'hello';
//?Inherit?by-reference
$example?=?function?()?use?(&$message)?{
????var_dump($message);
};
echo?$example();
//?The?changed?value?in?the?parent?scope
//?is?reflected?inside?the?function?call
$message?=?'world';
echo?$example();
//?Closures?can?also?accept?regular?arguments
$example?=?function?($arg)?use?($message)?{
????var_dump($arg?.?'?'?.?$message);
};
$example("hello");
?>
```
以上例程的輸出類似于:
~~~
Notice: Undefined variable: message in /example.php on line 6
NULL
string(5) "hello"
string(5) "hello"
string(5) "hello"
string(5) "world"
string(11) "hello world"
~~~
這些變量都必須在函數或類的頭部聲明。 從父作用域中繼承變量與使用全局變量是*不同*的。全局變量存在于一個全局的范圍,無論當前在執行的是哪個函數。而 閉包的父作用域是定義該閉包的函數(不一定是調用它的函數)。示例如下:
**Example #4 Closures 和作用域**
```
<?php
//?一個基本的購物車,包括一些已經添加的商品和每種商品的數量。
//?其中有一個方法用來計算購物車中所有商品的總價格,該方法使
//?用了一個?closure?作為回調函數。
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;
//?往購物車里添加條目
$my_cart->add('butter',?1);
$my_cart->add('milk',?3);
$my_cart->add('eggs',?6);
//?打出出總價格,其中有?5%?的銷售稅.
print?$my_cart->getTotal(0.05)?.?"\n";
//?最后結果是?54.29
?>
```
**Example #5 Automatic binding of *$this***
```
<?php
class?Test
{
????public?function?testing()
????{
????????return?function()?{
????????????var_dump($this);
????????};
????}
}
$object?=?new?Test;
$function?=?$object->testing();
$function();
????
?>
```
以上例程會輸出:
~~~
object(Test)#1 (0) {
}
~~~
以上例程在PHP 5.3中的輸出:
~~~
Notice: Undefined variable: this in script.php on line 8
NULL
~~~
As of PHP 5.4.0, when declared in the context of a class, the current class is automatically bound to it, making *$this* available inside of the function's scope. If this automatic binding of the current class is not wanted, then [static anonymous functions](http://php.net/manual/zh/functions.anonymous.php#functions.anonymous-functions.static) may be used instead.
### Static anonymous functions
As of PHP 5.4, anonymous functions may be declared statically. This prevents them from having the current class automatically bound to them. Objects may also not be bound to them at runtime.
**Example #6 Attempting to use *$this* inside a static anonymous function**
```
<?php
class?Foo
{
????function?__construct()
????{
????????$func?=?static?function()?{
????????????var_dump($this);
????????};
????????$func();
????}
};
new?Foo();
?>
```
以上例程會輸出:
~~~
Notice: Undefined variable: this in %s on line %d
NULL
~~~
**Example #7 Attempting to bind an object to a static anonymous function**
```
<?php
$func?=?static?function()?{
????//?function?body
};
$func?=?$func->bindTo(new?StdClass);
$func();
?>
```
以上例程會輸出:
~~~
Warning: Cannot bind an instance to a static closure in %s on line %d
~~~
- 序言
- 簡介
- PHP是什么?
- PHP能做什么?
- 基本語法
- 類型
- boolean(布爾型)
- integer(整型)
- float(浮點型)
- string(字符串)
- array(數組)
- object(對象)
- callable(可調用)
- resource(資源)
- NULL(無類型)
- 偽類型
- 類型轉換的判別
- 變量
- 基礎
- 預定義變量
- 變量范圍
- 可變變量
- 來自PHP之外的變量
- 常量
- 語法
- 魔術常量
- 表達式
- 運算符
- 運算符優先級
- 算術運算符
- 賦值運算符
- 位運算符
- 比較運算符
- 錯誤控制運算符
- 執行運算符
- 遞增/遞減運算符
- 邏輯運算符
- 字符串運算符
- 數組運算符
- 類型運算符
- 流程控制
- if
- else
- elseif/else if
- 流程控制的替代語法
- while
- do-whille
- for
- foreach
- break
- continue
- switch
- declare
- return
- require
- include
- require_once
- include_once
- goto
- 函數
- 用戶自定義函數
- 函數的參數
- 返回值
- 可變函數
- 內部 (內置)函數
- 匿名函數
- 類與對象
- 簡介
- 基本概念
- 屬性
- 類的自動加載
- 構造函數
- 訪問控制(可見性)