Laravel10中belongsTo关联select时附加属性无法生成的问题
问题描述
模型定义
User模型
protected $appends = [ 'full_name', 'avatar', ]; public function company(): HasOne { return $this->hasOne(Company::class); } /** * 返回用户照片可访问URL的获取器 * * @return Attribute */ public function avatar(): Attribute { return Attribute::make( get: static function (?string $value, array $attributes) { asset(str_replace('public', 'storage', self::$avatarPath) . '_' . $attributes['full_name'] . '_' . $attributes['id'] . '.webp' ); }, ); } public function fullName(): Attribute { return new Attribute( get: fn () => $this->first_name .' ' . $this->last_name ); }
Company模型
public function user(): BelongsTo { return $this->belongsTo(User::class); }
查询代码
public static function adminTableData(): Builder { return self::query()->with(['user' => function($query) { $query->select('id', 'first_name', 'last_name'); }])->paginate(10)->toJson(); }
错误信息
Undefined array key "full_name"
错误出现在User模型的avatar方法中:
$attributes['full_name'] . '_' . $attributes['id'] . '.webp'
问题原因与解决方案
核心原因
$attributes只存数据库字段:full_name是你通过$appends添加的附加属性,不属于数据库表字段,所以不会出现在$attributes数组里,直接读取自然报错。- 静态获取器无法访问模型实例:
avatar的get闭包用了static修饰,导致无法通过$this访问模型实例,而full_name依赖模型的first_name和last_name生成,静态环境下拿不到这个附加属性的值。
修复方案
方案1:去掉static,直接调用模型的full_name属性
修改avatar获取器,去掉static,用$this->full_name代替$attributes['full_name'],同时补上缺失的return:
public function avatar(): Attribute { return Attribute::make( get: function (?string $value, array $attributes) { return asset(str_replace('public', 'storage', self::$avatarPath) . '_' . $this->full_name . '_' . $attributes['id'] . '.webp' ); }, ); }
方案2:手动拼接full_name(适合必须用静态的场景)
直接从$attributes里取first_name和last_name拼接,不依赖附加属性:
public function avatar(): Attribute { return Attribute::make( get: static function (?string $value, array $attributes) { $fullName = $attributes['first_name'] . ' ' . $attributes['last_name']; return asset(str_replace('public', 'storage', self::$avatarPath) . '_' . $fullName . '_' . $attributes['id'] . '.webp' ); }, ); }
注:此方案要求查询时已选中first_name和last_name,你的代码已经满足这个条件。
额外修正
adminTableData方法的返回值声明错误——实际返回JSON字符串,却声明为Builder,建议修改:
public static function adminTableData(): string { return self::query()->with(['user' => function($query) { $query->select('id', 'first_name', 'last_name'); }])->paginate(10)->toJson(); }
内容的提问来源于stack exchange,提问作者Sasha
相关产品推荐
相关产品推荐

