flownative / graphql
Flownative GraphQL
v2.0.0
2024-01-18 08:52 UTC
Requires
- php: 8.1.* || 8.2.* || 8.3.*
- ext-json: *
- neos/flow: ^8.0 || ^9.0
- webonyx/graphql-php: ^14.0
Requires (Dev)
- roave/security-advisories: dev-latest
README
Neos Flow 的 GraphQL 库
这个 Flow 包为 webonyx/graphql-php 包提供了一个最小的包装。这个库不是提供大量功能或自动代码分析,它只解决基本必要的任务,不会干扰您与原始 GraphQL 库之间的实现。
示例
以下是一个 Hello-World 示例,它还包含了对 Api 类中提供的进一步查询和突变自动解析的支持
Classes/GraphQL/Api.php
:
<?php declare(strict_types=1); namespace Flownative\Example\GraphQL; final class Api { public function ping($_, array $arguments): array { return [ 'pong' => time() ]; } }
Resources/Private/GraphQL/schema.graphql
:
type Query { ping: String }
Classes/GraphQL/Endpoint.php
:
<?php declare(strict_types=1); namespace Flownative\Example\GraphQL; use Flownative\GraphQL\EndpointInterface; use GraphQL\Executor\ExecutionResult; use GraphQL\GraphQL; use GraphQL\Type\Schema; use Neos\Eel\FlowQuery\OperationResolver; final class Endpoint implements EndpointInterface { public function __construct(readonly private Api $api) { } public static function getPath(): string { return '/api/graphql'; } public function getSchemaUri(): string { return 'resource://Flownative.Example/Private/GraphQL/schema.graphql'; } public function __invoke($objectValue, $args, $_, ResolveInfo $resolveInfo): mixed { $fieldName = $resolveInfo->fieldName; if ($objectValue === null && method_exists($this->api, $fieldName)) { $result = $this->api->$fieldName($objectValue, $args); } elseif (is_array($objectValue)) { $result = $objectValue[$fieldName] ?? null; } elseif ($objectValue !== null && method_exists($objectValue, $fieldName)) { $result = $objectValue->$fieldName(); } elseif ($objectValue !== null && method_exists($objectValue, 'get' . ucfirst($fieldName))) { $methodName = 'get' . ucfirst($fieldName); $result = $objectValue->$methodName($objectValue); } elseif ($objectValue !== null && method_exists($objectValue, $fieldName . 'Query')) { $methodName = $fieldName . 'Query'; $query = $objectValue->$methodName(); if (!$query instanceof Query) { throw new RuntimeException(sprintf('Failed to resolve field "%s": %s->%s() returned %s, but expected %s', $fieldName, get_class($objectValue), $methodName, get_debug_type($query), Query::class), 1648713012); } if (!method_exists($this->api, $query->queryName)) { throw new RuntimeException(sprintf('Failed to resolve field "%s": %s->%s() returned %s, but %s->%s() does not exist', $fieldName, get_class($objectValue), $methodName, $query->queryName, get_class($this->api), $query->queryName), 1648713106); } $result = $this->api->{$query->queryName}(null, $query->arguments); } elseif ($objectValue !== null && property_exists($objectValue, $fieldName)) { $result = $objectValue->{$fieldName}; } else { throw new RuntimeException(sprintf('Failed to resolve field "%s" on subject %s', $fieldName, get_debug_type($objectValue)), 1613477425); } if ($result instanceof DateTimeInterface) { $result = $result->format(DATE_ISO8601); } return $result; } public function getTypeConfigDecorator(): ?callable { return static function ($typeConfig) { $typeConfig['resolveType'] = static function ($object) { if (method_exists($object, 'isOfType')) { return $object->isOfType(); } $classname = is_object($object) ? get_class($object) : ''; if ($position = strrpos($classname, '\\')) { return substr($classname, $position + 1); } return $position; }; return $typeConfig; }; } }
致谢和支持
这个库是由 Robert Lemke / Flownative 开发的。欢迎在 GitHub 项目中提出新功能、报告错误或提供错误修复。