2016-07-05 109 views
0

得到一定的专栏中,我有一个查询,如下所示:Laravel从查询生成器

$locations = Location::select(DB::raw("* , 1000*distance AS distance")) 
     ->whereIn("id", function ($q) use ($userLat, $distance, $userLng, $cityId) 
     { 
      $venues = $q->select('*') 
       ->from('locations') 
       ->where('city_id', $cityId) 
       ->havingRaw("lat BETWEEN $userlat AND $userlat+10") 
       ->havingRaw("lng BETWEEN $userLng AND $userlng+10") 
       ->get(); 
     }) 
     ->havingRaw('distance <' . $distance) 
     ->orderBy('distance') 
     ->take($limit) 
     ->get(); 

我得到Cardinality violation错误,我知道是因为嵌套查询。
我只需要从嵌套查询中获得id列,但我不能。
我试过使用get(['id'])但它没有奏效。
我甚至尝试过使用array_map并像array_map(function ($venue){return $venue->id}, $venues);那样回应,但我也得到了同样的错误。
我该如何解决只能从查询生成器中获取id列作为数组。 我怎么能通过

+0

删除'Location :: select'并仅尝试使用数据库门面。 – xhulio

回答

0

这只是一个猜测,但你的嵌套查询功能不应该由->get()执行,你没有指定id列。试试这个:

$locations = Location::select(DB::raw("* , 1000*distance AS distance")) 
    ->whereIn("id", function ($q) use ($userLat, $distance, $userLng, $cityId) 
    { 
     $venues = $q->select('id') 
      ->from('locations') 
      ->where('city_id', $cityId) 
      ->havingRaw("lat BETWEEN $userlat AND $userlat+10") 
      ->havingRaw("lng BETWEEN $userLng AND $userlng+10") 
      ; 
    }) 
    ->havingRaw('distance <' . $distance) 
    ->orderBy('distance') 
    ->take($limit) 
    ->get(); 

编辑:使用查询范围和计算的属性

$lat = ''; // latitude 
$lng = ''; // longitude 

$distance = 5; // distance amount 

$radius = compact('lat', 'lng', 'distance'); 

$targets = Location::withinRadius($radius) 
    ->with('city') 
    ->get() 
    ->map(function ($value, $key) use ($lat, $lng) { 
     return $value->target = [$lat, $lng]; 
    }) 
    ->filter(function ($value, $key) use ($distance) { 
     return $value->distance < $distance; 
    }) 
    ; 

应用程序/ Location.php

<?php 

namespace App; 

use Illuminate\Database\Eloquent\Model; 

class Location extends Model 
{ 
    // Add the attributes for inclusion in toArray() and toJson() 
    protected $appends = ['target', 'distance']; 

    // Hold the target Location 
    protected $_target = null; 

    // ... other model code 

    /** 
    * Return the query with radius limits 
    */ 
    public function scopeWithinRadius($q, $radius) 
    { 
     $target_lat = $radius['lat']; 
     $target_lng = $radius['lng']; 
     $distance = $radius['distance']; 

     $target_lat_range = [$target_lat + $this->adjustLat($distance * -1), $target_lat + $this->adjustLat($distance)]; 
     $target_lng_range = [$target_lng + $this->adjustLng($distance * -1), $target_lng + $this->adjustLng($distance)]; 

     return $q->havingRaw("lat BETWEEN " . $target_lat_range[0] ." AND ".$target_lat_range[1]) 
      ->havingRaw("lng BETWEEN " . $target_lng_range[0] ." AND ".$target_lng_range[1]) 
     ; 
    } 

    /** 
    * Return the amount to adjust latitude by for the given distance 
    */ 
    private function adjustLat($distance) 
    { 
     // return latitude adjustment amount 
    } 

    /** 
    * Return the amount to adjust longitude by for the given distance 
    */ 
    private function adjustLng($distance) 
    { 
     // return longitude adjustment amount 
    } 

    /** 
    * Get the Target coordinates 
    */ 
    public function getTargetAttribute() 
    { 
     return $this->_target; 
    } 

    /** 
    * Get the Target latitude 
    */ 
    public function getTargetLatAttribute() 
    { 
     return $this->_target[0]; 
    } 

    /** 
    * Get the Target longitude 
    */ 
    public function getTargetLngAttribute() 
    { 
     return $this->_target[1]; 
    } 

    /** 
    * Set the Target of the Location 
    */ 
    public function setTargetAttribute($value) 
    { 
     // check if value is a Location 
     if ($value instanceof Location) { 
      $value = [$value->lat, $value->lng]; 
     } 

     $this->_target = $value; 
    } 

    /** 
    * Determine the Distance from target 
    */ 
    public function getDistanceAttribute() 
    { 
     $lat1 = $this->lat; 
     $lng1 = $this->lng; 
     $lat2 = $this->target_lat; 
     $lng2 = $this->target_lng; 

     // calculate the distance between Location and points    
     // ... $distance = ... 

     return $distance; 
    } 

} 

应用程序/ City.php

<?php 

namespace App; 

use Illuminate\Database\Eloquent\Model; 

class City extends Model 
{ 
    // ... other model code 

    /** 
    * Get the Location of the City 
    */ 
    public function location() 
    { 
     return $this->hasMany('App\Location'); 
    } 
} 
+0

我在嵌套查询中使用“lat”和“lng”,所以只选择“id”将不起作用 – Mehrdad

+0

在传统SQL子查询中,除非引用'lat'和'lng'列你不需要选择它们。你在这里所做的没有其他建议。您从满足特定条件的记录中选择'id',这不需要'lat'和'lng'。 – Qevo

+0

距离是从哪里来的? – Qevo