玩轉 Laravel Helpers

coding01發表於2018-03-11

在使用 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 模型物件。

其它

玩轉 Laravel Helpers

更多全域性 Helpers 函式,參見: laravel.com/docs/5.6/he…

Helpers 函式實現原理

當我們在使用這些函式時,印入腦子裡的第一個問題就是:Laravel 是怎麼實現的?

所以我們需要從 Laravel 框架原始碼入手。

在 PhpStorm IDE 轉到這些全域性函式定義時,發現主要集中在這兩個檔案中:

"src/Illuminate/Foundation/helpers.php",
            
"src/Illuminate/Support/helpers.php"
複製程式碼

玩轉 Laravel Helpers

玩轉 Laravel Helpers

因為這些函式並不是定義在物件中,而要達到全域性載入的目標,Laravel 通過 Composer autoload 載入的方式載入:

玩轉 Laravel Helpers

引自: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 函式,來滿足我們自己的開發需求。

主要有以下幾步:

  1. 在專案中建立 helper.php 檔案
  2. 在 composer.json 中將 helper 檔案 autoload 載入
  3. composer dump-autoload
  4. 在 helper.php 檔案寫入我們的全域性函式
  5. test

舉個例子 ?

玩轉 Laravel Helpers

玩轉 Laravel Helpers

玩轉 Laravel Helpers

總結

學習 Laravel Helpers 實現原理,不僅有助於我們理解和使用這些 Helpers 方法,並且,通過研究每一個 Helper 函式是怎麼寫的,也有助於規範我們程式碼邏輯和思維。學其之所長。

參考:

  1. laravel.com/docs/5.6/he…
  2. laravel-news.com/creating-he…