博客

🥳 Gato GraphQL v0.9 正式发布!

Leonardo Losoviz
作者:Leonardo Losoviz ·

经过近 1.5 年的开发以及超过 16,000 次提交,Gato GraphQL 的新版本终于发布了! 🥳

版本 0.9 是该插件历史上最大的一次发布。这里是 changelog,以及所有新功能的完整说明:

github.com/GatoGraphQL/GatoGraphQL/releases/tag/0.9.3

该文档内容相当长(阅读时间超过 40 分钟!),因此以下是最重要变更的 TL;DR 摘要。

大幅完善 GraphQL Schema

WordPress 数据模型已被大量映射到 GraphQL schema 中。

GraphQL schema

其中,schema 包含以下改进:

  • 可从任意 CPT(包括任何主题和插件)中查询数据
  • 映射了自定义分类法(标签和分类)
  • 创建并返回更合适的 GraphQL 类型(例如:HTMLURLDateTime
  • 通过 input 对象对字段参数进行整理
  • 使用 oneof input 对象,通过不同属性(例如:idslug)选择实体
  • 返回 mutation 载荷
  • 查询设置(来自 wp_options)和元数据值(适用于文章、用户、评论和分类法)

自定义标量

GraphQL 服务器新增了对自定义标量类型的支持。自定义标量可以让您更好地表示数据,无论是通过字段参数接收输入,还是在响应中打印自定义输出。

已实现了若干标准的自定义标量类型,可直接在您的 GraphQL schema 中使用:

  • Date
  • DateTime
  • Email
  • HTML
  • URL
  • URLAbsolutePath

自定义枚举

现已支持自定义枚举类型。枚举是一种特殊的标量,限定为一组特定的允许值。这使您能够:

  • 验证此类型的任何参数是否为允许值之一
  • 通过类型系统传达字段始终为有限值集合之一

已实现了若干枚举类型,并在 GraphQL schema 的适当位置使用,包括:

  • CommentOrderByEnum
  • CommentStatusEnum
  • CommentTypeEnum
  • CustomPostOrderByEnum
  • CustomPostStatusEnum
  • MediaItemOrderByEnum
  • MenuOrderByEnum
  • TaxonomyOrderByEnum
  • UserOrderByEnum

Input 对象

GraphQL 服务器现在还支持 input 类型,您可以将自定义 input 对象添加到 GraphQL schema 中。Input 对象允许您将复杂对象作为字段输入传递,这对 mutation 尤其有用。

schema 中适当的位置已添加了若干 input 对象。例如,用于查询数据的字段(如 postsuserscomments 等)在字段参数 filtersortpagination 下接收复杂的 input 对象,用于变更数据的字段(如 createPostaddCommentToCustomPost 等)则在字段参数 input 下接收 input 对象。

Oneof Input 对象

"oneof" input 对象是一种特殊的 input 对象,要求恰好提供其中一个 input 字段,否则将返回验证错误。这种行为为输入引入了多态性。

例如,字段 Root.post 现在新增了字段参数 by,这是一个 oneof input 对象,允许通过不同属性(如 idslug)检索文章:

{
  postByID: post(by: {
    id: 1
  }) {
    id
    title
  }
 
  postBySlug: post(by: {
    slug: "hello-world"
  }) {
    id
    title
  }
}

其好处在于,单个字段即可应对不同的使用场景,从而避免为每个场景创建不同的字段(如 postByIDpostBySlug 等),使 GraphQL schema 更加简洁优雅。

已实现了若干 Oneof Input 对象:

  • Root.customPost(by:)
  • Root.mediaItem(by:)
  • Root.menu(by:)
  • Root.page(by:)
  • Root.postCategory(by:)
  • Root.postTag(by:)
  • Root.post(by:)
  • Root.user(by:)

操作指令

GraphQL 操作(即 querymutation 操作)现在也可以接收指令了。

将指令限制为特定类型

(字段)指令可被限制为仅应用于某些特定类型的字段。例如,将字段值转换为大写的指令 @strUpperCase 仅对 String 字段有意义,而不适用于 IntFloatBoolean。现在可以在指令解析器中声明这一限制。

打印 GraphQL Query 节点错误的完整路径

响应中现在包含返回错误的 GraphQL query 节点的完整路径(位于子项 extensions.path 下),使查找问题来源更加便捷。

例如,在以下 query 中,指令 @nonExisting 不存在:

query {
  myField @nonExisting
}

响应如下:

{
  "errors": [
    {
      "message": "There is no directive with name 'nonExisting'",
      "locations": [
        {
          "line": 2,
          "column": 7
        }
      ],
      "extensions": {
        "type": "QueryRoot",
        "field": "myField @nonExisting",
        "path": [
          "@nonExisting",
          "myField @nonExisting",
          "query { ... }"
        ],
        "code": "PoP\\ComponentModel\\e20"
      }
    }
  ],
  "data": {
    "id": "root"
  }
}

启用不安全的默认设置

Gato GraphQL 提供安全的默认设置:

  • 单一端点已禁用
  • GraphQL schema 中的「敏感」数据元素(如 User.roles,或按 status 过滤文章)不会对外暴露
  • 可查询的设置选项和元键(适用于文章、用户等)数量有限
  • 一次可查询的实体数量受限(适用于文章、用户等)

这些安全的默认设置是为了防止恶意攻击、保护「在线」站点安全所必需的。然而,在构建「静态」站点时(此时 WordPress 站点不易受到攻击,例如开发者笔记本上的开发站点、位于安全防火墙后面,或完全不对互联网公开的环境),则无需这些设置。

v0.9 开始,可以通过在 wp-config.php 中添加以下内容来启用不安全的默认设置:

define( 'GRAPHQL_API_ENABLE_UNSAFE_DEFAULTS', true );

或者,也可以将相同的键/值定义为环境变量。

启用不安全的默认设置后,插件的默认设置将发生如下变化:

  • 单一端点被启用
  • GraphQL schema 中的「敏感」数据元素被暴露
  • 所有设置选项和元键均可查询
  • 一次可查询的实体数量不受限制

按分类整理自定义端点和 Persisted Query

在创建自定义端点或 Persisted Query 时,可以为其添加「GraphQL 端点分类」,以整理所有端点:

编辑自定义端点时的端点分类

例如,可以按客户、应用程序或其他所需信息创建分类来管理端点:

端点分类列表

在自定义端点和 Persisted Query 列表中,可以查看各自的分类,点击任意分类链接或使用顶部的筛选器,将仅显示该分类下的所有条目。

带分类的自定义端点列表

通过内省查询 Schema 扩展

附加到 schema 元素的自定义元数据现在可通过字段 extensions 进行查询。

Schema 的所有内省元素均已升级,新增了该字段,每个元素返回对应「Extensions」类型的对象,该对象公开了该元素的自定义属性。

# Using "_" instead of "__" in introspection type name to avoid errors in graphql-js
type _SchemaExtensions {
  # Is the schema being namespaced?
  isNamespaced: Boolean!
}
 
extend type __Schema {
  extensions: _SchemaExtensions!
}
 
type _NamedTypeExtensions {
  # The type name
  elementName: String!
 
  # The "namespaced" type name
  namespacedName: String!
 
  # Enum-like "possible values" for EnumString type resolvers, `null` otherwise
  possibleValues: [String!]
 
  # OneOf Input Objects are a special variant of Input Objects where the type system asserts that exactly one of the fields must be set and non-null, all others being omitted.
  isOneOf: Boolean!
}
 
extend type __Type {
  # Non-null for named types, null for wrapping types (Non-Null and List)
  extensions: _NamedTypeExtensions
}
 
type _DirectiveExtensions {
  # If no objects are returned in the field (eg: because they failed validation), does the directive still need to be executed?
  needsDataToExecute: Boolean!
 
  # Names or descriptions of the types the field directives is restricted to, or `null` if it supports any type (i.e. it defines no restrictions)
  fieldDirectiveSupportedTypeNamesOrDescriptions: [String!]
}
 
extend type __Directive {
  extensions: _DirectiveExtensions!
}
 
type _FieldExtensions {
  isGlobal: Boolean!
 
  # Useful for nested mutations
  isMutation: Boolean!
 
  # `true` => Only exposed when "Expose "sensitive" data elements" is enabled
  isSensitiveDataElement: Boolean!
}
 
extend type __Field {
  extensions: _FieldExtensions!
}
 
type _InputValueExtensions {
  isSensitiveDataElement: Boolean!
}
 
extend type __InputValue {
  extensions: _InputValueExtensions!
}
 
type _EnumValueExtensions {
  isSensitiveDataElement: Boolean!
}
 
extend type __EnumValue {
  extensions: _EnumValueExtensions!
}

完成 GraphQL 服务器代码与 WordPress 的解耦

驱动插件的底层 GraphQL 服务器现在可以作为独立的 PHP 组件安装和运行,即独立于 WordPress 运行。

这为在其他框架(例如 Laravel)中使用 Gato GraphQL 打开了大门,也使其可以在任何 PHP 环境中运行,无论 WordPress 是否可用(例如在执行持续集成任务时)。

编辑 Schema 配置、自定义端点和 Persisted Query 时浏览文档

在编辑 Schema 配置、自定义端点和 Persisted Query 时显示的所有区块,现在都新增了「info」按钮,点击后可在模态窗口中显示相关文档。

点击「info」按钮...

...打开包含文档的模态窗口

更多新特性

如需了解所有其他新功能,请查阅新版本的完整说明,或浏览 changelog

欢迎从这里下载插件

如果您喜欢,欢迎帮忙传播爱心 ❤️


订阅我们的新闻通讯

及时了解 Gato GraphQL 的所有更新。