3

I'm trying to add an extension attribute to sales_order (\Magento\Sales\Api\Data\OrderInterface), and I have the following 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\Sales\Api\Data\OrderInterface">
        <attribute code="order_status" type="string">
            <resources>
                <resource  ref="anonymous"/>
            </resources>
            <join reference_table="aytech_order_approval" reference_field="order_id" join_on_field="entity_id">
                <field>order_status</field>
            </join>
        </attribute>
    </extension_attributes>
</config>

I have already created the table aytech_order_approval with the fields order_id and order_status, and in my code I am trying to test getting the attribute like this (I have manually inserted a row into the table with order_id = 1 and order_status = 'approved':

$orders = $this->orderRepository->getList(\Magento\Framework\App\ObjectManager::getInstance()->create('Magento\Framework\Api\SearchCriteriaInterface'))->getItems();

echo $orders[1]->getExtensionAttributes()->getOrderStatus();

However, I keep getting null. What am I doing wrong? Also I've made sure to clear the var/generation, and the generated class does indeed have the getOrderStatus method

1 Answer 1

9

(Fortunately or not, but ) Join Processor (Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface) isn't used everywhere and in particular it is not used in Sales module. As result, extension attributes aren't automatically added to "getList" and "get" methods result for Orders, Invoices and other entities of Sales module. You should do that by yourself, with defining plugin to appropriate method ("getList", "get" or maybe better both). In that plugin you can load all additional data and add it to OrderExtension object.

As a reference example see how it works for GiftMessage module. Three steps to get it done:

  1. declare extension attribute: app/code/Magento/GiftMessage/etc/extension_attributes.xml
  2. declare your plugin: app/code/Magento/GiftMessage/etc/di.xml
  3. add data to OrderExtension object(s) from plugin: \Magento\GiftMessage\Model\Plugin\OrderGet::afterGetList

P.S. One small suggestion, for the sake of performance, if you need to extend the collection of objects, try to do that in one call to database storage, and do not do that inside of the loop for every order. But most likely you already know that :)

And here is a code example for your plugin:

$ids = [];
foreach ($resultOrder->getItems() as $order) {
    $ids[] = $order->getEntityId();
}
$statuses = []; /* should be loaded for collected $ids */
foreach ($resultOrder->getItems() as $order) {
    $orderId = $order->getEntityId();
    if ($statuses[$orderId]) {
        $extensionAttributes = $order->getExtensionAttributes();
        $extensionAttributes->setOrderStatus($statuses[$orderId]);
    }
}
7
  • Thanks, in response to your last note, I know how to do this with collections (using addAttributeToSelect, etc) but how do I do this with repositories when getList returns me an array?
    – b_pcakes
    Jun 16, 2016 at 16:01
  • Also, in the plugin, How am I supposed to get the data (i.e. the order_status) from the table in the database?
    – b_pcakes
    Jun 16, 2016 at 17:30
  • getList does return to you not an array, but Magento\Sales\Api\Data\OrderSearchResultInterface with getItems() method and it does return an array of OrderInterface objects. You can loop through items and collect ids first, then you need to load additional data from your source table(s) and in another loop set extension attribute value with appropriate setter on auto-generated interface
    – user40988
    Jun 17, 2016 at 11:25
  • in plugin normally you may load additional data with collection related to your custom table(entity).
    – user40988
    Jun 17, 2016 at 11:34
  • updated answer with code snippet
    – user40988
    Jun 17, 2016 at 11:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.