前言
本文為《現代 PHP》一書的學習筆記。
環境
閉包
閉包是個在創造時就封裝了內部狀態的函式,這個被封裝的狀態會一直被保存在閉包中,即使環境消失了。
閉包的例子如下:
範例 2-19:基本的閉包
1 2 3 4 5
| $closure = function ($name) { return sprintf('Hello %s', $name); };
echo $closure("John");
|
- 建立了一個閉包物件,指派給了
$closure
變數。
閉包可以被當成是參數傳入其他的 PHP 函式。
範例 2-20:array_map 閉包
1 2 3 4 5
| $numbersPlusOne = array_map(function ($number) { return $number + 1; }, [1, 2, 3]);
print_r($numbersPlusOne);
|
array_map()
函式將自定義函式作用到陣列的每個元素,並返回帶有新値的陣列。
閉包和匿名函式(沒有名稱的函式)理論上是不同的事,不過 PHP 將他們視為相同。
PHP 使用 use
關鍵字來繫結狀態。
範例 2-21:繫節狀態到閉包
1 2 3 4 5 6 7 8 9 10 11
| function enclosePerson($name) { return function ($doCommand) use ($name) { return sprintf('%s, %s', $name, $doCommand); }; }
$clay = enclosePerson('Clay');
echo $clay('get me sweet tea!');
|
可以利用 use
關鍵字傳入多個參數到閉包中,利用逗號區分參數。
bindTo()
方法經常被一些 PHP 框架用來當成對應 URL 路由到匿名回呼函式的方式。這使得在匿名函式中可以用 $this
關鍵字存取主要應用程式物件。
範例 2-22:利用 bindTo() 繫結閉包狀態
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| class App { protected $routes = []; protected $responseStatus = '200 OK'; protected $responseContentType = 'text/html'; protected $responseBody = 'Hello world';
public function addRoute($routePath, $routeCallback) { $this->routes[$routePath] = $routeCallback->bindTo($this, __CLASS__); }
public function dispatch($currentPath) { foreach ($this->routes as $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; } }
$app = new App();
$app->addRoute('/users/josh', function () { $this->responseContentType = 'application/json;charset=utf8'; $this->responseBody = '{"name": "Josh"}'; });
$app->dispatch('/users/josh');
|
bindTo()
方法的第 2 個參數指定了閉包要連結的物件的類別。
利用 bindTo()
方法把一個物件的內部狀態連結到一個不同的物件。
參考資料
- Josh Lockhart(2015)。現代 PHP。台北市:碁峯資訊。