2

I created a custom module to store the details of discount per items. I have a custom tables to store informations (quote items, order items, invoice items), and I use a extension attributes to link these custom field to the main entities (quote, order, invoice).

Here is an excerpt of my extension_attributes.xml file :

<?xml version="1.0"?>
<!--
/**
 * Copyright © 2016 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<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="vendor_discounts_order_items" type="Vendor\MultipleDiscounts\Api\Data\DiscountOrderItemInterface[]" />
  </extension_attributes>


</config>

As you can see I use a custom type Array : DiscountOrderItemInterface[]. Here is my interface file :

<?php
/**
 *
 * @category DiscountOrderItemInterface
 * @author   *******
 * @license  All right reserved to *****
 * @link     *******
 */

namespace Vendor\MultipleDiscounts\Api\Data;

/**
 * DiscountOrderItemInterface
 *
 * @category DiscountOrderItemInterface
 * @author   *********
 * @license  All right reserved to ****
 * @link     ********
 */
interface DiscountOrderItemInterface extends DiscountItemInterface
{

    const ORDER_ID = 'order_id';
    const ORDER_ITEM_ID = 'order_item_id';

    /**
     * getOrderId
     *
     * @return int
     */
    public function getOrderId();

    /**
     * setOrderId
     *
     * @param int $orderId orderId
     *
     * @return \Vendor\MultipleDiscounts\Api\Data\DiscountOrderItemInterface
     */
    public function setOrderId($orderId);

    /**
     * getOrderItemId
     *
     * @return int
     */
    public function getOrderItemId();

    /**
     * setOrderItemId
     *
     * @param int $orderItemId orderItemId
     *
     * @return \Vendor\MultipleDiscounts\Api\Data\DiscountOrderItemInterface
     */
    public function setOrderItemId($orderItemId);
}

It's all going well, I can store informations, and retrieve it, display it on both backend and frontend. But when I try to get orders over webapi REST Magento tries to instanciate DiscountOrderItemInterface[] class and I run into this error (has it does not exists) :

Array
(
    [message] => Class \Vendor\MultipleDiscounts\Api\Data\DiscountOrderItemInterface[] does not exist
    [code] => -1
    [trace] => #0 /httpdocs/vendor/magento/framework/Reflection/MethodsMap.php(149): ReflectionClass->__construct('\\Vendor\\Mult...')
#1 /httpdocs/vendor/magento/framework/Reflection/MethodsMap.php(100): Magento\Framework\Reflection\MethodsMap->getMethodMapViaReflection('\\Vendor\\Mult...')
#2 /httpdocs/vendor/magento/framework/Reflection/DataObjectProcessor.php(77): Magento\Framework\Reflection\MethodsMap->getMethodsMap('\\Vendor\\Mult...')
#3 /httpdocs/var/generation/Magento/Framework/Reflection/DataObjectProcessor/Proxy.php(95): Magento\Framework\Reflection\DataObjectProcessor->buildOutputDataArray(Object(Vendor\MultipleDiscounts\Model\ResourceModel\DiscountOrderItem\Collection), '\\Vendoror\\Mult...')
#4 /httpdocs/vendor/magento/framework/Reflection/ExtensionAttributesProcessor.php(119): Magento\Framework\Reflection\DataObjectProcessor\Proxy->buildOutputDataArray(Object(Vendor\MultipleDiscounts\Model\ResourceModel\DiscountOrderItem\Collection), '\\Vendor\\Mult...')
#5 /httpdocs/vendor/magento/framework/Reflection/DataObjectProcessor.php(104): Magento\Framework\Reflection\ExtensionAttributesProcessor->buildOutputDataArray(Object(Magento\Sales\Api\Data\OrderExtension), '\\Magento\\Sales\\...')
#6 /httpdocs/vendor/magento/framework/Webapi/ServiceOutputProcessor.php(107): Magento\Framework\Reflection\DataObjectProcessor->buildOutputDataArray(Object(Magento\Sales\Model\Order\Interceptor), '\\Magento\\Sales\\...')
#7 /httpdocs/vendor/magento/framework/Webapi/ServiceOutputProcessor.php(59): Magento\Framework\Webapi\ServiceOutputProcessor->convertValue(Object(Magento\Sales\Model\Order\Interceptor), '\\Magento\\Sales\\...')
#8 /httpdocs/vendor/magento/module-webapi/Controller/Rest.php(312): Magento\Framework\Webapi\ServiceOutputProcessor->process(Object(Magento\Sales\Model\Order\Interceptor), 'Magento\\Sales\\A...', 'get')
#9 /httpdocs/vendor/magento/module-webapi/Controller/Rest.php(216): Magento\Webapi\Controller\Rest->processApiRequest()
#10 /httpdocs/var/generation/Magento/Webapi/Controller/Rest/Interceptor.php(24): Magento\Webapi\Controller\Rest->dispatch(Object(Magento\Framework\App\Request\Http))
#11 /httpdocs/vendor/magento/framework/App/Http.php(135): Magento\Webapi\Controller\Rest\Interceptor->dispatch(Object(Magento\Framework\App\Request\Http))
#12 /httpdocs/vendor/magento/framework/Interception/Interceptor.php(146): Magento\Framework\App\Http->launch()
#13 /httpdocs/var/generation/Magento/Framework/App/Http/Interceptor.php(26): Magento\Framework\App\Http\Interceptor->___callPlugins('launch', Array, Array)
#14 /httpdocs/vendor/magento/framework/App/Bootstrap.php(258): Magento\Framework\App\Http\Interceptor->launch()
#15 /httpdocs/index.php(39): Magento\Framework\App\Bootstrap->run(Object(Magento\Framework\App\Http\Interceptor))
#16 {main}
)

any help would be appreciated.

2

I finally manage to resolve this issue. After digging into the Magento core, I found that in the \Magento\Framework\Reflection\ExtensionAttributeProcessor::buildOutputDataArray method, Magento get the type of the extension object attribute (in my case : Vendor\MultipleDiscounts\Api\Data\DiscountOrderItemInterface[]). If type is array, then Magento will substring the [] characters.

In my case the type was wrong : object Collection.

I use an observer to set my extension_attribute (sales order load after) and I have to change my code like this :

Before :

...
$orderExtension = $order->getExtensionAttributes();
if ($orderExtension == null) {
    $orderExtension = $this->orderExtensionFactory->create();
}
$discountOrderItems = $this->discountOrderItemRepository->getListByOrderId($order->getId());
$orderExtension->setDiscountsOrderItems($discountOrderItems);
...

After :

...
$orderExtension = $order->getExtensionAttributes();
if ($orderExtension == null) {
    $orderExtension = $this->orderExtensionFactory->create();
}
$discountOrderItems = $this->discountOrderItemRepository->getListByOrderId($order->getId());
$orderExtension->setDiscountsOrderItems($discountOrderItems->getItems());
...

I just add ->getItems() method on my $discountOrderItems collection object to return an array of object.

Hope this can help others.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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