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
相关产品推荐
相关产品推荐

