当表中不存在列时,如何将paginate()与having()子句一起使用

YaF*_*red 18 laravel laravel-4

我有一个棘手的案例......

以下数据库查询不起作用:

DB::table('posts')
->select('posts.*', DB::raw($haversineSQL . ' as distance'))
->having('distance', '<=', $distance)
->paginate(10);
Run Code Online (Sandbox Code Playgroud)

它失败并显示消息:列距离不存在.

当paginate()尝试使用时计数记录时发生错误

select count(*) as aggregate from {query without the column names}
Run Code Online (Sandbox Code Playgroud)

由于列名被剥离,因此距离未知并引发异常.

在这种情况下,是否有人能够使用分页?

谢谢

Jon*_*eir 8

您可以计算WHERE零件中的距离:

DB::table('posts')
    ->whereRaw($haversineSQL . '<= ?', [$distance])
    ->paginate(10);
Run Code Online (Sandbox Code Playgroud)

如果您需要distance应用程序中的值,则必须计算两次:

DB::table('posts')
    ->select('posts.*', DB::raw($haversineSQL . ' as distance'))
    ->whereRaw($haversineSQL . '<= ?', [$distance])
    ->paginate(10);
Run Code Online (Sandbox Code Playgroud)


And*_*eas 7

这在查询构建器中有些问题,因为在进行聚合调用时会丢弃所有选择(如count(*)).现在的make-do解决方案是手动构建pagniator.

$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);
Run Code Online (Sandbox Code Playgroud)

使用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),
    ]);
}
Run Code Online (Sandbox Code Playgroud)


Ada*_*dam 6

这不是一个令人满意的答案,但如果您只需要在分页视图中显示简单的“下一个”和“上一个”链接,您可以使用该simplePaginate方法。它将执行更有效的查询,并且如果您使用having.

DB::table('posts')
->select('posts.*', DB::raw($haversineSQL . ' as distance'))
->having('distance', '<=', $distance)
->simplePaginate(10);
Run Code Online (Sandbox Code Playgroud)


小智 5

使用 Eloquent,我知道您可以将列传递给分页器,如下所示:

Post::having('distance','<=', $distance)
   ->paginate(10, array('*', DB::raw($haversineSQL . ' as distance')));
Run Code Online (Sandbox Code Playgroud)

不确定它是否可以在没有 Eloquent 的情况下工作,但你可以尝试一下。


Jul*_*atl 5

有一个更好的方法,也适用于链接:

        $curPage = \Illuminate\Pagination\Paginator::resolveCurrentPage();
        $total = $model->get()->count();
        $items = $model->forPage($curPage, $showPerPag)->get();
        $paginated = new \Illuminate\Pagination\LengthAwarePaginator($items, $total, $showPerPage, $curPage, ['path' => request()->url(), 'query' => request()->query()]);
Run Code Online (Sandbox Code Playgroud)