Laravel 4: How to add scope to DB::table?

后端 未结 4 1925
北荒
北荒 2021-01-12 18:38

With Eloquent models adding scopes is easy:

public function scopeMyScope($query)
{
   // Do stuff to that $query
}

But how to add scope to

相关标签:
4条回答
  • 2021-01-12 19:00

    DB::table doesn't have support for scopes. What you could do is simply write a little function that does some things with the query and returns it. The syntax isn't as nice but it works:

    function applyScope($query){
        $query->whereNotNull('deleted_at');
        $query->where('foo', 'bar');
        return $query;
    }
    

    And then:

    $query = DB::table('page_views')
        ->where('id', $this->id)
        ->where('agent', 'NOT LIKE', '%bot%');
    $query = applyScope($query);
    $views = $query->count(DB::raw('distinct session, DATE(created_at)'));
    

    Or a bit a shorter syntax:

    $views = applyScope( DB::table('page_views')
                           ->where('id', $this->id)
                           ->where('agent', 'NOT LIKE', '%bot%')
             )->count(DB::raw('distinct session, DATE(created_at)'));
    
    0 讨论(0)
  • 2021-01-12 19:05

    You could create a custom class that passes all functions to the DB facade exept your custom queries. Like this:

    <?php
    
    namespace App\Utilities;
    
    use DB;
    
    class CustomDB
    {
        private $db;
    
        private static $instance = null;
    
        private $exitCalls;
    
        private function __construct()
        {
            $this->exitCalls = ['get', 'find', 'pluck', 'first', 'value', 'chunk', 'chunkById', 'count', 'max', 'avg', 'exists', 'doesntExist'];
        }
    
        public function __call($name, $arguments)
        {
            $result = call_user_func_array([self::$instance->db, $name], $arguments);
    
            if (in_array($name, $this->exitCalls)) {
                return $result;
            }
    
            return self::$instance;
        }
    
        public static function table($string)
        {
            if (self::$instance == null) {
                self::$instance = new CustomDB();
            }
    
            self::$instance->db = DB::table($string);
    
            return self::$instance;
        }
    
        public function myCustomQuery()
        {
             self::$instance->db->where('name','=','frank');
             return self::$instance;
        }
    }
    

    Now you can simply call:

    CustomDB::table('users')->myCustomQuery()->get();
    
    0 讨论(0)
  • 2021-01-12 19:09

    Thanks to lukasgeiter answer I got the idea of creating a class for this, that extends DB and returns the beginning of a query that can be built upon:

    class PageViewQueryBuilder extends DB {
    
        public static function table()
        {
            $query = parent::table('page_views')
                ->where('agent', 'NOT LIKE', '%bot%')
                ->where('agent', 'NOT LIKE', '%spider%')
                ->where('agent', 'NOT LIKE', '%crawler%')
                ;
    
            return $query;
        }
    }
    

    I can now use this to create a number of different queries, all with the same where conditions.

    Get view count for a specific page:

    $count = PageViewQueryBuilder::table()
        ->where('page_id', $id)
        ->count(DB::raw('distinct session, DATE(created_at)'));
    

    Get all views for a specific page:

    $views = PageViewQueryBuilder::table()
        ->where('page_id', $id)
        ->orderBy('created_at', 'DESC')
        ->groupBy('session', DB::raw('DATE(created_at)'))
        ->get();
    

    Get the 10 most popular pages for the last three months:

    $views = PageViewQueryBuilder::table()
        ->selectRaw('page_id as page_id, count(distinct session, DATE(created_at)) as page_views')
        ->whereRaw('created_at BETWEEN NOW() - INTERVAL 3 MONTH AND NOW()')
        ->groupBy('page_id')
        ->orderBy('page_views', 'desc')
        ->limit(10)
        ->get();
    
    0 讨论(0)
  • 2021-01-12 19:12

    Been using lukas's solution works like a treat; I am calling the scope from the model where it has been defined it just avoids duplicating the function.

    $query = DB::table('page_views')
        ->where('id', $this->id)
        ->where('agent', 'NOT LIKE', '%bot%');
    $query = (new myModel())->scopeMyScope($query);
    $views = $query->count(DB::raw('distinct session, DATE(created_at)'));
    
    0 讨论(0)
提交回复
热议问题