Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How (and where) to register a custom query method in Laravel

In my application I needed to retrieve the users who were registered in last 7 days. Later I realized I also need to check for 30 days and 365 days and so on. So I wrote a query scope in my User.php:

public function scopeCreatedWithinDays($query,$day){
    $str = $day.' days ago';
    $carbon = new Carbon($str);
    $query->where('created_at', '>=', $carbon);
}

And I suddenly realized that this method is a good candidate for repeated use across all models. So I need to define this method in a common place so that I can easily get the rows created within last x days by simply calling $anyModel->createdWithinDays(30). But I don't know where to put it and how...

like image 339
Tanmay Avatar asked Dec 07 '17 21:12

Tanmay


2 Answers

There is also the option of macroing a method on the Query Builder:

\Illuminate\Database\Query\Builder::macro('createdWithinDays', function ($day) {
    return $this->where('created_at', '>=', new \Carbon\Carbon($day .' days ago'));
});

Now you should have that method available for any queries involving Query Builder, which includes all Eloquent queries.

No inheritance, no traits, no changes to any models and you have this method to use from DB:: as well.

AnyModel::createdWithinDays(4)->get();
DB::table('blah')->createdWithinDays(4)->get();

Sorry .. the 'and where' part: Add the macro to a Service Provider boot method.

like image 121
lagbox Avatar answered Oct 31 '22 14:10

lagbox


For reusable code you have 2 options:

  1. create base model and make all other models extend from this base model (this model should extend from Eloquent model)
  2. create trait and use this trait in all models that really need it.

There is no big difference, but it's better to create multiple traits with similar set of functionalities instead of creating one big class having multiple reusable methods.

Of course you can also mix this, so you can put the method in trait and use this trait in base model and make all models extend from this base model

like image 45
Marcin Nabiałek Avatar answered Oct 31 '22 15:10

Marcin Nabiałek