Skip to content

Magento2.4.4p4 REST API Error ‘Class array does not exist’

I had this issue during when I create a custom Rest API in fresh magento 2.4.4p4

enter image description here

As you can see the error I get is "Class array does not exist"

Below are my code folder structure, which I found to be correct already

app/code/Wowshop/ApiFarhan/
├── Api/
│   └── CustomInterface.php
├── etc/
│   ├── di.xml
│   ├── webapi.xml
│   └── module.xml
├── Model/
│   └── Custom.php
├── composer.json
└── registration.php

Please find below content of the 7 file here

app/code/Wowshop/ApiFarhan/Api/CustomInterface.php


namespace WowshopApiFarhanApi;

interface CustomInterface
{
    /**
     * POST for update address API
     * @param int $address_id
     * @param string $address_data
     * @return array
     */
    public function updateAddress($address_id, array $address_data);
    /**
     * POST to add new address for a customer
     * @param int $customer_id
     * @param array $address_data
     * @return array
     */
    public function addAddress($customer_id, array $address_data);
}

app/code/Wowshop/ApiFarhan/etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="WowshopApiFarhanApiCustomInterface" type="WowshopApiFarhanModelCustom"/>
</config>

app/code/Wowshop/ApiFarhan/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="Wowshop_ApiFarhan" setup_version="1.0.0"/>
</config>

app/code/Wowshop/ApiFarhan/etc/webapi.xml

<?xml version="1.0"?>
<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Webapi/etc/webapi.xsd">
    <route url="/V1/wowshop/address/add" method="POST">
        <service class="WowshopApiFarhanApiCustomInterface" method="addAddress"/>
        <resources>
            <resource ref="anonymous"/>
        </resources>
    </route>
    <route url="/V1/wowshop/address/update" method="POST">
        <service class="WowshopApiFarhanApiCustomInterface" method="updateAddress"/>
        <resources>
            <resource ref="anonymous"/>
        </resources>
    </route>
</routes>

app/code/Wowshop/ApiFarhan/Model/Custom.php

<?php

namespace WowshopApiFarhanModel;

use WowshopApiFarhanApiCustomInterface;
use MagentoCustomerApiAddressRepositoryInterface;
use MagentoCustomerApiDataAddressInterface;
use MagentoCustomerApiDataAddressInterfaceFactory;
use MagentoCustomerApiDataRegionInterfaceFactory;
use MagentoCustomerApiCustomerRepositoryInterface;

class Custom implements CustomInterface
{
    private $addressRepository;
    private $addressFactory;
    private $regionFactory;
    private $customerRepository;

    public function __construct(
        AddressRepositoryInterface $addressRepository,
        AddressInterfaceFactory $addressFactory,
        RegionInterfaceFactory $regionFactory,
        CustomerRepositoryInterface $customerRepository
    ) {
        $this->addressRepository = $addressRepository;
        $this->addressFactory = $addressFactory;
        $this->regionFactory = $regionFactory;
        $this->customerRepository = $customerRepository;
    }

     /**
     * Accept address_id and new address data and return the updated data to user
     * @author : Farhan
     *
     * @api
     * @param int $address_id Users address_id.
     * @param string $address_data Users address.
     * @return array Updated data to user
     */  
    public function updateAddress($address_id, array $address_data)
    {
        try {
            /** @var AddressInterface $address */
            $address = $this->addressRepository->getById($address_id);
            foreach ($address_data as $key => $value) {
                if (method_exists($address, 'set' . ucfirst($key))) {
                    $address->{'set' . ucfirst($key)}($value);
                }
            }
            $this->addressRepository->save($address);
            return ['address' => $this->convertAddressToArray($address)];
        } catch (Exception $exception) {
            return ['error' => $exception->getMessage()];
        }
    }

    /**
     * Convert AddressInterface to array
     *
     * @param AddressInterface $address
     * @return array
     */
    private function convertAddressToArray(AddressInterface $address)
    {
        return [
            'id' => $address->getId(),
            'customer_id' => $address->getCustomerId(),
            // 'region' => [
            //     'region_code' => $address->getRegion()->getRegionCode(),
            //     'region' => $address->getRegion()->getRegion(),
            //     'region_id' => $address->getRegion()->getRegionId()
            // ],
            'firstname' => $address->getFirstname(),
            'lastname' => $address->getLastname(),
            'telephone' => $address->getTelephone(),
            'street' => $address->getStreet(),
            'city' => $address->getCity(),
            'region' => $address->getRegion(),
            'postcode' => $address->getPostcode(),
            'country_id' => $address->getCountryId()
            // 'custom_attributes' => $address->getCustomAttributes()
        ];
    }


     /**
     * Accept customer_data and new address data and return the updated data to user
     * @author : Farhan
     *
     * @api
     * @param int $customer_id Users customer_id.
     * @param array $address_data Users address.
     * @return array Updated data to user
     */  
    public function addAddress($customer_id, array $address_data)
    {
        try {
            $customer = $this->customerRepository->getById($customer_id);

            /** @var AddressInterface $address */
            $address = $this->addressFactory->create();
            $address->setCustomerId($customer_id);

            // Set default values for required fields if not provided
            if (!isset($address_data['street'])) {
                throw new Exception("Street is a required field.");
            }
            if (!isset($address_data['country_id'])) {
                throw new Exception("Country ID is a required field.");
            }
            if (!isset($address_data['region']) || !isset($address_data['region']['region_code']) || !isset($address_data['region']['region_id'])) {
                throw new Exception("Region details are required fields.");
            }

            foreach ($address_data as $key => $value) {
                if (method_exists($address, 'set' . ucfirst($key))) {
                    $address->{'set' . ucfirst($key)}($value);
                }
            }

            // Manually set region data if provided
            if (isset($address_data['region'])) {
                $region = $this->regionFactory->create();
                $region->setRegionCode($address_data['region']['region_code']);
                $region->setRegion($address_data['region']['region']);
                $region->setRegionId($address_data['region']['region_id']);
                $address->setRegion($region);
            }

            $this->addressRepository->save($address);

            return ['address' => $this->convertAddressToArray($address)];
        } catch (Exception $exception) {
            return ['error' => $exception->getMessage()];
        }
    }

}

app/code/Wowshop/ApiFarhan/composer.json

{
    "name": "wowshop/api-farhan",
    "description": "Custom API module",
    "require": {
        "php": "~7.4.0||~8.0.0||~8.1.0"
    },
    "type": "magento2-module",
    "version": "1.0.0",
    "license": [
        "OSL-3.0",
        "AFL-3.0"
    ],
    "autoload": {
        "files": [
            "registration.php"
        ],
        "psr-4": {
            "Wowshop\ApiFarhan\": ""
        }
    }
}

app/code/Wowshop/ApiFarhan/registration.php

<?php
use MagentoFrameworkComponentComponentRegistrar;

ComponentRegistrar::register(
    ComponentRegistrar::MODULE,
    'Wowshop_ApiFarhan',
    __DIR__
);

I am unable to figure out how to resolve this isssue, from my checking the docblock I put already correct and same as per the CustomInterface.php and Custom.php

I have tried changing the @param array $address_data in both file to @param string[] $address_data or @param string $address_data but none helps as it gives out other error : Notice: Array to string conversion

Please help me understand how this error occur and how to fix this