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

前端 未结 3 1769
我在风中等你
我在风中等你 2021-02-02 16:55

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,

相关标签:
3条回答
  • 2021-02-02 17:12

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

    0 讨论(0)
  • 2021-02-02 17:22

    The answer was given when there was no query scope feature available.

    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 (Using the query scope):

    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.

    // Using a local query scope
    class Post extends Eloquent
    {
    
        public function scopeApproved($query)
        {
            return $query->where('approved', 1);
        }
    }
    

    You can use it like:

    $approvedPosts = Post::approved()->get();
    
    0 讨论(0)
  • 2021-02-02 17:28

    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.

    0 讨论(0)
提交回复
热议问题