What You Need to Know about GraphQL in Magento

GraphQL in Magento | What You Need to Know about GraphQL in Magento

Finding various approaches to working with APIs is easy, yet GraphQL emerges to be the most victorious for the simple fact because its many strengths can benefit you in the best way. But, what exactly is GraphQL and why so much buzz around it? Let’s figure out more here.

 

GraphQL is a data query language developed by Facebook. Magento supports GraphQL along with REST API architecture. There are some awesome GraphQL APIs already provided by Magento as a part of the installation.

 

Magento provides default GraphQL APIs for some of its modules. To access these APIs there are different API testing tools like GraphiQL, Postman, Firecamp, and so on. In this article, we make use of the GraphiQL chrome extension to test our GrpahQL APIs.

 

Grapql supports two types of operations :

  1. Queries 
  2. Mutation 

 

Queries are used to fetch only data from the database, whereas mutations are used to make changes in the database such as adding new records, updating existing records, deleting records. You can check out the existing GraphQL queries and mutations at your_domain_name/graphql endpoint.  


GraphQL in Magento Mutation OperationGraphQL in Magento Queries Operation

 

How to create graphql API for your custom Magento module

As we know, to build any custom Magento module we need the Vendor name and module name. In the article, we have used Sjinnovation as vendor name and GraphqlDemo as the module name.  Let's get started with the basic steps involved in creating a Magento module.

 

Create module.xml

app\code\Sjinnovation\GraphqlDemo\etc\module.xml

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Sjinnovation_GraphqlDemo" setup_version="1.1.0">
        <sequence>
            <module name="Magento_GraphQl"/>
            <module name="Sjinnovation_Videos"/>
        </sequence>
    </module>
</config>

 

To use Graphql in the custom module we need to specify a Magento graphql module in the dependency list ( i.e Magento_GraphQl) of our module.xml file. Additionally, you can specify the other necessary modules as per your requirement. We have used a module Sjinnovation_Videos which does all the required CRUD operations on the custom table in the database.

 

Register the module 

app\code\Sjinnovation\GraphqlDemo\registration.php

<?php \Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Sjinnovation_GraphqlDemo',
    __DIR__
);

 

GraphQL Query 

 

Setup Graphql Schema

Create a new file with the name schema.graphqls in etc directory

 app\code\Sjinnovation\GraphqlDemo\etc\schema.graphqls

type Query {
getVideoData : [VideoData] @resolver (class:"\\Sjinnovation\\GraphqlDemo\\Model\\Resolver\\VideoDataResolver") @doc(description:"List of videos")
}
type VideoData {
video_id: Int @doc(description: "Video Id")
title: String @doc(description: "Video Title")
sub_title: String @doc(description: "Video Sub-title")
url: String @doc(description: "Video URL")
banner_url: String @doc(description: "Video Banner URL")
}

 

Let’s look at the above code. To define any query operation make use of query type. In the above code :

  1. getVideoData is the query name. 
  2. VideoData is a custom graphql return type
  3. @resolver specifies the resolver class which will be invoked when the  getVideoData query gets fired.
  4. @doc allows to insert documentation for query, fields
  5. VideoData returns the object having video id, title, sub-title, URL, and banner URL. 

 

Setup Resolver for GraphQL query

Let’s create a resolver class for the above query. Create VideoDataResolver class at \Sjinnovation\GraphqlDemo\Model\Resolver directory.

 

<?php

declare(strict_types=1);

namespace Sjinnovation\GraphqlDemo\Model\Resolver;

use Magento\Framework\GraphQl\Config\Element\Field;
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
use Magento\Framework\GraphQl\Query\ResolverInterface;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;

class VideoDataResolver implements ResolverInterface
{
    /**
    * @param Field $field
    * @param \Magento\Framework\GraphQl\Query\Resolver\ContextInterface $context
    * @param ResolveInfo $info
    * @param array|null $value
    * @param array|null $args
    * @return array|\Magento\Framework\GraphQl\Query\Resolver\Value|mixed
    * @throws GraphQlInputException
    */

    private $dataProvider;
    

    public function __construct(
        \Sjinnovation\GraphqlDemo\Model\Resolver\DataProvider\Videos $dataProvider
    ) {
        $this->dataProvider = $dataProvider;
    }

    public function resolve(
        Field $field,
        $context,
        ResolveInfo $info,
        array $value = null,
        array $args = null)
    {
        return $this->dataProvider->getVideos();
    }
}

 

Let’s have a look at the resolver code. The first step, import all the required GrapQL dependencies. The next step is to implement ResolverInterface. Following this, define required dependencies in the class constructor. Here we have created a data provider which will fetch the required results. And at last override resolve function which makes a call to function of the data provider and returns the result.

 

Lets create data provider. Create Videos class at \Sjinnovation\GraphqlDemo\Model\Resolver\DataProvider

 

<?php
namespace Sjinnovation\GraphqlDemo\Model\Resolver\DataProvider;

use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
use Magento\Framework\Exception\LocalizedException;

class Videos
{
    protected $_videoFactory;

    protected $_objectManager;

    public function __construct(
        \Sjinnovation\Videos\Model\ResourceModel\Videos\CollectionFactory $videoFactory,
        \Magento\Framework\ObjectManagerInterface $objectManager
        )
    {
        $this->_videoFactory  = $videoFactory;
        $this->_objectManager = $objectManager;
    }
 
