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: