As yet undocumented, Laravel 5.3 quietly added a new tap() global helper function, improving the framework’s declarative capabilities. It’s a subtle idiom picked up from Ruby and Lodash that allows you to “tap” into a chain.

You will not use this function often. It does take control of stodgy imperative solutions with right-to-left assignments souring solutions in an unpleasant direction. The end result will be saving 2 or 3 lines on each use while making that code read top-down, left-to-right.

tap() to perform intermediate actions

Starting with a simple example I’ve grabbed some code from Laravel’s AuthenticateSession@handle(). Veteran PHP developers are plenty familiar with the imperative solution:

A Laravel 5.4 declarative refresh?

Some devs might be cringing as that use syntactical bloat but most of us know what the PHP closure dream is:


// assign object
// make call using object (or not even using that object!)
// return object

tap() to restore state

Eloquent create and update methods support a ['timestamps' => false] option. If this were implemented as a chainable method, the result is fairly readable.

Now that Message model object can be chained:

If you recognize this code has the same pattern of DB::transaction(), Laravel 5.4 rewrote the method to use tap().


// capture state
// make call using object
// restore state
// return that object

Collection tap()

Laravel 5.4 also made its Collection class tappable, which will expose the full power of this approach. Now arbitrary code can be run mid-pipeline without having to break the chain. For Laravel 5.3 or below, copy and paste the 5 line method as a Collection macro into your project’s AppServiceProvider@boot().

Here’s one example I used for a Laravel web site supporting both English and French Canadian locales. Instead of hardcoding months into language translation files, I used Carbon for these month of the year dropdown <option>s. Hence this model decorator method:

With just one extra language, I’m happy with this solution. For more language support, the set/restore states would be extracted into other methods to make this even more readable.

Collection tap() to handle console command progress bars

This is the most typical use case I’ve had in collections and it makes commands some of the cleanest code in my projects. You can even keep its method chain for the full handle() duration.

Laravel Query Builder tap() macro

Lastly, what if you wanted a progress bar when the eager-loaded Eloquent memory footprint of that collection pipeline is too high? chunk() the result into pages and use a query extension macro to accomplish the same chaining abilities.

reorder()? Laravel developers using Postgresql may appreciate this method as COUNT aggregates cannot be run on queries with an ORDER BY clause. (Thanks, SQL99 standards.) reorder() is a Laravel query Builder macro to strip orderBy() already applied to the Builder object.

Laravel is aimed at MySQL installs but I’ve found this helper an integral part of a Laravel app on top of Postgresql. Upvote my obscure issue thread to hopefully bring this into the mainstream. If DHH approves, surely I’m onto something.