在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称(OpenSource Name):digiaonline/graphql-php开源软件地址(OpenSource Url):https://github.com/digiaonline/graphql-php开源编程语言(OpenSource Language):PHP 100.0%开源软件介绍(OpenSource Introduction):GraphQLThis is a PHP implementation of the GraphQL specification based on the JavaScript reference implementation. Related projectsRequirements
Table of contentsInstallationRun the following command to install the package through Composer: composer require digiaonline/graphql ExampleHere is a simple example that demonstrates how to build an executable schema from a GraphQL schema file that contains the Schema Definition Language (SDL) for a Star Wars-themed schema (for the schema definition itself, see below). In this example we use that SDL to build an executable schema and use it to query for the name of the hero. The result of that query is an associative array with a structure that resembles the query we ran. use Digia\GraphQL\Language\FileSourceBuilder;
use function Digia\GraphQL\buildSchema;
use function Digia\GraphQL\graphql;
$sourceBuilder = new FileSourceBuilder(__DIR__ . '/star-wars.graphqls');
$schema = buildSchema($sourceBuilder->build(), [
'Query' => [
'hero' => function ($rootValue, $arguments) {
return getHero($arguments['episode'] ?? null);
},
],
]);
$result = graphql($schema, '
query HeroNameQuery {
hero {
name
}
}');
\print_r($result); The script above produces the following output: Array
(
[data] => Array
(
[hero] => Array
(
[name] => "R2-D2"
)
)
) The GraphQL schema file used in this example contains the following: schema {
query: Query
}
type Query {
hero(episode: Episode): Character
human(id: String!): Human
droid(id: String!): Droid
}
interface Character {
id: String!
name: String
friends: [Character]
appearsIn: [Episode]
}
type Human implements Character {
id: String!
name: String
friends: [Character]
appearsIn: [Episode]
homePlanet: String
}
type Droid implements Character {
id: String!
name: String
friends: [Character]
appearsIn: [Episode]
primaryFunction: String
}
enum Episode { NEWHOPE, EMPIRE, JEDI } Creating a schemaIn order to execute queries against your GraphQL API, you first need to define the structure of your API. This is done
by creating a schema. There are two ways to do this, you can either do it using SDL or you can do it programmatically.
However, we strongly encourage you to use SDL, because it is easier to work with. To make an executable schema from
SDL you need to call the The
To create the Resolver registryThe resolver registry is essentially a flat map with the type names as its keys and their corresponding resolver instances as its values. For smaller projects you can use an associative array and lambda functions to define your resolver registry. However, in larger projects we suggest that you implement your own resolvers instead. You can read more about resolvers under the Resolvers section. Associative array example: $schema = buildSchema($source, [
'Query' => [
'hero' => function ($rootValue, $arguments) {
return getHero($arguments['episode'] ?? null);
},
],
]); Resolver class example: $schema = buildSchema($source, [
'Query' => [
'hero' => new HeroResolver(),
],
]); Resolver middlewareIf you find yourself writing the same logic in multiple resolvers you should consider using middleware. Resolver middleware allow you to efficiently manage functionality across multiple resolvers. Before middleware example: $resolverRegistry = new ResolverRegristry([
'Query' => [
'hero' => function ($rootValue, $arguments) {
return getHero($arguments['episode'] ?? null);
},
],
], [
'middleware' => [new BeforeMiddleware()],
]);
$schema = buildSchema($source, $resolverRegistry); class BeforeMiddleware implements ResolverMiddlewareInterface
{
public function resolve(callable $resolveCallback, $rootValue, array $arguments, $context, ResolveInfo $info) {
$newRootValue = $this->doSomethingBefore();
return $resolveCallback($newRootValue, $arguments, $context, $info);
}
} After middleware example: $resolverRegistry = new ResolverRegristry([
'Query' => [
'hero' => function ($rootValue, $arguments) {
return getHero($arguments['episode'] ?? null);
},
],
], [
'middleware' => [new AfterMiddleware()],
]);
$schema = buildSchema($source, $resolverRegistry); class AfterMiddleware implements ResolverMiddlewareInterface
{
public function resolve(callable $resolveCallback, $rootValue, array $arguments, $context, ResolveInfo $info) {
$result = $resolveCallback($rootValue, $arguments, $context, $info);
$this->doSomethingAfter();
return $result;
}
} Resolver middleware can be useful for a number of things; such as logging, input sanitization, performance measurement, authorization and caching. If you want to learn more about schemas you can refer to the specification. ExecutionQueriesTo execute a query against your schema you need to call the $query = '
query HeroNameQuery {
hero {
name
}
}';
$result = graphql($schema, $query); If you want to learn more about queries you can refer to the specification. ResolversEach type in a schema has a resolver associated with it that allows for resolving the actual value. However, most
types do not need a custom resolver, because they can be resolved using the default resolver. Usually these resolvers
are lambda functions, but you can also define your own resolvers by extending A resolver function receives four arguments:
Lambda function example: function ($rootValue, array $arguments, $context, ResolveInfo $info): string {
return [
'type' => 'Human',
'id' => '1000',
'name' => 'Luke Skywalker',
'friends' => ['1002', '1003', '2000', '2001'],
'appearsIn' => ['NEWHOPE', 'EMPIRE', 'JEDI'],
'homePlanet' => 'Tatooine',
];
} Type resolver example: class HumanResolver extends AbstractTypeResolver
{
public function resolveName($rootValue, array $arguments, $context, ResolveInfo $info): string
{
return $rootValue['name'];
}
} Field resolver example: class NameResolver extends AbstractFieldResolver
{
public function resolve($rootValue, array $arguments, $context, ResolveInfo $info): string
{
return $rootValue['name'];
}
} The N+1 problemThe resolver function can return a value, a promise or an array of promises. This resolver function below illustrates how to use promise to solve the N+1 problem, the full example can be found in this test case. $movieType = newObjectType([
'fields' => [
'title' => ['type' => stringType()],
'director' => [
'type' => $directorType,
'resolve' => function ($movie, $args) {
DirectorBuffer::add($movie['directorId']);
return new Promise(function (callable $resolve, callable $reject) use ($movie) {
DirectorBuffer::loadBuffered();
$resolve(DirectorBuffer::get($movie['directorId']));
});
}
]
]
]); VariablesYou can pass in variables when executing a query by passing them to the $query = '
query HeroNameQuery($id: ID!) {
hero(id: $id) {
name
}
}';
$variables = ['id' => '1000'];
$result = graphql($schema, $query, null, null, $variables); ContextIn case you need to pass in some important contextual information to your queries you can use the $contextValues = [
'currentlyLoggedInUser' => $currentlyLoggedInUser,
];
$result = graphql($schema, $query, null, $contextValues, $variables); ScalarsThe leaf nodes in a schema are called scalars and each scalar resolves to some concrete data. The built-in, or specified scalars in GraphQL are the following:
Custom scalarsIn addition to the specified scalars you can also define your own custom scalars and let your schema know about
them by passing them to the Custom Date scalar type example: $dateType = newScalarType([
'name' => 'Date',
'serialize' => function ($value) {
if ($value instanceof DateTime) {
return $value->format('Y-m-d');
}
return null;
},
'parseValue' => function ($value) {
if (\is_string($value)){
return new DateTime($value);
}
return null;
},
'parseLiteral' => function ($node) {
if ($node instanceof StringValueNode) {
return new DateTime($node->getValue());
}
return null;
},
]);
$schema = buildSchema($source, [
'Query' => QueryResolver::class,
[
'types' => [$dateType],
],
]); Every scalar has to be coerced, which is done by three different functions. The Advanced usageIf you are looking for something that isn't yet covered by this documentation your best bet is to take a look at the tests in this project. You'll be surprised how many examples you'll find there. IntegrationLaravelHere is an example that demonstrates how you can use this library in your Laravel project. You need an application service to expose this library to your application, a service provider to register that service, a controller and a route for handling the GraphQL POST requests. app/GraphQL/GraphQLService.php class GraphQLService
{
private $schema;
public function __construct(Schema $schema)
{
$this->schema = $schema;
}
public function executeQuery(string $query, array $variables, ?string $operationName): array
{
return graphql($this->schema, $query, null, null, $variables, $operationName);
}
} app/GraphQL/GraphQLServiceProvider.php class GraphQLServiceProvider
{
public function register()
{
$this->app->singleton(GraphQLService::class, function () {
$schemaDef = \file_get_contents(__DIR__ . '/schema.graphqls');
$executableSchema = buildSchema($schemaDef, [
'Query' => QueryResolver::class,
]);
return new GraphQLService($executableSchema);
});
}
} app/GraphQL/GraphQLController.php class GraphQLController extends Controller
{
private $graphqlService;
public function __construct(GraphQLService $graphqlService)
{
$this->graphqlService = $graphqlService;
}
public function handle(Request $request): JsonResponse
{
$query = $request->get('query');
$variables = $request->get('variables') ?? [];
$operationName = $request->get('operationName');
$result = $this->graphqlService->executeQuery($query, $variables, $operationName);
return response()->json($result);
}
} routes/api.php Route::post('/graphql', 'app\GraphQL\GraphQLController@handle'); ContributorsThis project exists thanks to all the people who contribute. Contribute. BackersThank you to all our backers! |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论