Creating custom console command in Magento 2

In Magento 2, Many application we need to do perform many things after did any deployment. Or other similar thing that we need to do every time or do perform that some specific of time. In that case we can use Magento cron or also we can create one console command for the same.

Like if we need to perform anything after the deployment then the console command is good thing to do. We need to implement all the thing in one console command.

When we run deployment commnad and once it’s completed so we just need to run our custom console command, it’s run everything that we need to perform everytime when we do deployment.

Let’s create small module for console command.

Register our custom module to Magento application

We need to create registration.php file for register our custom module in Magento 2.

<?php
//file path: MAGENTO_ROOT/app/code/RS/SimpleCmd/registration.php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'RS_SimpleCmd',
    __DIR__
);

Configure module version and module dependency

We need to create module.xml file for configure module version and module dependency.

<?xml version="1.0" ?>
<!-- file path: MAGENTO_ROOT/app/code/RS/SimpleCmd/etc/module.xml -->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
	<module name="RS_SimpleCmd" setup_version="1.0.0">
	</module>
</config>

Register your custom console command in Magento application

Using di.xml we can register our custome commnad in Magento 2 Application. We need to add arguments on Magento\Framework\Console\CommandList this class adds the new console command in Magento 2. In that argument we need to give command class and command name.

<?xml version="1.0"?>
<!-- file path: MAGENTO_ROOT/app/code/RS/SimpleCmd/etc/di.xml -->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Framework\Console\CommandList">
        <arguments>
            <argument name="commands" xsi:type="array">
                <item name="simplecmd" xsi:type="object">RS\SimpleCmd\Console\Simple</item>
            </argument>
        </arguments>
    </type>
</config>

Creating the console command class

Magento 2 create console command using symfony library. We create console command extending of the symfony library class.

<?php
//file path: MAGENTO_ROOT/app/code/RS/SimpleCmd/Console/Simple.php 
namespace RS\SimpleCmd\Console;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class Simple extends Command
{
    protected function configure()
    {
        $this->setName('rs:simple:command');
        $this->setDescription('This is simple command for demo');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $output->writeln('Hi, Your custom command is called and executed successfully!');
        return \Magento\Framework\Console\Cli::RETURN_SUCCESS;
    }
}

Let’s check the output.

Output

Custom console command in Magento command list.

Custom command output

That’s all for create custom console command in Magento 2 application.

Creating extension attributes in Magento 2

About Extension Attribute

Using Extension attribute we can extends the data interface functionality without modify the actual file. We can add additional fields to Data interface as per our needs.

We can create extension attributes using extension_attributes.xml file. In that file need to pass the data interface and your attribute name that you need to create.

It’s not require to create that field in database. We can create extension attribute without the database field or attribute.

Let’s create one small module for extension attributes.

Register extension attribute module in Magento 2 Application.

Using registration.php file we can register our module component to Magento 2 application.

<?php
//file path: MAGENTO_ROOT/app/code/RS/ExtAttributes/registration.php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'RS_ExtAttributes',
    __DIR__
);

After register the our module to Magento, Need to config module version and dependency.

Config module dependency and configure module version.

Using module.xml we can configure module version and module dependency.

<?xml version="1.0" ?>
<!-- file path: MAGENTO_ROOT/app/code/RS/ExtAttributes/etc/module.xml -->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
	<module name="RS_ExtAttributes" setup_version="1.0.0">
	</module>
</config>

Create extension attribute

Using extension_attributes.xml file we can create extension attributes.

<?xml version="1.0" ?>
<!-- file path: MAGENTO_ROOT/app/code/RS/ExtAttributes/etc/extension_attributes.xml -->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
    <extension_attributes for="Magento\Catalog\Api\Data\ProductInterface">
        <attribute code="custom_note" type="string" />
    </extension_attributes>
</config>

In above example I did not create any attribute or database field for that extension attribute. We can create extension attribute without any attribute or any database field.

Validate extension attribute is created or not

For validating extension attribute, We need to install this module.

php bin/magento module:enable RS_ExtAttributes
php bin/magento setup:upgrade
php bin/magento setup:di:compile

After that just open that Product extension class from the generated derectory.

just check that two

<magento_root>/generated/code/Magento/Catalog/Api/Data/ProductExtension.php

<magento_root>/generated/code/Magento/Catalog/Api/Data/ProductExtensionInterface.php

It’s auto generated extension attribute methods to that both class.

Let me add the screen sorts.

Get extension attribute data

At the moment creating the custom script to get extension attribute and it’s data

<?php

use Magento\Framework\App\Bootstrap;
use Magento\Framework\App\State;
use Magento\Catalog\Api\ProductRepositoryInterface;

require 'app/bootstrap.php';

$bootstrap = Bootstrap::create(BP, $_SERVER);
$objectManager = $bootstrap->getObjectManager();
$state = $objectManager->get(State::class);
$state->setAreaCode('frontend');

