Laravel中如何编写对比关联模型属性的Scope查询?
解决Laravel中Transaction模型的Crossed Scope问题
你原来的代码无法运行的核心原因是:Scope方法用于构建数据库查询语句,此时还没有具体的Transaction模型实例,不能直接通过$this访问关联模型的属性(比如$this->origin_account)——这些属性只有模型实例被加载后才能访问,而Scope需要在数据库层面完成字段比较。
下面提供两种可行的实现方式:
方法一:使用Join关联表直接比较字段
这种方式效率较高,直接通过SQL Join关联两个关联表,对比entity_id:
public function scopeCrossed($query) { return $query->join('accounts', 'transactions.origin_account_id', '=', 'accounts.id') ->join('concepts', 'transactions.concept_id', '=', 'concepts.id') ->where('accounts.entity_id', '<>', 'concepts.entity_id') ->select('transactions.*'); // 明确选择transactions表字段,避免关联表字段冲突 }
注意事项
- 确保表名(
accounts、concepts、transactions)与你的数据库实际表名一致; - 如果
Transaction和Account的关联外键不是默认的origin_account_id,需调整Join语句中的外键字段。
方法二:使用Eloquent关联的子查询方式
若更倾向于用Eloquent关联语法而非原生Join,可结合whereHas和子查询实现:
public function scopeCrossed($query) { return $query->whereHas('originAccount', function ($accountQuery) { $accountQuery->whereExists(function ($conceptQuery) { $conceptQuery->from('concepts') ->whereColumn('concepts.id', 'transactions.concept_id') ->whereColumn('concepts.entity_id', '<>', 'accounts.entity_id'); }); }); }
前提
需确保Transaction模型已定义正确的关联方法:
// Transaction模型中 public function originAccount() { return $this->belongsTo(Account::class, 'origin_account_id'); } public function concept() { return $this->belongsTo(Concept::class); }
内容的提问来源于stack exchange,提问作者E. Barney
相关产品推荐
相关产品推荐

