SlideShare a Scribd company logo
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.
PHP, the GraphQL ecosystem and GraphQLite
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

More Related Content

What's hot (20)

PPT
Command line arguments.21
myrajendra
 
PDF
Tutorial: Building a GraphQL API in PHP
Andrew Rota
 
PDF
Character Array and String
Tasnima Hamid
 
PPTX
L9 wrapper classes
teach4uin
 
PPTX
Static keyword ppt
Vinod Kumar
 
PPTX
OOPs in Java
Ranjith Sekar
 
PPT
Java naming conventions
Lovely Professional University
 
PDF
Arrays in java
TharuniDiddekunta
 
PPTX
Java interface
BHUVIJAYAVELU
 
PPT
A Deeper look into Javascript Basics
Mindfire Solutions
 
PDF
Kotlin vs Java | Edureka
Edureka!
 
PPTX
What is Angular?
Albiorix Technology
 
PDF
Basic i/o & file handling in java
JayasankarPR2
 
DOCX
Linq in C#
Umar Farooq
 
PPTX
String in java
Ideal Eyes Business College
 
PPT
Inheritance in java
Lovely Professional University
 
PPTX
Java 101 Intro to Java Programming
agorolabs
 
PDF
Javapolymorphism
karthikenlume
 
PPT
Java basic
Sonam Sharma
 
Command line arguments.21
myrajendra
 
Tutorial: Building a GraphQL API in PHP
Andrew Rota
 
Character Array and String
Tasnima Hamid
 
L9 wrapper classes
teach4uin
 
Static keyword ppt
Vinod Kumar
 
OOPs in Java
Ranjith Sekar
 
Java naming conventions
Lovely Professional University
 
Arrays in java
TharuniDiddekunta
 
Java interface
BHUVIJAYAVELU
 
A Deeper look into Javascript Basics
Mindfire Solutions
 
Kotlin vs Java | Edureka
Edureka!
 
What is Angular?
Albiorix Technology
 
Basic i/o & file handling in java
JayasankarPR2
 
Linq in C#
Umar Farooq
 
Inheritance in java
Lovely Professional University
 
Java 101 Intro to Java Programming
agorolabs
 
Javapolymorphism
karthikenlume
 
Java basic
Sonam Sharma
 

Similar to PHP, the GraphQL ecosystem and GraphQLite (20)

PPTX
Building a GraphQL API in PHP
Andrew Rota
 
PPTX
Introduction to GraphQL
Rodrigo Prates
 
PDF
GraphQL - A love story
bwullems
 
PDF
GraphQL for Native Apps
Emanuele Di Saverio
 
PDF
Performant APIs with GraphQL and PHP (Dutch PHP 2019)
Andrew Rota
 
PDF
GraphQL + relay
Cédric GILLET
 
PPTX
GraphQL Introduction with Spring Boot
vipin kumar
 
PPTX
An intro to GraphQL
valuebound
 
PPTX
Introduction to GraphQL
Bhargav Anadkat
 
PPT
Graphql presentation
Vibhor Grover
 
PDF
Modern APIs with GraphQL
Taikai
 
PDF
GraphQL-PHP: Dos and don'ts
Václav Šír
 
PDF
Introduction to GraphQL (or How I Learned to Stop Worrying about REST APIs)
Hafiz Ismail
 
PPTX
GraphQL API Gateway and microservices
Mohammed Shaban
 
PDF
GraphQL ♥︎ GraphDB
GraphRM
 
PDF
Marco Liberati - Graph analytics
Codemotion
 
PDF
DEVOXX UK 2018 - GraphQL as an alternative approach to REST
luisw19
 
PDF
Graphql
Neven Rakonić
 
PDF
REST to GraphQL migration: Pros, cons and gotchas
Alexey Ivanov
 
PDF
Building and deploying GraphQL Servers with AWS Lambda and Prisma I AWS Dev D...
AWS Germany
 
Building a GraphQL API in PHP
Andrew Rota
 
Introduction to GraphQL
Rodrigo Prates
 
GraphQL - A love story
bwullems
 
GraphQL for Native Apps
Emanuele Di Saverio
 
Performant APIs with GraphQL and PHP (Dutch PHP 2019)
Andrew Rota
 
GraphQL + relay
Cédric GILLET
 
GraphQL Introduction with Spring Boot
vipin kumar
 
An intro to GraphQL
valuebound
 
Introduction to GraphQL
Bhargav Anadkat
 
Graphql presentation
Vibhor Grover
 
Modern APIs with GraphQL
Taikai
 
GraphQL-PHP: Dos and don'ts
Václav Šír
 
