How to use paginate() with a having() clause when column does not exist in table

前端 未结 7 1890
不知归路
不知归路 2020-12-01 06:41

I have a tricky case ...

Following database query does not work:

DB::table(\'posts\')
->select(\'posts.*\', DB::raw($haversineSQL . \' as distance         


        
7条回答
  •  不知归路
    2020-12-01 07:12

    This is somewhat of a problem with the query builder as all selects are discarded when doing an aggregate call (like count(*)). The make-do solution for now is to construct the pagniator manually.

    $query = DB::table('posts')
        ->select(DB::raw('(c1 - c2) as distance'))
        ->having('distance', '<=', 5);
    
    $perPage = 10;
    $curPage = Paginator::getCurrentPage(); // reads the query string, defaults to 1
    
    // clone the query to make 100% sure we don't have any overwriting
    $itemQuery = clone $query;
    $itemQuery->addSelect('posts.*');
    // this does the sql limit/offset needed to get the correct subset of items
    $items = $itemQuery->forPage($curPage, $perPage)->get();
    
    // manually run a query to select the total item count
    // use addSelect instead of select to append
    $totalResult = $query->addSelect(DB::raw('count(*) as count'))->get();
    $totalItems = $totalResult[0]->count;
    
    // make the paginator, which is the same as returned from paginate()
    // all() will return an array of models from the collection.
    $paginatedItems = Paginator::make($items->all(), $totalItems, $perPage);
    

    Tested with the following schema using MySQL:

    Schema::create('posts', function($t) {
        $t->increments('id');
        $t->integer('c1');
        $t->integer('c2');
    });
    
    for ($i=0; $i < 100; $i++) { 
        DB::table('posts')->insert([
            'c1' => rand(0, 10),
            'c2' => rand(0, 10),
        ]);
    }
    

提交回复
热议问题