2 min to read
淺入淺出 PHP 閉包 Closure
匿名函數(在 PHP 5.3 中被引入)會產生這個類型的對象。在過去,這個類別被認為是一個實現細節 ...
Closure 類別
用於代表
匿名函數
的類別。 匿名函數(在 PHP 5.3 中被引入)會產生這個類型的對象。在過去,這個類別被認為是一個實現細節,但現在可以依賴它做一些事情。自 PHP 5.4 起,這個類別帶有一些方法,允許在匿名函數建立後對其進行更多的控制。 除了此處列出的方法外,還有一個__invoke
方法。這是為了與其他實現了__invoke()
魔術方法的對象保持一致性,但調用匿名函數的過程與它無關。
直接省略前言,畢竟會 Google PHP、Closure、閉包之類的,然後跑來這裏讀文章的人,通常已經知道自己要什麼了,所以我們就直接進入主題吧。
閉包你是 WTF ?
如果我們希望有個功能是輸出「Hello $變數」,那我們會很直覺的直接 echo "Hello $變數"
來解決,如果思考到重複使用的話,可能就會把這段獨立出來變成一個方法,直接拿官方文件的範例來講的話,那就會像這樣:
function createGreeter($who) {
return function() use ($who) {
echo "Hello $who";
};
}
$greeter = createGreeter("World");
$greeter(); // Hello World
之後如果要重複使用的話,只要不斷 new 一個閉包,並且去執行閉包,那麼就可以做到重複使用同樣的功能。
$小明 = createGreeter("小明");
$小明(); // Hello 小明
$小美 = createGreeter("小美");
$小美(); // Hello 小美
$虛空雷神獸EX = createGreeter("虛空雷神獸EX");
$虛空雷神獸EX(); // Hello 虛空雷神獸EX
但這樣會變成要不斷建立閉包、執行閉包,所以如果要把這段程式碼精簡化的話,那麼直接在建立方法同時直接賦予到變數。
$hello = function() use ($who) {
return "Hello $who";
};
echo $hello("小明"); // Hello 小明
接下來就來個簡單的小範例,我們在 model
當中寫個 scope
方法來提供模糊搜尋,把 Builder
丟進去處理模糊搜尋,最後再把 Builder
丟回來給我。
/**
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $column
* @param string $value
* @param string $side
* @param boolean $isNotLike
* @param boolean $isAnd
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeLike(Builder $query, $column, $value, $side = 'both', $isNotLike = false, $isAnd = true)
{
$operator = $isNotLike ? 'not like' : 'like';
// 1. 使用閉包將字串中包含萬用字元的內容取代為常數字元。
$escape_like_str = function ($str)
{
return str_replace(
['!', '%', '_'],
['!!', '!%', '!_'],
$str
);
};
// 2. 根據模糊方式來彙整出相對應的搜尋內容
switch ($side)
{
case 'none':
$value = $escape_like_str($value);
break;
case 'before':
case 'left':
$value = "%{$escape_like_str($value)}";
break;
case 'after':
case 'right':
$value = "{$escape_like_str($value)}%";
break;
case 'both':
case 'all':
default:
$value = "%{$escape_like_str($value)}%";
break;
}
return $isAnd ? $query->where($column, $operator, $value) : $query->orWhere($column, $operator, $value);
}
回應