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.