fieldwork/craftql

该软件包最新版本(2.0.0-beta1)的许可信息不可用。

Craft 的 GraphQL 实现

维护者

详细信息

github.com/EMT/craftql

源代码

安装: 12

依赖项: 0

建议者: 0

安全性: 0

星标: 0

关注者: 3

分支: 53

语言:JavaScript

类型:craft-plugin

2.0.0-beta1 2019-02-05 19:52 UTC

This package is auto-updated.

Last update: 2024-09-26 02:24:06 UTC


README

CraftQL seen through the GraphiQL UI

Build Status

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
    }
  }
}

为安装中的每个 Entry Type 自动创建类型。如果您有一个名为 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} Mutationupsert{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 + 块句柄。例如 BodyTextBodyImage。您可以使用响应中的 __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 为 63Post 与评论相关,则可以使用以下内容:

{
  entries(relatedTo:[{element:63}], section:comments) {
    ...on Comments {
      id
      author {
        name
      }
      commentText
    }
  }
}

注意,relatedTo: 参数接受关系数组。默认情况下,relatedTo: 查找匹配 所有 关系的元素。如果您想切换到与 任何 关系相关的元素,可以使用 orRelatedTo:

上述方法通常需要为源内容和相关内容分别发出请求。这相当于额外的 HTTP 请求和延迟。如果您使用的是 "connection" 方法来 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)
      }
    }
  }
}

您还可以使用cropfitstretch参数指定确切的裁剪,这些参数在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
          }
        }
      }
    }
  }
}

类别和标签

可以通过顶级categoriestags字段查询分类法。这两个字段的工作方式与其craft.entriescraft.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字段级别权限。默认情况下,令牌没有任何权利。您必须点击“作用域”部分来调整每个令牌可以做什么。

token scopes

作用域允许您配置哪些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.0.0-RC1
  • 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