Magento 2 GraphQL
Published: 2024-06-28 13:04:25


**Introduction:
**
GraphQL is a query language for APIs. developed by Facebook (now Meta). It allows developers to get the data they need and only receive it in response to their queries. Magento 2 supports GraphQL to help you streamline your data processes.

 Three main operations of GraphQL are in use:

queries (for reading and receiving information);
mutations (needed for taking actions, creating data, and changing information,insert,update,delete);
subscriptions (this operation isn’t available in Magento yet, but it provides the opportunity to get data from the server in real-time automatically after a while, for instance, for notification.


Queries:
For reading and receiving information.

Mutations:
It is an operation of GraphQL by which you can insert new data or modify the existing data.
Mutations requests should be in the POST method only. You can optionally send a GET query request in a URL.
Data with Mutations : Query is used to fetch data but there could be a need where a person needs to make changes in backend data. So to achieve this in GraphQL we use Mutations.
Mutation Operations :
– creating new data
– updating existing data
– deleting existing data


Why Use GraphQL:
Developers can request only the data they need, which results in smaller and more efficient data transfers. This is especially important for mobile and low-bandwidth devices.
It has a simple and intuitive syntax, making it easy for developers to learn and use. This simplicity reduces the learning curve and allows developers to focus on building their applications.
Developers can create custom GraphQL queries, mutations, and types, allowing them to extend the platform’s default schema and create custom functionality that meets their specific requirements.
It allows for optimized queries, which can significantly improve application performance. This is because it reduces the number of API requests required to fetch data.




Requirements for Run GraphQL in Magento 2:
You can check your GraphQL query response by installing chrome extension ChromeiQL Or Altair.
If you install a browser extension, make sure it can set request headers. 



Access a graphQL Endpoint in Magento 2:
https://<magento2-server>/graphql



Add This Sample Graphql (Already Defined By Magento 2) In The Editor And Send A Request To Get Product Data And Test Whether The Graphql Environment Is Setup or Not.
#Request
{
  products(
    filter: { sku: { eq: "24-WB01" } }
  ) {
    items {
      name
      sku
    }
  }
}

#Response:
{
  "data": {
    "products": {
      "items": [
        {
          "name": "Voyage Yoga Bag",
          "sku": "24-WB01"
        }
      ]
    }
  }
}




Define GraphQL Schema (Create Custom GraphQL):

When making a GraphQL request in Magento, the request supports the HTTP GET and POST methods. Mutations requests should be in the POST method only. You can optionally send a GET query request in a URL.

For example, http://<host>/graphql?query=%7Bproducts sent a GET request with a query string in the URL.

First Create A Custom Module For Our Graphql And Make A Below Files At Specific Path

A GraphQL schema defines the types, queries, and mutations your API will support.

Next, create a file in app/code/Vendor/Module/etc/schema.graphls directory like in the example below. Note that the etc/schema.graphqls part is mandatory.




Schema.graphqls (Reference):

Defines the basic structure of queries and mutations.
Defines which attributes can be used for input and output in GraphQL queries and mutations.
Requests and responses contain separate lists of valid features.
Points to the resolvers that verify and process the input data and response.
Is the source for displaying the schema in a GraphQL browser.
Defines which objects are cached.



type Query {
myCustomQuery(input: MyCustomInput!): MyCustomOutput @resolver(class: "Vendor\\Module\\Model\\Resolver\\MyCustomQuery")
}


Now Create a Resolver Class For add custom logic and return output data at below path


Vendor/Module/Model/Resolver/MyCustomQuery.php








GraphQL Authorization (Reference):

Authorization tokens: Commerce generates a JSON Web Token (JWT), a set of cryptographically signed credentials. All calls that perform an action on behalf of a logged-in customer or admin provide an authorization token. Authorization tokens are stateless. Commerce does not need to know the state of a client to execute a request--the token contains all of the information needed for authorization and authentication.

Session cookies: A session cookie is information generated by Commerce that is stored in the client's browser. It contains details about the session, including the time period the user can access resources. Cookies are stateful, thereby increasing complexity and possibly latency.

Adobe recommends that you use authorization tokens instead of session cookies for GraphQL requests. 

Adobe Commerce provides separate token services for customers and administrators. When you request a token from one of these services, the service returns a unique access token in exchange for the account's username and password.

GraphQL provides a mutation that returns a token on behalf of a logged-in customer, but you must use a REST call to fetch an admin token. Any time you make a GraphQL or REST call that requires a token, specify the HTTP Authorization request header and assign the value as Bearer <token>. Request headers provide an example.




Admin tokens:

In Adobe Commerce and Magento Open Source GraphQL, you specify an admin token only if you need to query products, categories, price rules, or other entities that are scheduled to be in a campaign (staged content). Staging is supported in Adobe Commerce only. See Staging queries for more information.

Adobe Commerce and Magento Open Source do not provide a GraphQL mutation that generates an admin token. You must use a REST endpoint such as POST /V1/tfa/provider/google/authenticate instead. Generate the admin token shows how to use this endpoint.

By default, an admin token is valid for 4 hours. You can change these values from Admin by selecting Stores > Settings > Configuration > Services > OAuth > Access Token Expiration > Admin Token Lifetime.










Customer tokens:

The generateCustomerToken mutation requires the customer email address and password in the payload, as shown in the following example.

By default, a customer token is valid for 1 hour. You can change these values from Admin by selecting Stores > Settings > Configuration > Services > OAuth > Access Token Expiration > Customer Token Lifetime.

#Request
mutation {
  generateCustomerToken(email: "customer@example.com", password: "password") {
    token
  }
}


#Response
 {
   "data": {
     "generateCustomerToken": {
       "token": "hoyz7k697ubv5hcpq92yrtx39i7x10um"
     }
   }
 }


generateCustomerTokenAsAdmin: for remote shopping assistant

#Request
mutation{
  generateCustomerTokenAsAdmin(input: {
    customer_email: "customer@gmail.com"
  }){
    customer_token
  }




Set Header For Customer Authentication:


Key: Authorization
Value: Bearer {Token}



Query Example (Without Parameters):

Create a schema.graphql file under etc directory and put below code.

Vendor/Module/etc/schema.graphql


#Magento GraphQL Query Schema

type Query {
testcustomer: returnData
@resolver(class: "Dolphin\\Core\\Model\\Resolver\\Customer") @doc(description: "Returns information about a customer")
}

type returnData @doc(description: "Testcustomer defines the customer name and other details") {
    entity_id: Int
    firstname: String
    lastname: String
    email: String
}


Here we create a query with name testcustomer and assign a resolver class
Add description text using @doc(description:’abc’) & provide the fields for customers.
Now, Create a Resolver Class at Vendor/Module/Model/Resolver/Customer.php
Add Your Custom Logic and return data in this resolver class

<?php
namespace Dolphin\Core\Model\Resolver;

use Magento\Framework\GraphQl\Config\Element\Field;
use Magento\Framework\GraphQl\Query\ResolverInterface;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;

class CustomData implements ResolverInterface
{
    private $customDataProvider;

    public function __construct(
        \Dolphin\Core\Model\Resolver\DataProvider\CustomData $customDataProvider
    ) {
        $this->customDataProvider = $customDataProvider;
    }
    public function resolve(
        Field $field,
        $context,
        ResolveInfo $info,
        array $value = null,
        array $args = null
    ) {
        $customData = $this->customDataProvider->getCustomData();
        return $customData;
    }
}


That’s It Now Open Your Editor And Run This GraphQl.
Note: Don’t Forget To Add Customer Token In Header Before Send A Request.

#Request
query {
  testcustomer {
    entity_id
    firstname
    lastname
    email
  }
}



Our Graphql Response Provides The Customer Data.

#Response
{
  "data": {
    "testcustomer": {
      "entity_id": 208,
      "firstname": "maulik",
      "lastname": "maulik",
      "email": "demo@gmail.com"
    }
  }
}





Mutation Example (With Parameters):

Vendor/Module/etc/schema.graphql


# mutation examples for update a record

type Mutation {
  recordUpdate(input: editInput!): editOutput
    @resolver(class: "Dolphin\\Core\\Model\\Resolver\\RecordUpdate")
    @doc(description: "Data Update")

}


Here recordUpdate is the graphql schema  which accepts input as a parameter.
(The exclamation(!) point indicates the value is non-nullable).
Additionally passed a resolver class which contains an operation logic of update record.
we pass the input fields like below into the editInput.


input editInput {
  car_id: Int @doc(description: "Record Id")
  manufacturer: String @doc(description: "The manufacturer Name")
  model: String @doc(description: "The model")
}




We set some fields as an input which is used to get the user input & update the data.
editOutput is set the output data of graphql response.


type editOutput {
  status: Boolean
  message: String
}


Here status returns the value true/false And message shows a custom message to the user.
Create a Resolver File For Custom Logic and Set Return Data.
Make Sure the output data and structure are same as defined in the schema file else it will be returned null.


        $recordUpdate = [];
        $recordUpdate["status"] = $status;
        $recordUpdate["message"] = $message;
        return $recordUpdate;


Main function recordUpdate contains the output data with the key we passed on editOutput.

#Request
mutation {
  recordUpdate(input:{ car_id: 10,manufacturer:"Honda",model:"RTX" }) {
    status
    message
  }
}




#Response
{
  "data": {
    "recordUpdate": {
      "status": true,
      "message": "Data Update Successfully"
    }
  }
}



Magento 2 GraphQL Exception Handling:

Adobe Commerce and Magento Open Source provide the following exception classes in Magento\Framework\GraphQl\Exception\Class.

Exceptions:

CLASS


DESCRIPTION
GraphQlAlreadyExistsException


Thrown when data already exists
GraphQlAuthenticationException


Thrown when an authentication fails
GraphQlAuthorizationException


authorization error occurs
GraphQlInputException


query contains invalid input
GraphQlNoSuchEntityException


an expected resource doesn't exist





EOD