From f9740c5f2c6c6dbc3861c0cf7d840c7ebc14de02 Mon Sep 17 00:00:00 2001 From: vladar Date: Sun, 23 Oct 2016 22:16:32 +0700 Subject: [PATCH] Work in progress on better docs --- docs/getting-started.md | 182 +++++++++++++++++++++++++++++++++++++ docs/index.md | 81 +++++++++++++++++ docs/overview.md | 94 +++++++++++++++++++ docs/type-system.md | 1 + examples/01-blog/README.md | 3 +- mkdocs.yml | 7 ++ 6 files changed, 367 insertions(+), 1 deletion(-) create mode 100644 docs/getting-started.md create mode 100644 docs/index.md create mode 100644 docs/overview.md create mode 100644 docs/type-system.md create mode 100644 mkdocs.yml diff --git a/docs/getting-started.md b/docs/getting-started.md new file mode 100644 index 0000000..fa7a5d6 --- /dev/null +++ b/docs/getting-started.md @@ -0,0 +1,182 @@ +# Installation + +Using [composer](https://getcomposer.org/doc/00-intro.md): +add `composer.json` file to your project root folder with following contents: +``` +{ + "require": { + "webonyx/graphql-php": "^0.8" + } +} +``` +and run `composer install`. + +If you already have composer.json file - simply run: `composer require webonyx/graphql-php` + +If you are upgrading, see [upgrade instructions](https://github.com/webonyx/graphql-php/blob/master/UPGRADE.md) + +# Install Tools (optional) +While it is possible to communicate with GraphQL API using regular HTTP tools it is way +more convenient for humans to use [GraphiQL](https://github.com/graphql/graphiql) - an in-browser +ide for exploring GraphQL APIs. + +It provides syntax-highlighting, auto-completion and auto-generated documentation for +GraphQL API. + +The easiest way to use it is to install one of the existing Google Chrome extensions: + + - [ChromeiQL](https://chrome.google.com/webstore/detail/chromeiql/fkkiamalmpiidkljmicmjfbieiclmeij) + - [GraphiQL Feen](https://chrome.google.com/webstore/detail/graphiql-feen/mcbfdonlkfpbfdpimkjilhdneikhfklp) + +Alternatively you can follow instructions on [GraphiQL](https://github.com/graphql/graphiql) +page and install it locally. + + +# Hello World +Let's create type system that will be capable to process following simple query: +``` +query { + echo(message: "Hello World") +} +``` + +To do so we need an object type with field `echo`: + +```php + 'Query', + 'fields' => [ + 'echo' => [ + 'type' => Type::string(), + 'args' => [ + 'message' => Type::nonNull(Type::string()), + ], + 'resolve' => function ($root, $args) { + return $root['prefix'] . $args['message']; + } + ], + ], +]); +``` + +Same could be written as separate class: + +```php + [ + 'echo' => [ + 'type' => Type::string(), + 'args' => [ + 'message' => Type::nonNull(Type::string()), + ], + 'resolve' => function ($root, $args) { + return $root['prefix'] . $args['message']; + } + ], + ], + ]; + parent::__construct($config); + } +} +``` + +Or for those who prefer composition over inheritance: +```php +definition ?: ($this->definition = new \GraphQL\Type\Definition\ObjectType([ + 'name' => 'Query', + 'fields' => [ + 'echo' => [ + 'type' => Type::string(), + 'args' => [ + 'message' => Type::nonNull(Type::string()), + ], + 'resolve' => function ($root, $args) { + return $root['prefix'] . $args['message']; + } + ], + ], + ])); + } +} +``` + +The interesting piece here is `resolve` option of field definition. It is responsible for retuning +value for our field. **Scalar** values will be directly included in response while **complex object** +values will be passed down to nested field resolvers (not in this example though). + +Field resolvers is the main mechanism of **graphql-php** to bind type system with your +underlying data source. + +Now when our type is ready, let's create GraphQL endpoint for it `graphql.php`: + +```php + $queryType, // or new MyApp\Type\QueryType() +]); + +$rawInput = file_get_contents('php://input'); + +try { + $rootValue = ['prefix' => 'You said: ']; + $result = GraphQL::execute($schema, $rawInput, $rootValue); +} catch (\Exception $e) { + $result = [ + 'error' => [ + 'message' => $e->getMessage() + ] + ]; +} +header('Content-Type: application/json; charset=UTF-8'); +echo json_encode($result); +``` + +Our example is ready. Try it by running: +```sh +php -S localhost:8000 graphql.php +curl http://localhost:8000 -d "query { echo(message: \"Hello World\") }" +``` + +Or grab the full [source code](https://github.com/webonyx/graphql-php/blob/master/examples/00-hello-world). +Obviously hello world only scratches the surface of what is possible. +So check out next example, which is closer to real-world apps. + +Or just keep reading about [type system](types/) definitions. + +# Blog example +It is often easier to start with full-featured example and then get back to documentation +for your own work. + +Check out [Blog example of GraphQL API](https://github.com/webonyx/graphql-php/tree/master/examples/01-blog). +It is quite close to real-world GraphQL hierarchies. Follow instructions and try it yourself in ~10 minutes. diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..1faaef5 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,81 @@ +# About GraphQL + +GraphQL is a modern way to build HTTP APIs consumed by web and mobile clients. +It is intended to be a replacement for REST and SOAP APIs (even for **existing applications**). + +GraphQL itself is a [specification](https://github.com/facebook/graphql) designed by Facebook +engineers. Various implementations of this specification were written +[for different languages and environments](http://graphql.org/code/). + +Great overview of GraphQL features and benefits is presented on [official website](http://graphql.org/). +All of them equally apply to this PHP implementation. + + +# About graphql-php + +**graphql-php** is an implementation of GraphQL specification in PHP (5.4+, 7.0+). +It is based on [JavaScript implementation](https://github.com/graphql/graphql-js) +published by Facebook as a reference for others. + +This library is a thin wrapper around your existing data layer and business logic. +It doesn't dictate how these layers are implemented or which storage engines +are used. Instead it provides tools for creating rich API for your existing app. + +These tools include: + + - Primitives to express your app as a Type System + - Tools for validation and introspection of this Type System + - Tools for parsing, validating and executing GraphQL queries against this Type System + - Rich error reporting + +## Usage Example +```php +use GraphQL\GraphQL; +use GraphQL\Schema; + +$query = ' +{ + hero { + id + name + friends { + name + } + } +} +'; + +$schema = new Schema([ + // ... + // Type System definition for your app goes here + // ... +]); + +$result = GraphQL::execute($schema, $query); +``` + +Result returned: +```php +[ + 'hero' => [ + 'id' => '2001', + 'name' => 'R2-D2', + 'friends' => [ + ['name' => 'Luke Skywalker'], + ['name' => 'Han Solo'], + ['name' => 'Leia Organa'], + ] + ] +] +``` + +Also check out full [Type System](https://github.com/webonyx/graphql-php/blob/master/tests/StarWarsSchema.php) +and [data source](https://github.com/webonyx/graphql-php/blob/master/tests/StarWarsData.php) +of this example. + +## Current Status +Current version supports all features described by GraphQL specification +(including April 2016 add-ons) as well as some experimental features like +Schema Language parser. + +Ready for real-world usage. \ No newline at end of file diff --git a/docs/overview.md b/docs/overview.md new file mode 100644 index 0000000..284b740 --- /dev/null +++ b/docs/overview.md @@ -0,0 +1,94 @@ +# Concepts +GraphQL is data-centric. On the very top level it is built around three major concepts: +**Schema**, **Query** and **Mutation**. + +You are expected to expresses your application as **Schema** (aka Type System) and expose it +with single HTTP endpoint. Application clients (e.g. web or mobile clients) send **Queries** +to this endpoint to request structured data and **Mutations** to perform changes. + +## Queries +Queries are expressed in simple language that resembles JSON: + +```graphql +{ + hero { + name + friends { + name + } + } +} +``` + +It was designed to mirror the structure of expected response: +```json +{ + "hero": { + "name": "R2-D2", + "friends": [ + {"name": "Luke Skywalker"}, + {"name": "Han Solo"}, + {"name": "Leia Organa"} + ] + } +} +``` +**graphql-php** runtime parses Queries, makes sure that they are valid for given Type System +and executes using data resolving tools provided by you as a part of integration. + +## Mutations +Mutations use advanced features of the very same query language (like arguments and variables) +and have only semantic difference from Queries: +```graphql +mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) { + createReview(episode: $ep, review: $review) { + stars + commentary + } +} +``` +Variables `$ep` and `$review` are sent alongside with mutation. Full HTTP request might look like this: +```json +// POST /graphql-endpoint +// Content-Type: application/javascript +// +{ + "query": "mutation CreateReviewForEpisode...", + "variables": { + "ep": "JEDI", + "review": { + "stars": 5, + "commentary": "This is a great movie!" + } + } +} +``` +As you see variables may include complex objects and they will be correctly validated by +**graphql-php** runtime. + +Another nice feature of GraphQL mutations is that they also hold the query for data to be +returned after mutation. In our example mutation will return: +``` +{ + "createReview": { + "stars": 5, + "commentary": "This is a great movie!" + } +} +``` + +# Type System +Type system is a heart of GraphQL integration. That's where **graphql-php** comes into play. + +It provides following tools and primitives to describe your App as hierarchy of types: + + * Primitives to work with **objects** and **interfaces** + * Primitives for defining **enumerations** and **unions** + * Primitives for defining custom **scalar types** + * Built-in scalar types: `ID`, `String`, `Int`, `Float`, `Boolean` + * Built-in type modifiers: `ListOf` and `NonNull` + +# Further Reading +To get deeper understanding of GraphQL concepts - [read the docs on official website](http://graphql.org/learn/) + +To get started with your own app - continue to next section ["Getting Started"](getting-started/) \ No newline at end of file diff --git a/docs/type-system.md b/docs/type-system.md new file mode 100644 index 0000000..7fb92d6 --- /dev/null +++ b/docs/type-system.md @@ -0,0 +1 @@ +TODOC diff --git a/examples/01-blog/README.md b/examples/01-blog/README.md index 18142ad..87e2229 100644 --- a/examples/01-blog/README.md +++ b/examples/01-blog/README.md @@ -1,5 +1,6 @@ ## Blog Example -Simple yet full-featured example of GraphQL API. Models simple blog with Stories and Users. +Simple yet full-featured example of GraphQL API. Models blogging platform with Stories, Users +and hierarchical comments. ### Run locally ``` diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..f3c9aa5 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,7 @@ +site_name: graphql-php +pages: +- About: index.md +- Overview: overview.md +- Getting Started: getting-started.md +- Type System: type-system.md +theme: readthedocs