Tap in Laravel
In this tutorial, we will talk about tap in Laravel. We will discuss tap
helper function and tap
method on collections in detail.
Table of Contents
Tap Helper Function
Old implementation
Laravel comes up with a tap
function. It is a pretty odd function, inspired by Ruby. Here is the basic implementation of Tap
helper function.
function tap($value, $callback) { $callback($value); return $value; }
The above code will accept an argument and it will call an anonymous function with that argument. After calling the callback function, it will return the argument.
Let’s see how we can use it in a meaningful way. For instance:
<?php return tap($photo, function($photo) { $photo->validated = true; $photo->save(); });
In the above example, we pass a single argument (Photo Model) and a callback function that simply sets validated to true and save the model. This function will then return the Photo Model instance back to the caller.
New implementation
In the latest versions of Laravel 5.4 and in Laravel 5.5, Higher Order Tap
came in. It introduced the ability to shorten tap
calls. Here is the new implementation of Tap
function.
function tap($value, $callback = null) { if (is_null($callback)) { return new HigherOrderTapProxy($value); } $callback($value); return $value; }
Callback function is now optional. You could also chain multiple methods of the argument passed. For example
<?php $photo = App\Photo::find(1); return tap($photo)->update([ 'validated' => 'true', ])
We are able to chain any of the Model’s method on tap call. Update method normally returns true or false, but we have used the tap
function here. In this case, it will return Photo model we tapped in. Tap makes it helpful to return the Object passed as an argument.
How it works?
Tap is a very helpful function, but sometimes its quite confusing to think how it works. Let me explain to you how it actually works.
If the callback function is not given as it is optional, Laravel will return a new instance of HigherOrderTapProxy
. There is call
magic method defined in the HigherOrderTapProxy
class. Call
magic method is called dynamically by the language if the
called method is not defined in the class. Since, there are no methods defined in the HigherOrderTapProxy
class except call
magic method, it will call it every time you chain any method calls with tap
function. In the call
magic method, our update method or any method that we called, will be called with the parameters and it will return the argument that we passed orginally to the tap function.
Here are the actual contents of the call magic method in HigherOrderTapProxy
class.
public function __call($method, $parameters) { $this->target->{$method}(...$parameters); return $this->target; }
In the above code, target
property is the argument that we passed inside the tap.
Laravel Collection Tap Method
Laravel also includes a tap
method on collections that allows you to tap into a collection at a specific point and do something with those results. Tap
does not affect the results of the main collection. It is beneficial in debugging your code and finding where things get wrong while working with collections.
Let’s use an example to explain this method. You have the following array.
$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'], ];
Now let’s try to use the tap
method on this array. First, we have to convert this array into a collection and then tap the collection at a specific point.
return collect($photos) ->where('validated', true) ->tap(function ($validated) { return var_dump($validated->pluck('file_name')); }); });
Above code will output the following for the first tap:
wallpaper spring mac fruit
Tap versus Pipe
In Laravel, there is also a similar method to tap
named pipe
. They are similar in a sense because both of them are used inside a collection pipeline. There is one difference between tap and pipe. Tap allows you to work with data but it does not modify the original return value. On the other hand, pipe modifies the data based on its return value.
For instance:
return collect($photos) ->where('validated', true) ->pipe(function ($validated) { return $validated->where('extension', 'jpg')->pluck('file_name'); }); });
Above code will output the following based on the $photos
array.
wallpaper fruit
On the other hand if we used the above code with tap like this:
return collect($photos) ->where('validated', true) ->tap(function ($validated) { return $validated->where('extension', 'jpg')->pluck('file_name'); }); });
It will return the all of the photos array where validated
is set to 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" }
Leave your comments and queries below. I will respond to them as fast as I can.