markhuot / craftql
Craft 的 GraphQL 实现
Requires
- craftcms/cms: ^3.0.0
- react/http: ^0.7
- webonyx/graphql-php: ^0.11.0
- dev-master
- 2.x-dev
- 2.0.0-beta1
- 1.3.7
- 1.3.6
- 1.3.5
- 1.3.4
- 1.3.3
- 1.3.2
- 1.3.1
- 1.3.0
- 1.2.1
- 1.2.0
- 1.1.0
- 1.0.0
- 1.0.0-beta.29
- 1.0.0-beta.28
- 1.0.0-beta.27
- 1.0.0-beta.26
- 1.0.0-beta.25
- 1.0.0-beta.24
- 1.0.0-beta.23
- 1.0.0-beta.22
- 1.0.0-beta.21
- 1.0.0-beta.20
- 1.0.0-beta.19
- 1.0.0-beta.18
- 1.0.0-beta.17
- 1.0.0-beta.16
- 1.0.0-beta.15
- 1.0.0-beta.14
- 1.0.0-beta.13
- 1.0.0-beta.12
- 1.0.0-beta.11
- 1.0.0-beta.10
- 1.0.0-beta.9
- 1.0.0-beta.8
- 1.0.0-beta.7
- 1.0.0-beta.6
- 1.0.0-beta.5
- 1.0.0-beta.4
- 1.0.0-beta.3
- 1.0.0-beta.2
- 1.0.0-beta.1
- dev-dependabot/composer/react/http-1.7.0
- dev-2.x-remove-factories
- dev-imager
- dev-graphqlphp-update
- dev-builder-refactor3
- dev-alternates
- dev-builder-refactor2
- dev-builder-refactor
- dev-caching-perofrmance
- dev-geo-address-field-schema
- dev-batch-queries-defer
- dev-conflicting-type-names
- dev-user-tokens
- dev-commerce
- dev-security
- dev-subscriptions
This package is auto-updated.
Last update: 2024-09-16 23:22:47 UTC
README
Craft CMS 实现的嵌入式 GraphQL 服务器。无需配置,CraftQL 允许您通过熟悉的 GraphQL 界面访问 Craft 的所有功能。
示例
安装完成后,您可以使用简单的 Hello World 测试您的安装
{
helloWorld
}
如果一切顺利,您现在可以使用几乎与您的 Twig 模板相同的语法查询 Craft CMS。
{ entries(section:[news], limit:5, search:"body:salty") { ...on News { title url body } } }
CraftQL 提供了一个顶级 entries
字段,它接受与您的模板中 craft.entries
相同的参数。这是最常用的字段/访问点。例如,
query fetchNews { # The query, `query fetchNews` is completely optional entries(section:[news]) { # Arguments match `craft.entries` ...on News { # GraphQL is strongly typed, so you must specify each Entry Type you want data from id # A field to return title # A field to return body # A field to return } } }
为您的安装中的每个条目类型自动创建类型。如果您有一个名为 news
的部分和一个名为 news
的条目类型,GraphQL 类型将被命名为 News
。如果您有一个名为 news
的部分和一个名为 pressRelease
的条目类型,GraphQL 类型将被命名为 NewsPressRelease
。约定是将部分处理程序和条目处理程序混合在一起,除非它们相同,在这种情况下将使用部分处理程序。
query fetchNews { entries(section:[news]) { ...on News { # Any fields on the News entry type id title body } ...on NewsPressRelease { # Any fields on the Press Release entry type id title body source contactInfo downloads { title url } } } }
要修改内容,请确保您的令牌具有写入权限,然后使用顶级的 upsert{EntryType}
变异
。 upsert{EntryType}
接受每个在 Craft 中定义的字段参数。
mutation createNewEntry($title:String, $body:String) { upsertNews( title:$title, body:$body, ) { id url } }
以上可以通过以下变量传递,
{ "title": "My first mutation!", "body": "<p>Here's the body of my first mutation</p>", }
矩阵字段
处理矩阵字段类似于处理条目类型:如果您有一个处理程序为 body
的矩阵字段,包含的块类型将被命名为 Body
+ 块处理程序。例如 BodyText
或 BodyImage
。您可以使用响应中的键 __typename
来遍历块并显示相应的组件。
{ entries(section: [news]) { ... on News { id title body { # Your Matrix Field ... on BodyText { # Block Type __typename # Ensures the response has a field describing the type of block blockHeading # Fields on Block Type, uses field handle blockContent # Fields on Block Type, uses field handle } ... on BodyImage { # Block Type __typename # Ensures the response has a field describing the type of block blockDescription # Fields on Block Type, uses field handle image { # Fields on Block Type, uses field handle id # Fields on image field on Block Type, uses field handles } } } } } }
日期
CraftQL 中的所有日期都输出为 Timestamp
标量,它表示 Unix 时间戳。例如,
{ entries { dateCreated # outputs 1503368510 } }
可以使用 @date
指令将日期转换为人类友好的格式,
{ entries { dateCreated @date(as:"F j, Y") # outputs August 21, 2017 } }
关系
根据您的需求,可以通过几种方式检索相关条目。
类似于 craft.entries.relatedTo(entry)
,您可以在 entries
顶级查询字段上使用 relatedTo
参数。例如,如果您有一个 ID 为 63
的 Post
与评论相关,可以使用以下内容。
{ entries(relatedTo:[{element:63}], section:comments) { ...on Comments { id author { name } commentText } } }
注意,relatedTo:
参数接受一个关系数组。默认情况下,relatedTo:
查找匹配 所有 关系的项目。如果您想切换到与 任何 关系相关的项目,可以使用 orRelatedTo:
。
上述方法通常需要为源内容和相关内容分别发出请求。这相当于额外的 HTTP 请求和延迟。如果您使用 CraftQL 的“连接”方法,则可以使用 EntryEdge
类型的 relatedEntries
字段在单个请求中检索关系。相同的请求可以重写如下,以在单个请求中获取帖子及其评论。
{ entriesConnection(id:63) { edges { node { ...on Post { title body } } relatedEntries(section:comments) { edges { node { ...on Comment { author { name } commentText } } } } } } }
转换
您可以通过指定任何资产字段的参数来向CraftQL请求图像转换。注意:为了使其生效,存储图像的卷必须在卷设置中启用“公开URL”,否则CraftQL将返回null
值。
如果您在Craft UI中定义了命名的转换,您可以按其handle引用转换。
{ entries { ...on Post { imageFieldHandle { thumbnail: url(transform: thumb) } } } }
您还可以使用crop
、fit
或stretch
参数指定确切的裁剪,具体请参考Craft文档。
{ entries { ...on Post { imageFieldHandle { poster: url(crop: {width: 1280, height: 720, position: topLeft, quality: 50, format: jpg}) } } } }
草稿
最好通过entriesConnection
查询上的边缘节点获取草稿。您可以使用以下查询获取一个条目的所有草稿:
{ entriesConnection(id:63) { edges { node { # the published node, as `craft.entries` would return id title } drafts { # an array of drafts edges { node { # the draft content id title ...on Post { # draft fields are still referenced by entry type, as usual body } } draftInfo { # the `draftInfo` field returns the meta data about the draft draftId name notes } } } } } }
类别和标签
可以通过顶层categories
或tags
字段查询分类法。这两个字段与它们的craft.entries
和craft.tags
对应字段工作方式相同。
{ categories { # lists all categories, or use `tags` to get all tags id title } }
为了增加功能,可以通过相关的Connection
字段查询类别和标签。这提供了一个返回相关条目的位置。
{ categoriesConnection { totalCount edges { node { title # the category title } relatedEntries { entries { title # an entry title, that's related to this category } } } } }
用户
您可以通过顶层users
字段查询用户。
{ users { id name email } }
您还可以通过upsertUser
字段修改用户。当传递一个id:
时,它将更新用户。如果缺少id:
属性,它将创建一个新用户。
mutation { upsertUser(id:1, firstName:"Mark", lastName:"Huot") { id name # returns `Mark Huot` after the mutation } }
还可以设置权限,但您必须始终传递用户的所有权限列表。例如:
mutation { upsertUser(id:1, permissions:["accessCp","editEntries:17","createEntries:17","deleteEntries:17"]) { id name # returns `Mark Huot` after the mutation } }
安全
CraftQL支持GraphQl字段级别权限。默认情况下,令牌没有任何权利。您必须点击“作用域”部分来调整每个令牌可以做什么。
作用域允许您配置哪些GraphQL字段和条目类型包含在模式中。
第三方字段支持
要将CraftQL支持添加到您的第三方字段插件,您需要监听craftQlGetFieldSchema
事件。此事件在您的自定义字段上触发,并将“模式构建器”传递给事件处理器,允许您指定自定义字段提供的字段模式。例如,在您的插件的::init
方法中,您可以指定:
Event::on(\my\custom\Field::class, 'craftQlGetFieldSchema', function (\markhuot\CraftQL\Events\GetFieldSchema $event) { // the custom field is passed as the event sender $field = $event->sender; // the schema exists on a public property of the event $event->schema // you can add as many fields as you need to for your field. Typically you'll // pass your field in, which will automatically set the name and description // based on the Craft config. ->addStringField($field); // the schema is a fluent builder and can be chained to set multiple properties // of the custom field $event->schema->addEnumField('customField') ->lists() ->description('This is a custom description for the field') ->values(['KEY' => 'Label', 'KEY2' => 'Another label']); });
上述内容在调用Post条目类型上的excerpt
字段时将生成一个与以下大致等价的模式:
type CustomFieldEnum { # Label KEY # Another label KEY2 } type Post { # The field instructions are automatically included excerpt: String # This is a custom description for the field customField: [CustomFieldEnum] }
如果您的自定义字段解析一个对象,您也可以将其暴露给CraftQL。例如,如果您正在实现一个暴露地图的自定义字段,该地图具有纬度、经度和缩放级别,它可能看起来像:
Event::on(\craft\base\Field::class, 'craftQlGetFieldSchema', function ($event) { $field = $event->sender; $object = $event->schema->createObjectType('MapPoint') ->addStringField('lat') ->addStringField('lng') ->addStringField('zoom'); $event->schema->addField($field)->type($object); });
路线图
没有任何软件是完美的。为了使CraftQL功能完整,还有很多工作要做。一些悬而未决的项目包括:
- 矩阵字段尚未包含在模式中
- 表格字段尚未包含在模式中
- 资产突变(通过传递URL或资产ID实现)
- 在突变期间通过POST $_FILES将文件上传到资产
- 自动化测试尚未启用
- 自动化测试实际上尚未测试任何内容
- 突变需要更多的测试
-
relatedEntries:
改进以获取源/目标 - 持久查询
- 子类化的枚举字段能够返回原始字段值
要求
- Craft 3.6.0+
- PHP 7.0+
安装
如果您尚未安装Craft 3,请先安装它。
$ composer create-project craftcms/craft my-awesome-site -s beta
一旦您有了Craft 3的运行版本,您就可以使用Composer安装CraftQL。
$ composer require markhuot/craftql:^1.0.0
运行CLI服务器
CraftQL 内置了PHP原生网络服务器。当通过提供的网络服务器运行 CraftQL 时,启动过程仅在初次启动时发生。这有可能大大加快响应时间,因为PHP可以在请求之间保持状态。一般来说,我观察到性能提升了5倍(从500ms到<100ms)。
注意:这也可能产生意外的副作用,因为Craft并非原生设计为以这种方式运行。不要在生产环境中使用此功能,可能会导致内存泄漏、服务器火灾和IT告警通知:)。
php craft craftql/server