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

Laravel 8.42:如何在hasOneThrough关联中使用latestOfMany?

在Laravel的hasOneThrough关联中实现类似latestOfMany的逻辑

Laravel的latestOfMany确实仅支持hasOne和morphOne关联,但我们可以通过手动构建子查询约束来实现hasOneThrough下获取关联模型最新记录的需求。

问题分析

你给出的直接在hasOneThrough上调用->ofMany('created_at', 'MAX')的写法无法得到正确结果,因为Laravel会忽略中间表B的关联约束,最终取的是全局所有C记录中created_at最大的那条,而不是当前A模型关联的B对应的C记录中的最大值。

可行解决方案

方案1:子查询筛选最新记录

通过嵌套子查询,先定位到当前A关联的所有C中最新的那条记录的ID,再关联到C模型:

// A.php
public function latestC()
{
    return $this->hasOneThrough(C::class, B::class)
        ->whereIn('c.id', function ($query) {
            $query->selectRaw('MAX(c.id)')
                ->from('b')
                ->join('c', 'b.id', '=', 'c.b_id')
                ->whereColumn('b.a_id', 'a.id')
                ->groupBy('b.a_id');
        });
}

如果存在多条C记录created_at相同的情况,用MAX(c.id)作为兜底可以保证唯一结果,避免返回多条记录。

方案2:链式关联+latestOfMany

如果需求允许,也可以拆分关联:先在B模型中定义获取最新C的hasOne关联,再在A模型中通过hasOneThrough关联这个最新的C(此方案取的是每个B的最新C中,属于A的所有C里的最新一条):

// B.php
public function latestC()
{
    return $this->hasOne(C::class)->latestOfMany();
}

// A.php
public function latestC()
{
    return $this->hasOneThrough(
        C::class,
        B::class,
        'a_id', // B表关联A表的外键
        'id',   // C表关联B表的外键
        'id',   // A表的主键
        'id'    // B表的主键
    )->latestOfMany('created_at');
}

方案3:自定义ofMany约束

直接在hasOneThrough中给ofMany方法传入闭包,补充中间表的关联约束:

// A.php
public function latestC()
{
    return $this->hasOneThrough(C::class, B::class)
        ->ofMany(
            ['created_at' => 'MAX', 'id' => 'MAX'],
            function ($query) {
                // 补充中间表B的关联条件,确保只查询当前A对应的B下的C
                $query->join('b', 'c.b_id', '=', 'b.id')
                    ->whereColumn('b.a_id', 'a.id');
            }
        );
}

以上三种方案都可以实现hasOneThrough关联下获取最新记录的效果,你可以根据实际业务场景选择最合适的写法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 19:37:37