Introducting the Tappable trait to use 'tap' with any class
As you might know, the Laravel framework comes with a handy tap method which allows you to call the given closure with the given value and then return the value. Sounds confusing? It probably is until you've seen it! Let's take a look at this example:
// without tap:function getServer($id) { $server = ServerModel::findOrFail($id); Log::debug('Server was found', $server->toArray()); return $server;} // with tap:function getServer($id) { return tap(ServerModel::findOrFail($id), function ($server) { Log::debug('Server was found', $server->toArray()); });}
Lately we've used a Tappable
trait in one of our projects to avoid the global tap
helper method. This allowed us to call tap
directly on an instance. The example above could be rewritten like this:
function getServer($id) { return ServerModel::findOrFail($id)->tap(function ($server) { Log::debug('Server was found', $server->toArray()); });}
This might look like a small difference but we think it's more readable and it even gets better when the logic increases, for example when you use Eloquent scopes.
// beforetap(ServerModel::active()->paid()->withTrashed()->findOrFail($id), function ($server) { Log::debug('Server was found', $server->toArray());}); // afterServerModel::active() ->paid() ->withTrashed() ->findOrFail($id) ->tap(function ($server) { Log::debug('Server was found', $server->toArray()); });
We've submitted a PR to make this trait available in the illuminate/support
repository. Luckily it was accepted and is it's now available in Laravel 5.8.17!