    public function getVideos()
    {
        $videoData = [];
        try {
            $collection = $this->_videoFactory->create();
            $videoData = $collection->getData();

        } catch (NoSuchEntityException $e) {
            throw new GraphQlNoSuchEntityException(__($e->getMessage()), $e);
        }
        return $videoData;
    }

   
}

 

Lets look at getVideos() function code. It gets all the records from the database table and returns the collection to the resolver. 

 

Please make sure you insert some sample data in the database table

 

Let’s test it out. Execute following commands

php bin/magento cache:clean

php bin/magento setup:upgrade

 

GraphQL in Magento Command Panel

 

GraphQL Mutation 

Now, let’s edit our graphql schema to include mutation.

 

type Query {
getVideoData : [VideoData] @resolver (class:"\\Sjinnovation\\GraphqlDemo\\Model\\Resolver\\VideoDataResolver") @doc(description:"List of videos")
}
type VideoData {
video_id: Int @doc(description: "Video Id")
title: String @doc(description: "Video Title")
sub_title: String @doc(description: "Video Sub-title")
url: String @doc(description: "Video URL")
banner_url: String @doc(description: "Video Banner URL")
}

type Mutation {
createVideo(input: VideoInput!): VideoOutput @resolver (
class: "\\Sjinnovation\\GraphqlDemo\\Model\\Resolver\\CreateVideo") @doc(
description: "Insert new video")
}

input VideoInput {
title: String @doc(description: "Video Title")
sub_title: String @doc(description: "Video Sub-title")
url: String @doc(description: "Video URL")
banner_url: String @doc(description: "Video Banner URL")
}

type VideoOutput {
message: String @doc(description: "status message")
}

 

  • Mutation operation is named as createVideo. 
  • VideoInput is a custom graphql input type having all the input variables 
  • VideoOutput is a custom graphql output type that sends the status message

 

As we can see for the above mutation, we have a new resolver to be created. So let’s create a CreateVideo resolver class at \Sjinnovation\GraphqlDemo\Model\Resolver

 

<?php

declare(strict_types=1);

namespace Sjinnovation\GraphqlDemo\Model\Resolver;

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

class CreateVideo implements ResolverInterface
{
    /**
    * @param Field $field
    * @param \Magento\Framework\GraphQl\Query\Resolver\ContextInterface $context
    * @param ResolveInfo $info
    * @param array|null $value
    * @param array|null $args
    * @return array|\Magento\Framework\GraphQl\Query\Resolver\Value|mixed
    * @throws GraphQlInputException
    */

    private $dataProvider;
   

    public function __construct(
        \Sjinnovation\GraphqlDemo\Model\Resolver\DataProvider\Videos $dataProvider
    ) {
        $this->dataProvider = $dataProvider;
    }

    public function resolve(
        Field $field,
        $context,
        ResolveInfo $info,
        array $value = null,
        array $args = null)
    {
        try {
        return $this->dataProvider->insertVideo($args['input']);
    }
    catch (\Exception $e) {
          throw new GraphQlInputException(__($e->getMessage()));
      }
    }
}

 

Again, this resolver is going to implement ResolverInterface and override its resolve function. GraphQL input objects/variables are stored in $args parameter which is passed to insertVideo function of dataprovider class. 

 

Let’s create insertVideo() function in dataprovider class.

 

<?php
namespace Sjinnovation\GraphqlDemo\Model\Resolver\DataProvider;

use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
use Magento\Framework\Exception\LocalizedException;

class Videos
{
    protected $_videoFactory;

    protected $_objectManager;

    public function __construct(
        \Sjinnovation\Videos\Model\ResourceModel\Videos\CollectionFactory $videoFactory,
        \Magento\Framework\ObjectManagerInterface $objectManager
        )
    {
        $this->_videoFactory  = $videoFactory;
        $this->_objectManager = $objectManager;
    }
    /**
    * @params int $id
    * this function return all the word of the day by id
    **/
    public function getVideos()
    {
        $videoData = [];
        try {
            $collection = $this->_videoFactory->create();
            $videoData = $collection->getData();

        } catch (NoSuchEntityException $e) {
            throw new GraphQlNoSuchEntityException(__($e->getMessage()), $e);
        }
        return $videoData;
    }

    public function insertVideo($data)
    {
        if($this->validateURL($data['url']) && $this->validateURL($data['banner_url']))
        {
            if(is_array($data)) {
            $video = $this->_objectManager->create('Sjinnovation\Videos\Model\Videos');
            $video->setData($data)->save();
            }
        return ['message' => 'Success'];
        }
        else {
            throw new LocalizedException(__('URL must be valid'));
        }
    }

    public function validateURL($url) {
        if(filter_var($url, FILTER_VALIDATE_URL))
            return True;
        else
            return False;
    }
}

 

First, we validate the required URLs. You can validate the required fields as per the requirements. Next, we create a new video model instance using object manager and set the data to model. And finally, we save the model which does the insert operation in the database table. 

 

Let’s see the test results 

GraphQL in Magento Command Panel  

 

So there you go!

 

You can also read about Magento Salesforce integration while for any other help or assistance, contact our experts in Mageno services. We can certainly help you with all of your major and minor concerns. 

 

Legred Vaz
Legred Vaz
Software Engineer
A Dive into Cybersecurity by Mahmudul Hassan from SJ Innovation

A Dive into Cybersecurity

MAHMUDUL HASSAN
Custom Module Development in Magento 2

Magento 2 Custom Module Development

Akshay Naik
Overcoming Mistakes

Mistakes I made as a leader and my way of overcoming them

ARIF ISLAM