Make custom query builder method (query scope) for

2019-02-20 08:47发布

问题:

I have multiple models, all with timestamps. I'm often using whereDate to get all rows from today and yesterday, like this:

ModelName::whereDate('created_at', now()->today())->get();
ModelName::whereDate('created_at', now()->yesterday())->get();

I want to have it shorter, simplier, like:

ModelName::today()->get();
ModelName::yesterday()->get();

I can not find any methods to do this, so I found in documentation that I can make own "scopes". The problem is, that I can make it for specified model, but I can not find a way to make it globally, for all models. Now I need to paste this scope methods in every model class. This works, but I need to repeat this code in every model class, so it's not a good way to do this I'm sure.

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class ModelName extends Model
{


    /**
     * Custom scope (query builder method) to easy return all items from today
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeToday($query)
    {
        return $query->whereDate('created_at', now()->today());
    }


    /**
     * Custom scope (query builder method) to easy return all items from yesterday
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeYesterday($query)
    {
        return $query->whereDate('created_at', now()->yesterday());
    }
}

回答1:

You can define the local scopes in a trait:

<?php
namespace App\Traits;

trait Scopes
{
    public function scopeToday($query)
    {
        return $query->whereDate('created_at', now()->today());
    }

    public function scopeYesterday($query)
    {
        return $query->whereDate('created_at', now()->yesterday());
    }
}

Then use the trait in any model you like:

use App\Traits\Scopes;

And to use the traits:

ModelName::today()->get();
ModelName::yesterday()->get();

Another way to do that is to create and extend a base model class and define the scopes there, but I'd use a trait.