3

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.

asked Apr 10, 2017 at 11:29

1 Answer 1

3

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.

answered Apr 11, 2017 at 2:36

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.