翻译进度
2
分块数量
3
参与人数

Scalar Types

这是一篇社区协同翻译的文章,你可以点击右边区块信息里的『改进』按钮向译者提交改进建议。

内置标量类型

GraphQL 规范描述了几种内置的标量类型。在 graphql-php 中,它们作为 GraphQL\Type\Definition\Type 类的静态方法公开:

<?php
use GraphQL\Type\Definition\Type;

// 内置标量类型
Type::string();  // String 类型
Type::int();     // Int 类型
Type::float();   // Float 类型
Type::boolean(); // Boolean 类型
Type::id();      // ID 类型

这些方法返回 GraphQL\Type\Definition\ScalarType(实际上是其中一个子类)的实例。直接在类型定义中使用它们,或者包装在 TypeRegistry 中(如果使用的话)。

Ellison 翻译于 3周前

编写自定义标量类型

除了内置标量类型以外,你还可以使用其他的验证规则来定义你的标量类型。
这些类型中典型的例子如 邮箱日期链接 等等。

想要实现你自定义的类型,你必须了解 GraphQL 中标量是如何呈现的。
在 GraphQL 中以下情况会涉及到标量:

  1. 当转换应用程序返回的 内部表示 (例如存储在数据库或源码中的硬编码)为包含 序列化 表示的响应时。

  2. 当将客户端传入的 输入值 与 GraphQL 查询一起转换为应用程序的 内部表示 时。

  3. 将在 GraphQL 查询(例如字段参数值)中硬编码的 文字输入值 转化为应用程序的 内部表示 时。

这些情况由抽象类 ScalarType 中的 serializeparseValueparseLiteral 方法来分别处理。

以下是一个 邮箱 类型的简单示例:

<?php
namespace MyApp;

use GraphQL\Error\Error;
use GraphQL\Error\InvariantViolation;
use GraphQL\Language\AST\StringValueNode;
use GraphQL\Type\Definition\ScalarType;
use GraphQL\Utils\Utils;

class EmailType extends ScalarType
{
    // 注意:名称可以省略。在这种情况下它将从类名推断出来
    // (「Type」前缀会被去掉)
    public $name = 'Email';

    /**
     * 在响应中包含一个序列化的内部值
     *
     * @param string $value
     * @return string
     */
    public function serialize($value)
    {
        // 假设邮箱的内部表示总是正确的:
        return $value;

        // 如果它可能不正确,并且你想确保响应中只包含正确的值。
        // 请使用下面的代码:
        // if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
        //     throw new InvariantViolation("Could not serialize following value as email: " . Utils::printSafe($value));
        // }
        // return $this->parseValue($value);
    }

    /**
     * 解析外部输入的值(查询变量)以用作输入
     *
     * @param mixed $value
     * @return mixed
     */
    public function parseValue($value)
    {
        if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
            throw new Error("Cannot represent following value as email: " . Utils::printSafeJson($value));
        }
        return $value;
    }

    /**
     * 解析外部输入的文字变量值(查询变量)以用作输入
     * 
     * 例如:
     * {
     *   user(email: "user@example.com") 
     * }
     *
     * @param \GraphQL\Language\AST\Node $valueNode
     * @return string
     * @throws Error
     */
    public function parseLiteral($valueNode)
    {
        // 注意:抛出 GraphQL\Error\Error 比 \UnexpectedValueException 更有益于定位在
                // GraphQL 查询的错误位置:
        if (!$valueNode instanceof StringValueNode) {
            throw new Error('Query error: Can only parse strings got: ' . $valueNode->kind, [$valueNode]);
        }
        if (!filter_var($valueNode->value, FILTER_VALIDATE_EMAIL)) {
            throw new Error("Not a valid email", [$valueNode]);
        }
        return $valueNode->value;
    }
}

或者使用行内样式:

<?php
use GraphQL\Type\Definition\CustomScalarType;

$emailType = new CustomScalarType([
    'name' => 'Email',
    'serialize' => function($value) {/* See function body above */},
    'parseValue' => function($value) {/* See function body above */},
    'parseLiteral' => function($valueNode) {/* See function body above */},
]);
Honvid 翻译于 3周前

本文章首发在 Laravel China 社区
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

参与译者:3
讨论数量: 0
发起讨论


暂无话题~