Laravel 从查询生成器获取特定列

Posted

技术标签:

【中文标题】Laravel 从查询生成器获取特定列【英文标题】:Laravel get certain column from Query builder 【发布时间】:2016-11-07 07:28:42 【问题描述】:

我有一个查询如下:

$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-&gt;id, $venues); 一样返回某事,但我也遇到了同样的错误。 如何解决从查询生成器中仅获取 id 列作为数组。 我怎么能通过

【问题讨论】:

删除 Location::select 并尝试仅使用 DB 外观。 【参考方案1】:

这只是一个猜测,但您的嵌套查询函数不应该由-&gt;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;
    )
    ;

app/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;
    


app/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');
    

【讨论】:

我在嵌套查询中使用 latlng,因此仅选择 id 将不起作用 在传统的 SQL 子查询中,除非您引用 latlng 列,否则您不需要选择它们。你在这里所做的一切都没有暗示。您从满足特定条件的记录中选择id,不需要latlng distance 来自哪里? 距离是一个函数参数

以上是关于Laravel 从查询生成器获取特定列的主要内容,如果未能解决你的问题,请参考以下文章

使用 laravel 查询生成器在另一个表中使用列值

Laravel 查询生成器,有问题 [重复]

如何在 laravel 查询生成器中为同一列构建多个条件的查询?

如何在执行查询之前从Laravel的查询生成器获取原始查询字符串?

如何在 laravel 中使用查询生成器根据 id 从多个表中获取数据

Laravel 查询生成器 - 日期现在在哪里使用碳