Strapi - 如何使用自定义属性扩展 graphql 类型模式?
Posted
技术标签:
【中文标题】Strapi - 如何使用自定义属性扩展 graphql 类型模式?【英文标题】:Strapi - How to extend graphql type schema with custom property? 【发布时间】:2020-02-28 13:40:28 【问题描述】:假设我在创建为 Strapi 内容类型的作者类型架构上具有“firstName”和“lastName”属性。
我可以使用 graphql 查询它们,但是如果我想查询 'fullName' 属性而不在我的内容类型上添加该字段怎么办?
由于字段不存在,现在它显示:Cannot query field \"fullName\" on type \"Author\"。
如何使用附加的“虚拟”字段扩展现有类型架构?
【问题讨论】:
【参考方案1】:我设法在 api/author/config 文件夹中的 schema.graphql 文件中使用以下代码来实现:
module.exports =
definition: `type AuthorOverride
firstName: String
lastName: String
fullName: String
`,
query: `
authors: [AuthorOverride]
`,
type:
Author: false
,
resolver:
Query:
authors:
description: 'Return the authors',
resolver: 'Author.find'
;
关键是在使用不同类型名称(AuthorOverride)的同时使用附加字段定义架构以避免重复类型错误。
另外,设置 type: Author: false 以便原始类型不可查询。
现在,在我的解析器函数“Author.find”(放置在我的 Author.js 控制器中)中,我可以映射 fullName 值。
如果有人对在 Strapi 中扩展 graphql 架构有更合适的解决方案,请随时发布。
【讨论】:
【参考方案2】:刚刚找到这篇文章,也找到了合适的解决方案。这个example repo 演示了如何使用带有自定义控制器方法和自定义 GraphQL 模式的服务函数来获得你想要的。我刚刚在自己的项目中实现了相同的功能。
您的案例不需要服务功能。你只需要做两件事:
-
在
/api/authors/config/schema.graphql.js
中定义fullName
属性,如下所示:
module.exports =
definition:
extend type Author
fullName: AuthorFullName
type AuthorFullName
firstName: String
lastName: String
`,
;
-
接下来,您需要为
Author
覆盖find
和findOne
控制器方法,如下所示:
module.exports =
async find( ctx )
let entities;
if ( ctx.query._q )
entities = await strapi.services.author.search( ctx.query );
else
entities = await strapi.services.author.find( ctx.query );
// Add computed field `fullName` to entities.
entities.map( entity =>
entity.fullName = `$entity.firstName $entity.lastName`;
return entity;
);
return entities.map( entity => sanitizeEntity( entity, model: strapi.models.author ) );
,
async findOne( ctx )
const id = ctx.params;
let entity = await strapi.services.author.findOne( id );
if ( ! entity )
return ctx.notFound();
// Add computed field `fullName` to entity.
entity.fullName = `$entity.firstName $entity.lastName`;
return sanitizeEntity( entity, model: strapi.models.author );
,
;
这允许 REST API 调用返回 fullName
,并告诉 GraphQL 在其架构中也包含 fullName
,以便 find
和 findOne
可以正确地将其传递给 GraphQL。
我希望这会有所帮助,因为我觉得在学习了这些之后我的等级提升了很多!
【讨论】:
这是金子!我也觉得学了这个就升级了!!!!!!谢谢@wavematt【参考方案3】:这些都不适合我。从docs 看来,他们似乎已经将v4
更改为在全局上下文中扩展,而不是每个模块/实体(src/api/...
)。像这样:
// src/index.js
"use strict";
module.exports =
register( strapi )
const extensionService = strapi.plugin("graphql").service("extension");
const extension = () => (
typeDefs: `
type Author
fullName: String
`,
resolvers:
Author:
fullName(author)
return strapi.service("api::author.author").getFullName(author);
,
,
,
);
extensionService.use(extension);
,
;
这可能是错误的,我希望是这样。在我看来,从架构上讲,这是一个后退阶段。但是,您始终可以将此逻辑添加到每个实体文件夹中的文件(例如src/api/graphql/index.js
),然后将其导入此全局文件。有点像上面的服务逻辑发生的事情,以保持关注点分离。这只是有点“手动”。
对于那些想看看strapi.service("api::author.author").getFullName(author)
正在打电话的人:
// src/api/author/services/author.js
"use strict";
const createCoreService = require("@strapi/strapi").factories;
module.exports = createCoreService("api::author.author", () => (
getFullName(author)
return `$author.firstName $author.lastName`;
,
));
【讨论】:
以上是关于Strapi - 如何使用自定义属性扩展 graphql 类型模式?的主要内容,如果未能解决你的问题,请参考以下文章