Laravel纬度和纬度半径经度

时间:2016-12-23 13:31:10

标签: php laravel laravel-5

我正在尝试查找{lat}/{long} X半径范围内的所有邮政编码,但我收到的是TypeError

我收到此错误:

  

类型错误:传递给App \ Transformers \ PostcodesTransformer :: transform()的参数1必须是App \ Postcodes的实例,给出stdClass的实例,在/ home / vagrant / postcode-data / vendor / league / fractal中调用第338行的/src/Scope.php

查询是:

$postcodes = DB::select("Select 
    id, 
    postcode, 
    latitude, 
    longitude, 
    district, 
    postal_town, 
    county, 
    country, 
    northing, 
    easting, 
    type,
    acos(sin(".$lat.")*sin(radians(latitude)) + cos(".$lat.")*cos(radians(latitude))*cos(radians(longitude)-".$lon.")) * ".$R." As distance
        From (
            Select *
            From uk_postcodes
            Where latitude Between ".$minLat." And ".$maxLat."
              And longitude Between ".$minLon." And ".$maxLon."
        ) As FirstCut
        Where acos(sin(".$lat.")*sin(radians(latitude)) + cos(".$lat.")*cos(radians(latitude))*cos(radians(longitude)-".$lon.")) * ".$R."< ".$rad."
        Order by distance");
    return $this->response->withCollection($postcodes, new PostcodesTransformer); 

DB::select查询的结果会返回stdClass

我如何让它返回Postcodes类的实例?

2 个答案:

答案 0 :(得分:1)

这里有两个答案。第一个是我认为错误的方式,但它是对你的问题更直接的答案。

我们需要以某种方式使用Eloquent获取此查询,但为了处理该表,我们需要首先从postcodes表中进行选择,将查询转换为使用临时表。

DB::query("
    Create Temporary Table FirstCut Select *
    From uk_postcodes
    Where latitude Between ".$minLat." And ".$maxLat."
    And longitude Between ".$minLon." And ".$maxLon
);

现在我们可以使用您的模型将您的postcodes表加入。我们必须从模型开始,因为这是返回App\Postcodes

实例的唯一方法
Postcodes::join('FirstCut', 'FirstCut.zipcode', '=', 'postcodes.zipcode') // Guessing column names here
    ->selectRaw('id, postcode, latitude, longitude, district, postal_town, county, country, northing, easting, type,
         acos(sin(".$lat.")*sin(radians(latitude)) + cos(".$lat.")*cos(radians(latitude))*cos(radians(longitude)-".$lon.")) * ".$R." As distance'
    )
    ->whereRaw("acos(sin($lat)*sin(radians(latitude)) + cos($lat)*cos(radians(latitude))*cos(radians(longitude)-$lon)) * $R< $rad")
    ->orderByRaw('distance')
    ->get();

处理此问题的第二种方法是从PostcodeTransformers中抽象逻辑,创建一个使用该逻辑的新逻辑,并且还可以处理stdClass。然后,您需要做的就是传递新的StdClassTransformer而不是PostcodesTransformer

答案 1 :(得分:0)

根据您的代码,您没有使用Laravel的Eloquent Model概念来对数据库进行查询。

阅读:Eloquent: Getting Started

所以你可以拥有像这样的Postcode对象集合:

创建一个名为Postcode的模型,如下所示:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Postcode extends Model
{
    protected $table = 'postcodes';
    protected $guarded = ['id'];
}

然后在创建查询时,你可以这样做,你可以使用Laravel的查询构建器的方法 - selectRaw()

$postcodes = Postcode::selectRaw("
    *,
    acos(sin(".$lat.")*sin(radians(latitude)) + cos(".$lat.")*cos(radians(latitude))*cos(radians(longitude)-".$lon.")) * ".$R." As distance
        From (
            Select *
            From uk_postcodes
            Where latitude Between ".$minLat." And ".$maxLat."
              And longitude Between ".$minLon." And ".$maxLon."
        ) As FirstCut
        Where acos(sin(".$lat.")*sin(radians(latitude)) + cos(".$lat.")*cos(radians(latitude))*cos(radians(longitude)-".$lon.")) * ".$R."< ".$rad."
")
->orderBy('distance', 'asc')
->get();

现在,您将获得Postcode模型对象的集合,而不是StdClass。如果你更深入地打破你的选择原始查询会更好,因为在我看来它不会起作用!