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

Laravel 8 使用eager loading时如何访问关联子查询返回的first_name等字段

你当前的写法没有问题,拿不到字段是Laravel预加载关联的特性导致的:with预加载的关联数据会单独存放在模型的relations属性中,不会直接合并到主模型的属性里,主模型get()方法指定的字段仅作用于clients主表,所以你把关联表字段加进去自然无法识别。

几种常见的访问方案

1. 直接访问关联属性(最常用)

你预加载的是contacts关联,如果这是一对一关联(你的查询里限定了contact_type_id=1,通常对应单个联系人),直接通过关联属性访问即可:

// 单个联系人的情况
echo $client->contacts->first_name;
echo $client->contacts->last_name;

// 如果是一对多关联,contacts返回集合,需要取对应项
echo $client->contacts->first()?->first_name;

如果这个类型的联系人是常用场景,建议单独定义一个一对一关联,写法更清晰:

// 在Client模型中新增关联
public function primaryContact()
{
    return $this->hasOne(Contact::class)->where('contact_type_id', 1);
}

// 预加载的时候直接用这个关联
$clients = Client::with('primaryContact')
    ->orderBy('client_name')
    ->get(['id', 'client_name', 'city', 'state']);

// 访问更直观
echo $client->primaryContact->first_name;

2. 定义访问器实现直接读取

如果要实现你期望的$client->first_name直接读取的效果,可以在Client模型中添加两个访问器:

// 加在Client模型里
public function getFirstNameAttribute()
{
    return $this->contacts?->first_name;
}

public function getLastNameAttribute()
{
    return $this->contacts?->last_name;
}

添加后就可以直接通过主模型属性调用这两个字段,不需要每次写关联路径。

3. 用连表查询直接合并字段

如果你不想用关联,也可以用join代替with预加载,直接把关联表字段查出来合并到主模型:

$clients = Client::select('clients.id', 'clients.client_name', 'clients.city', 'clients.state', 'contacts.first_name', 'contacts.last_name')
    ->join('contacts', function ($join) {
        $join->on('clients.id', '=', 'contacts.client_id')
            ->where('contacts.contact_type_id', '=', 1);
    })
    ->orderBy('client_name')
    ->get();

// 此时可以直接读取
echo $client->first_name;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 09:09:05