php - Laravel 5.6 中嵌套关系的展平结果

标签 php laravel eloquent

我有一个具有以下模型的 laravel 应用程序

Location (hasOne: Device)  : [id, device_id, lat, lng] 
Device (hasMany: Location) : [id, name]

我需要获取给定设备的最新位置。假设我有一组设备 ID。

[1, 2, 3]

我正在尝试制作一个 api,它应该对请求给出一个简单的响应。显然,响应应该是这样的。

[
    {
    "device_id": "1",
    "name": "A",
    "lat":"8.311",
    "lng":"11.1111"
    },
    {
    "device_id": "2",
    "name": "B",
    "lat":"8.1111",
    "lng":"88.1111"
    },
    {
    "device_id": "3",
    "name": "C",
    "lat":"5.1111",
    "lng":"25.1111"
    }
]

我尝试了很多方法来找到一个有效的解决方案来得到正确的答案。到目前为止,我能想到的最佳解决方案是使用 device_id 直接从 Location 表中获取最新位置。所以我试过了。

Location::whereIn('device_id', [1, 2, 3])->get()

它给出了给定设备的所有位置条目。但我只想要每个设备的最新位置条目。所以我试过了。

Location::whereIn('device_id', [1, 2])->latest()->first()->get()

这显然为我提供了每个设备的多个位置。我不确定如何解决这个问题。

>>> Location::whereIn('device_id', [1, 2])->get()
=> Illuminate\Database\Eloquent\Collection {#2883
     all: [
       App\Location {#2895
         id: 1,
         device_id: 1,
         lat: "39",
         lng: "53",
         extras: "JCRskRtaBJ",
         delete_flag: 0,
         created_at: "2018-07-25 12:11:21",
         updated_at: "2018-07-25 12:11:21",
       },
       App\Location {#2903
         id: 3,
         device_id: 1,
         lat: "73",
         lng: "23",
         extras: "0cOy8rne9S",
         delete_flag: 0,
         created_at: "2018-07-25 12:11:21",
         updated_at: "2018-07-25 12:11:21",
       },
       App\Location {#2894
         id: 5,
         device_id: 2,
         lat: "55",
         lng: "28",
         extras: "rT18VZxA7i",
         delete_flag: 0,
         created_at: "2018-07-25 12:11:21",
         updated_at: "2018-07-25 12:11:21",
       },
       App\Location {#2885
         id: 7,
         device_id: 1,
         lat: "58",
         lng: "74",
         extras: "TAbM4x53iH",
         delete_flag: 0,
         created_at: "2018-07-25 12:11:21",
         updated_at: "2018-07-25 12:11:21",
       },
       App\Location {#2900
         id: 8,
         device_id: 1,
         lat: "47",
         lng: "7",
         extras: "yhr4sbUs2R",
         delete_flag: 0,
         created_at: "2018-07-25 12:11:21",
         updated_at: "2018-07-25 12:11:21",
       },
       App\Location {#2882
         id: 9,
         device_id: 2,
         lat: "27",
         lng: "60",
         extras: "NqRPvaqosG",
         delete_flag: 0,
         created_at: "2018-07-25 12:11:21",
         updated_at: "2018-07-25 12:11:21",
       },
       App\Location {#2915
         id: 10,
         device_id: 1,
         lat: "35",
         lng: "37",
         extras: "6e7yHT4qP3",
         delete_flag: 0,
         created_at: "2018-07-25 12:11:21",
         updated_at: "2018-07-25 12:11:21",
       },
     ],
   }

我正在寻找一个仅从位置类返回 latlng 并将其附加为属性的查询,这样我就可以得到一个简单的 json 响应。无论如何有可能做到吗?

最佳答案

你可以使用 Eloquent: API Resources 得到你想要的:

首先在 Device 模型中创建一个新关系,即使 hasMany 是它们之间的真正关系,您也可以将 hasOnelatest() 获取最后一个位置:

public function lastLocation()
{
    return $this->hasOne('App\Location')->latest();
}

然后你必须创建一个设备资源:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class Device extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'device_id' => $this->id,
            'name' => $this->name,
            'lat' => $this->lastLocation->lat,
            'lng' => $this->lastLocation->lng,
        ];
    }
}

最后在 Controller 中你可以这样做:

use App\Device;
use App\Http\Resources\Device as DeviceResource;

function YourMethod() {
    $devices = Device::with('lastLocation')
                       ->whereIn([1, 2, 3])
                       ->get();
    return DeviceResource::collection($devices);
}

文档中提到的另一件事:

By default, your outer-most resource is wrapped in a data key when the resource response is converted to JSON. So, for example, a typical resource collection response looks like the following:

{
    "data": [
        {
            "id": 1,
            "name": "Eladio Schroeder Sr.",
            "email": "therese28@example.com",
        },
        {
            "id": 2,
            "name": "Liliana Mayert",
            "email": "evandervort@example.com",
        }
    ]
}

删除数据包装器:

If you would like to disable the wrapping of the outer-most resource, you may use the withoutWrapping method on the base resource class. Typically, you should call this method from your AppServiceProvider or another service provider that is loaded on every request to your application :

public function boot()
{
    Resource::withoutWrapping();
}

关于php - Laravel 5.6 中嵌套关系的展平结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51522712/

相关文章:

php - 根据sql结果显示行

php - 在 laravel 数据透视表上过滤

php - 将 Laravel 模型移回 App/文件夹根目录

php - Paypal 登录 session 然后将其保存以便更快地结帐

Laravel hasMany 关系全部分离

php - 不要重写代表文件的 URL

php - Wordpress 导航菜单页面项目随机消失

php - Laravel 5.2 查询 1 个表以获取邮政编码然后获取 ID 并查询另一个

PHP 变量到 PayPal JavaScript

mysql - Eloquent 创建空白条目