Laravel 4: How to apply a WHERE condition to all q

2019-03-13 05:39发布

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?

3条回答
再贱就再见
2楼-- · 2019-03-13 06:06

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.

查看更多
我命由我不由天
3楼-- · 2019-03-13 06:10

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

查看更多
Lonely孤独者°
4楼-- · 2019-03-13 06:18

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.

查看更多
登录 后发表回答