Lighthouse GraphQL使用未迁移模型报错:期望可迭代对象问题
问题描述
我在使用Lighthouse GraphQL时遇到问题:希望结合数据库中的NormalWorkHours和OverrideWorkHours两张表,通过方法计算后返回临时的WorkHours类型数据给前端,无需持久化存储。目前尝试创建WorkHours模型实例并返回,但出现错误:
"debugMessage": "User Error: expected iterable, but did not find one for field Restaurant.getWorkHours."
相关代码
WorkHours模型
class WorkHours extends Model { use HasFactory, Uuids; protected $fillable = [ 'dayofweek', 'open_time', 'close_time', 'timezone', ]; public function restaurant() { return $this->belongsTo(Restaurant::class); } }
Restaurant模型
class Restaurant extends Model { use HasFactory, Uuids; /** * The attributes that are mass assignable. * * @var array */ protected $fillable = [ 'name', 'selected' ]; public function user() { return $this->belongsTo(User::class); } public function category() { return $this->belongsToMany(RestaurantCategory::class); } public function address() { return $this->hasOne(Address::class); } public function normalWorkHours() { return $this->hasMany(NormalWorkHours::class); } public function overrideWorkHours() { return $this->hasMany(OverrideWorkHours::class); } public function getWorkHours() { $workHours = new WorkHours; $workHours->dayofweek = $this->normalWorkHours[0]->dayofweek; $workHours->open_time = $this->normalWorkHours[0]->open_time; $workHours->close_time = $this->normalWorkHours[0]->close_time; $workHours->timezone = $this->normalWorkHours[0]->timezone; return $workHours; } }
GraphQL Restaurant类型定义
type Restaurant { id: ID! user_id: ID! name: String! selected: Boolean image_path: String created_at: DateTime! updated_at: DateTime! user: User! @belongsTo category: [RestaurantCategory!] @belongsToMany ingredients: [Ingredient] @hasMany additions: [AdditionsCollection!] @hasMany alergens: [Alergens] @hasMany extraIngredients: [ExtraIngredients] @hasMany mealSizes: [MealSize!] @hasMany sauces: [Sauces!] @hasMany address: Address! @hasOne normalWorkHours: [NormalWorkHours] @hasMany overrideWorkHours: [OverrideWorkHours] @hasMany getWorkHours: [WorkHours] @method }
GraphQL WorkHours类型定义
type WorkHours { dayOfWeek: Int @rename(attribute: "dayofweek") openTime: String @rename(attribute: "open_time") closeTime: String @rename(attribute: "close_time") timezone: Int closed: Boolean! }
解决方案
错误核心是GraphQL类型定义与模型方法返回值不匹配:GraphQL中getWorkHours定义为数组类型[WorkHours],但模型方法返回的是单个WorkHours实例,所以Lighthouse期望可迭代对象却没找到。以下是两种修复方案:
方案一:返回单个WorkHours实例(修改GraphQL类型)
- 更新Restaurant的GraphQL类型定义,将数组改为单个类型:
getWorkHours: WorkHours @method
- 修改模型方法,补充必填字段并处理空数据:
public function getWorkHours() { // 处理normalWorkHours为空的情况,避免索引报错 if ($this->normalWorkHours->isEmpty()) { return null; } $normalHour = $this->normalWorkHours->first(); $workHours = new WorkHours(); $workHours->dayofweek = $normalHour->dayofweek; $workHours->open_time = $normalHour->open_time; $workHours->close_time = $normalHour->close_time; $workHours->timezone = $normalHour->timezone; // 给必填的closed字段赋值,根据业务逻辑设置 $workHours->closed = false; return $workHours; }
方案二:返回WorkHours数组(保持GraphQL类型不变)
该方案实现OverrideWorkHours优先覆盖、NormalWorkHours补充的业务逻辑:
public function getWorkHours() { $workHoursList = []; // 先处理OverrideWorkHours(优先使用覆盖规则) foreach ($this->overrideWorkHours as $overrideHour) { $workHours = new WorkHours(); $workHours->dayofweek = $overrideHour->dayofweek; $workHours->open_time = $overrideHour->open_time; $workHours->close_time = $overrideHour->close_time; $workHours->timezone = $overrideHour->timezone; $workHours->closed = isset($overrideHour->closed) ? $overrideHour->closed : false; $workHoursList[] = $workHours; } // 再处理NormalWorkHours,排除已被覆盖的星期几 $overriddenDays = collect($workHoursList)->pluck('dayofweek')->toArray(); foreach ($this->normalWorkHours as $normalHour) { if (!in_array($normalHour->dayofweek, $overriddenDays)) { $workHours = new WorkHours(); $workHours->dayofweek = $normalHour->dayofweek; $workHours->open_time = $normalHour->open_time; $workHours->close_time = $normalHour->close_time; $workHours->timezone = $normalHour->timezone; $workHours->closed = false; $workHoursList[] = $workHours; } } return $workHoursList; }
关键注意事项
- 必须给
WorkHours类型中的closed字段赋值,因为它定义为Boolean!(非空必填),否则会触发字段缺失错误。 - 处理关联数据为空的场景,避免
[0]索引或遍历空集合报错。 - 无需持久化
WorkHours实例,直接创建内存中的模型实例返回即可,Lighthouse会自动解析字段。
内容的提问来源于stack exchange,提问作者Laimonas Rupeika
相关产品推荐
相关产品推荐

