Laravel 4: How to apply a WHERE condition to all queries of an Eloquent class?

戏子无情 提交于 2019-12-20 10:00:31

问题


I'm trying to implement an "approved' state for a table I have, it's pretty straightforward, basically, if the row's approve column equals 1; that row should be retrieved, otherwise it shouldn't.

The problem is, now I have to go through the whole codebase and add a WHERE statement(i.e., function call) which is not only time consuming but also inefficient(if I ever want to remove that feature, etc.)

How can I do that? Is it as easy as adding $this->where(..) inside the Eloquent child class' constructor? Wouldn't that affect other CRUD operations? such as not updating an unapproved row?


回答1:


You can override the main query, only for the Post model, like

class Post extends Eloquent
{
    protected static $_allowUnapprovedPosts = false;
    public function newQuery()
    {
        $query = parent::newQuery();
        if(! static::$_allowUnapprovedPosts)
        {
            $query->where('approved', '=', 1);
        }
        else{
            static::$_allowUnapprovedPosts = false;
        }
        return $query;
    }

    // call this if you need unapproved posts as well
    public static function allowUnapprovedPosts()
    {
        static::$_allowUnapprovedPosts = true;
        return new static;
    }
}

Now, simply use anything, but unapproved users won't appear in the result.

$approvedPosts = Post::where('title',  'like', '%Hello%');

Now, if you need to retrieve all posts even unapproved ones then you can use

$approvedPosts = Post::allowUnapprovedPosts()->where('title',  'like', '%Hello%');

Update:

Since, Laravel now provides Global Query Scopes, leverage that instead of this hacky solution, notice the date of this answer, it's too old and so much things changed by now.




回答2:


The closest thing I found is Eloquent query scope.

Even though it requires a minor change in my code(prefixing queries) it still gives me what I'm looking with great flexibility.

Here's an example:

Create a function within the Eloquent child class:

class Post extends Eloquent {

    public function scopeApproved($query)
    {
        return $query->where('approved', '=', 1/*true*/);
    }

}

Then simply use it like this:

$approvedPosts = Post::approved()-><whatever_queries_you_have_here>;

Works perfectly. No ugly repeated WHERE function calls. easy to modify. Much easier to read(approved() makes much more sense than where('approved', '=', 1) )




回答3:


You can use global scope for your need, docs for that are here : https://laravel.com/docs/5.6/eloquent#query-scopes

Good example is SoftDeletingScope which is applied to all queries by default on models which use SoftDeletes trait.



来源:https://stackoverflow.com/questions/18678779/laravel-4-how-to-apply-a-where-condition-to-all-queries-of-an-eloquent-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!