Search code examples
phplaravelooptraitscode-reuse

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...


Solution

  • 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.