在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称(OpenSource Name):youshido-php/GraphQL开源软件地址(OpenSource Url):https://github.com/youshido-php/GraphQL开源编程语言(OpenSource Language):PHP 100.0%开源软件介绍(OpenSource Introduction):Looking for Maintainers!Unfortunatelly, we cannot longer support this package and are looking for someone to take the ownership. Currently Only PRs with bugfixes and not breaking BC are being merged. It's very sad to acknowledge this, but we hope that someone can take it further with the community. Please, PM @viniychuk if you are interested in taking over. GraphQLThis is a pure PHP realization of the GraphQL protocol based on the working draft of the official GraphQL Specification located on http://facebook.github.io/graphql/. GraphQL is a query language for APIs. It brings a new paradigm to the world of client-server communication and delivers a much more predictable behavior and smallest possible over-the-wire responses to any request. GraphQL advanced in many ways and has fundamental quality improvements:
Table of Contents
Getting StartedYou should be better off starting with some examples and "Star Wars" become a somewhat "Hello world" for the GraphQL implementations. If you're looking just for that – you can get it via this link – Star Wars example. On the other hand, we prepared a step-by-step guide for those who wants to get up to speed bit by bit. InstallationInstall GraphQL package using composer. If you're not familiar with it, you should check out their manual.
Run Alternatively you can run the following commands: mkdir graphql-test && cd graphql-test
composer init -n
composer require youshido/graphql Now you're ready to create your
Create an <?php
namespace Sandbox;
use Youshido\GraphQL\Execution\Processor;
use Youshido\GraphQL\Schema\Schema;
use Youshido\GraphQL\Type\Object\ObjectType;
use Youshido\GraphQL\Type\Scalar\StringType;
require_once 'vendor/autoload.php';
$processor = new Processor(new Schema([
'query' => new ObjectType([
'name' => 'RootQueryType',
'fields' => [
'currentTime' => [
'type' => new StringType(),
'resolve' => function() {
return date('Y-m-d H:ia');
}
]
]
])
]));
$processor->processPayload('{ currentTime }');
echo json_encode($processor->getResponseData()) . "\n"; You can now execute {
data: { currentTime: "2016-05-01 19:27pm" }
} Just like that, you have created a If you're having any troubles – here're some troubleshooting points:
Also, you can always check if script from the examples folder work. Tutorial – Creating Blog SchemaFor our learning example we'll architect a GraphQL Schema for a Blog. You'll probably be using our package along with your favorite framework (we have a Symfony version here), but for the purpose of this tutorial we're keeping it all examples as plain php code.
Our Blog will have
Supposedly server should reply with a relevant json response: {
data: {
latestPost: {
title: "This is a post title",
summary: "This is a post summary"
}
}
} It looks very simple and straight forward, so let's go ahead and write code that can handle this request. Creating Post schemaWe'll take a quick look on different approaches you can use to define your schema. Each of them has it's own pros and cons, inline approach might seem to be easier and faster when object oriented gives you more flexibility and freedom as your project grows. You should definitely use OOP approach every time you can reuse the type you're creating. We're going to create Inline approachYou can create inline-index.php <?php
namespace InlineSchema;
use Youshido\GraphQL\Execution\Processor;
use Youshido\GraphQL\Schema\Schema;
use Youshido\GraphQL\Type\Object\ObjectType;
use Youshido\GraphQL\Type\Scalar\StringType;
// including autoloader
require_once __DIR__ . '/vendor/autoload.php';
// instantiating Processor and setting the schema
$processor = new Processor(new Schema([
'query' => new ObjectType([
// root query by convention has a name RootQueryType
'name' => 'RootQueryType',
'fields' => [
'latestPost' => [
'type' => new ObjectType([ // Post type is being created as ObjectType
'name' => 'Post', // name of our type – "Post"
'fields' => [
'title' => new StringType(), // defining "title" field, type - String
'summary' => new StringType(), // defining "summary" field, type - String
],
]),
'resolve' => function () { // resolver for latestPost field
return [ // for now it returns a static array with data
"title" => "New approach in API has been revealed",
"summary" => "In two words - GraphQL Rocks!",
];
}
]
]
])
]));
// creating payload and running it through processor
$payload = '{ latestPost { title, summary } }';
$processor->processPayload($payload);
// displaying result
echo json_encode($processor->getResponseData()) . "\n"; To check if everything is working – execute inline-index.php: {
data: {
latestPost: {
title: "New approach in API has been revealed",
summary: "In two words - GraphQL Rocks!"
}
}
}
Object oriented approachIt's a common situation when you need to use the same custom type in different places, so we're going to create a separate class for the Create a file <?php
namespace Examples\Blog\Schema;
use Youshido\GraphQL\Type\Object\AbstractObjectType;
use Youshido\GraphQL\Type\Scalar\StringType;
class PostType extends AbstractObjectType // extending abstract Object type
{
public function build($config) // implementing an abstract function where you build your type
{
$config
->addField('title', new StringType()) // defining "title" field of type String
->addField('summary', new StringType()); // defining "summary" field of type String
}
public function getName()
{
return "Post"; // if you don't do getName – className without "Type" will be used
}
} Now let's create the main entry point for this example – <?php
namespace Examples\Blog;
use Examples\Blog\Schema\PostType;
use Youshido\GraphQL\Execution\Processor;
use Youshido\GraphQL\Schema\Schema;
use Youshido\GraphQL\Type\Object\ObjectType;
require_once __DIR__ . '/vendor/autoload.php';
require_once __DIR__ . '/Schema/PostType.php'; // including PostType definition
$rootQueryType = new ObjectType([
'name' => 'RootQueryType',
'fields' => [
'latestPost' => [
'type' => new PostType(),
'resolve' => function ($source, $args, $info)
{
return [
"title" => "New approach in API has been revealed",
"summary" => "In two words - GraphQL Rocks!",
];
}
]
]
]);
$processor = new Processor(new Schema([
'query' => $rootQueryType
]));
$payload = '{ latestPost { title, summary } }';
$processor->processPayload($payload);
echo json_encode($processor->getResponseData()) . "\n"; Ensure everything is working properly by running Next step would be to create a separate class for the latestPostField by extending <?php
namespace Examples\Blog\Schema;
use Youshido\GraphQL\Execution\ResolveInfo;
use Youshido\GraphQL\Field\AbstractField;
class LatestPostField extends AbstractField
{
public function getType()
{
return new PostType();
}
public function resolve($value, array $args, ResolveInfo $info)
{
return [
"title" => "New approach in API has been revealed",
"summary" => "In two words - GraphQL Rocks!",
];
}
} And now we can update our <?php
namespace Examples\Blog;
use Examples\Blog\Schema\LatestPostField;
use Youshido\GraphQL\Execution\Processor;
use Youshido\GraphQL\Schema\Schema;
use Youshido\GraphQL\Type\Object\ObjectType;
require_once __DIR__ . '/vendor/autoload.php';
require_once __DIR__ . '/Schema/PostType.php'; // including PostType definition
require_once __DIR__ . '/Schema/LatestPostField.php';
$rootQueryType = new ObjectType([
'name' => 'RootQueryType',
'fields' => [
new LatestPostField()
]
]);
$processor = new Processor(new Schema([
'query' => $rootQueryType
]));
$payload = '{ latestPost { title, summary } }';
$processor->processPayload($payload);
echo json_encode($processor->getResponseData()) . "\n"; Choosing approach for your projectWe would recommend to stick to object oriented approach for the several reasons (that matter the most for the GraphQL specifically):
With that being said, we use inline approach a lot to explore and bootstrap ideas or to develop simple fields/resolver that are going to be used in one place only. With the inline approach you can be fast and agile in creating mock-data server to test your frontend or mobile client.
We'll continue to work on the Blog Schema to explore all essentials details of developing GraphQL server. Query DocumentsIn GraphQL terms – query document describe a complete request received by GraphQL service. It contains list of Operations and Fragments. Both are fully supported by our PHP library. There are two types of Operations in GraphQL:
You've already seen examples of request
response {
data: { likePost: 2 }
}
Note, that the response type of this mutation is a scalar <?php
namespace Examples\Blog;
use Examples\Blog\Schema\LatestPostField;
use Youshido\GraphQL\Execution\Processor;
use Youshido\GraphQL\Schema\Schema;
use Youshido\GraphQL\Type\NonNullType;
use Youshido\GraphQL\Type\Object\ObjectType;
use Youshido\GraphQL\Type\Scalar\IntType;
require_once __DIR__ . '/vendor/autoload.php';
require_once __DIR__ . '/Schema/PostType.php'; // including PostType definition
require_once __DIR__ . '/Schema/LatestPostField.php';
$rootQueryType = new ObjectType([
'name' => 'RootQueryType',
'fields' => [
new LatestPostField()
]
]);
$rootMutationType = new ObjectType([
'name' => 'RootMutationType',
'fields' => [
// defining likePost mutation field
'likePost' => [
// we specify the output type – simple Int, since it doesn't have a structure
'type' => new IntType(),
// we need a post ID and we set it to be required Int
'args' => [
'id' => new NonNullType(new IntType())
],
// simple resolve function that always returns 2
'resolve' => function () {
return 2;
},
]
]
]);
$processor = new Processor(new Schema([
'query' => $rootQueryType,
'mutation' => $rootMutationType
]));
$payload = 'mutation { likePost(id: 5) }';
$processor->processPayload($payload);
echo json_encode($processor->getResponseData()) . "\n"; Run {"data":{"likePost":2}} Now, let's make our <?php
namespace Examples\Blog\Schema;
use Youshido\GraphQL\Type\Object\AbstractObjectType;
use Youshido\GraphQL\Type\Scalar\IntType;
use Youshido\GraphQL\Type\Scalar\StringType;
class PostType extends AbstractObjectType
{
public function build($config)
{
// you can define fields in a single addFields call instead of chaining multiple addField()
$config->addFields([
'title' => new StringType(),
'summary' => new StringType(),
'likesCount' => new IntType()
]);
}
// Since our class named by a convention, we can remove getName() method
} Secondly, modify public function resolve($value, array $args, ResolveInfo $info)
{
return [
"title" => "New approach in API has been revealed",
"summary" => "In two words - GraphQL Rocks!",
"likesCount" => 2
];
} Lastly, we're going to change <?php
// ...
$rootMutationType = new ObjectType([
'name' => 'RootMutationType',
'fields' => [
'likePost' => [
'type' => new PostType(),
'args' => [
'id' => new NonNullType(new IntType())
],
'resolve' => function () {
return [
'title' => 'New approach in API has been revealed',
'summary' => 'In two words - GraphQL Rocks!',
'likesCount' => 2
];
},
]
]
]);
// ...
$payload = 'mutation { likePost(id: 5) { title, likesCount } }';
//... Execute $rootMutationType = new ObjectType([
'name' => 'RootMutationType',
'fields' => [
'likePost' => [
'type' => new PostType(),
'args' => [
'id' => new NonNullType(new IntType())
],
'resolve' => function ($source, $args, $resolveInfo) {
return [
'title' => 'Title for the post #' . $args['id'], // we can be sure that $args['id'] is always set
'summary' => 'In two words - GraphQL Rocks!',
'likesCount' => 2
];
},
]
]
]); Now you have a basic understanding of how queries and mutations are structured and ready to move on to the details of the GraphQL Type System and PHP-specific features of the GraphQL server architecture. Type SystemType is an atom of definition in GraphQL Schema. Every field, object, or argument has a type. GraphQL is a strongly typed language.
There are Scalar TypesList of GraphQL Scalar types:
|
请发表评论