Laravel 5.4多对多Eloquent关联:用户模型定义holdings关联求助
嘿,这个需求我之前处理过,Laravel的Eloquent关联完全能轻松实现,不用自己写一堆复杂的查询逻辑。下面是具体的实现步骤,跟着来就行:
实现方案
首先得理清楚关联链条:用户 ↔(多对多)账户 ↔(一对多)持仓。要直接从User模型拿到所有持仓,我们可以用hasManyThrough关联来打通这个多对多转一对多的关系。
第一步:准备中间表模型(如果还没有的话)
因为用户和账户是通过user_accounts这个中间表关联的,最好给它建个对应的模型UserAccount,这样关联起来更清晰:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class UserAccount extends Model { protected $table = 'user_accounts'; public $timestamps = false; // 要是你的表没加created_at/updated_at就加上这句,有的话就删掉 }
第二步:在User模型里定义关联
先把用户和账户的多对多关联写好,这是基础,然后再定义holdings关联:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { // 用户和账户的多对多关联 public function accounts() { return $this->belongsToMany(Account::class, 'user_accounts'); } // 重点:用户的所有持仓关联 public function holdings() { return $this->hasManyThrough( Holding::class, // 最终要关联的持仓模型 UserAccount::class, // 中间的用户-账户关联模型 'user_id', // UserAccount表中关联User的外键 'account_id', // Holding表中关联Account的外键 'id', // User表的主键字段 'account_id' // UserAccount表中关联Account的外键 ); } }
第三步:使用这个关联
现在你就可以像用普通关联一样操作了,比如:
// 获取ID为1的用户所有持仓 $user = User::find(1); $userHoldings = $user->holdings; // 预加载持仓,避免N+1查询问题,性能更好 $usersWithHoldings = User::with('holdings')->get();
额外说明
- 要是你的
user_accounts表有时间戳字段,记得把UserAccount模型里的public $timestamps = false;删掉。 - 这种方式是完全利用Eloquent的关联机制,支持预加载、添加查询约束(比如
$user->holdings()->where('xxx', 'yyy')->get())等所有Eloquent的特性,比自己写whereIn的查询要规范得多,也更符合Laravel的最佳实践。
内容的提问来源于stack exchange,提问作者madz
相关产品推荐
相关产品推荐

