Can I use Guzzle for GraphQL API consumption?

Viewed 7025

There isn't a lot of information in the google-verse about consuming GraphQL API's in PHP. There are several packages that from my perspective, are mostly about creating your own GraphQL API, but nothing specific to consuming. It's possible that I'm over complicating things or that the solution to my question is obvious. I've solved my problem and will post the answer.

4 Answers

I didn't want to pull these packages in when I barely understood what they provided and I just wanted to use the same tools I was used to in the REST world for a lightweight transition. The answer is Yes, you can use Guzzle for consuming a GraphQL API.

There are probably ways to make this prettier, but for now, this is what's working. You pass authorization through the Authorization header and Content-Type must be set to application/json.

When constructing your query be wary of quotes, spacing, and line breaks. I haven't yet figured out a way to make the code prettier and still maintain a valid query. The first portion {"query": "query { is a requirement for every query. The object name must be wrapped in double quotes and the query body "query { }" must be wrapped in double quotes as well.

$graphQLquery = '{"query": "query { viewer { repositories(last: 100) { nodes { name id isPrivate nameWithOwner } } } } "}';

use GuzzleHttp\Client;

$response = (new Client)->request('post', '{graphql-endpoint}', [
    'headers' => [
        'Authorization' => 'bearer ' . $token,
        'Content-Type' => 'application/json'
    ],
    'body' => $graphQLquery
]);

Just make normal post request from guzzle. Add form params as query and variables. Put your query in query form param and and variables as array of key value.

  $response = $this->client->post('https://grapqlEndPoint', [
        'form_params' => [
            'query' => '
                query($username: String!) {
                    users(username: $username) {
                        username               
                    }
                }',
            'variables' => [
                'username' => $username
            ]
        ]
    ]);

    echo $response->getBody()->getContents();

I would like to add a few things on top of what Vim Diesel has mentioned as the answer to his post.

As of 2021, when i followed the code's formatting I do end up with a malformed payload as the error message. To correct this I removed the query body query { } and used '"query": "query queryName{ }"'

If you do need to include variables for the GraphQL query, you can do as the following (from GraphQL documentation):

$graphQLquery = '{"query": "query { viewer { repositories(last: 100) { nodes { name id isPrivate nameWithOwner } } } } "}, "variables": { "isPrivate": "True", "name": "JohnDoe", ... }';

You can separate the query using single quotes ' and a period . in PHP to avoid hardcoding variables and for formatting as well.

Full example code below of what worked for me.

use GuzzleHttp\Client;

$name = 'JohnDoe';
$graphQLquery = '{'.
    '"query": "query viewer {'.
                  'repositories(last: 100) {'.
                      'nodes {'.
                         'name'. 
                         'id'. 
                         'isPrivate'. 
                         'nameWithOwner'. 
                      '}'.
                  '}'. 
             '}",'.
    '"variables": { "name": "'.$name.'", "id": "1", "isPrivate ": "True", "nameWithOwner": "VimDiesel"}'.
 '}';'



$response = (new Client)->request('post', '{graphql-endpoint}', [
    'headers' => [
        'Authorization' => $token,
        'Content-Type' => 'application/json'
    ],
    'body' => $graphQLquery
]);

I was able to send a mutation with the GuzzleHttp\Client using the following code:

$graphQLBody = [
    'query' => 'mutation ($name: String!) {
        create(
            input:{
                name: $name,
            }
        ) {
            user {
                id,
                name,
            }
            errors {
                messages
            }
        }
    }',
    'variables' => [
        'name' => $name,
    ]
];

$response = $this->client->request('post', $this->apiEndpoint, [
    'headers' => [
        'Authorization' => 'bearer ' . $token,
        'Content-Type' => 'application/json'
    ],
    'body' => json_encode($graphQLBody)
]);
Related