Create a Custom GraphQl in Magento 2 – Part 2: How to create and use mutation

Create a Custom GraphQl in Magento 2 – Part 2: How to create and use mutation

Earlier we talked about creating and reading the posts using query. Today we will discuss creating new posts using Graphql.

To learn more about creating query in graphql, visit the link below:

Magento2 How to create a custom GraphQL – Part1: Create a simple graphql query

Watch part1 on youtube: https://youtu.be/3TtWi8oPm6I

To perform CRUD operations we will make use of mutations. A mutation can create, update, or delete objects and fields.

The structure of mutation involves:

  • The keyword mutation
  • The mutation name
  • The input object or attributes
  • The output object, which specifies which data to be returned

To learn more visit Magento2 DevDocs

Begin with modifying the Know/ModuleGraphql/etc/schema.graphqls and adding the mutation schema to it.

type Mutation {
    createPost(
        input: createPostInput!
        @doc(description: "An input object that contains changes related to the posts.")
    ): Posts
        @resolver(class: "Know\\ModuleGraphql\\Resolver\\CreatePost")
        @doc(description: "Create or update a post.")
}

Now again modify the schema.graphqls and add createPostInput input to it:

input createPostInput @doc(description: "Contains details about the posts.") {
    entity_id: Int
    title: String!
    description: String!
    categories: String
    created_at: String
    updated_at: String
}

Now according to the schema definition add CreatePost resolver class. Know/ModuleGraphql/Resolver/CreatePost.php

<?php
namespace Know\ModuleGraphql\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 CreatePost implements ResolverInterface
{
    /**
     * @inheritDoc
     */
    public function resolve(
        Field $field,
        $context,
        ResolveInfo $info,
        array $value = null,
        array $args = null
    ) {
        if (empty($args['input']) || !is_array($args['input'])) {
            throw new GraphQlInputException(
                __('"Input" value should be specified and in the form of array.')
            );
        }
    }
}

To handle api business logic create CreatePost model. Know/ModuleGraphql/Model/CreatePost.php

<?php
namespace Know\ModuleGraphql\Model;

use Magento\Framework\GraphQl\Exception\GraphQlInputException;

class CreatePost
{
    private \Know\Module\Model\Post $post;

    private \Know\Module\Model\ResourceModel\Post $resource;

    public function __construct(
        \Know\Module\Model\Post $post,
        \Know\Module\Model\ResourceModel\Post $resource
    ) {
        $this->post = $post;
        $this->resource = $resource;
    }

    public function execute(int $postId, array $postData): \Know\Module\Model\Post
    {
        // Validate the data.
        $this->validateData($postData);
        // Entity model object
        $post = $this->post;
        // If id found load the data
        if ($postId) {
            $this->resource->load($post, $postId);
        }

        $post->setData($postData);
        // Save the post data.
        $this->resource->save($post);
        // Load the updated data.
        if ($post->getId()) {
            $this->resource->load($post, $post->getId());
        }
        return $post;
    }

    private function validateData(array $postData): void
    {
        $errors = [];
        if (empty($postData['title'])) {
            $errors[] = "title";
        }

        if (empty($postData['description'])) {
            $errors[] = "description";
        }

        if (!empty($errors)) {
            throw new GraphQlInputException(
                __('Required parameters are missing: %1', implode(",", $errors))
            );
        }
    }
}

Add the CreatePost model instance and process the request with it. So the final file will look like Know/ModuleGraphql/Resolver/CreatePost.php

<?php
namespace Know\ModuleGraphql\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 CreatePost implements ResolverInterface
{
    private \Know\ModuleGraphql\Model\CreatePost $createPost;

    public function __construct(\Know\ModuleGraphql\Model\CreatePost $createPost)
    {
        $this->createPost = $createPost;
    }

    /**
     * @inheritDoc
     */
    public function resolve(
        Field $field,
        $context,
        ResolveInfo $info,
        array $value = null,
        array $args = null
    ) {
        if (empty($args['input']) || !is_array($args['input'])) {
            throw new GraphQlInputException(
                __('"Input" value should be specified and in the form of array.')
            );
        }

        $data = $args['input'];
        $entity_id = isset($data['entity_id']) ? (int) $data['entity_id'] : 0;
        $post = $this->createPost->execute($entity_id, $data);
        if (empty($postData = $post->toArray())) {
            return [];
        }

        return [
            "id"    =>  $postData["entity_id"],
            "title"    =>  $postData["title"],
            "description"    =>  $postData["description"],
            "categories"    =>  $postData["categories"],
            "created"    =>  $postData["created_at"],
            "updated"    =>  $postData["updated_at"],
        ];
    }
}

Flush the cache


    php bin/magento c:c

Implement the mutation:

mutation {
  createPost(
    input: {
      title: "My New Post"
      description: "Create post using Graphql."
      categories: "Graphql, Mutations"
    }
  ) {
    id
    title
    description
    categories
    created
    updated
  }
}

Send mutation request and it will return following output

{
  "data": {
    "createPost": {
      "id": 12,
      "title": "My New Post",
      "description": "Create post using Graphql.",
      "categories": "Graphql, Mutations",
      "created": "2022-09-01 15:22:40",
      "updated": "2022-09-01 15:22:40"
    }
  }
}

The output screenshot:

createPost Mutation implementation and output

Leave a Reply

Your email address will not be published.