Laravel 关系模型中的范围不起作用
Laravel scope in Model with Relation not working
我有一个名为 owners
的 table,它是一个商店所有者列表,我想查询这个 table 及其关系 stores
并获得商店与用户的距离。目前,用户位置是硬编码的,但如果可以的话,我打算将其传递给查询范围。非常感谢任何提示,谢谢!
<?php class Owner extends Eloquent {
protected $table = 'owners';
public function scopeDistance($query) {
$lat = '45.529999';
$lng = '-122.680000';
return $query->select(DB::raw("*,
( 3959 * acos( cos( radians(?) ) *
cos( radians( lat ) )
* cos( radians( lng ) - radians(?)
) + sin( radians(?) ) *
sin( radians( lat ) ) )
) AS distance"))
->setBindings([$lat, $lng, $lat]);
}
public function stores()
{
return $this->belongsTo('Store','store_id')->Distance();
}
public function storesDist()
{
$lat = '47';
$lng = '-124';
return $this->belongsTo('Store','store_id')->select(DB::raw("*,
( 3959 * acos( cos( radians(?) ) *
cos( radians( lat ) )
* cos( radians( lng ) - radians(?)
) + sin( radians(?) ) *
sin( radians( lat ) ) )
) AS distance"))
->setBindings([$lat, $lng, $lat]);
}
<?php
class OwnersController extends \BaseController {
public function getStoresNearUserA()
{
// This returns Call to undefined method Illuminate\Database\Query\Builder::Distance()
return Owner::orderBy('id')->with('stores')->get();
}
public function getStoresNearUserB()
{
// This works
return Owner::orderBy('id')->with('storesDist')->get();
}
************************************************ **更新
RE: First solution
// app/models/BaseModel.php
<?php
class BaseModel extends Eloquent {
public function scopeDistance($query) {
return $query->orderBy('id');
}
....app/models/Store.Php
<?php
class Store extends \Eloquent {
protected $table = 'owners';
....app/models/Owner.Php
<?php
class Owner extends \BaseModel {
protected $table = 'owners';
public function stores()
{
return $this->belongsTo('Store','store_id')->Distance();
}
...app/controllers/OwnerController.php
<?php
class OwnersController extends \BaseController {
public function getStoreOwners()
{
return Owner::orderBy('id')->with('stores')->get();
}
...My Error :
Call to undefined method Illuminate\Database\Query\Builder::Distance()
您在 setBindings
中有错误 - where
是默认值。所以只需将第二个参数设置为 select
就可以了:
public function scopeDistance($query, $lat, $lng)
{
return $query->select(DB::raw("*,
( 3959 * acos( cos( radians(?) ) *
cos( radians( lat ) )
* cos( radians( lng ) - radians(?)
) + sin( radians(?) ) *
sin( radians( lat ) ) )
) AS distance"))
->setBindings([$lat, $lng, $lat], 'select');
}
您也可以使用
->addBinging($lat, 'select')->addBinding($lng, 'select')->addBinding($lat, 'select');
这将是安全的,因为现在,万一 select
有任何其他绑定(我承认这很少见,但仍然..)你会搞砸查询。
另外请注意,您不能像这样在关系查询上使用 Owner
模型范围。我建议您在 BaseModel
中定义此范围,然后 Owner
和 Store
模型将扩展它,您将能够在两者中使用该范围。
我有一个名为 owners
的 table,它是一个商店所有者列表,我想查询这个 table 及其关系 stores
并获得商店与用户的距离。目前,用户位置是硬编码的,但如果可以的话,我打算将其传递给查询范围。非常感谢任何提示,谢谢!
<?php class Owner extends Eloquent {
protected $table = 'owners';
public function scopeDistance($query) {
$lat = '45.529999';
$lng = '-122.680000';
return $query->select(DB::raw("*,
( 3959 * acos( cos( radians(?) ) *
cos( radians( lat ) )
* cos( radians( lng ) - radians(?)
) + sin( radians(?) ) *
sin( radians( lat ) ) )
) AS distance"))
->setBindings([$lat, $lng, $lat]);
}
public function stores()
{
return $this->belongsTo('Store','store_id')->Distance();
}
public function storesDist()
{
$lat = '47';
$lng = '-124';
return $this->belongsTo('Store','store_id')->select(DB::raw("*,
( 3959 * acos( cos( radians(?) ) *
cos( radians( lat ) )
* cos( radians( lng ) - radians(?)
) + sin( radians(?) ) *
sin( radians( lat ) ) )
) AS distance"))
->setBindings([$lat, $lng, $lat]);
}
<?php
class OwnersController extends \BaseController {
public function getStoresNearUserA()
{
// This returns Call to undefined method Illuminate\Database\Query\Builder::Distance()
return Owner::orderBy('id')->with('stores')->get();
}
public function getStoresNearUserB()
{
// This works
return Owner::orderBy('id')->with('storesDist')->get();
}
************************************************ **更新
RE: First solution
// app/models/BaseModel.php
<?php
class BaseModel extends Eloquent {
public function scopeDistance($query) {
return $query->orderBy('id');
}
....app/models/Store.Php
<?php
class Store extends \Eloquent {
protected $table = 'owners';
....app/models/Owner.Php
<?php
class Owner extends \BaseModel {
protected $table = 'owners';
public function stores()
{
return $this->belongsTo('Store','store_id')->Distance();
}
...app/controllers/OwnerController.php
<?php
class OwnersController extends \BaseController {
public function getStoreOwners()
{
return Owner::orderBy('id')->with('stores')->get();
}
...My Error :
Call to undefined method Illuminate\Database\Query\Builder::Distance()
您在 setBindings
中有错误 - where
是默认值。所以只需将第二个参数设置为 select
就可以了:
public function scopeDistance($query, $lat, $lng)
{
return $query->select(DB::raw("*,
( 3959 * acos( cos( radians(?) ) *
cos( radians( lat ) )
* cos( radians( lng ) - radians(?)
) + sin( radians(?) ) *
sin( radians( lat ) ) )
) AS distance"))
->setBindings([$lat, $lng, $lat], 'select');
}
您也可以使用
->addBinging($lat, 'select')->addBinding($lng, 'select')->addBinding($lat, 'select');
这将是安全的,因为现在,万一 select
有任何其他绑定(我承认这很少见,但仍然..)你会搞砸查询。
另外请注意,您不能像这样在关系查询上使用 Owner
模型范围。我建议您在 BaseModel
中定义此范围,然后 Owner
和 Store
模型将扩展它,您将能够在两者中使用该范围。