iT邦幫忙

2019 iT 邦幫忙鐵人賽

1
Software Development

Laravel 原始碼分析系列 第 38

分析 Collection(2)

以下先大概列幾個與原生 PHP 函式相關的方法:

Native Collection
array_chunk() chunk()
array_combine() combine()
array_diff() diff()
array_flip() flip()
array_filter() filter()
array_map() map()
array_reduce() reduce()
array_slice() slice()
array_walk() each()

通常 Collection 的實作,都有加強原生對 array 處理的方便性,這些就不多做說明。來提一些比較有趣的。

transform()

這個方法跟 map() 其實是一樣的,但它會改變原本的物件的內容:

public function transform(callable $callback)
{
    $this->items = $this->map($callback)->all();

    return $this;
}

pipe()

這個 pipe 的意義,與 Bash 的 | 類似,把該物件交由 callback 處理

public function pipe(callable $callback)
{
    return $callback($this);
}

tap()

public function tap(callable $callback)
{
    $callback(new static($this->items));

    return $this;
}

之前曾提過 tap() 函式。這個方法也是類似的概念,它的等價程式碼如下:

$callback = function($items) {
    //
};

$collection->tap($callback);

tap($collection, $callback);

讓 collection 自帶 tap() 方法,會串聯方法或是語意,都會比原本的 tap() 函式來的好。

toBase()

這個方法是用在繼承 Collection 的類別如 Eloquent Collection,如果想轉成單純的 Collection 的話,可以使用這個。

public function toBase()
{
    return new self($this);
}

筆者也有自定義類別是繼承 Collection 的,不過設計上比較單純,所以還沒用過這個方法。

wrap()unwrap()

wrap() 會使用 Collection 把傳入的參數包裝起來,unwrap() 則是解包裝。

public static function wrap($value)
{
    return $value instanceof self
        ? new static($value)
        : new static(Arr::wrap($value));
}

public static function unwrap($value)
{
    return $value instanceof self ? $value->all() : $value;
}

其中會注意到,warp() 裡面還用到了 Arr::wrap(),因此非 array 的參數也可以正常使用。

// class Arr
public static function wrap($value)
{
    if (is_null($value)) {
        return [];
    }

    return ! is_array($value) ? [$value] : $value;
}

when()unless()

這兩個方法很有趣,when() 是當 $value 是 true 的時候,就會執行 callback;unless() 則相反。

public function when($value, callable $callback, callable $default = null)
{
    if ($value) {
        // 如果 $value 是 true 就執行 callback
        return $callback($this, $value);
    } elseif ($default) {
        // 如果 $value 不是 true 且有 default callback 的話,就換執行 default callback 
        return $default($this, $value);
    }

    return $this;
}

public function unless($value, callable $callback, callable $default = null)
{
    return $this->when(! $value, $callback, $default);
}

可以注意到上面 unless() 寫法很有趣,它把 $value 反相後丟到 when,即可做出 unless 的方法。這特性在 Laravel 也很常見,比方說 isEmpty()isNotEmpty()

public function isEmpty()
{
    return empty($this->items);
}

public function isNotEmpty()
{
    return ! $this->isEmpty();
}

可以看到 isNotEmpty() 其實就是 isEmpty() 的相反。

會這樣設計的原因是:用起來比較直覺語意,可以參考下面兩段程式碼即可了解:

if (!$collection->isEmpty()) {
    //
}

if ($collection->isNotEmpty()) {
    //
}

Laravel 框架很多設計都是環繞在直覺語意上的,非常值得參考。


上一篇
分析 Collection(1)
下一篇
分析 Collection(3)--Higher Order Messages
系列文
Laravel 原始碼分析46
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言