本文參照轉譯:php
http://derekmd.com/2017/02/la...laravel
https://murze.be/2017/02/lara...緩存
Laravel 5.3 中增長了一個新的全局幫助函數 tap()
,改進了框架的聲明能力。這個微妙的語法是從 Ruby
和 Lodash
借鑑而來,容許你去 tap
成鏈。框架
先看看 tap()
幫助函數的代碼,只有短短的幾行:ide
function tap($value, $callback) { $callback($value); return $value; }
你須要傳一個值和一個回調到方法中,值做爲回調的參數,回調將執行,最後值被返回。函數
從一個簡單的例子開始,提取 Laravel
的 AuthenticateSession@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 的 create
和 update
方法支持 ['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()
幫助函數重寫。
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, ''); } }); }
對於更多的語言支持,設置/恢復狀態將提取到其餘方法,使其更加可讀。
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(); }); }