你可以为 nuwave/lighthouse 6.6 的 @find 指令创建自定义查询吗?

huangapple go评论65阅读模式
英文:

Can i create custom query for @find directive with nuwave/lighthouse 6.6?

问题

In Laravel 9.48 / Nuwave/Lighthouse 6.6应用程序中,我需要使用@find指令获取单个行,以添加一些附加字段,这些字段不在数据库中,但是根据published和created_at_formatted计算“on fly” published_label,created_at_formatted基于created_at:

{
  article(id:1)  {
     id
     title
     text
     text_shortly
     creator {
        id
        username
        email
        status
     }
      published
      published_label
      created_at_formatted 
      created_at
  }
}

我尝试创建自定义查询,就像我为@paginate指令创建自定义查询一样,该指令有可能使用自定义解析器和withc命令:

php artisan lighthouse:query Article

新文件app/GraphQL/Queries/Article.php已创建,并修改了GraphQL文件:

extend type Query {
    articles(
        filterByPublished: Boolean @where(key: "filterByPublished")
        filterByTitle: String @where(key: "filterByTitle")
        sortedBy: String @where(key: "sortedBy")
        page: Int @where(key: "page")
        count: Int @where(key: "count")
    ): [Article!]! @paginate(defaultCount: 10, resolver: "App\\GraphQL\\Queries\\Builders\\CustomArticles@index")

#    article(id: ID! @eq): Article @find
    article(id: ID! @eq): Article @find(resolver: "App\\GraphQL\\Queries\\Article")
}

命令没有引发任何错误:

php artisan lighthouse:validate-schema

但我的请求返回错误:

"Cannot return null for non-nullable field \"Article.published_label\"

看起来我的自定义查询没有被调用。

阅读文档https://lighthouse-php.com/6/api-reference/directives.html#find,我没有找到任何提到解析器的信息...我该如何处理?

英文:

In laravel 9.48 / nuwave/lighthouse 6.6 app I need getting single row with @find directive to add some additive fields
which I do not have in database ,but calculate “on fly” published_label based on published and created_at_formatted and created_at_formatted
based on created_at :

{
  article(id:1)  {
     id
     title
     text
     text_shortly
     creator {
        id
        username
        email
        status
     }
      published
      published_label
      created_at_formatted 
      created_at
  }
}

I tried to create custom query, like I do with custom query for @paginate( directiver, which has possibility to use custom resolver and withc command

php artisan lighthouse:query Article

new file app/GraphQL/Queries/Article.php was created.

and modified graphql file :

extend type Query {
    articles(
        filterByPublished: Boolean @where(key: "filterByPublished")
        filterByTitle: String @where(key: "filterByTitle")
        sortedBy: String @where(key: "sortedBy")
        page: Int @where(key: "page")
        count: Int @where(key: "count")
    ): [Article!]! @paginate(defaultCount: 10, resolver: "App\\GraphQL\\Queries\\Builders\\CustomArticles@index")

#    article(id: ID! @eq): Article @find
    article(id: ID! @eq): Article @find(resolver: "App\\GraphQL\\Queries\\Article")
}

Command did not raise any errors

php artisan lighthouse:validate-schema

and my request returned error :

"Cannot return null for non-nullable field \"Article.published_label\"

looks like my custom query was not called.

Reading docs at https://lighthouse-php.com/6/api-reference/directives.html#find
I did not fond any resolver mentioned here...
How can I make it ?

答案1

得分: 1

以下是翻译好的内容:

  1. 不需要在这里创建一个自定义的 @find 指令。

我可以看到有两种实现你想要的方式:

  1. 在你的 Article 模型上创建一个 "published_label" 属性,一种快速而简单的方式:
public function publishedLabel(): Attribute
{
  return Attribute::get(fn () => "Published since " . $this->published_at->format(...));
}
  1. 创建一个专用的解析器,这是一种干净的方式(依我个人看法):
namespace App\GraphQL\Resolvers\Types\Article;
use App\Models\Article;

class PublishedLabel {
  public function __invoke(Article $parent): string {
    return "Published since " . $parent->published_at->format(...);
  }
}

然后在你的 GraphQL 定义中使用它:

type Article {
  ...
  published: Datetime!
  published_label: String! @field(resolver: "App\\GraphQL\\Resolvers\\Types\\Article\\PublishedLabel")
}

在这第二种方式中,你甚至可以考虑一些参数,例如 "locale"、"format"(短/长)等,以实现无限的可能性:

type Article {
  ...
  published: Datetime!
  published_label(locale: String = "en"): String! @field(resolver: "App\\GraphQL\\Resolvers\\Types\\Article\\PublishedLabel")
}

然后,在你的解析器中使用这些参数:

namespace App\GraphQL\Resolvers\Types\Article;
use App\Models\Article;

class PublishedLabel {
  public function __invoke(Article $parent, $args): string {
    $locale = $args['locale'];
    $publishedAt = $parent->published_at;

    return ....;
  }
}
英文:

No need to create a custom @find directive here.

I can see two ways to achieve what you want:

  1. Create a the "published_label" attribute on your Article model, the quick and dirty way :
public function publishedLabel(): Attribute
{
  return Attribute::get(fn () => "Published since " . $this->published_at->format(...));
}
  1. Create a dedicated resolver, the clean way IMHO :
namespace App\GraphQL\Resolvers\Types\Article;
use App\Models\Article;

class PublishedLabel {
  public function __invoke(Article $parent): string {
    return "Published since " . $parent->published_at->format(...);
  }
}
// then in your graphql definition
type Article {
  ...
  published: Datetime!
  published_label: String! @field(resolver: "App\\GraphQL\\Resolvers\\Types\\Article\\PublishedLabel")
}

Read more about this here : https://lighthouse-php.com/master/api-reference/directives.html#field

Bonus

With this second way, you can even imagine some arguments, such as "locale", "format" (short/long), ... for endless possibilities

type Article {
  ...
  published: Datetime!
  published_label(locale: String = "en"): String! @field(resolver: "App\\GraphQL\\Resolvers\\Types\\Article\\PublishedLabel")
}
namespace App\GraphQL\Resolvers\Types\Article;
use App\Models\Article;

class PublishedLabel {
  public function __invoke(Article $parent, $args): string {
    $locale = $args['locale'];
    $publishedAt = $parent->published_at;

    return ....;
  }
}

huangapple
  • 本文由 发表于 2023年5月13日 15:22:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/76241536.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定