why GraphQL doesn't work when accessed from PHP

rediskapsts
Shopify Partner
4 0 3

I'm trying to run a simple GraphQL query using cUrl in PHP, why do I get the error {"errors":{"query":"Required parameter missing or invalid"}}, when I run a similar query through Postman I get the correct response

 

$url = 'https://'.$shop_url.'/admin/api/2023-01/graphql.json';

$query = '{shop { name }}';

$requestData = [
    'query' => $query
];

$s = curl_init();
curl_setopt($s, CURLOPT_URL, $url);
curl_setopt($s, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($s, CURLOPT_HTTPHEADER, array('Content-type: application/json'));
curl_setopt($s, CURLOPT_HTTPHEADER, array('X-Shopify-Access-Token: '.$brand->getShopifyCustomAccessToken()));
curl_setopt($s, CURLOPT_POSTFIELDS, json_encode($requestData));
curl_setopt($s, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($s, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($s, CURLOPT_SSL_VERIFYHOST, 0);

$response = curl_exec($s);

 

Replies 2 (2)

Liam
Shopify Staff
2731 302 783

Hi Rediskapsts,

 

The error message you're getting suggests that there is a problem with your query parameter. Here are a couple things you could check to debug this:

  1. Check if $brand->getShopifyCustomAccessToken() is returning the correct token. If the token is invalid or expired, you might get errors.

  2. You're setting the CURLOPT_HTTPHEADER option twice, which means the second call is overriding the first one.'s possible that you're not sending the Content-Type header correctly because of this. Try combining them into a single array:

   curl_setopt($s, CURLOPT_HTTPHEADER, array(
       'Content-Type: application/json',
       'X-Shopify-Access-Token: '.$brand->getShopifyCustomAccessToken()
   ));
  1. Make sure that $query is correctly formatted as a string. If there are special characters or newlines in it, you might need to escape them.

  2. It's recommended to use application/graphql as Content-Type when sending a GraphQL query. So, you should change 'Content-Type: application/json' to 'Content-Type: application/graphql'.

  3. The GraphQL query should be sent as raw body, not as a JSON encoded array. So, change json_encode($requestData) to just $query.

Here's how the corrected code might look like:

$url = 'https://'.$shop_url.'/admin/api/2023-01/graphql.json';

$query = '{shop { name }}';

$s = curl_init();

curl_setopt($s, CURLOPT_URL, $url);
curl_setopt($s, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($s, CURLOPT_HTTPHEADER, array(
    'Content-Type: application/graphql',
    'X-Shopify-Access-Token: '.$brand->getShopifyCustomAccessToken()
));
curl_setopt($s, CURLOPT_POSTFIELDS, $query);
curl_setopt($s, CURLOPT_RETURNTRANSFER, true);
curl_setopt($s, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($s, CURLOPT_SSL_VERIFYHOST, 0);

$response = curl_exec($s);

If you're still getting errors after trying these steps, it might be a good idea print out the full response from cURL to see if there's any additional about what's going wrong. You can do this by adding echo curl_error($s); after curl_exec($s);.

 

Hope this helps!

Liam | Developer Advocate @ Shopify 
 - Was my reply helpful? Click Like to let me know! 
 - Was your question answered? Mark it as an Accepted Solution
 - To learn more visit Shopify.dev or the Shopify Web Design and Development Blog

rediskapsts
Shopify Partner
4 0 3

Hi Liam,

 

All of these tips are pretty obvious and none of them solve the problem:

  1. $brand->getShopifyCustomAccessToken() is correct and works fine with other REST API requests, and I also assume that I would receive an error that would indicate that the token is invalid.
  2. Also works great with other REST API requests, but I combined them into one array and this did not affect the result.
  3. As you can see in my example there are no line breaks or special characters.
  4. I tried to use also 'Content-Type: application/graphql', it did not affect the result.
  5. 'json_encode($requestData)' returns a string which is valid JSON, but I also tried passing $query with the values '{shop { name }}', '{"query":"{shop { name }}"}' and '{"query": "query { shop { name } }"}' it didn't help.