Powerup Laravel Eloquent and Query Builder (THE MAGIC SPELL)

While working with Laravel Eloquent and Query Builder, I faced a scenario where I had to repeat similar kind of long boring where('column', 'like', 'string') condition for multiple columns. This was kind of hard to read and also did not look nice. See it yourself if you don’t believe me:

So I tried to make it a little bit better and more readable. To achieve the goal, I tried different options that Laravel provided me.

First I thought of making query constraints for querying strings. So I used query scopes (

..Duh) and placed them in my base model which extends the Eloquent model. And then my every other models will extend my custom base model.

And now my query will look like this:

Everything is working so good so far and the query looks shorted and clean as well. I have accomplished the goal…..!!!

But wait! There is an issue. My scopes are working fine with the Eloquent Models, but what If I want to use Query Builder instead of Model? Scopes won’t work for Query Builder, right?

So a few decades

later , I read the Laravel document and found a magic spell called Macro. What this magic spell does is it allows you to inject your own method to a class from outside. Wait!!! What?

Suppose, we have our query builder class which is \Illuminate\Database\Query\Builder::class, now using macro, we can inject our startsWith() and contains() method to the Query Builder class. Let’s just see how to do this:

In your AppServiceProvider::boot() method you can inject your custom method through macro().

Now I can remove the scopes from my base model because Models will also get these query builder functions I am inject because they also extends query builder at some point. In the code above, I showed how to inject one method to my Builder class. But I need more than one method to inject. So here is a pretty good way to do that:

Custom methods should return closure accepting necessary parameters.

Now use mixin() (which also use macro() under the hood) to inject all the method of QueryHelper::class to our Query Builder.

Now we can use our custom query method everywhere both Eloquent model and Query Builder.

While working with Laravel Eloquent and Query Builder, I faced a scenario where I had to repeat similar kind of long boring where(‘column’, ‘like’, ‘string’) condition for multiple columns. This was kind of hard to read and also did not look nice. See it yourself if you don’t believe me:

So I tried to make it a little bit better and more readable. To achieve the goal, I tried different options that Laravel provided me.

First I thought of making query constraints for querying strings. So I used query scopes (

..Duh) and placed them in my base model which extends the Eloquent model. And then my every other models will extend my custom base model.

And now my query will look like this:

Everything is working so good so far and the query looks shorted and clean as well. I have accomplished the goal…..!!!

But wait! There is an issue. My scopes are working fine with the Eloquent Models, but what If I want to use Query Builder instead of Model? Scopes won’t work for Query Builder, right?

So a few decades

later , I read the Laravel document and found a magic spell called Macro. What this magic spell does is it allows you to inject your own method to a class from outside. Wait!!! What?

Suppose, we have our query builder class which is \Illuminate\Database\Query\Builder::class, now using macro, we can inject our startsWith() and contains() method to the Query Builder class. Let’s just see how to do this:

In your AppServiceProvider::boot() method you can inject your custom method through macro().

Now I can remove the scopes from my base model because Models will also get these query builder functions I am inject because they also extends query builder at some point. In the code above, I showed how to inject one method to my Builder class. But I need more than one method to inject. So here is a pretty good way to do that:

Custom methods should return closure accepting necessary parameters.

Now use mixin() (which also use macro() under the hood) to inject all the method of QueryHelper::class to our Query Builder.

Now we can use our custom query method everywhere both Eloquent model and Query Builder.

You can do a lot more than this with macro(). You can make query helper method which can accept relationship column or do more complex stuff. Have fun with macro() – The magic spell.

Maybe another few decades later I will come up with another article on how the macro really works. Stay happy and stay safe until then. ♡

You can do a lot more than this with macro(). You can make query helper method which can accept relationship column or do more complex stuff. Have fun with macro() – The magic spell.

Maybe another few decades later I will come up with another article on how the macro really works. Stay happy and stay safe until then. ♡

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *