SlideShare uma empresa Scribd logo
1 de 101
Baixar para ler offline
GraphQL in the
PHP ecosystem
What is GraphQL?
GraphQL ?
• GraphQL is a protocol
GraphQL ?
• GraphQL is a protocol
• It is not:
• A fancy new database
• A database query language like SQL
GraphQL ?
• GraphQL is a protocol
• GraphQL is a challenger to those other
protocols:
• REST
• Web-services (SOAP/WSDL based)
A bit of history
Web-services
(~1999)
• Strongly typed
• Self-describing (WSDL)
• XML-based
A bit of history
Web-services
(~1999)
• Strongly typed
• Self-describing (WSDL)
• XML-based
A bit of history
Web-services
(~1999)
REST
(~2005)
• Strongly typed
• Self-describing (WSDL)
• XML-based
• Weakly typed
• Non self-describing
(still OpenAPI for doc)
• Mostly JSON based
A bit of history
Web-services
(~1999)
REST
(~2005)
• Strongly typed
• Self-describing (WSDL)
• XML-based
• Weakly typed
• Non self-describing
(still OpenAPI for doc)
• Mostly JSON based
A bit of history
Web-services
(~1999)
REST
(~2005)
GraphQL
(2015)
• Strongly typed
• Self-describing (WSDL)
• XML-based
• Weakly typed
• Non self-describing
(still OpenAPI for doc)
• Mostly JSON based
• Strongly typed
• Self-describing
• JSON based
• + Client driven queries
GraphQL ?
It is developed by Facebook and was first used in
the Facebook API.
Facebook also provides:
• A JS client (to query a GraphQL server)
• A NodeJS server library
Tons of server implementations exist.
Why GraphQL?
What problem does GraphQL solves?
• Your API often changes
• You develop a new feature but your API
does not exactly respond to your needs.
What problem does GraphQL solves?
• For instance: you are developing a
marketplace. You need a page to display a
product, along some company information.
/api/product/42 /api/company/35
REST
What problem does GraphQL solves?
• Alternative, still REST
• But what if some pages don’t need the
company details?
/api/product/42
REST
What problem does GraphQL solves?
• Yet another alternative, still REST
/api/product/42?with_company=true
REST
Flags hell 😨! Probably one
flag per consumer of the API
What problem does GraphQL solves?
• GraphQL to the rescue!
• GraphQL is a paradigm shift.
• The client asks for the list of fields it wants.
GET /graphql?query= Single endpoint
The name of the query is « products »
List of fields requested
What problem does GraphQL solves?
• GraphQL to the rescue!
• Another request of the same query with a
different set of fields
No need to change the code on the
server-side! All this data in one API call!
GET /graphql?query=
GraphQL types
Types
GraphQL is strongly typed.
It comes with a « schema
language » but this is rarely
used while developing.
It is however useful to
understand what is going on.
≠
Schema language
product(id: 42) {
name
company {
name
logo
country {
name
}
}
}
Query language
Types
Note:
• [Product] ➔ an array of
Products
• String ➔ a string (or null)
• String! ➔ a non-nullable string
Hence:
• [Product!]! ➔ An array (non-
nullable) of products that are also
non-nullable.
Types
Some « scalar » types:
• ID: a unique identifier (~=String)
• String
• Int
• Float
• Boolean
No support for « Date » in the
standard (but custom types are
supported by some implementations)
Types
Support for “arguments”:
• product(id: ID!)
➔ the product query
requires an “id” field of
type “ID” to be passed.
Types
Bonus:
• Support for interfaces
• Support for Union types
• Support for “InputType” (to pass complex
objects in queries)
Mutations
So far, we mostly talked about queries (because
this is what is fun in GraphQL).
GraphQL can also do mutations (to change the
state of the DB)
Out of
GraphQL
scope
Transport is out of scope
• You usually do GraphQL over HTTP/HTTPS
• But nothing prevents you from using GraphQL
over UDP, or mail, …
Transport is out of scope
• You usually do GraphQL over HTTP/HTTPS
• But nothing prevents you from using GraphQL
over UDP, or mail, or homing pigeon whatever!
Authentication is out of scope
• GraphQL does not deal with authentication.
• You are free to deal with it in any way you want:
• Session-based
• or using Oauth2
• or using a token…
• Authentication can happen using a REST API,
or even using a GraphQL mutation!
Pagination is out of scope
• GraphQL does not deal with pagination in the
standard.
• You are free to add limit/offset parameters to
your queries
• “Relay” is providing some conventions to deal
with pagination (more on that later)
The GraphQL
ecosystem
Ecosystem (a small part of…)
Browser
GraphQL
Client
Server
GraphQL
Middleware DB
RelayJS
Apollo
ReactJS
Express-
graphql
NodeJS
Webonyx/
GraphQL-
PHP
PHP
GraphiQL
(for dev!)
Zoom on GraphQL in PHP
Core library Wrapper library
• Low level
• Parsing
• Service requests
• Powerful
• Feature complete
• Hard to use (poor DX)
• High level
• Opiniated
• Easy to use
Zoom on GraphQL in PHP
Core library Wrapper library
• webonyx/graphql-php
• De-facto standard in PHP
• Youshido/GraphQL
•  Abandonned 
Zoom on GraphQL in PHP
Core library Wrapper library
• API Platform (Symfony)
• Overblog GraphQL Bundle (Symfony)
• Lighthouse (Laravel)
• … and now GraphQLite
Zoom of Webonyx/GraphQL-PHP
Define a type
Zoom of Webonyx/GraphQL-PHP
Define a query
Zoom of Webonyx/GraphQL-PHP
Actually resolving a query
Costs VS benefits
Costs Gains
Strict types
Self-described
Client
driven
Work
You need a wrapper library
Costs Gains
Strict types
Self-described
Client
driven
Work
GraphQL
library
Strategies
Schema-first Code-first
• Design the GraphQL schema first
• Find a way to link it to your code
• Design your domain code
• Generate the schema from the code
Strategies
Schema-first Code-first
• Overblog GraphQL Bundle
• Lighthouse
• API Platform
• GraphQLite
Strategies
Schema-first Code-first
• Overblog GraphQL Bundle
• Lighthouse
• API Platform
• GraphQLite
Lighthouse
Strategies
Schema-first Code-first
• Overblog GraphQL Bundle
• Lighthouse
• API Platform
• GraphQLite
API Platform
GraphQLite
The idea
Let’s imagine we want to do a simple “echo”
query in PHP.
The idea
Let’s imagine we want to do a simple “echo”
query in PHP.
The idea
Using webonyx/GraphQL-PHP
type Query {
echo(message: String!): String
}
The idea
The same “echo” method in pure PHP
function echoMsg(string $message): string
{
return $message;
}
function echoMsg(string $message): string
{
return $message;
}
The idea
The same “echo” method in pure PHP
Query name
Arguments
Return type
Resolver
The idea
The same “echo” method in pure PHP
/**
* @Query
*/
function echoMsg(string $message): string
{
return $message;
}
The idea
• PHP is already typed.
• We should be able to get types from PHP and
convert them to a GraphQL schema
PHP
objects
GraphQL
objects
GraphQLite
Works well with Doctrine
Bonus:
• It plays nice with Doctrine ORM too
• (we also have native bindings with TDBM, our
in-house ORM)
DB
model
PHP
objects
GraphQL
objects
Doctrine GraphQLite
GraphQLite
GraphQLite is:
• Framework agnostic
• Symfony bundle and Laravel package
available
• PHP 7.2+
• Based on Webonyx/GraphQL-PHP
Demo time!
Our playground
First query
namespace AppController;
use AppEntityPost;
use AppRepositoryPostRepository;
use TheCodingMachineGraphQLiteAnnotationsQuery;
class PostController
{
/**
* @var PostRepository
*/
private $postRepository;
public function __construct(PostRepository $postRepository)
{
$this->postRepository = $postRepository;
}
/**
* @Query()
*/
public function getPosts(?string $search): array
{
return $this->postRepository->findAllFilterBySearch($search);
}
}
First query
First query
namespace AppController;
use AppEntityPost;
use AppRepositoryPostRepository;
use TheCodingMachineGraphQLiteAnnotationsQuery;
class PostController
{
/**
* @var PostRepository
*/
private $postRepository;
public function __construct(PostRepository $postRepository)
{
$this->postRepository = $postRepository;
}
/**
* @Query()
* @return Post[]
*/
public function getPosts(?string $search): array
{
return $this->postRepository->findAllFilterBySearch($search);
}
}
First query
<?php
namespace AppEntity;
use TheCodingMachineGraphQLiteAnnotationsField;
use TheCodingMachineGraphQLiteAnnotationsType;
/**
* @Type()
*/
class Post
{
//…
/**
* @Field(outputType="ID")
*/
public function getId(): int
{
return $this->id;
}
/**
* @Field()
*/
public function getMessage(): string
{
return $this->message;
}
/**
* @Field()
*/
public function getCreated(): DateTimeImmutable
{
return $this->created;
}
}
First query
First query
<?php
namespace AppEntity;
use TheCodingMachineGraphQLiteAnnotationsField;
use TheCodingMachineGraphQLiteAnnotationsType;
/**
* @Type()
*/
class Post
{
// …
/**
* @Field()
*/
public function getAuthor(): User
{
return $this->author;
}
}
First query
First query
<?php
namespace AppEntity;
use TheCodingMachineGraphQLiteAnnotationsField;
use TheCodingMachineGraphQLiteAnnotationsType;
/**
* @Type()
*/
class User implements UserInterface
{
// …
/**
* @Field(outputType="ID!")
*/
public function getId(): int
{
return $this->id;
}
/**
* @Field()
*/
public function getLogin(): string
{
return $this->login;
}
// …
First query
Improving our
sample
Improving our sample
What if I want to get the list of comments from my
“post” type?
(Assuming I have no “getComments” method in
the Post class)
Improving our sample
Say hello to “type extension”!
You can add fields in an existing type, using the
“@ExtendType” annotation.
Improving our sample
namespace AppTypes;
use AppEntityComment;
use AppRepositoryCommentRepository;
use TheCodingMachineGraphQLiteAnnotationsExtendType;
use AppEntityPost;
use TheCodingMachineGraphQLiteAnnotationsField;
/**
* @ExtendType(class=Post::class)
*/
class PostType
{
/**
* @var CommentRepository
*/
private $commentRepository;
public function __construct(CommentRepository $commentRepository)
{
$this->commentRepository = $commentRepository;
}
/**
* @Field()
* @return Comment[]
*/
public function getComments(Post $post): array
{
return $this->commentRepository->findByPost($post);
}
}
Improving our sample
namespace AppTypes;
use AppEntityComment;
use AppRepositoryCommentRepository;
use TheCodingMachineGraphQLiteAnnotationsExtendType;
use AppEntityPost;
use TheCodingMachineGraphQLiteAnnotationsField;
/**
* @ExtendType(class=Post::class)
*/
class PostType
{
/**
* @var CommentRepository
*/
private $commentRepository;
public function __construct(CommentRepository $commentRepository)
{
$this->commentRepository = $commentRepository;
}
/**
* @Field()
* @return Comment[]
*/
public function getComments(Post $post): array
{
return $this->commentRepository->findByPost($post);
}
}
It is a service!
Improving our samplenamespace AppTypes;
use AppEntityComment;
use AppRepositoryCommentRepository;
use TheCodingMachineGraphQLiteAnnotationsExtendType;
use AppEntityPost;
use TheCodingMachineGraphQLiteAnnotationsField;
/**
* @ExtendType(class=Post::class)
*/
class PostType
{
/**
* @var CommentRepository
*/
private $commentRepository;
public function __construct(CommentRepository $commentRepository)
{
$this->commentRepository = $commentRepository;
}
/**
* @Field()
* @return Comment[]
*/
public function getComments(Post $post): array
{
return $this->commentRepository->findByPost($post);
}
}
Current object
is passed as first
parameter
Improving our sample
Improving our sample
Even better: fields can have their own arguments.
For instance, you may want to fetch a paginated
list of comments.
Improving our sample
namespace AppTypes;
use AppEntityComment;
use AppRepositoryCommentRepository;
use TheCodingMachineGraphQLiteAnnotationsExtendType;
use AppEntityPost;
use TheCodingMachineGraphQLiteAnnotationsField;
/**
* @ExtendType(class=Post::class)
*/
class PostType
{
// …
/**
* @Field()
* @return Comment[]
*/
public function getComments(Post $post, int $limit = 20, int $offset = 0): array
{
return $this->commentRepository->findByPost($post)
->setMaxResults($limit)
->setFirstResult($offset)
->getResult();
}
}
From the 2nd parameter,
arguments are added to the field
Improving our sample
Native pagination?
Yes please!
Native pagination
Actually, you don’t even have to bother adding
pagination as GraphQLite integrates natively with
Porpaginas.
(Porpaginas integrates with Doctrine and TDBM)
Native pagination
use PorpaginasDoctrineORMORMQueryResult;
/**
* @ExtendType(class=Post::class)
*/
class PostType
{
// …
/**
* @Field()
* @return Comment[]
*/
public function getComments(Post $post): ORMQueryResult
{
return new ORMQueryResult($this->commentRepository->findByPost($post));
}
}
Needed for Doctrine ORM.
Not even necessary for TDBM 5 ResultIterator’s that can be returned directly.
Authentication and
authorization
Authentication and authorization
@Logged and @Right annotations can be used
with @Field too!
More features?
More features!
TDBM integration
Inheritance / interfaces
More features!
Everything is clearly documented at:
Thanks @JUN for the help
https://graphqlite.thecodingmachine.io
What’s next?
• Release of GraphQLite 4 in June
• Deferred type support
• Injection of services in method
parameters
• Improved performances
• Custom scalar types
• Enum’s support
• …
So… GraphQL
everywhere?
GraphQL everywhere?
• GraphQLite makes it trivial to write a GraphQL
API. It is now easier to start a GraphQL API
than a REST API! o/
• GraphQL makes a lot of sense for most of our
projects because it eases the separation
between front-end and back-end
• And the tooling in JS/TS is awesome
GraphQL everywhere?
• Performance warning! GraphQL itself is fast
but…
• N+1 problem
• It is easy to write slow queries ➔ Warning with
front facing websites.
GraphQL everywhere?
• Two strategies available to avoid the “N+1”
problem:
• Analyzing the GraphQL query and “joining”
accordingly
• Or the “data-loader” pattern
• + a need to set limits on the queries
complexity to avoid “rogue” queries
Questions?
@david_negrier
@moufmouf
graphqlite.thecodingmachine.io
We are hiring!
More cool stuff:
• https://www.thecodingmachine.com/open-source/
• https://thecodingmachine.io
David Négrier
From the client
side
…
Apollo to the
rescue!
Zoom on Apollo
• Apollo is a GraphQL client (it is a JS lib).
• It has bindings with:
• Angular
• React
• VueJS
• You bundle a React/Angular/Vue component
in a Apollo component and Apollo takes in
charge the query to the server
Dependencies in package.json
{
"devDependencies": {
"@symfony/webpack-encore": "^0.22.0",
"axios": "^0.18.0",
"vue": "^2.5.17",
"vue-loader": "^15.4.2",
"vue-router": "^3.0.2",
"vue-template-compiler": "^2.5.17",
"vuex": "^3.0.1",
"webpack-notifier": "^1.6.0",
"apollo-cache-inmemory": "^1.3.12",
"apollo-client": "^2.4.8",
"apollo-link": "^1.2.6",
"apollo-link-http": "^1.5.9",
"graphql": "^14.0.2",
"graphql-tag": "^2.10.0",
"vue-apollo": "^3.0.0-beta.27"
},
"license": "UNLICENSED",
"private": true,
"scripts": {
"dev-server": "encore dev-server",
"dev": "encore dev",
"watch": "encore dev --watch",
"build": "encore production --progress"
}
}
Declarative usage
<template>
<div>
<div class="row col">
<h1>Posts</h1>
</div>
<form>
<div class="form-row">
<div class="col-8">
<input v-model="search" type="text" class="form-control" placeholder="Search">
</div>
</div>
</form>
<ApolloQuery
:query="require('../graphql/posts.gql')"
:variables="{ search }"
>
<template slot-scope="{ result: { loading, error, data } }">
// ……… Do something with {{data}}
</template>
</ApolloQuery>
</div>
</template>
<script>
export default {
name: 'posts',
data () {
return {
search: ''
};
},
}
</script>
graphql/posts.gql
query searchPosts ($search: String) {
posts(search: $search) {
id
message
author {
login
}
comments {
items {
id
message
author {
login
}
}
}
}
}
Declarative usage
<template>
<div>
<div class="row col">
<h1>Posts</h1>
</div>
<form>
<div class="form-row">
<div class="col-8">
<input v-model="search" type="text" class="form-control" placeholder="Search">
</div>
</div>
</form>
<ApolloQuery
:query="require('../graphql/posts.gql')"
:variables="{ search }"
>
<template slot-scope="{ result: { loading, error, data } }">
// ……… Do something with {{data}}
</template>
</ApolloQuery>
</div>
</template>
<script>
export default {
name: 'posts',
data () {
return {
search: ''
};
},
}
</script>
Declarative usage
<ApolloQuery
:query="require('../graphql/posts.gql')"
:variables="{ search }"
>
<template slot-scope="{ result: { loading, error, data } }">
<!-- Loading -->
<div v-if="loading" class="loading apollo row col">Loading...</div>
<!-- Error -->
<div v-else-if="error" class="error apollo row col">An error occurred</div>
<!-- Result -->
<div v-else-if="data" class="result apollo ">
<div v-for="post in data.posts" class="border">
<div class="row">
<div class="col">
<h3>Article</h3>
{{ post.message }}
</div>
</div>
<div class="row col"><em>Authored by: {{ post.author.login }}</em></div>
<div class="row">
<div class="col">
<h3>Comments</h3>
<div v-for="comment in post.comments.items" class="border">
<div class="row border">
<div class="col">
<p>Comment:</p>
{{ comment.message }}
<p>By: {{ comment.author.login }}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- No result -->
<div v-else class="no-result apollo">No result :(</div>
</template>
</ApolloQuery>
But where is Redux?
• Apollo comes internally with its own store.
• Redux is really less useful with Apollo and you
can simply scrap ~90% of your reducers.
• Still useful for niche places (like managing the
current logged user)
Questions?
@david_negrier
@moufmouf
graphqlite.thecodingmachine.io
We are hiring!
More cool stuff:
• https://www.thecodingmachine.com/open-source/
• https://thecodingmachine.io
David Négrier

Mais conteúdo relacionado

Mais procurados

Mais procurados (20)

Introduction to PySpark
Introduction to PySparkIntroduction to PySpark
Introduction to PySpark
 
React & GraphQL
React & GraphQLReact & GraphQL
React & GraphQL
 
REST vs GraphQL
REST vs GraphQLREST vs GraphQL
REST vs GraphQL
 
SPARQL Tutorial
SPARQL TutorialSPARQL Tutorial
SPARQL Tutorial
 
RDF/OWLの概要及びOSS実装、及び活用イメージについて
RDF/OWLの概要及びOSS実装、及び活用イメージについてRDF/OWLの概要及びOSS実装、及び活用イメージについて
RDF/OWLの概要及びOSS実装、及び活用イメージについて
 
Property graph vs. RDF Triplestore comparison in 2020
Property graph vs. RDF Triplestore comparison in 2020Property graph vs. RDF Triplestore comparison in 2020
Property graph vs. RDF Triplestore comparison in 2020
 
【ナレッジグラフ推論チャレンジ】SPARQLと可視化ツールを用いた推論検討例
【ナレッジグラフ推論チャレンジ】SPARQLと可視化ツールを用いた推論検討例【ナレッジグラフ推論チャレンジ】SPARQLと可視化ツールを用いた推論検討例
【ナレッジグラフ推論チャレンジ】SPARQLと可視化ツールを用いた推論検討例
 
Liquibase
LiquibaseLiquibase
Liquibase
 
Stop Reinventing the Wheel! Use Linked Data to Build Better APIs
Stop Reinventing the Wheel! Use Linked Data to Build Better APIsStop Reinventing the Wheel! Use Linked Data to Build Better APIs
Stop Reinventing the Wheel! Use Linked Data to Build Better APIs
 
Introduction to GraphQL: Mobile Week SF
Introduction to GraphQL: Mobile Week SFIntroduction to GraphQL: Mobile Week SF
Introduction to GraphQL: Mobile Week SF
 
RDF Semantic Graph「RDF 超入門」
RDF Semantic Graph「RDF 超入門」RDF Semantic Graph「RDF 超入門」
RDF Semantic Graph「RDF 超入門」
 
Building Modern APIs with GraphQL
Building Modern APIs with GraphQLBuilding Modern APIs with GraphQL
Building Modern APIs with GraphQL
 
【2018年3月時点】Oracle BI ベストプラクティス
【2018年3月時点】Oracle BI ベストプラクティス【2018年3月時点】Oracle BI ベストプラクティス
【2018年3月時点】Oracle BI ベストプラクティス
 
GraphQL Introduction
GraphQL IntroductionGraphQL Introduction
GraphQL Introduction
 
Introduction to GraphQL
Introduction to GraphQLIntroduction to GraphQL
Introduction to GraphQL
 
Oracle Cloud Infrastructure:2022年8月度サービス・アップデート
Oracle Cloud Infrastructure:2022年8月度サービス・アップデートOracle Cloud Infrastructure:2022年8月度サービス・アップデート
Oracle Cloud Infrastructure:2022年8月度サービス・アップデート
 
Large Scale Graph Analytics with JanusGraph
Large Scale Graph Analytics with JanusGraphLarge Scale Graph Analytics with JanusGraph
Large Scale Graph Analytics with JanusGraph
 
Intro to GraphQL
 Intro to GraphQL Intro to GraphQL
Intro to GraphQL
 
これからのJDK/JVM 何を選ぶ?どう選ぶ?
これからのJDK/JVM 何を選ぶ?どう選ぶ?これからのJDK/JVM 何を選ぶ?どう選ぶ?
これからのJDK/JVM 何を選ぶ?どう選ぶ?
 
PySpark Programming | PySpark Concepts with Hands-On | PySpark Training | Edu...
PySpark Programming | PySpark Concepts with Hands-On | PySpark Training | Edu...PySpark Programming | PySpark Concepts with Hands-On | PySpark Training | Edu...
PySpark Programming | PySpark Concepts with Hands-On | PySpark Training | Edu...
 

Semelhante a PHP, the GraphQL ecosystem and GraphQLite

Rapid API Development ArangoDB Foxx
Rapid API Development ArangoDB FoxxRapid API Development ArangoDB Foxx
Rapid API Development ArangoDB Foxx
Michael Hackstein
 

Semelhante a PHP, the GraphQL ecosystem and GraphQLite (20)

GraphQL in Ruby on Rails - basics
GraphQL in Ruby on Rails - basicsGraphQL in Ruby on Rails - basics
GraphQL in Ruby on Rails - basics
 
Graphql usage
Graphql usageGraphql usage
Graphql usage
 
apidays LIVE Australia 2020 - Have your cake and eat it too: GraphQL? REST? W...
apidays LIVE Australia 2020 - Have your cake and eat it too: GraphQL? REST? W...apidays LIVE Australia 2020 - Have your cake and eat it too: GraphQL? REST? W...
apidays LIVE Australia 2020 - Have your cake and eat it too: GraphQL? REST? W...
 
GraphQL - The new "Lingua Franca" for API-Development
GraphQL - The new "Lingua Franca" for API-DevelopmentGraphQL - The new "Lingua Franca" for API-Development
GraphQL - The new "Lingua Franca" for API-Development
 
Rapid API Development ArangoDB Foxx
Rapid API Development ArangoDB FoxxRapid API Development ArangoDB Foxx
Rapid API Development ArangoDB Foxx
 
Polyglot Grails
Polyglot GrailsPolyglot Grails
Polyglot Grails
 
CONDG April 23 2020 - Baskar Rao - GraphQL
CONDG April 23 2020 - Baskar Rao - GraphQLCONDG April 23 2020 - Baskar Rao - GraphQL
CONDG April 23 2020 - Baskar Rao - GraphQL
 
Elixir absinthe-basics
Elixir absinthe-basicsElixir absinthe-basics
Elixir absinthe-basics
 
Building a GraphQL API in PHP
Building a GraphQL API in PHPBuilding a GraphQL API in PHP
Building a GraphQL API in PHP
 
GraphQL Europe Recap
GraphQL Europe RecapGraphQL Europe Recap
GraphQL Europe Recap
 
Hands On - GraphQL
Hands On - GraphQLHands On - GraphQL
Hands On - GraphQL
 
Cascalog at Strange Loop
Cascalog at Strange LoopCascalog at Strange Loop
Cascalog at Strange Loop
 
About Clack
About ClackAbout Clack
About Clack
 
GraphQL - A query language to empower your API consumers (NDC Sydney 2017)
GraphQL - A query language to empower your API consumers (NDC Sydney 2017)GraphQL - A query language to empower your API consumers (NDC Sydney 2017)
GraphQL - A query language to empower your API consumers (NDC Sydney 2017)
 
Implementing OpenAPI and GraphQL services with gRPC
Implementing OpenAPI and GraphQL services with gRPCImplementing OpenAPI and GraphQL services with gRPC
Implementing OpenAPI and GraphQL services with gRPC
 
GraphQL + relay
GraphQL + relayGraphQL + relay
GraphQL + relay
 
Getting Started with Spring for GraphQL
Getting Started with Spring for GraphQLGetting Started with Spring for GraphQL
Getting Started with Spring for GraphQL
 
Powering an API with GraphQL, Golang, and NoSQL
Powering an API with GraphQL, Golang, and NoSQLPowering an API with GraphQL, Golang, and NoSQL
Powering an API with GraphQL, Golang, and NoSQL
 
Modern APIs with GraphQL
Modern APIs with GraphQLModern APIs with GraphQL
Modern APIs with GraphQL
 
Marco Liberati - Graph analytics
Marco Liberati - Graph analyticsMarco Liberati - Graph analytics
Marco Liberati - Graph analytics
 

Mais de JEAN-GUILLAUME DUJARDIN

Mais de JEAN-GUILLAUME DUJARDIN (16)

Do you speak technique ?
Do you speak technique ?Do you speak technique ?
Do you speak technique ?
 
Methode Agile
Methode Agile Methode Agile
Methode Agile
 
Livre blanc docker
Livre blanc docker Livre blanc docker
Livre blanc docker
 
Conception d'un Extranet
Conception d'un ExtranetConception d'un Extranet
Conception d'un Extranet
 
Etude des Frameworks PHP
Etude des Frameworks PHPEtude des Frameworks PHP
Etude des Frameworks PHP
 
Framework JavaScript Web - Brief techno
Framework JavaScript Web - Brief technoFramework JavaScript Web - Brief techno
Framework JavaScript Web - Brief techno
 
Modèle cahier des charges site web
Modèle cahier des charges site webModèle cahier des charges site web
Modèle cahier des charges site web
 
Gérer un pic d'audience
Gérer un pic d'audienceGérer un pic d'audience
Gérer un pic d'audience
 
3 piliers d'un bon référencement web
3 piliers d'un bon référencement web3 piliers d'un bon référencement web
3 piliers d'un bon référencement web
 
Brief Nouveaux outils collaboratifs
Brief Nouveaux outils collaboratifsBrief Nouveaux outils collaboratifs
Brief Nouveaux outils collaboratifs
 
Livre Blanc Web temps réel - Node JS
Livre Blanc Web temps réel - Node JSLivre Blanc Web temps réel - Node JS
Livre Blanc Web temps réel - Node JS
 
Livre Blanc Sauvetage de projets
Livre Blanc Sauvetage de projetsLivre Blanc Sauvetage de projets
Livre Blanc Sauvetage de projets
 
Intranet 2.0
Intranet 2.0Intranet 2.0
Intranet 2.0
 
Hec Web Marketing
Hec Web MarketingHec Web Marketing
Hec Web Marketing
 
Livre blanc améliorez les performances de vos projets web - v1.1
Livre blanc   améliorez les performances de vos projets web - v1.1Livre blanc   améliorez les performances de vos projets web - v1.1
Livre blanc améliorez les performances de vos projets web - v1.1
 
TCM - Livre blanc sur les plateformes communautaires Open Source
TCM - Livre blanc sur les plateformes communautaires Open SourceTCM - Livre blanc sur les plateformes communautaires Open Source
TCM - Livre blanc sur les plateformes communautaires Open Source
 

Último

CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
masabamasaba
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 

Último (20)

call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 

PHP, the GraphQL ecosystem and GraphQLite

  • 1. GraphQL in the PHP ecosystem
  • 3. GraphQL ? • GraphQL is a protocol
  • 4. GraphQL ? • GraphQL is a protocol • It is not: • A fancy new database • A database query language like SQL
  • 5. GraphQL ? • GraphQL is a protocol • GraphQL is a challenger to those other protocols: • REST • Web-services (SOAP/WSDL based)
  • 6. A bit of history Web-services (~1999) • Strongly typed • Self-describing (WSDL) • XML-based
  • 7. A bit of history Web-services (~1999) • Strongly typed • Self-describing (WSDL) • XML-based
  • 8. A bit of history Web-services (~1999) REST (~2005) • Strongly typed • Self-describing (WSDL) • XML-based • Weakly typed • Non self-describing (still OpenAPI for doc) • Mostly JSON based
  • 9. A bit of history Web-services (~1999) REST (~2005) • Strongly typed • Self-describing (WSDL) • XML-based • Weakly typed • Non self-describing (still OpenAPI for doc) • Mostly JSON based
  • 10. A bit of history Web-services (~1999) REST (~2005) GraphQL (2015) • Strongly typed • Self-describing (WSDL) • XML-based • Weakly typed • Non self-describing (still OpenAPI for doc) • Mostly JSON based • Strongly typed • Self-describing • JSON based • + Client driven queries
  • 11. GraphQL ? It is developed by Facebook and was first used in the Facebook API. Facebook also provides: • A JS client (to query a GraphQL server) • A NodeJS server library Tons of server implementations exist.
  • 13. What problem does GraphQL solves? • Your API often changes • You develop a new feature but your API does not exactly respond to your needs.
  • 14. What problem does GraphQL solves? • For instance: you are developing a marketplace. You need a page to display a product, along some company information. /api/product/42 /api/company/35 REST
  • 15. What problem does GraphQL solves? • Alternative, still REST • But what if some pages don’t need the company details? /api/product/42 REST
  • 16. What problem does GraphQL solves? • Yet another alternative, still REST /api/product/42?with_company=true REST Flags hell 😨! Probably one flag per consumer of the API
  • 17. What problem does GraphQL solves? • GraphQL to the rescue! • GraphQL is a paradigm shift. • The client asks for the list of fields it wants. GET /graphql?query= Single endpoint The name of the query is « products » List of fields requested
  • 18. What problem does GraphQL solves? • GraphQL to the rescue! • Another request of the same query with a different set of fields No need to change the code on the server-side! All this data in one API call! GET /graphql?query=
  • 20. Types GraphQL is strongly typed. It comes with a « schema language » but this is rarely used while developing. It is however useful to understand what is going on.
  • 21. ≠ Schema language product(id: 42) { name company { name logo country { name } } } Query language
  • 22. Types Note: • [Product] ➔ an array of Products • String ➔ a string (or null) • String! ➔ a non-nullable string Hence: • [Product!]! ➔ An array (non- nullable) of products that are also non-nullable.
  • 23. Types Some « scalar » types: • ID: a unique identifier (~=String) • String • Int • Float • Boolean No support for « Date » in the standard (but custom types are supported by some implementations)
  • 24. Types Support for “arguments”: • product(id: ID!) ➔ the product query requires an “id” field of type “ID” to be passed.
  • 25. Types Bonus: • Support for interfaces • Support for Union types • Support for “InputType” (to pass complex objects in queries)
  • 26. Mutations So far, we mostly talked about queries (because this is what is fun in GraphQL). GraphQL can also do mutations (to change the state of the DB)
  • 28. Transport is out of scope • You usually do GraphQL over HTTP/HTTPS • But nothing prevents you from using GraphQL over UDP, or mail, …
  • 29. Transport is out of scope • You usually do GraphQL over HTTP/HTTPS • But nothing prevents you from using GraphQL over UDP, or mail, or homing pigeon whatever!
  • 30. Authentication is out of scope • GraphQL does not deal with authentication. • You are free to deal with it in any way you want: • Session-based • or using Oauth2 • or using a token… • Authentication can happen using a REST API, or even using a GraphQL mutation!
  • 31. Pagination is out of scope • GraphQL does not deal with pagination in the standard. • You are free to add limit/offset parameters to your queries • “Relay” is providing some conventions to deal with pagination (more on that later)
  • 33. Ecosystem (a small part of…) Browser GraphQL Client Server GraphQL Middleware DB RelayJS Apollo ReactJS Express- graphql NodeJS Webonyx/ GraphQL- PHP PHP GraphiQL (for dev!)
  • 34. Zoom on GraphQL in PHP Core library Wrapper library • Low level • Parsing • Service requests • Powerful • Feature complete • Hard to use (poor DX) • High level • Opiniated • Easy to use
  • 35. Zoom on GraphQL in PHP Core library Wrapper library • webonyx/graphql-php • De-facto standard in PHP • Youshido/GraphQL •  Abandonned 
  • 36. Zoom on GraphQL in PHP Core library Wrapper library • API Platform (Symfony) • Overblog GraphQL Bundle (Symfony) • Lighthouse (Laravel) • … and now GraphQLite
  • 40. Costs VS benefits Costs Gains Strict types Self-described Client driven Work
  • 41. You need a wrapper library Costs Gains Strict types Self-described Client driven Work GraphQL library
  • 42. Strategies Schema-first Code-first • Design the GraphQL schema first • Find a way to link it to your code • Design your domain code • Generate the schema from the code
  • 43. Strategies Schema-first Code-first • Overblog GraphQL Bundle • Lighthouse • API Platform • GraphQLite
  • 44. Strategies Schema-first Code-first • Overblog GraphQL Bundle • Lighthouse • API Platform • GraphQLite Lighthouse
  • 45. Strategies Schema-first Code-first • Overblog GraphQL Bundle • Lighthouse • API Platform • GraphQLite API Platform
  • 47. The idea Let’s imagine we want to do a simple “echo” query in PHP.
  • 48. The idea Let’s imagine we want to do a simple “echo” query in PHP.
  • 49. The idea Using webonyx/GraphQL-PHP type Query { echo(message: String!): String }
  • 50. The idea The same “echo” method in pure PHP function echoMsg(string $message): string { return $message; }
  • 51. function echoMsg(string $message): string { return $message; } The idea The same “echo” method in pure PHP Query name Arguments Return type Resolver
  • 52. The idea The same “echo” method in pure PHP /** * @Query */ function echoMsg(string $message): string { return $message; }
  • 53. The idea • PHP is already typed. • We should be able to get types from PHP and convert them to a GraphQL schema PHP objects GraphQL objects GraphQLite
  • 54. Works well with Doctrine Bonus: • It plays nice with Doctrine ORM too • (we also have native bindings with TDBM, our in-house ORM) DB model PHP objects GraphQL objects Doctrine GraphQLite
  • 55. GraphQLite GraphQLite is: • Framework agnostic • Symfony bundle and Laravel package available • PHP 7.2+ • Based on Webonyx/GraphQL-PHP
  • 58. First query namespace AppController; use AppEntityPost; use AppRepositoryPostRepository; use TheCodingMachineGraphQLiteAnnotationsQuery; class PostController { /** * @var PostRepository */ private $postRepository; public function __construct(PostRepository $postRepository) { $this->postRepository = $postRepository; } /** * @Query() */ public function getPosts(?string $search): array { return $this->postRepository->findAllFilterBySearch($search); } }
  • 60. First query namespace AppController; use AppEntityPost; use AppRepositoryPostRepository; use TheCodingMachineGraphQLiteAnnotationsQuery; class PostController { /** * @var PostRepository */ private $postRepository; public function __construct(PostRepository $postRepository) { $this->postRepository = $postRepository; } /** * @Query() * @return Post[] */ public function getPosts(?string $search): array { return $this->postRepository->findAllFilterBySearch($search); } }
  • 62. <?php namespace AppEntity; use TheCodingMachineGraphQLiteAnnotationsField; use TheCodingMachineGraphQLiteAnnotationsType; /** * @Type() */ class Post { //… /** * @Field(outputType="ID") */ public function getId(): int { return $this->id; } /** * @Field() */ public function getMessage(): string { return $this->message; } /** * @Field() */ public function getCreated(): DateTimeImmutable { return $this->created; } }
  • 64. First query <?php namespace AppEntity; use TheCodingMachineGraphQLiteAnnotationsField; use TheCodingMachineGraphQLiteAnnotationsType; /** * @Type() */ class Post { // … /** * @Field() */ public function getAuthor(): User { return $this->author; } }
  • 66. First query <?php namespace AppEntity; use TheCodingMachineGraphQLiteAnnotationsField; use TheCodingMachineGraphQLiteAnnotationsType; /** * @Type() */ class User implements UserInterface { // … /** * @Field(outputType="ID!") */ public function getId(): int { return $this->id; } /** * @Field() */ public function getLogin(): string { return $this->login; } // …
  • 69. Improving our sample What if I want to get the list of comments from my “post” type? (Assuming I have no “getComments” method in the Post class)
  • 70. Improving our sample Say hello to “type extension”! You can add fields in an existing type, using the “@ExtendType” annotation.
  • 71. Improving our sample namespace AppTypes; use AppEntityComment; use AppRepositoryCommentRepository; use TheCodingMachineGraphQLiteAnnotationsExtendType; use AppEntityPost; use TheCodingMachineGraphQLiteAnnotationsField; /** * @ExtendType(class=Post::class) */ class PostType { /** * @var CommentRepository */ private $commentRepository; public function __construct(CommentRepository $commentRepository) { $this->commentRepository = $commentRepository; } /** * @Field() * @return Comment[] */ public function getComments(Post $post): array { return $this->commentRepository->findByPost($post); } }
  • 72. Improving our sample namespace AppTypes; use AppEntityComment; use AppRepositoryCommentRepository; use TheCodingMachineGraphQLiteAnnotationsExtendType; use AppEntityPost; use TheCodingMachineGraphQLiteAnnotationsField; /** * @ExtendType(class=Post::class) */ class PostType { /** * @var CommentRepository */ private $commentRepository; public function __construct(CommentRepository $commentRepository) { $this->commentRepository = $commentRepository; } /** * @Field() * @return Comment[] */ public function getComments(Post $post): array { return $this->commentRepository->findByPost($post); } } It is a service!
  • 73. Improving our samplenamespace AppTypes; use AppEntityComment; use AppRepositoryCommentRepository; use TheCodingMachineGraphQLiteAnnotationsExtendType; use AppEntityPost; use TheCodingMachineGraphQLiteAnnotationsField; /** * @ExtendType(class=Post::class) */ class PostType { /** * @var CommentRepository */ private $commentRepository; public function __construct(CommentRepository $commentRepository) { $this->commentRepository = $commentRepository; } /** * @Field() * @return Comment[] */ public function getComments(Post $post): array { return $this->commentRepository->findByPost($post); } } Current object is passed as first parameter
  • 75. Improving our sample Even better: fields can have their own arguments. For instance, you may want to fetch a paginated list of comments.
  • 76. Improving our sample namespace AppTypes; use AppEntityComment; use AppRepositoryCommentRepository; use TheCodingMachineGraphQLiteAnnotationsExtendType; use AppEntityPost; use TheCodingMachineGraphQLiteAnnotationsField; /** * @ExtendType(class=Post::class) */ class PostType { // … /** * @Field() * @return Comment[] */ public function getComments(Post $post, int $limit = 20, int $offset = 0): array { return $this->commentRepository->findByPost($post) ->setMaxResults($limit) ->setFirstResult($offset) ->getResult(); } } From the 2nd parameter, arguments are added to the field
  • 79. Native pagination Actually, you don’t even have to bother adding pagination as GraphQLite integrates natively with Porpaginas. (Porpaginas integrates with Doctrine and TDBM)
  • 80. Native pagination use PorpaginasDoctrineORMORMQueryResult; /** * @ExtendType(class=Post::class) */ class PostType { // … /** * @Field() * @return Comment[] */ public function getComments(Post $post): ORMQueryResult { return new ORMQueryResult($this->commentRepository->findByPost($post)); } } Needed for Doctrine ORM. Not even necessary for TDBM 5 ResultIterator’s that can be returned directly.
  • 81.
  • 83. Authentication and authorization @Logged and @Right annotations can be used with @Field too!
  • 86. More features! Everything is clearly documented at: Thanks @JUN for the help https://graphqlite.thecodingmachine.io
  • 87. What’s next? • Release of GraphQLite 4 in June • Deferred type support • Injection of services in method parameters • Improved performances • Custom scalar types • Enum’s support • …
  • 89. GraphQL everywhere? • GraphQLite makes it trivial to write a GraphQL API. It is now easier to start a GraphQL API than a REST API! o/ • GraphQL makes a lot of sense for most of our projects because it eases the separation between front-end and back-end • And the tooling in JS/TS is awesome
  • 90. GraphQL everywhere? • Performance warning! GraphQL itself is fast but… • N+1 problem • It is easy to write slow queries ➔ Warning with front facing websites.
  • 91. GraphQL everywhere? • Two strategies available to avoid the “N+1” problem: • Analyzing the GraphQL query and “joining” accordingly • Or the “data-loader” pattern • + a need to set limits on the queries complexity to avoid “rogue” queries
  • 92. Questions? @david_negrier @moufmouf graphqlite.thecodingmachine.io We are hiring! More cool stuff: • https://www.thecodingmachine.com/open-source/ • https://thecodingmachine.io David Négrier
  • 94. Zoom on Apollo • Apollo is a GraphQL client (it is a JS lib). • It has bindings with: • Angular • React • VueJS • You bundle a React/Angular/Vue component in a Apollo component and Apollo takes in charge the query to the server
  • 95. Dependencies in package.json { "devDependencies": { "@symfony/webpack-encore": "^0.22.0", "axios": "^0.18.0", "vue": "^2.5.17", "vue-loader": "^15.4.2", "vue-router": "^3.0.2", "vue-template-compiler": "^2.5.17", "vuex": "^3.0.1", "webpack-notifier": "^1.6.0", "apollo-cache-inmemory": "^1.3.12", "apollo-client": "^2.4.8", "apollo-link": "^1.2.6", "apollo-link-http": "^1.5.9", "graphql": "^14.0.2", "graphql-tag": "^2.10.0", "vue-apollo": "^3.0.0-beta.27" }, "license": "UNLICENSED", "private": true, "scripts": { "dev-server": "encore dev-server", "dev": "encore dev", "watch": "encore dev --watch", "build": "encore production --progress" } }
  • 96. Declarative usage <template> <div> <div class="row col"> <h1>Posts</h1> </div> <form> <div class="form-row"> <div class="col-8"> <input v-model="search" type="text" class="form-control" placeholder="Search"> </div> </div> </form> <ApolloQuery :query="require('../graphql/posts.gql')" :variables="{ search }" > <template slot-scope="{ result: { loading, error, data } }"> // ……… Do something with {{data}} </template> </ApolloQuery> </div> </template> <script> export default { name: 'posts', data () { return { search: '' }; }, } </script>
  • 97. graphql/posts.gql query searchPosts ($search: String) { posts(search: $search) { id message author { login } comments { items { id message author { login } } } } }
  • 98. Declarative usage <template> <div> <div class="row col"> <h1>Posts</h1> </div> <form> <div class="form-row"> <div class="col-8"> <input v-model="search" type="text" class="form-control" placeholder="Search"> </div> </div> </form> <ApolloQuery :query="require('../graphql/posts.gql')" :variables="{ search }" > <template slot-scope="{ result: { loading, error, data } }"> // ……… Do something with {{data}} </template> </ApolloQuery> </div> </template> <script> export default { name: 'posts', data () { return { search: '' }; }, } </script>
  • 99. Declarative usage <ApolloQuery :query="require('../graphql/posts.gql')" :variables="{ search }" > <template slot-scope="{ result: { loading, error, data } }"> <!-- Loading --> <div v-if="loading" class="loading apollo row col">Loading...</div> <!-- Error --> <div v-else-if="error" class="error apollo row col">An error occurred</div> <!-- Result --> <div v-else-if="data" class="result apollo "> <div v-for="post in data.posts" class="border"> <div class="row"> <div class="col"> <h3>Article</h3> {{ post.message }} </div> </div> <div class="row col"><em>Authored by: {{ post.author.login }}</em></div> <div class="row"> <div class="col"> <h3>Comments</h3> <div v-for="comment in post.comments.items" class="border"> <div class="row border"> <div class="col"> <p>Comment:</p> {{ comment.message }} <p>By: {{ comment.author.login }}</p> </div> </div> </div> </div> </div> </div> </div> <!-- No result --> <div v-else class="no-result apollo">No result :(</div> </template> </ApolloQuery>
  • 100. But where is Redux? • Apollo comes internally with its own store. • Redux is really less useful with Apollo and you can simply scrap ~90% of your reducers. • Still useful for niche places (like managing the current logged user)
  • 101. Questions? @david_negrier @moufmouf graphqlite.thecodingmachine.io We are hiring! More cool stuff: • https://www.thecodingmachine.com/open-source/ • https://thecodingmachine.io David Négrier