Laravel tap 用法

本文參照轉譯:php

http://derekmd.com/2017/02/la...laravel

https://murze.be/2017/02/lara...緩存

Laravel 5.3 中增長了一個新的全局幫助函數 tap(),改進了框架的聲明能力。這個微妙的語法是從 RubyLodash 借鑑而來,容許你去 tap 成鏈。框架

先看看 tap() 幫助函數的代碼,只有短短的幾行:ide

function tap($value, $callback)
{
   $callback($value);

   return $value;
}

你須要傳一個值和一個回調到方法中,值做爲回調的參數,回調將執行,最後值被返回。函數

執行中間操做

從一個簡單的例子開始,提取 LaravelAuthenticateSession@handle() 的一些代碼,一些 PHP 開發者很是熟悉的解決方案:網站

$response = $next($request);
 
$this->storePasswordHashInSession($request);
 
return $response;

使用 tap() 幫助函數:this

return tap($next($request), function () use ($request) {
    $this->storePasswordHashInSession($request);
});

另外的一個簡單的例子,讓咱們看看 Illuminate\Cache\Repository 下的 pull 方法,此函數將從指定鍵的緩存中獲取值,並將其刪除。pull 方法的實現:.net

public function pull($key, $default = null)
{
   $value = $this->get($key, $default);

   $this->forget($key) // returns a boolean;

   return $value;
}

上面的例子中,$this-> forget() 返回一個布爾值,因此要使咱們的函數返回原始值,須要將其儲存到臨時變量 $value 中。如下是 tap() 的實現,再也不須要臨時變量:翻譯

public function pull($key, $default = null)
{
   return tap($this->get($key, $default), function ($value) use ($key) {
      $this->forget($key);
   });
}

恢復狀態

Eloquent 的 createupdate 方法支持 ['timestamps' => false] 選項。若是這被實現成鏈式方法,結果的可讀性會更好。

// Method defined in App\Model that App\Message extends.
public function keepingTimestamps(callable $callback)
{
    try {
        $timestamps = $this->timestamps;
        $this->timestamps = false;
 
        return tap($this, $callback);
    } finally {
        $this->timestamps = $timestamps;
    }
}

如今 Message 模型能夠鏈式使用以上的方法:

request()->user()->latestMessage->keepingTimestamps(function ($message) {
    $message->markRead(); // updates a 'read_at' timestamp instead
}); // returns the latestMessage

若是你寫的代碼有 DB::transaction() 相同的模式,你能夠在 Laravel 5.4 使用 tap() 幫助函數重寫。

Collection

Laravel 5.4 中也能夠在 Collection 類中使用 tap() 方法。你能夠在任何地方使用,而不須要破壞鏈式。對於 Laravel 5.3 及更早的版本,你只須要複製粘貼五行代碼的方法做爲 Collection macro 到你項目的 AppServiceProvider@boot() 便可。

這裏有一個例子,用於 Laravel 網站支持英語和法語。取代月份的語言翻譯文件,使用 Carbon 列出一年每月份的 <option>。所以這個模型的修飾方法:

public function monthOptions()
{
    return collect(range(1, 12))
        ->keyByValue() // custom Collection macro
        ->tap(function () {
            if (App::getLocale() === 'fr') {
                setlocale(LC_TIME, 'fr_CA');
            }
        })
        ->map(function ($month) {
            return sprintf('%02d - %s', $month,
                Carbon::now()->month($month)->formatLocalized('%B'));
        })
        ->tap(function () {
            if (App::getLocale() === 'fr') {
                setlocale(LC_TIME, '');
            }
        });
}

對於更多的語言支持,設置/恢復狀態將提取到其餘方法,使其更加可讀。

使用 Collection tap() 處理控制檯命令進度條

這是在集合中最典型的用例。你甚至能夠在 handle() 處理過程當中保持其方法鏈。

public function handle()
{
    Club::findOrFail($this->option('club'))
        ->members()
        ->subscribed()
        ->get()
        ->tap(function ($members) {
            $this->output->progressStart($members->count());
        })
        ->each(function ($member) {
            Mail::to($member)->queue(new Newsletter($member, $this->matchReport());
 
            $this->output->progressAdvance();
        })
        ->tap(function () {
            $this->output->progressFinish();
        });
}
 
public function matchReport()
{
     return once(function () {
          return MatchReport::ofRound($this->option('round'))->firstOrFail();
     });
}
相關文章
相關標籤/搜索