$productRepository = $objectManager->create(ProductRepositoryInterface::class);
$product = $productRepository->getById(1);
$extentionAttr = $product->getExtensionAttributes();

print_r(get_class_methods($extentionAttr));
print_r($extentionAttr->getCustomNote()); /* return null due to that we need to set menually when product data is load */

That’s all for creating extensions attribute in Magento 2.

Create custom rest API in Magento 2

Magento 2 has a lot of pre-defined apis, That provide the access of all the default magento entities. If we implement a new thing in our Magento application and that data we need to pass in to a third-party service provider then we need to do the custom rest api for accessing the custom data into the third-party service provider.

In Magento 1 it is difficult to create a custom rest api. But Magento 2 provides a good structure to create a Rest API.

Magento 2 has webapi.xml for registering our new rest api in Magento 2 application. And in that file have details about which interface and which method is responsible for processing our request and give response to the consumer.

Also need to create an Interface for defining the type of argument and response type. We need to pass the request as per type mentioned on the interface.

Let’s create a custom API step by step.

Register new Module for custom rest API.

Let’s create a registration.php file to register our custom module component.

<?php
//file path: MAGENTO_ROOT/app/code/RS/RestApi/registration.php

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'RS_RestApi',
    __DIR__
);

Define the module version and module dependency.

Creating the module.xml file for config module version and other module dependency.

<?xml version="1.0"?>
<!-- file path: MAGENTO_ROOT/app/code/RS/RestApi/etc/module.xml -->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="RS_RestApi" setup_version="1.0.0" />
</config>

Register custom rest API.

Creating the webapi.xml for register new custom api in Magento 2 application. In this file have interface to represent the api request and response.

Also need to set the API type like GET and POST. In this file also we need to define the api endpoint.

Below webapi.xml, I registered a custom rest api that returns the user details. getAll is a method that represents the request and response.

Let’s create the webapi.xml file.

<?xml version="1.0"?>
<!-- file path: MAGENTO_ROOT/app/code/RS/RestApi/etc/webapi.xml -->
<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../app/code/Magento/Webapi/etc/webapi.xsd">
    <route method="GET" url="/V1/rs/restapi/getDetails">
        <service class="RS\RestApi\Api\UserRepositoryInterface" method="getAll"/>
        <resources>
            <resource ref="anonymous"/>
        </resources>
    </route>
</routes>

Create the interfaces for this api.

We need to create a few interfaces for this api. And one interface for response type. Also we need to create one more interface for the result interface.

UserRepositoryInterface.php

<?php
//file path: MAGENTO_ROOT/app/code/RS/RestApi/Api/UserRepositoryInterface.php 

namespace RS\RestApi\Api;

interface UserRepositoryInterface
{
    /**
     * Get all users
     * 
     * @api
     * 
     * @return \RS\RestApi\Api\Data\UserInfoSearchResultsInterface
     */
    public function getAll();
}

UserInfoInterface.php

<?php
//file path: MAGENTO_ROOT/app/code/RS/RestApi/Api/Data/UserInfoInterface.php 

namespace RS\RestApi\Api\Data;
 
interface UserInfoInterface
{
    const NAME = "name";
    const POST = "post";
    const EXP = "exeperience";

    /**
     * Get user name
     * 
     * @return string
     */
    public function getName();

    /**
     * Set user name
     * 
     * @param string $name
     * @return $this
     */
    public function setName($name);

    /**
     * Get user post
     * 
     * @return string
     */
    public function getPost();

    /**
     * Set user post
     * 
     * @param string $post
     * @return $this
     */
    public function setPost($post);

    /**
     * Get user exeperience
     * 
     * @return string
     */
    public function getExeperience();

    /**
     * Set user exeperience
     * 
     * @param string $exp
     * @return $this
     */
    public function setExeperience($exp);
}

UserInfoSearchResultsInterface.php

<?php
//file path: MAGENTO_ROOT/app/code/RS/RestApi/Api/Data/UserInfoSearchResultsInterface.php

namespace RS\RestApi\Api\Data;

use Magento\Framework\Api\SearchResultsInterface;

interface UserInfoSearchResultsInterface extends SearchResultsInterface
{
    /**
     * Get data list.
     *
     * @return \RS\RestApi\Api\Data\UserInfoInterface[]
     */
    public function getItems();

    /**
     * Set data list.
     *
     * @param \RS\RestApi\Api\Data\UserInfoInterface[] $items
     *
     * @return $this
     */
    public function setItems(array $items);
}

Let’s implement that all the interface.

We need to create a few models that implement this interface. Need to create a di.xml file for configuring all interface overriding classes.

di.xml

