Zend certified PHP/Magento developer

Magento 2.4.3-p3 extension attribute not available in API

I’m trying to add a custom order attribute (BC_Pdfinvoice) and make it available in the Order API response.

I created a module and added an extension_attributes.xml file here Vendor/Module/etc/extension_attributes.xml:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
<extension_attributes for="MagentoSalesApiDataOrderInterface">
    <attribute code="BC_Pdfinvoice" type="string"/>
</extension_attributes>
</config>

Then added Vendor/Module/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">
<virtualType name="MagentoSalesModelResourceModelOrderGrid" type="MagentoSalesModelResourceModelGrid">
<arguments>
<argument name="columns" xsi:type="array">
<item name="BC_Pdfinvoice" xsi:type="string">sales_order.BC_Pdfinvoice</item>
</argument>
</arguments>
</virtualType>
<type name="MagentoSalesApiOrderRepositoryInterface">
<plugin name="BC_Pdfinvoice" type="VendorModulePluginModelOrderAddCustomOrderAttribute" />
</type>
</config>

And the plugin Vendor/Module/Plugin/Model/Order/AddCustomOrderAttribute.php:

<?php

namespace VendorModulePluginModelOrder;

use MagentoSalesApiDataOrderSearchResultInterface;
use MagentoSalesModelOrderFactory;
use MagentoSalesApiOrderRepositoryInterface;
use MagentoSalesApiDataOrderExtensionFactory;
use MagentoSalesApiDataOrderInterface;

class AddCustomOrderAttribute
{
    /**
     * @var OrderFactory
     */
    private $orderFactory;

    /**
     * @var OrderExtensionFactory
     */
    private $orderExtensionFactory;

    /**
     * @param OrderExtensionFactory $extensionFactory
     * @param OrderFactory $orderFactory
     */
    public function __construct(
        OrderExtensionFactory $extensionFactory,
        OrderFactory $orderFactory
    ) {
        $this->orderExtensionFactory = $extensionFactory;
        $this->orderFactory = $orderFactory;
    }

    /**
     * Set "BC_Pdfinvoice" to order data
     *
     * @param OrderRepositoryInterface $subject
     * @param OrderSearchResultInterface $searchResult
     *
     * @return OrderSearchResultInterface
     */
    public function setBCPdfInvoiceData(OrderInterface $order)
    {
        if ($order instanceof MagentoSalesModelOrder) {
            $myCustomOrderAttribute = $order->getBCPdfInvoice();
        } else {
            $orderModel = $this->orderFactory->create();
            $orderModel->load($order->getId());
            $myCustomOrderAttribute = $orderModel->getBCPdfInvoice();
        }

        $extensionAttributes = $order->getExtensionAttributes();
        $orderExtensionAttributes = $extensionAttributes ? $extensionAttributes
            : $this->orderExtensionFactory->create();
            
        $orderExtensionAttributes->setBCPdfInvoice($myCustomOrderAttribute);
        
        $order->setExtensionAttributes($orderExtensionAttributes);
    }
    
    /**
     * Add "BC_Pdfinvoice" extension attribute to order data object
     * to make it accessible in API data
     *
     * @param OrderRepositoryInterface $subject
     * @param OrderSearchResultInterface $searchResult
     *
     * @return OrderSearchResultInterface
     */
    public function afterGetList(
        OrderRepositoryInterface $subject,
        OrderSearchResultInterface $orderSearchResult
    ) {
        foreach ($orderSearchResult->getItems() as $order) {
            $this->setBCPdfInvoiceData($order);
        }
        return $orderSearchResult;
    }

    /**
     * Add "BC_Pdfinvoice" extension attribute to order data object
     * to make it accessible in API data
     *
     * @param OrderRepositoryInterface $subject
     * @param OrderInterface $order
     *
     * @return OrderInterface
     */
    public function afterGet(
        OrderRepositoryInterface $subject,
        OrderInterface $resultOrder
    ) {
        $this->setBCPdfInvoiceData($resultOrder);
        return $resultOrder;
    }
}

I removed ‘generated’, ran upgrade, compile, deploy commands, placed an order and tested the API call using Postman:

https://domain.com/rest/V1/orders?searchCriteria[filterGroups][0][filters][0][field]=entity_id&searchCriteria[filterGroups][0][filters][0][value]=17219&searchCriteria[filterGroups][0][filters][0][conditionType]=eq

The call is successful, but my custom attribute ‘BC_Pdfinvoice’ is not in the response.

The field was successfully created in the relevant database tables, as per my Vendor/Module/etc/db_schema.xml:

<?xml version="1.0"?>

<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
<table name="sales_order" resource="sales" engine="innodb" comment="Sales Order">
<column xsi:type="varchar" name="BC_Pdfinvoice" nullable="true" length="255" comment="Custom Order Attribute"/>
</table>
<table name="sales_order_grid" resource="sales" engine="innodb" comment="Sales Order">
<column xsi:type="varchar" name="BC_Pdfinvoice" nullable="true" length="255" comment="Custom Order Attribute"/>
</table>
<table name="quote" resource="checkout" engine="innodb" comment="Quote">
<column xsi:type="varchar" name="BC_Pdfinvoice" nullable="true" length="255" comment="Custom Order Attribute"/>
</table>
<table name="sales_invoice" resource="sales" engine="innodb" comment="Sales Invoice">
<column xsi:type="varchar" name="BC_Pdfinvoice" nullable="true" length="255" comment="Custom Order Attribute"/>
</table>
</schema>

Any help would be greatly appreciated 🙂