Laravel Tap Function
Laravel 5.4 introduces a new tap method. Here is the underlying implementation. You give it a value as its first argument and a closure or a callback function as a second argument that accepts that value. For instance:
return tap('some value', function($data) {
});
So, 'some value' will be stored in the variable $data, and a callback function will be called with that variable. Below is the Laravel 5.4 implementation of the tap function.
function tap($value, $callback)
{
$callback($value);
return $value;
}
Notice behind the scenes, it triggers your callback function with the value and then returns the original value. So, if we run the above code it's going to return 'some value'.
Laravel Collection tap Method
There is also a tap method on the Collection that allows you to tap into a collection at a particular point and see the results at that specific point without affecting the main collection. It is beneficial for debugging your code and finding where the code goes wrong.
Let's demonstrate this feature with the help of an example. You have the following array:
$actors = [
['actor' => 'Robert Downey', 'oscar' => 0, 'aboveFifty' => 1],
['actor' => 'Tom Cruise', 'oscar' => 0, 'aboveFifty' => 1],
['actor' => 'Johnny Depp', 'oscar' => 0, 'aboveFifty' => 1],
['actor' => 'Tom Hanks', 'oscar' => 1, 'aboveFifty' => 1],
['actor' => 'Matt Damon', 'oscar' => 1, 'aboveFifty' => 0],
['actor' => 'Leonardo DiCaprio', 'oscars' => 1, 'aboveFifty' => 0]
];
Now we convert this array into a collection, filter the data and tap into it at two different points.
return collect($actors)
->where('aboveFifty', 1)
->tap(function ($collection) {
echo($collection->pluck('actor'));
})
->where('oscar', 1)
->tap(function ($collection) {
echo($collection->pluck('actor'));
});
This code will output the following for the first tap:
Robert Downey
Tom Cruise
Johnny Depp
Tom Hanks
And this for the second tap:
Tom Hanks
Tap versus Pipe
Laravel also provides another similar method named pipe. They are similar because they could be performed inside a collection pipeline but they have one primary difference. Tap allows you to do something with the data but does not modify the data. Pipe modifies the data in the collection based on its return value. For example:
return collect($actors)
->where('aboveFifty', 1)
->pipe(function ($collection) {
return $collection->push(['actor' => 'Brad Pitt', 'oscar' => 1, 'aboveFifty' => 1]);
});
The above code outputs the following:
Robert Downey
Tom Cruise
Johnny Depp
Tom Hanks
Brad Pitt
Higher Order Tap
New in Laravel 5.5 is the higher order tap. Here is the Laravel 5.5 implementation.
function tap($value, $callback = null)
{
if (is_null($callback)) {
return new HigherOrderTapProxy($value);
}
$callback($value);
return $value;
}
Now, you could see that the callback function is optional. If the callback function is not given, it will return HigherOrderTapProxy. So, what is HigherOrderTapProxy? Let's demonstrate it with an example.
$user = User::find(1);
$data = [
'name' => 'David',
'email' => 'David@example.com'
];
return tap($user)->update($data);
Now, you are updating the first user value with the new data in the database. You tap the user model and then updated it with the data. As you know update method returns a boolean value. However, you have used the tap function, so it will first call the update method on the user and then return the user variable. Above code will return this JSON response.
{
id: 1,
name: "David",
email: "David@example.com",
created_at: "2017-09-30 10:34:07",
updated_at: "2017-09-30 10:38:26"
}
This is confusing because you called the update method on the user and update do not return the eloquent model, it returns a boolean. But, you have got the full model. So, this is how it works behind the scenes. If you do not give a callback function to the tap, it returns a new HigherOrderTapProxy. HigherOrderTapProxy just have a __call magic method. The __call magic method gets called dynamically if the method is not defined in the class. In HigherOrderTapProxy class, the update method is called, and then it returns the original value. In our case, it is the user.