【问题标题】:Lighthouse/GraphQL - Getting `null` for Polymorphic Relation in GraphQL Schema for Soft DeletesLighthouse/GraphQL - 在 GraphQL 模式中为软删除的多态关系获取“null”
【发布时间】:2020-06-01 22:09:29
【问题描述】:

我有一个平台可以让用户下载声音片段。声音剪辑的制作者可以查看他们的下载历史记录,但他们也可以删除他们不想再下载的文件。每个下载事件都有一个 DB 记录,该记录与两个不同的表具有多态关系,具体取决于声音剪辑类型。

我正在尝试组合一个 GraphQL 查询,该查询将返回选定日期范围内的下载统计信息,包括软删除文件的下载统计信息。 Laravel 查询正在返回软删除的记录,但软删除的记录在 graphQL 端不可用。

Laravel Download 模型(每个下载事件在此处创建一条记录) - 它可以是 BirdSoundHumanSound 记录:

class Download extends BaseModel
{
    protected $types = [
        'bird' => BirdSound::class,
        'human' => HumanSound::class,
    ];

    /**
     * @return MorphTo|EloquentBuilder|QueryBuilder
     */
    public function downloadable() : MorphTo
    {
        return $this->morphTo();
    }
}

Laravel BirdSound 模型(有一个等效的 HumanSound 模型)。对于可供下载的每个文件,此表中都有一条记录:

class BirdSounds extends Sounds
{
    use SoftDeletes;

    /**
     * @return MorphMany|EloquentBuilder|QueryBuilder
     */
    public function Download(): MorphMany
    {
        return $this->morphMany(Download::class, 'downloadable');
    }
}

GraphQL 架构:

type Download {
    id: ID!
    name: String!
    email: String!
    downloadable: Downloadable @morphTo
}

interface Downloadable {
    id: ID!
    name: String
    freeDownloads: [Download!] @morphMany
}

type BirdSound implements Downloadable {
    id: ID!
    name: String
    duration: String
    user: User @belongsTo(relation: "user")
    filename: String
    freeDownloads: [Download] @morphMany 
}

type HumanSound implements Downloadable {
    id: ID!
    name: String
    snippet: Int
    user: User @belongsTo(relation: "user")
    artwork_id: Int
    freeDownloads: [Download] @morphMany
}

# Using DownloadCount type to handle the data returned by the laravel function that counts the downloads
type DownloadCount {
    downloadable_id: Int
    downloadable_type: String
    count: Int
    downloadable: MediaInfo
}

# Using MediaInfo instead of the actual `downloadable` object in order to include soft-deleted records, 
# which I can't get working with the polymorphic relationship for lighthouse
type MediaInfo {
    id: ID! # ID of the downloadable record
    name: String # name from the BirdSound or HumanSound
}

extend type Query {
    myTopDownloads(downloaded_at: DateRange)): [DownloadCount]  
        @field(resolver: "App\\GraphQL\\Queries\\FreeDownloads@topDownloads")
}

获取数据的 Laravel 函数:

public function topDownloads($rootValue, array $args, GraphQLContext $context, ResolveInfo $resolveInfo)
{
    return auth()->guard('graphql')->user()->freeDownloads()
                    ->selectRaw('id, downloadable_id, downloadable_type, count(downloadable_id) as count')
                    ->groupBy('downloadable_id')
                    ->orderBy('count', 'desc')
                    ->with(['downloadable' => function($query){
                        $query->withTrashed();
                    }])
                    ->limit($limit)
                    ->get();
}

上面的 Laravel 查询返回下载信息和相关的可下载数据,无论它是否被软删除,并且使用上面描述的 graphQL 模式,我可以通过 MediaInfo 上的关系访问 downloadable 对象Download 对象。但是,我无法弄清楚如何获得在 graphQL 中可用的模型上定义的实际 downloadable 关系 - 该关系始终显示 null

我尝试了以下方法:

更改媒体类型

type Media {
    id: Int
    downloadable_id: Int
    name: String
    downloadable_type: String
    count: Int
    downloadable: Downloadable @morphTo @softDeletes
}

在查询中添加trashed: Trash(我假设它只是一维的,这就是它不起作用的原因):

extend type Query {
    myTopDownloads(trashed: Trash, downloaded_at: DateRange)): [Download]  
        @field(resolver: "App\\GraphQL\\Queries\\FreeDownloads@topDownloads")
}

...我已经尝试了上述示例的多种变体,所有这些都导致downloadable 对象的null 或我得到一个错误。

查询示例:

{
  myTopDownloads{
    downloadable_id
    downloadable_type
    count
    downloadable(trashed:WITH) {
      __typename
      id
      name
    }
  }
}

"debugMessage": "@trashed 仅用于使用 SoftDeletes 特征的模型类。",

Laravel 模型都使用 SoftDeletes 特征,我找不到有关向 graphQL 类型添加特定特征的文档(例如:在我的 BirdSound 类型中)。

假设问题可能在于它是一种多态关系,但这是我使用 GraphQL 的第一个项目,我仍在努力解决一些细节问题。 .对此的任何见解都会很棒!

【问题讨论】:

    标签: graphql laravel-lighthouse


    【解决方案1】:

    根据灯塔,在多态关系中,您应该指向一个联合,指示它可能返回的类型。

    union Downloadable = HumanSound | BirdSound
    

    https://lighthouse-php.com/master/eloquent/polymorphic-relationships.html#one-to-many

    要查询这些类型,请使用符号指定给定类型,返回哪些字段

    {
      myTopDownloads{
        downloadable_id
        downloadable_type
        count
        downloadable(trashed:WITH) {
          __typename
          ... on BirdSound {
            id
            name
          }
          ... on HumanSound {
            id
            name
          }
        }
      }
    }
    

    https://graphql.org/learn/schema/#union-types

    不要忘记您需要在模型中指定关系,包括返回类型,并删除实现。

    【讨论】:

      猜你喜欢
      • 2022-07-12
      • 2020-08-11
      • 2020-05-01
      • 2019-07-11
      • 2021-10-22
      • 2019-12-02
      • 2020-04-20
      • 2020-04-18
      • 2018-09-28
      相关资源
      最近更新 更多