如何使用'在laravel 5中的关系列中使用paginate

时间:2016-10-22 15:57:06

标签: mysql laravel laravel-5 eloquent

我需要抓住那些与经销商关系密切的车辆。距离< 200

Vehicle::join('dealers', 'vehicles.dealer_id', '=', 'dealers.id')
     ->select(DB::raw("dealers.id, ( cos( radians(latitude) ) * cos( radians( longitude ) ) ) AS distance"))
     ->havingRaw('distance < 200');

我正试图在别名&#39;距离&#39;上使用havingRaw。来自关系(belongsTo)经销商。但失败了,错误:

  

未找到列:1054未知列&#39;距离&#39;在&#39;有条款&#39;

更新

当我将paginate函数添加到上述查询中时,实际上会出现问题。

$vehicle = Vehicle::join('dealers', 'vehicles.dealer_id', '=', 'dealers.id')
 ->select(DB::raw("dealers.id, ( cos( radians(latitude) ) * cos( radians( longitude ) ) ) AS distance"))
 ->havingRaw('distance < 200');

$result = $vehicle->paginate(15);

5 个答案:

答案 0 :(得分:4)

更新

如果对查询使用 program Project1; uses Vcl.Forms, Unit1 in 'Unit1.pas' {Form1}, Unit2 in 'Unit2.pas' {Form2}; {$R *.res} var MainForm: TForm1; begin Application.Initialize; Application.MainFormOnTaskbar := True; if Login then begin Application.CreateForm(TForm1, Form1); Application.Run; end else Application.Terminate; end. laravel将尝试执行以下SQL代码来计算可能匹配的总数:

paginate()

如您所见,此查询中没有此类列或别名select count(*) as aggregate from `vehicles` inner join `dealers` on `vehicles`.`dealer_id` = `dealers`.`id` having distance < 200

我原来的答案中的

选项2 也将解决这个问题。

原始答案

这种接缝是MySQL严格模式的问题。如果使用laravel 5.3默认情况下启用严格模式。您有两种选择:

选项1:在distance

中禁用MySQL的严格模式
config/database.php

选项2:使用WHERE condtition

...
'mysql' => [
    ...
    'strict' => false,
    ...
],
...

文档:

  

标准SQL的MySQL扩展允许HAVING中的引用   选择列表中的别名表达式的子句。启用   ONLY_FULL_GROUP_BY禁用此扩展,因此需要HAVING   使用非混淆表达式编写的子句。

Server SQL Modes - ONLY_FULL_GROUP_BY

答案 1 :(得分:2)

答案已更新,对应更新的问题

问题在于查询构建器,因为在进行聚合调用时会丢弃所有选择(如count(*))。目前,make-do解决方案是手动构建paginator:

$query = Vehicle::join('dealers', 'vehicles.dealer_id', '=', 'dealers.id')
             ->select(DB::raw("dealers.id, ( cos( radians(latitude) ) * cos( radians( longitude ) ) ) AS distance"))
             ->having('distance', '<', '200');

$perPage = 10;
$curPage = \Illuminate\Pagination\Paginator::resolveCurrentPage();

$itemQuery = clone $query;

$items = $itemQuery->forPage($curPage, $perPage)->get();

$totalResult = $query->addSelect(DB::raw('count(*) as count'))->get();
$totalItems = $totalResult->first()->count;

$vehicles = new \Illuminate\Pagination\LengthAwarePaginator($items->all(), $totalItems, $perPage);

答案 2 :(得分:1)

havinghavingRaw无法访问查询中生成的字段 从laravel docs看这个例子 enter image description here

您的查询必须像这样

Vehicle::join('dealers', 'vehicles.dealer_id', '=', 'dealers.id')
            ->select(DB::raw("dealers.id, ( cos( radians(latitude) ) * cos( radians( longitude ) ) ) AS distance"))
            ->havingRaw('(cos(radians(latitude)) * cos(radians(longitude))) < 200');

答案 3 :(得分:0)

我做的事情似乎与你要做的事情类似:

public function scopeNearest($query, Geo $geo, $miles = 25)
{
    return $query
        ->select(DB::raw("*, ( 3959 * acos( cos( radians({$geo->lat}) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians({$geo->lng}) ) + sin( radians({$geo->lat}) ) * sin( radians( lat ) ) ) ) AS distance"))
        ->groupBy('id')
        ->having('distance', '<', $miles)
        ->orderBy('distance');
}

在这个例子中,我有一个处理纬度和经度坐标的单独模型,以及名为Geo的地址信息。您可能不需要这种级别的分离,因此您可以重构这样的事情:

public function scopeNearest($query, $lat, $lng, $miles = 25)
{
    return $query
        ->select(DB::raw("*, ( 3959 * acos( cos( radians({$lat}) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians({$lng}) ) + sin( radians({$lat}) ) * sin( radians( latitude ) ) ) ) AS distance"))
        ->groupBy('id')
        ->having('distance', '<', $miles)
        ->orderBy('distance');
}

请记住,为了计算距离,您需要两点。该模型将能够使用自己的latitudelongitude列来检查两点之间的距离,并将作为参数提供给范围查询的纬度和经度。

你可以把它放在你的车型中,然后像这样打电话:

Vehicle::nearest($latitude, $longitude, 200);

这对于您的用例未经测试,因此我无法保证它能够开箱即用,但希望它能为您指明正确的方向。

答案 4 :(得分:0)

这应该有效:

Vehicle::join('dealers', 'vehicles.dealer_id', '=', 'dealers.id')
 ->select(DB::raw("dealers.id, ( cos( radians(latitude) ) * cos( radians( longitude ) ) ) AS distance")->havingRaw('distance < 200'));