You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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类型)

  1. 更新Restaurant的GraphQL类型定义,将数组改为单个类型:
getWorkHours: WorkHours @method
  1. 修改模型方法,补充必填字段并处理空数据:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 02:10:32