<?xml version="1.0"?>
<!-- file path: MAGENTO_ROOT/app/code/RS/RestApi/etc/di.xml -->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="RS\RestApi\Api\Data\UserInfoInterface" type="RS\RestApi\Model\Api\Data\UserInfo"/>
    <preference for="RS\RestApi\Api\Data\UserInfoSearchResultsInterface" type="RS\RestApi\Model\Api\Data\UserInfoSearchResult"/>
    <preference for="RS\RestApi\Api\UserRepositoryInterface" type="RS\RestApi\Model\UserRepository"/>
</config>

UserRepository.php

<?php
//file path: MAGENTO_ROOT/app/code/RS/RestApi/Model/UserRepository.php 

namespace RS\RestApi\Model;

use Magento\Framework\Data\Collection;
use RS\RestApi\Api\Data\UserInfoInterfaceFactory;
use RS\RestApi\Api\Data\UserInfoSearchResultsInterfaceFactory;
use RS\RestApi\Api\UserRepositoryInterface;
 
class UserRepository implements UserRepositoryInterface
{
    /**
     * Creating static data
     */
    private $users = [
        [
            "name" => "Raju",
            "post" => "Magento",
            "exeperience" => "8 Years",
        ],
        [
            "name" => "Ketan",
            "post" => "QA",
            "exeperience" => "6 Years",
        ],
        [
            "name" => "Mahendra",
            "post" => "Java",
            "exeperience" => "11 Years",
        ]
    ];

    /**
     * @var Collection
     */
    private $collection;

    /**
     * @var UserInfoInterfaceFactory
     */
    private $userInfoFactory;

    /**
     * @var UserInfoSearchResultsInterfaceFactory
     */
    private $userInfoSearchResultsFactory;

    /**
     * 
     * @param UserInfoSearchResultsInterfaceFactory $userInfoSearchResultsFactory,
     * @param Collection $collection
     * @param UserInfoInterface $userInfoFactory
     */
    public function __construct(
        UserInfoSearchResultsInterfaceFactory $userInfoSearchResultsFactory,
        Collection $collection,
        UserInfoInterfaceFactory $userInfoFactory
    ) {
        $this->userInfoSearchResultsFactory = $userInfoSearchResultsFactory;
        $this->collection = $collection;
        $this->userInfoFactory = $userInfoFactory;
    }

    /**
     * Get all users
     * 
     * @api
     * 
     * @return UserInfoSearchResultsInterface
     */
    public function getAll()
    {
        foreach ($this->users as $user) {
            $item = $this->userInfoFactory->create()->setData($user);
            $this->collection->addItem($item);
        }
        $searchResults = $this->userInfoSearchResultsFactory
            ->create();
        $searchResults->setItems($this->collection->getItems());
        $searchResults->setTotalCount($this->collection->getSize());

        return $searchResults;
    }
}

UserInfo.php

<?php
//file path: MAGENTO_ROOT/app/code/RS/RestApi/Model/Api/Data/UserInfoInterface.php 
namespace RS\RestApi\Model\Api\Data;

use Magento\Framework\DataObject;
use RS\RestApi\Api\Data\UserInfoInterface;
 
class UserInfo extends DataObject implements UserInfoInterface
{
    /**
     * Get user name
     * 
     * @return string
     */
    public function getName()
    {
        return $this->getData(self::NAME);
    }

    /**
     * Set user name
     * 
     * @param string $name
     * @return $this
     */
    public function setName($name)
    {
        return $this->setData(self::NAME, $name);
    }

    /**
     * Get user post
     * 
     * @return string
     */
    public function getPost()
    {
        return $this->getData(self::POST);
    }

    /**
     * Set user post
     * 
     * @param string $post
     * @return $this
     */
    public function setPost($post)
    {
        return $this->setData(self::POST, $post);
    }

    /**
     * Get user exeperience
     * 
     * @return string
     */
    public function getExeperience()
    {
        return $this->getData(self::EXP);
    }

    /**
     * Set user exeperience
     * 
     * @param string $exp
     * @return $this
     */
    public function setExeperience($exp)
    {
        return $this->setData(self::EXP, $exp);
    }
}

UserInfoSearchResult.php

<?php
//file path: MAGENTO_ROOT/app/code/RS/RestApi/Model/Api/Data/UserInfoSearchResult.php 

namespace RS\RestApi\Model\Api\Data;

use Magento\Framework\Api\SearchResults;
use RS\RestApi\Api\Data\UserInfoSearchResultsInterface;

class UserInfoSearchResult extends SearchResults implements UserInfoSearchResultsInterface
{

}

I have created all the interfaces and models that require creating a custom simple api. I am attaching the output.

Output.

That’s all for create custom rest api in Magento 2.

We can also set specific role in our custom api. Please reach out me if you need more help contact us : rsadadiya@gmail.com Or if you need hire me for create or customised your application or your APIs. Please click here to view more information about hire.