在本文,咱們將討論 Laravel 中的 tap
。咱們將詳細討論 tap
幫助函數和 collection
中的 tap
方法。php
Laravel提出了一個 tap
功能。這是一個很是奇怪的功能,受Ruby的啓發。這是 tap
助手功能的基本實現。laravel
function tap($value, $callback) { $callback($value); return $value; }
上面的代碼將接受一個參數,它將使用該參數調用一個匿名函數。在調用回調函數後,它將返回參數。 讓咱們看看咱們如何以有意義的方式使用它。例如:spring
<?php $photo = App\Photo::find(1); return tap($photo, function($photo) { $photo->validated = true; $photo->save(); });
在上面的例子中,咱們傳遞一個參數(照片模型)和一個回調函數,該函數簡單地將 validated
設置爲 true
並保存模型。這個函數而後將照片模型實例返回給調用者。數組
在最新版本的Laravel 5.4和Laravel 5.5中,更高級的 tap
來了。它引入了更短的使用方式。這裏是 tap
函數的新實現。bash
function tap($value, $callback = null) { if (is_null($callback)) { return new HigherOrderTapProxy($value); } $callback($value); return $value; }
回調函數如今是可選的。你還能夠鏈式使用參數中的多個方法,這裏其實也就是照片Model中支持的方法。例如函數
<?php $photo = App\Photo::find(1); return tap($photo)->update([ 'validated' => 'true', ])
咱們可以將任何模型的方法經過 tap
鏈式調用。此更新方法一般返回 true
或 false
,可是這裏使用了 tap
函數。在這種狀況下,它將返回照片模型。tap
能夠幫助你返回做爲參數傳遞的對象。post
tap
是一個很是有用的功能,但有時它很難理解它是如何工做的。 這裏來解釋它是如何工做的。ui
若是沒有給出回調函數,由於它是可選的,Laravel將返回 HigherOrderTapProxy
的新實例。 在 HigherOrderTapProxy
類中定義了調用魔術方法。 調用魔術方法是由語言動態調用的(所謂的方法在類中沒有定義)。 由於除了調用魔術方法,HigherOrderTapProxy
類中沒有定義方法,因此每次使用 tap
函數任何方法調用時都會調用它。 在調用魔術方法中,咱們的更新方法或任何咱們調用的方法將被參數調用,而且它將返回咱們最初傳遞給 tap
函數的參數。this
這裏是 HigherOrderTapProxy
類中調用魔術方法的實際內容。調試
// vendor/laravel/framework/src/Illuminate/Support/HigherOrderTapProxy.php public function __call($method, $parameters) { $this->target->{$method}(...$parameters); return $this->target; }
在上面的代碼中,target
屬性是咱們在tap中傳遞的參數。
Laravel還在 collection
類中有一個 tap
方法,可以讓你在特定的地方傳入參數到 tap中,並對這些結果進行處理。tap
不會影響主要 collection 的結果。 這對調試代碼和查找在處理集合時出現錯誤的地方頗有幫助。 咱們用一個例子來解釋這個方法。 初始化如下數組。
$photos = [ ['file_name' => 'wallpaper', 'validated' => true, 'extension' => 'jpg'], ['file_name' => 'spring', 'validated' => true, 'extension' => 'png'], ['file_name' => 'flowers', 'validated' => false, 'extension' => 'jpg'], ['file_name' => 'mac', 'validated' => true, 'extension' => 'png'], ['file_name' => 'books', 'validated' => false, 'extension' => 'jpg'], ['file_name' => 'mobiles', 'validated' => false, 'extension' => 'jpg'], ['file_name' => 'glass', 'validated' => false, 'extension' => 'png'], ['file_name' => 'fruit', 'validated' => true, 'extension' => 'jpg'], ];
如今讓咱們嘗試在這個數組上使用 tap
方法。首先,咱們必須將這個數組轉換爲一個集合,而後在特定點處 tap
這個集合。
return collect($photos) ->where('validated', true) ->tap(function ($validated) { return var_dump($validated->pluck('file_name')); }); });
上面的代碼將會輸出如下結果:
wallpaper spring mac fruit
在Laravel中,也有相似的方法叫管道。 它們在某種意義上是類似的,由於它們都在集合管道中使用。 tap
和 pipe
之間有一個區別。 tap
容許你使用數據,但不會修改原始返回值。 另外一方面,pipe
根據返回值修改數據。 例如:
return collect($photos) ->where('validated', true) ->pipe(function ($validated) { return $validated->where('extension', 'jpg')->pluck('file_name'); }); });
輸出結果爲
wallpaper fruit
另外一方面,若是咱們像這樣使用上面的代碼:
return collect($photos) ->where('validated', true) ->tap(function ($validated) { return $validated->where('extension', 'jpg')->pluck('file_name'); }); });
它將返回驗證設置爲true的全部照片數組。
結果爲
0: { file_name: "wallpaper", validated: true, extension: "jpg" }, 1: { file_name: "spring", validated: true, extension: "png" }, 3: { file_name: "mac", validated: true, extension: "png" }, 7: { file_name: "fruit", validated: true, extension: "jpg" }
更多PHP知識,請前往PHPCasts