[TOC]
#### 定义
ScalarType
GraphQL规范描述了一些内置的标量类型,在graphql-php中它们作为 GraphQL\Type\Definition\Type 类的静态方法公开。
~~~
use GraphQL\Type\Definition\Type;
// Built-in Scalar types:
Type::string(); // String type
Type::int(); // Int type
Type::float(); // Float type
Type::boolean(); // Boolean type
Type::id(); // ID type
~~~
这些方法返回 GraphQL\Type\Definition\ScalarType的实例(实际上是子类之一)。你可以直接使用他们或放到自己的TypeRegistry 中
#### 自定义标量类型
除了内置标量类型,您还可以通过附加验证来定义自己的标量类型,常见的这样的类型如:Email,Date,Url 等。
为了实现你自己的类型你必须了解scalars在graphql中是如何表示的。graphql在以下情况下会对scalars进行处理。
1. 当将您的应用程序返回的值的内部表示(如,存储在数据库 或 硬编码在源代码中)转换为包含在响应(response)中的 序列化表示(serialize)。
2. 当将变量($variables )中由客户端随同GraphQL query 一起传递的输入值转换为应用程序的内部表示时。
3. 当将在 Graphql query 硬编码的输入字面量值(如 字段 参数值)转换为应用程序的内部表示时。
以上情况分别通过实现抽象类 ScalarType 的方法 serialize,pareValue and parseLiteral 来完成。
#### 注意
* 对于 pareValue 和 parseLiteral两种 除了 null 可以返回任意内置标量类型的值,如果返回的是null,表示当前值不能满足 ScalarType的 验证,则结果会抛出错误。
* parseLiteral的参数是节点对象,可能通过$valueNode->value 或取它的值 (假设变量名是$valueNode)
下面是一个简单的 Email 类型:
~~~
namespace MyApp;
use GraphQL\Error\Error;
use GraphQL\Language\AST\StringValueNode;
use GraphQL\Type\Definition\ScalarType;
use GraphQL\Utils;
class EmailType extends ScalarType
{
// Note: name can be omitted. In this case it will be inferred from class name
// (suffix "Type" will be dropped)
public $name = 'Email';
/**
* Serializes an internal value to include in a response.
*
* @param string $value
* @return string
*/
public function serialize($value)
{
// Assuming internal representation of email is always correct:
return $value;
// If it might be incorrect and you want to make sure that only correct values are included in response -
// use following line instead:
// return $this->parseValue($value);
}
/**
* Parses an externally provided value (query variable) to use as an input
*
* @param mixed $value
* @return mixed
*/
public function parseValue($value)
{
if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
throw new \UnexpectedValueException("Cannot represent value as email: " . Utils::printSafe($value));
}
return $value;
}
/**
* Parses an externally provided literal value (hardcoded in GraphQL query) to use as an input.
*
* E.g.
* {
* user(email: "user@example.com")
* }
*
* @param \GraphQL\Language\AST\Node $valueNode
* @return string
* @throws Error
*/
public function parseLiteral($valueNode)
{
// Note: throwing GraphQL\Error\Error vs \UnexpectedValueException to benefit from GraphQL
// error location in query:
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;
}
}
~~~
或使用行间样式定义
~~~
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 */},
]);
~~~