概念
閉包(closures)是指在建立時封裝的狀態的函數,匿名函數(Anonymous functions)是指沒有名稱的函數。在PHP中,閉包和匿名函數被看成一種東西。理論上是不同的,可以理解閉包是由匿名函數構成的一種“結構”。
像string,int等,可以把閉包函數作為變數的值來使用。PHP會自動把此種運算式轉換成內建類 Closure 的對象執行個體。把一個 closure 對象賦值給一個變數的方式與普通變數賦值的文法是一樣的,最後也要加上分號。
建立閉包
$anonyFunc = function ($name) { return 'Hello ' . $name;}; echo $anonyFunc->__invoke("Josh");echo $anonyFunc("Josh");
閉包的情況是:
1. 建立一個繼承Closure類的閉包對象
2. 實現Closure類中的__invoke()方法
2. 把閉包賦值給$anonyFunc對象
3. 調用變數名後面有(),實際調用__invoke()方法
在array_map中的例子,這種做法更簡單,比傳統的先定義一個函數再調用要快一點,之前的做法還把回調的實現和使用場所隔離開了。
[2,3,4]
use傳參
"Clay, get me sweet tea!"
enclosePerson()接收一個$name參數,返回一個封裝了$name參數的閉包對象。即使閉包最終離開了enclosePerson()函數的範圍,但是返回的閉包對象$clay中仍然會保留$name參數被附著給閉包時的值。也就說,$name變數仍然存在在閉包中!這就是所說的, 即便閉包所在的環境不存在了,閉包中的封裝的狀態依然顧存在。
bindTo()
閉包有一個方法叫bindTo().這個方法可以吧Closure對象的內部狀態綁定到其他對象上。第一個參數是具體的new出來的類變數, 如果要讀某個類的protected和private就要把類名用string的形式寫到 bindTo 第二個參數上,當然也可以寫成new出來的類變數,PHP會翻譯成string的類名,所以說還是直接家string類名吧,如果在class內部的話就直接寫__CLASS__嘍。這麼做之後就可以在匿名函數中使用$this關鍵字引用重要的應用對象。
class Foo{ private $name; function __construct($name){ $this->name = $name; }}$obj = new Foo('Sam');$cl = function() { return "Hello " . $this->name;};$cl = $cl->bindTo($obj, 'Foo');// 'Foo'也可以直接寫成$objecho($cl());
bindTo()方法經常被一些PHP架構用來將路由地址映射到匿名回呼函數上。這些架構將一個匿名函數綁定到應用程式物件上。可以在匿名函數中使用$this關鍵詞來引用應用程式物件
routes[$routePath] = $routeCallback->bindTo($this, __CLASS__); } public function dispatch($currentPath) { foreach ($this->routesas $routePath => $callback) { if ($routePath === $currentPath) { $callback(); } } header('HTTP/1.1 ' . $this->responseStatus); header('Content-type: ' . $this->responseContentType); header('Content-length: ' . mb_strlen($this->responseBody)); echo $this->responseBody; }}
調用
addRoute('/users/josh', function () { $this->responseContentType = 'application/json;charset=utf8'; $this->responseBody = '{"name": "Josh"}';});$app->dispatch('/users/josh');
參考:
http://oomusou.io/php/php-bindTo/
《modern php》