Laravel 8使用with()加载自定义属性报addEagerConstraints() on string错误
问题解决方法
错误原因
你遇到的报错是因为with()是Eloquent提供的关联预加载方法,仅支持调用返回关联对象的方法(比如你模型中定义的sender、receiver方法),而你写的typeName()方法直接返回字符串,不属于关联定义,所以框架尝试调用关联方法的addEagerConstraints时就会抛出错误。
正确实现方案
你需要用Laravel的「访问器」实现不需要数据库字段的动态属性,操作步骤如下:
- 修改
CoinTransaction模型,定义type_name的访问器,同时配置自动追加序列化属性:
如果你用的是Laravel 9+,也可以用新的访问器定义语法:class CoinTransaction extends Model { use HasFactory; protected $guarded = ['id']; // 配置序列化时自动追加的动态属性 protected $appends = ['type_name']; // 兼容所有Laravel版本的访问器写法 public function getTypeNameAttribute() { switch($this->type){ case 0: return 'Topup'; default: return 'Unknown'; } // Laravel 8+ 也可以用更简洁的match语法: // return match($this->type) { // 0 => 'Topup', // default => 'Unknown' // }; } // 原有其他方法保持不变 public function sender() { return $this->belongsTo(User::class, 'sender_id'); } public function receiver() { return $this->belongsTo(User::class, 'receiver_id'); } }use Illuminate\Database\Eloquent\Casts\Attribute; protected function typeName(): Attribute { return Attribute::make( get: fn () => match($this->type) { 0 => 'Topup', default => 'Unknown' } ); } - 修改业务代码,不需要再用
with()加载该属性,模型序列化时会自动带上type_name字段:$transaction = CoinTransaction::create([ 'receiver_id' => auth()->user()->id, 'coin' => $request->coin, 'balance' => $predefineCoin->balance ?? 1000, 'type' => 0, 'description' => $request->description ]); // 直接返回即可,不需要额外查询加载属性 return response()->json([ 'status' => 200, 'message' => 'OK', 'data' => $transaction ]);
内容的提问来源于stack exchange,提问作者darektoa
相关产品推荐
相关产品推荐

