[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 */},
]);
~~~