我有一个平台可以让用户下载声音片段。声音剪辑的制作者可以查看他们的下载历史记录,但他们也可以删除他们不想再下载的文件。每个下载事件都有一个 DB 记录,该记录与两个不同的表具有多态关系,具体取决于声音剪辑类型。
我正在尝试组合一个 GraphQL 查询,该查询将返回选定日期范围内的下载统计信息,包括软删除文件的下载统计信息。Laravel 查询正在返回软删除记录,但软删除记录在 graphQL 端不可用。
LaravelDownload
模型(每个下载事件在此处创建一个记录) - 它可以是一个BirdSound
或一个HumanSound
记录:
class Download extends BaseModel
{
protected $types = [
'bird' => BirdSound::class,
'human' => HumanSound::class,
];
/**
* @return MorphTo|EloquentBuilder|QueryBuilder
*/
public function downloadable() : MorphTo
{
return $this->morphTo();
}
}
LaravelBirdSound
模型(有一个等效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 模式,我可以通过对象上downloadable
的MediaInfo
关系访问该Download
对象。但是,我无法弄清楚如何获得downloadable
在 graphQL 中可用的模型上定义的实际关系 - 关系总是显示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")
}
...我尝试了上述示例的多种变体,所有这些都导致对象 anull
或downloadable
我收到错误。
查询示例:
{
myTopDownloads{
downloadable_id
downloadable_type
count
downloadable(trashed:WITH) {
__typename
id
name
}
}
}
"debugMessage": "@trashed 仅用于使用 SoftDeletes 特征的模型类。",
Laravel 模型都使用 SoftDeletes 特征,我找不到有关向 graphQL 类型添加特定特征的文档(例如:在我的BirdSound
类型中)。
我认为问题可能在于它是一种多态关系,但这是我使用 GraphQL 的第一个项目,我仍在努力了解一些细节......对此的任何见解都会很棒!