在使用 Laravel 函式時,我們都避免不了使用其提供的各種各樣的全域性函式,也稱為輔助函式。
主要集中為處理陣列、檔案路徑、路由和字串等。
今天主要說說我喜歡的幾個常用 Helper 函式,以及 Helpers 實現原理,最後依葫蘆畫瓢,自定義我們自己的全域性函式。
4 個好玩的 Helpers 函式
data_get()
The data_get function retrieves a value from a nested array or object using "dot" notation:
The data_get function also accepts a default value, which will be returned if the specified key is not found
data_get() 函式利用“.”符號,從巢狀陣列或者物件中檢索數值,其中第三個引數是設定預設值,當檢索健不存在時。
$array = ['albums' => ['rock' => ['count' => 75]]];
$count = data_get($array, 'albums.rock.count');
// 75
$avgCost = data_get($array, 'albums.rock.avg_cost', 0);
// 0
$object->albums->rock->count = 75;
$count = data_get($object, 'albums.rock.count');
// 75
$avgCost = data_get($object, 'albums.rock.avg_cost', 0);
// 0
複製程式碼
在多級巢狀中,並不是每級 key 值都一致,對於同級不同 key 值,可以使用萬用字元 (*) 代替,如:
$array = ['albums' => ['rock' => ['count' => 75], 'punk' => ['count' => 12]]];
$counts = data_get($array, 'albums.*.count');
// [75, 12]
$array = ['albums' => ['rock', 'punk' => ['count' => 12]]];
$counts = data_get($array, 'albums.*.count');
// [NULL, 12]
複製程式碼
str_plural()
對於我這英語不好的人來說,如何將單數形式寫成複數形式,有時候就會鬧出笑話了,但使用 str_plural() 方法,那就便捷多了,其中第二個引數是數值,如果大於 1 時,則轉為複數形式,否則還是單數形式。
str_plural('dog'); // dogs
str_plural('cat'); // cats
str_plural('dog', 2); // dogs
str_plural('cat', 1); // cat
str_plural('child'); // children
str_plural('person'); // people
str_plural('fish'); // fish
str_plural('deer', 2); // deer
str_singular('children') // child
複製程式碼
同時也有複數轉單數函式:str_singular()
value() and with()
value() 函式根據傳入的值,返回資料,如果,傳入的是閉包函式,則會直接執行閉包函式,返回結果:
$result = value(5);
// 5
$result = value(function () {
return false;
});
// false
複製程式碼
value() 個人覺得,更多用在於高階函式中,閉包函式作為高階函式的傳值傳入;
和 value() 相比,可以利用 with() 函式傳入引數值:
$callback = function ($value) {
return (is_numeric($value)) ? $value * 2 : 0;
};
$result = with(5, $callback);
// 10
$result = with(null, $callback);
// 0
$result = with(5, null);
// 5
複製程式碼
tap()
<?php
function tap($value, $callback)
{
$callback($value);
return $value;
}
複製程式碼
傳入 value 值,並對 value 值進行操作,最後再返回 value。tap 函式就好將 value 值進行鍍金,修改 value 物件的狀態和屬性,最後返回結果可以進行後續操作。如:
<?php
return tap($user)->update([
'name' => $name,
'age' => $age,
]);
複製程式碼
當我們傳入一個 $user model 到 tap 方法後,我們就可以鏈式各種 Model 函式,正常情況下,update 方法返回的是 boolean 型別,正因為我們用了 tap 函式,update 方法返回的是 user model 物件,可以繼續鏈式 Model 方法,操作 user 模型物件。
其它
更多全域性 Helpers 函式,參見: laravel.com/docs/5.6/he…
Helpers 函式實現原理
當我們在使用這些函式時,印入腦子裡的第一個問題就是:Laravel 是怎麼實現的?
所以我們需要從 Laravel 框架原始碼入手。
在 PhpStorm IDE 轉到這些全域性函式定義時,發現主要集中在這兩個檔案中:
"src/Illuminate/Foundation/helpers.php",
"src/Illuminate/Support/helpers.php"
複製程式碼
因為這些函式並不是定義在物件中,而要達到全域性載入的目標,Laravel 通過 Composer autoload 載入的方式載入:
引自:docs.phpcomposer.com/04-schema.h…
Files
如果你想要明確的指定,在每次請求時都要載入某些檔案,那麼你可以使用 'files' autoloading。通常作為函式庫的載入方式(而非類庫)。
例項
{
"autoload": {
"files": ["src/MyLibrary/functions.php"]
}
}
複製程式碼
接下來我們看看其中一個函式是怎麼寫的:
if (! function_exists('tap')) {
/**
* Call the given Closure with the given value then return the value.
*
* @param mixed $value
* @param callable|null $callback
* @return mixed
*/
function tap($value, $callback = null)
{
if (is_null($callback)) {
return new HigherOrderTapProxy($value);
}
$callback($value);
return $value;
}
}
複製程式碼
可以看出,每個函式都是以這種格式的:
if (! function_exists('xxx')) {
function xxx() {
// ...
}
}
複製程式碼
注: 從 tap 函式原始碼可以看出,無論傳入的閉包函式有沒有返回值,函式返回的值,都是 $value,和傳入的值一樣,這樣也就達到「鏈式程式設計」的目標。
自定義 Helpers 函式
如果以上 Helpers 函式還滿足不了你的話,我們就可以通過上文的方式來自定義 Helpers 函式,來滿足我們自己的開發需求。
主要有以下幾步:
- 在專案中建立 helper.php 檔案
- 在 composer.json 中將 helper 檔案 autoload 載入
- composer dump-autoload
- 在 helper.php 檔案寫入我們的全域性函式
- test
舉個例子 ?
總結
學習 Laravel Helpers 實現原理,不僅有助於我們理解和使用這些 Helpers 方法,並且,通過研究每一個 Helper 函式是怎麼寫的,也有助於規範我們程式碼邏輯和思維。學其之所長。
參考: