hero

GraphQL by PoP

CMS-agnostic GraphQL server in PHP

Get Started →

Designed for optimal experience

Fast

Queries are resolved in linear time on the number of types involved

Simple

Resolvers deal with IDs (instead of objects), removing the need to implement batching/deferred

Extensible

Types have their resolvers attached by injection, and resolvers can override each other

Powerful

The engine is based on executing directives, allowing any type of custom functionality

# Query what you need. Get predictable results

Send a GraphQL query to your API and get exactly the data you need.

query PostsWithComments {
  posts {
    title
    comments {
      date
      content
      author {
        name
      }
    }
  }
}

The response from the API always mirrors the GraphQL query.

{
  "data": {
    "posts": [
      {
        "title": "Hello world!",
        "comments": [
          {
            "date": "2020-04-08",
            "content": "Check us out!",
            "author": {
              "name": "Leo"
            }
          }
        ]
      }
    ]
  }
}

Rock-solid architecture

⧐ Code-first approach ⧏

The schema is generated from code. Work with your teammates concurrently on the schema without conflicts, without tooling, and without bureaucracy.

⧐ Dynamic schema ⧏

The resolvers attach themselves to the types. Each field can be handled by different resolvers, and the chosen one is selected on runtime, depending on the context.

⧐ Public/private schema managed through ACLs ⧏

From a single source of truth, expose different schemas for different users, managing it through Access Control Lists based on the user being logged-in or not, roles, capabilities, or custom rules.

⧐ Field/directive-based versioning ⧏

In addition to evolving the GraphQL schema, every field and directive can be independently versioned, and the specific version to use is chosen through field/directive arguments in the query.

⧐ Robust caching ⧏

Cache the response from the query in several layers (server, CDN, etc) using standard HTTP caching, defining the max age field by field. Cache the results from expensive operations in disk or memory, defining the expiry time field by field.

⧐ Nested mutations ⧏

Perform mutations on every type, not just on the root type, and have a mutation be executed on the result from another mutation. The schema gets neater and slimmer!

⧐ Automatic namespacing ⧏

No need to worry if different teams or 3rd party providers using the same names for their types and interfaces. Create neater schemas by removing the 'MyCompanyName' prefix from your types, you won't need it.

⧐ Proactive warnings/deprecations ⧏

Issues with the query are shown in the response to the query, and not just when doing introspection. Avoid your users from never finding out that your schema has been upgraded!

# Extend your server with innovative features

Extended GraphQL server

# → Execute the query through the URL

The URL-based PoP Query Language (PQL) enables to send the query through GET, and use standard solutions for caching, file uploads, and others.

Send your query using the PQL via GET.

/?query=
  posts.
    title|
    comments.
      date|
      content|
      author.
        name

The response mirrors the shape of the query.

{
  "data": {
    "posts": [
      {
        "title": "Hello world!",
        "comments": [
          {
            "date": "2020-04-08",
            "content": "Check us out!",
            "author": {
              "name": "Leo"
            }
          }
        ]
      }
    ]
  }
}

# → Add scripting-language capabilities to the query

PQL enables to compose fields, compose directives, control the execution order of the fields in the query, and much more. Resolve multiple operations in a single query.

Composed fields are resolved at the API-level.

/?
format=Y-m-d&
query=
  posts.
    if (
      hasComments(),
      sprintf(
        "This post has %s comment(s) and title '%s'", [
          commentCount(),
          title()
        ]
      ),
      sprintf(
        "This post was created on %s and has no comments", [
          date(format: if(not(empty($format)), $format, d/m/Y))
        ]
      )
    )@postDesc

A single query can produce complex results.

{
  "data": {
    "posts": [
      {
        "postDesc": "This post was created on 2020-01-01 and has no comments"
      },
      {
        "postDesc": "This post has 1 comment(s) and title 'Hello world!'"
      },
      {
        "postDesc": "This post has 2 comment(s) and title 'Markup: HTML Tags and Formatting'"
      },
    ]
  }
}

WordPress-ready!

The GraphQL API for WordPress plugin brings all the power of GraphQL by PoP into your WordPress site

# Superpower your API

Superpower your API