简体   繁体   English

Laravel 5.3无法使用派生字段对模型进行分页

[英]Laravel 5.3 can't paginate model with derived field

I have a Property model and I have made the following scope: 我有一个Property模型,并且进行了以下范围的设计:

public function scopeSearch($query, $search)
{
    return $this->addSelect(DB::raw("( 3959 * acos( cos( radians(".$search['latitude'].") ) * cos( radians( properties.latitude ) )
                      * cos( radians( properties.longitude ) - radians(".$search['longitude'].") ) + sin( radians(".$search['latitude'].") )
                      * sin( radians( properties.latitude ) ) ) ) AS distance"))
        ->having('distance', '<=', $search['radius']);
}

If I then try and get some paginated results like so: 如果然后我尝试得到一些类似的分页结果:

$properties = Property::search($search)
        ->addSelect('properties.*')
        ->paginate($this->per_page);

I get the following error: 我收到以下错误:

QueryException in Connection.php line 729:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'distance' in 'having clause' (SQL: select count(*) as aggregate from `properties` where `properties`.`deleted_at` is null having `distance` <= 25)

Looks like the pagination is doing a count query that doesn't run the addSelect() methods so the field distance doesn't exist. 分页似乎正在执行不运行addSelect()方法的计数查询,因此字段距离不存在。 Is there a way to get it to add the selects as well? 有没有办法让它也添加选择?

Full stack trace: 完整堆栈跟踪:

in Connection.php line 729
at Connection->runQueryCallback('select count(*) as aggregate from `properties` where `properties`.`deleted_at` is null having `distance` <= ?', array('25'), object(Closure)) in Connection.php line 685
at Connection->run('select count(*) as aggregate from `properties` where `properties`.`deleted_at` is null having `distance` <= ?', array('25'), object(Closure)) in Connection.php line 349
at Connection->select('select count(*) as aggregate from `properties` where `properties`.`deleted_at` is null having `distance` <= ?', array('25'), true) in Builder.php line 1610
at Builder->runSelect() in Builder.php line 1596
at Builder->get() in Builder.php line 1671
at Builder->getCountForPagination() in Builder.php line 491
at Builder->paginate('10') in PropertiesController.php line 143
at PropertiesController->search_results(object(Request))
at call_user_func_array(array(object(PropertiesController), 'search_results'), array(object(Request))) in Controller.php line 80
at Controller->callAction('search_results', array(object(Request))) in ControllerDispatcher.php line 146
at ControllerDispatcher->call(object(PropertiesController), object(Route), 'search_results') in ControllerDispatcher.php line 94
at ControllerDispatcher->Illuminate\Routing\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 52
at Pipeline->Illuminate\Routing\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 103
at Pipeline->then(object(Closure)) in ControllerDispatcher.php line 96
at ControllerDispatcher->callWithinStack(object(PropertiesController), object(Route), object(Request), 'search_results') in ControllerDispatcher.php line 54
at ControllerDispatcher->dispatch(object(Route), object(Request), 'App\Http\Controllers\PropertiesController', 'search_results') in Route.php line 174
at Route->runController(object(Request)) in Route.php line 140
at Route->run(object(Request)) in Router.php line 724
at Router->Illuminate\Routing\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 52
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in VerifyCsrfToken.php line 64
at VerifyCsrfToken->handle(object(Request), object(Closure))
at call_user_func_array(array(object(VerifyCsrfToken), 'handle'), array(object(Request), object(Closure))) in Pipeline.php line 136
at Pipeline->Illuminate\Pipeline\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 32
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in ShareErrorsFromSession.php line 49
at ShareErrorsFromSession->handle(object(Request), object(Closure))
at call_user_func_array(array(object(ShareErrorsFromSession), 'handle'), array(object(Request), object(Closure))) in Pipeline.php line 136
at Pipeline->Illuminate\Pipeline\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 32
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in StartSession.php line 64
at StartSession->handle(object(Request), object(Closure))
at call_user_func_array(array(object(StartSession), 'handle'), array(object(Request), object(Closure))) in Pipeline.php line 136
at Pipeline->Illuminate\Pipeline\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 32
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in AddQueuedCookiesToResponse.php line 37
at AddQueuedCookiesToResponse->handle(object(Request), object(Closure))
at call_user_func_array(array(object(AddQueuedCookiesToResponse), 'handle'), array(object(Request), object(Closure))) in Pipeline.php line 136
at Pipeline->Illuminate\Pipeline\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 32
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in EncryptCookies.php line 59
at EncryptCookies->handle(object(Request), object(Closure))
at call_user_func_array(array(object(EncryptCookies), 'handle'), array(object(Request), object(Closure))) in Pipeline.php line 136
at Pipeline->Illuminate\Pipeline\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 32
at Pipeline->Illuminate\Routing\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 103
at Pipeline->then(object(Closure)) in Router.php line 726
at Router->runRouteWithinStack(object(Route), object(Request)) in Router.php line 699
at Router->dispatchToRoute(object(Request)) in Router.php line 675
at Router->dispatch(object(Request)) in Kernel.php line 246
at Kernel->Illuminate\Foundation\Http\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 52
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in CheckForMaintenanceMode.php line 44
at CheckForMaintenanceMode->handle(object(Request), object(Closure))
at call_user_func_array(array(object(CheckForMaintenanceMode), 'handle'), array(object(Request), object(Closure))) in Pipeline.php line 136
at Pipeline->Illuminate\Pipeline\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 32
at Pipeline->Illuminate\Routing\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 103
at Pipeline->then(object(Closure)) in Kernel.php line 132
at Kernel->sendRequestThroughRouter(object(Request)) in Kernel.php line 99
at Kernel->handle(object(Request)) in index.php line 59

What you can do is copying the whole definition of distance column into having part. 你可以做的是整个定义复制distance列到having一部分。 In fact you should use havingRaw function to achieve this. 实际上,您应该使用havingRaw函数来实现此目的。

However you should for both addSelect and havingRaw use bindings because now your code is vulnerable to SQL injection. 但是,您应该对addSelecthavingRaw使用绑定,因为现在您的代码容易受到SQL注入的攻击。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM