You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Laravel Eloquent中从嵌套关联获取单条指定行数据?

问题描述

我有三个一对多关联的模型:Client拥有多个Point,Point拥有多个OrderPower。order_powers表包含value和date_from字段,date_from是该订购功率值生效的起始日期。

模型代码

Client 模型

public function points() {
    return $this->hasMany(Point::class);
}

public function order_powers() {
    return $this->hasManyThrough(OrderPower::class, Point::class);
}

Point 模型

public function clients() {
    return $this->belongsTo(Client::class);
}

public function order_powers() {
    return $this->hasMany(OrderPower::class);
}

OrderPower 模型

注:原代码方法名有误,已修正为正确的关联名称

public function point() {
    return $this->belongsTo(Point::class);
}

需求

在单页中展示:

  • 单个Client的数据
  • 该Client所属的Point的数据
  • 每个Point对应的订购功率,仅显示date_from最新的一条数据的value值

当前问题

我使用Inertia和Vue的ClientController渲染代码如下,目前前两点已实现,但第三点存在问题:当前控制器会返回每个Point的所有order_powers,尝试用first()或take(1)会导致所有Point只显示同一条order_power,而非每个Point自身最新的那条。

当前控制器代码

return Inertia::render('Clientshow', [
    'client' => [
        'id' => $client->id,
        'name' => $client->name,
        'street' => $client->street,
        'city' => $client->city,
        'points' => $client->points()->with(['order_powers'=>function ($q)
        {
            $q->orderBy('date_from','desc');
        }
        ])->get(),         
    ],
]);

示例场景

  • 一个Client有两个Point
  • 每个Point有两个OrderPower
  • Vue中每个Point会显示两个值,我只想显示每个Point自己最新的那一个

Vue组件数据结构

>client:Reactive
   id:33
   name:"ClientName"
   street:"StreetName"
   city:"CityName"
  >points:Array[2]
   >0:Object
     client_id:33
     created_at:"2022-10-13T15:31:37.000000Z"
     id:65
     >order_powers:Array[2] <- 我只想显示其中一个对象的value字段值
      >0:Object
      >1:Object
     pp_type:"xxxx"
     updated_at:"2022-10-13T15:31:37.000000Z"
   >1:Object

解决方案

方法一:在Point模型新增关联(推荐)

在Point模型中添加一个关联,直接指向该Point最新的OrderPower:

public function latest_order_power() {
    return $this->hasOne(OrderPower::class)->latest('date_from');
}

然后修改控制器中的关联加载逻辑:

return Inertia::render('Clientshow', [
    'client' => [
        'id' => $client->id,
        'name' => $client->name,
        'street' => $client->street,
        'city' => $client->city,
        'points' => $client->points()->with('latest_order_power')->get(),         
    ],
]);

Vue中直接调用该关联的value字段即可:

<div v-for="point in client.points" :key="point.id">
  <p>最新订购功率:{{ point.latest_order_power?.value }}</p>
</div>

方法二:查询时通过子查询获取最新值

如果不想新增关联,可以在查询Point时,用子查询直接取出最新的value:

return Inertia::render('Clientshow', [
    'client' => [
        'id' => $client->id,
        'name' => $client->name,
        'street' => $client->street,
        'city' => $client->city,
        'points' => $client->points()
            ->selectRaw('points.*, (SELECT value FROM order_powers WHERE order_powers.point_id = points.id ORDER BY date_from DESC LIMIT 1) AS latest_order_power_value')
            ->get(),         
    ],
]);

Vue中直接使用新增的字段:

<div v-for="point in client.points" :key="point.id">
  <p>最新订购功率:{{ point.latest_order_power_value }}</p>
</div>

方法三:Vue端处理(备选)

如果后端不想修改,可利用后端已按date_from倒序排序的特性,在Vue中取数组第一个元素:

<div v-for="point in client.points" :key="point.id">
  <p>最新订购功率:{{ point.order_powers[0]?.value }}</p>
</div>

注:使用可选链?.避免数组为空时出现报错

内容的提问来源于stack exchange,提问作者sunnyluk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 17:25:50