Eloquent may be killing you

Feb 1, 2019 · 3 min read
Image for post
Image for post
a visual representative of how your DBA feels about you, probably

I am learning Laravel, making a little ‘job application’ app to check things out. While implementing a quick check in a blade template to see whether or not a user already applied for a job, I learned a very valuable lesson.

First off, never run queries in a view.

Eloquent has many beautiful relationship methods that allow you to whip up relevant information fast and easy, however they are also very easy to abuse if you do not know what you are doing.

At first, I implemented my features this way:

Image for post
Image for post
see that “@if count() “ statement? what you don’t see is that it is nested within a foreach loop..

As stated in the caption, this block is within a foreach loop. For those that do not understand: this means that the view is running a query ( and yes, that beautiful Eloquent syntax you love to abuse is actually a database query, hence the ‘get()’ ), every. single. time. that loop iterates..

Now you may not notice the effects of this on your local machine, but god help you if you were to push that up to a server somewhere and it begins to operate with any reasonable amount of data.

What’s a better way to do this? Let me show you a possible solution.

Step 1: Run the query once, in the controller.

within the controller that returns your view. Note the ‘toArray’ function, which is necessary because eloquent will return a ‘collection’ — instead of an array — which cannot be used within php’s array methods ( such as in_array(), as seen below )

$userJobs will now look like this:

Image for post
Image for post
$userJobs, an array of jobs that the currently authenticated user is related to

Step 2: convert your view-query monstrosity into the following line:

Image for post
Image for post
still within that foreach loop, that iterates through the full job array

As mentioned in the caption, the foreach loop that this line is nested inside of is iterating through all jobs. That being said, this line now simply checks the current job’s id against the array of jobs that the user is associated to. Iterating through an array of single values is always going to be a million times faster ( probably literally ) than running a full database query every single iteration..

And you will live to code another day.

Long story short, the first ( and very inefficient ) method worked.. in that it produced the correct ‘output’. However, the second is an ‘algorithmic adjustment’ that dramatically improved the efficiency of the operation.

..I don’t just mean that it dramatically improved the efficiency, however. I mean that it literally raised it from the bottomless pits of hell, sacrificed itself for its sins and born it again as something that even deserves to exist in this world.

So what did we learn? Eloquent is actually a really great tool that provides very readable method to fetch your elements. I am thoroughly enjoying working with Eloquent and Laravel. Today, however, I stumbled upon a landmine that made me wake up from a very bad nightmare and realize that — if wielded wrong — this battle-axe will chop your own head off.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store