Laravel 5.6预加载关联时报错:addEagerConstraints方法不存在
addEagerConstraints不存在错误 嘿,我来帮你搞定这个问题!你遇到的错误根源很明确:你的latestFinancial方法返回的不是一个关联关系构造器,而是直接执行查询后得到的单个模型实例,而with()预加载需要的是一个完整的关联关系定义,这样Laravel才能自动构建预加载的查询逻辑。
为什么会报错?
你在latestFinancial里调用了->latest()->first(),这行代码会立刻触发数据库查询,返回一个FinancialAndRisk模型(或者null),而不是Laravel关联系统需要的HasMany/HasOne关系对象。addEagerConstraints是关联关系类才有的方法,所以当with()尝试调用这个方法时,自然会抛出“方法不存在”的错误。
修复方案
这里有两种完美的解决方式,看你需求选:
方案1:把latestFinancial改成hasOne关联(推荐)
既然你要的是每个公司最新的一条财务记录,本质上是一对一的关联关系,直接用hasOne并指定排序规则即可,这样完全兼容预加载:
class Company extends Model { // ... 其他代码不变 public function financial() { return $this->hasMany('Noetic\Plugins\Conxn\Models\Company\FinancialAndRisk', 'company_id'); } // 修改这里,用hasOne替代hasMany+first() public function latestFinancial() { return $this->hasOne('Noetic\Plugins\Conxn\Models\Company\FinancialAndRisk', 'company_id')->latest(); } }
改完之后,你控制器里的Company::with('latestFinancial')->get()就能正常运行了,返回的每个company对象里的latestFinancial就是对应的最新财务记录(单个对象,不是数组)。
方案2:在预加载时用闭包筛选最新记录
如果你想保留原有的financial关联,也可以在控制器的预加载逻辑里直接筛选最新的一条:
public function index() { $companies = Company::with(['financial' => function($query) { // 只取每个公司最新的一条财务记录 $query->latest()->take(1); }])->get(); return response()->json(['companies' => $companies], 200); }
不过这种方式返回的financial字段是一个数组(哪怕只有一条数据),如果需要单个对象的话,方案1更友好。
额外小提示
如果原来的latestFinancial方法是用来在单个公司实例上获取最新记录的(比如$company->latestFinancial()),可以把它改成一个实例方法,避免和关联关系混淆:
public function getLatestFinancial() { return $this->financial()->latest()->first(); }
这样在单个模型上用$company->getLatestFinancial()就能拿到最新记录,同时关联关系latestFinancial用于预加载,各司其职。
内容的提问来源于stack exchange,提问作者Nitish Kumar

