Closure,匿名函數,又稱為Anonymous functions,是php5.3的時候引入的。匿名函數就是沒有定義名字的函數,也就是閉包(Closure。這點牢牢記住就能理解匿名函數的定義了。例如以下程式碼(檔名是do.php)
<?php function A() { return 100; }; function B(Closure $callback) { return $callback(); } $a = B(A()); print_r($a);//输出:Fatal error: Uncaught TypeError: Argument 1 passed to B() must be an instance of Closure, integer given, called in D:\web\test\do.php on line 11 and defined in D:\web\test\do.php:6 Stack trace: #0 D:\web\test\do.php(11): B(100) #1 {main} thrown in D:\web\test\do.php on line 6 ?>
這裡的A()永遠沒有辦法用來當B的參數,因為A它並不是「匿名」函數。閉包
將匿名函數在普通函數中當做參數傳入,也可以被回傳。三個例子:<?php
$f = function () {
return 100;
};
function B(Closure $callback)
{
return $callback();
}
$a = B($f);
print_r($a);//输出100
<?
$func = function( $param ) {
echo $param;
};
$func( 'hello word' );
//输出:hello word
連接閉包和外界變數的關鍵字:USE閉包可以保存所在程式碼區塊上下文的一些變數和值。不能呼叫所在程式碼區塊的上下文變量,而需要透過使用use關鍵字。到,dollar沒有在use關鍵字中聲明,在這個匿名函數裡也就不能獲取到它,所以開發中要注意這個問題。的變量,但我發現好像是不可以的:
<?php //例一 //在函数里定义一个匿名函数,并且调用它 function printStr() { $func = function( $str ) { echo $str; }; $func( ' hello my girlfriend ! ' ); } printStr();//输出 hello my girlfriend ! //例二 //在函数中把匿名函数返回,并且调用它 function getPrintStrFunc() { $func = function( $str ) { echo $str; }; return $func; } $printStrFunc = getPrintStrFunc(); $printStrFunc( ' do you love me ? ' );//输出 do you love me ? //例三 //把匿名函数当做参数传递,并且调用它 function callFunc( $func ) { $func( ' no!i hate you ' ); } $printStrFunc = function( $str ) { echo $str.'<br>'; }; callFunc( $printStrFunc ); //也可以直接将匿名函数进行传递。如果你了解js,这种写法可能会很熟悉 callFunc( function( $str ) { echo $str; //输出no!i hate you } );
額,原來use所引用的也只不過是變量的一個副本clone而已。要達到這個效果,其實在變數前面加上一個& 符號就可以了:
<?php function getMoney() { $rmb = 1; $dollar = 8; $func = function() use ( $rmb ) { echo $rmb; echo $dollar; }; $func(); } getMoney(); //输出:1
好,這樣匿名函數就可以引用上下文的變數了。 use所引用的變量,而外界則不能得到這些變量,這樣形成'閉包'這個概念可能會更清晰一些。 #好吧,扯了這麼多,那麼如果我們要呼叫一個類別裡面的匿名函式呢?
綁定的概念 上面的範例的Closure只是全域的的匿名函數,好了,那我們現在要指定一個類別有一個匿名函數。 。定之後,就好像A中有這麼個函數一樣,但是這個函數是public還是private,bind的最後一個參數就說明了這個函數的可呼叫範圍。 上面大家看到了bindTo,我們來看官網的介紹<?php function getMoney() { $rmb = 1; $func = function() use ( $rmb ) { echo $rmb.'<br>'; //把$rmb的值加1 $rmb++; }; $func(); echo $rmb; } getMoney(); //输出: //1 //1Closure::bind — 複製一個閉包,綁定指定的$this物件和類別作用域。 說明public static Closure Closure::bind ( Closure $closure , object $newthis [, mixed $newscope = 'static' ] )
這個方法是
Closure: :bindTo() 的靜態版本。查看它的文件以取得更多資訊。
參數
closure需要綁定的匿名函數。 newthis
需要綁定到匿名函數的對象,或 NULL 建立未綁定的閉包。
newscope
想要綁定給閉包的類別作用域,或是 'static' 表示不改變。如果傳入一個對象,則使用這個對象的型別名稱。 類別作用域用來決定在閉包中 $this 物件的 私有、保護方法 的可見性。 (備註:可以傳入類別名稱或類別的實例,預設值是'static', 表示不改變。)
傳回值:
傳回一個新的Closure 物件或在失敗時返回FALSE
<?php function getMoney() { $rmb = 1; $func = function() use ( &$rmb ) { echo $rmb.'<br>'; //把$rmb的值加1 $rmb++; }; $func(); echo $rmb; } getMoney(); //输出: //1 //2
我們再來看個例子加深下理解:
<?php function getMoneyFunc() { $rmb = 1; $func = function() use ( &$rmb ) { echo $rmb.'<br>'; //把$rmb的值加1 $rmb++; }; return $func; } $getMoney = getMoneyFunc(); $getMoney(); $getMoney(); $getMoney(); //输出: //1 //2 //3
我們再看一個demo:
<?php class A { public static function testA() { return function($i) { //返回匿名函数 return $i+100; }; } } function B(Closure $callback) { return $callback(200); } $a = B(A::testA()); print_r($a);//输出 300
透過上面的幾個例子,其實匿名綁定的理解就不難了....我們在看一個擴充的demo(引入trait特性)
<?php class A { public $base = 100; } class B { private $base = 1000; } $f = function () { return $this->base + 3; }; $a = Closure::bind($f, new A); print_r($a());//输出 103 echo PHP_EOL; $b = Closure::bind($f, new B , 'B'); print_r($b());//输出1003例如現在我們用現在購物環境
(PHP 5 >= 5.4.0, PHP 7)補充說明:閉包可以使用USE關鍵連接外部變數。
總結:PHP閉包的特性其實用CLASS就可以實現類似甚至強大得多的功能,更不能和js的閉包相提並論了吧,只能期待PHP以後對
閉包支援的改進。不過匿名函數還是挺有用的,例如在使用preg_replace_callback等之類的函數可以不用在外部宣告
回呼函數了。合理使用閉包能讓程式碼更簡潔精煉。
以上是php 中的closure用法實例詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!