Introduction to GraphQL (or How I Learned to Stop Worrying about REST APIs)
Hafiz Ismail
 
GraphQL API Gateway and microservices
Mohammed Shaban
 
GraphQL ♥︎ GraphDB
GraphRM
 
Marco Liberati - Graph analytics
Codemotion
 
DEVOXX UK 2018 - GraphQL as an alternative approach to REST
luisw19
 
REST to GraphQL migration: Pros, cons and gotchas
Alexey Ivanov
 
Building and deploying GraphQL Servers with AWS Lambda and Prisma I AWS Dev D...
AWS Germany
 
Ad

More from JEAN-GUILLAUME DUJARDIN (16)

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

Recently uploaded (20)

PDF
Odoo CRM vs Zoho CRM: Honest Comparison 2025
Odiware Technologies Private Limited
 
PPTX
Fundamentals_of_Microservices_Architecture.pptx
MuhammadUzair504018
 
PPTX
Equipment Management Software BIS Safety UK.pptx
BIS Safety Software
 
PPTX
MiniTool Power Data Recovery Full Crack Latest 2025
muhammadgurbazkhan
 
PPTX
Tally software_Introduction_Presentation
AditiBansal54083
 
PDF
Streamline Contractor Lifecycle- TECH EHS Solution
TECH EHS Solution
 
PDF
Digger Solo: Semantic search and maps for your local files
seanpedersen96
 
PDF
Alexander Marshalov - How to use AI Assistants with your Monitoring system Q2...
VictoriaMetrics
 
PDF
Powering GIS with FME and VertiGIS - Peak of Data & AI 2025
Safe Software
 
PPTX
Human Resources Information System (HRIS)
Amity University, Patna
 
DOCX
Import Data Form Excel to Tally Services
Tally xperts
 
PPTX
3uTools Full Crack Free Version Download [Latest] 2025
muhammadgurbazkhan
 
PDF
Thread In Android-Mastering Concurrency for Responsive Apps.pdf
Nabin Dhakal
 
PDF
Beyond Binaries: Understanding Diversity and Allyship in a Global Workplace -...
Imma Valls Bernaus
 
PPTX
Java Native Memory Leaks: The Hidden Villain Behind JVM Performance Issues
Tier1 app
 
PDF
Revenue streams of the Wazirx clone script.pdf
aaronjeffray
 
PPTX
Platform for Enterprise Solution - Java EE5
abhishekoza1981
 
PDF
Alarm in Android-Scheduling Timed Tasks Using AlarmManager in Android.pdf
Nabin Dhakal
 
PDF
iTop VPN With Crack Lifetime Activation Key-CODE
utfefguu
 
PDF
Understanding the Need for Systemic Change in Open Source Through Intersectio...
Imma Valls Bernaus
 
Odoo CRM vs Zoho CRM: Honest Comparison 2025
Odiware Technologies Private Limited
 
Fundamentals_of_Microservices_Architecture.pptx
MuhammadUzair504018
 
Equipment Management Software BIS Safety UK.pptx
BIS Safety Software
 
MiniTool Power Data Recovery Full Crack Latest 2025
muhammadgurbazkhan
 
Tally software_Introduction_Presentation
AditiBansal54083
 
Streamline Contractor Lifecycle- TECH EHS Solution
TECH EHS Solution
 
Digger Solo: Semantic search and maps for your local files
seanpedersen96
 
Alexander Marshalov - How to use AI Assistants with your Monitoring system Q2...
VictoriaMetrics
 
Powering GIS with FME and VertiGIS - Peak of Data & AI 2025
Safe Software
 
Human Resources Information System (HRIS)
Amity University, Patna
 
Import Data Form Excel to Tally Services
Tally xperts
 
3uTools Full Crack Free Version Download [Latest] 2025
muhammadgurbazkhan
 
Thread In Android-Mastering Concurrency for Responsive Apps.pdf
Nabin Dhakal
 
Beyond Binaries: Understanding Diversity and Allyship in a Global Workplace -...
Imma Valls Bernaus
 
Java Native Memory Leaks: The Hidden Villain Behind JVM Performance Issues
Tier1 app
 
Revenue streams of the Wazirx clone script.pdf
aaronjeffray
 
Platform for Enterprise Solution - Java EE5
abhishekoza1981
 
Alarm in Android-Scheduling Timed Tasks Using AlarmManager in Android.pdf
Nabin Dhakal
 
iTop VPN With Crack Lifetime Activation Key-CODE
utfefguu
 
Understanding the Need for Systemic Change in Open Source Through Intersectio...
Imma Valls Bernaus
 

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.
  • 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