Magento – Return nested array/data via WS-I compliant SOAP API V2

apisoap

I'm stuck on how to return the results to Magento for it to generate a SOAP response via the WS-I compliant SOAP API V2. The below is what I'm currently working on. I'm basically trying different structures with stdClass, arrays etc.

Here I'm trying to return details (name, created time, qty etc.) of all products purchased by a given customer (hard-coded for now).

V2.php

<?php
class Foo_Bar_Model_Api_V2 extends Foo_Bar_Model_API
{
    public function history()
    {
        $customerId = 999;
        $collection = Mage::getModel("sales/order")->getCollection()->addFieldToFilter('customer_id', $customerId);

        foreach ($collection as $order) {
            $orderID = $order->getId();
            $order = Mage::getModel("sales/order")->load($orderID);
            $orderedItems = $order->getAllItems();

            foreach ($orderedItems as $item) {
//                $stdClass = new stdClass();
//                $stdClass->name                 = $item->getName();
//                $stdClass->created_at           = $item->getCreatedAt();
//                $stdClass->qty_ordered          = $item->getQtyOrdered();
//                $stdClass->price                = $item->getPrice();
//                $stdClass->base_currency_code   = $order->getBaseCurrencyCode();
                $array = array(
                    "name"                  => $item->getName(),
                    "created_at"            => $item->getCreatedAt(),
                    "qty_ordered"           => $item->getQtyOrdered(),
                    "price"                 => $item->getPrice(),
                    "base_currency_code"    => $order->getBaseCurrencyCode()
                );
                //$result[] = Mage::helper('api')->wsiArrayPacker($array);
                $result[] = $array;
            }

        }
        Mage::log(print_r($result,1),null,__CLASS__.'.log',true);
        return $result;
    }
}

wsi.xml

<xsd:schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:{{var wsdl.name}}">
    <xsd:complexType name="foobarHistoryEntity">
        <xsd:sequence>
            <xsd:element name="name" type="xsd:string" minOccurs="0" />
            <xsd:element name="created_at" type="xsd:string" minOccurs="0" />
            <xsd:element name="qty_ordered" type="xsd:string" minOccurs="0" />
            <xsd:element name="price" type="xsd:string" minOccurs="0" />
            <xsd:element name="base_currency_code" type="xsd:string" minOccurs="0" />
        </xsd:sequence>
    </xsd:complexType>
    <xsd:complexType name="foobarHistoryEntityArray">
        <xsd:sequence>
            <xsd:element minOccurs="0" maxOccurs="unbounded" name="complexObjectArray" type="typens:foobarHistoryEntity" />
        </xsd:sequence>
    </xsd:complexType>
    <xsd:element name="foobarHistoryRequestParam">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element minOccurs="1" maxOccurs="1" name="sessionId" type="xsd:string" />
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
    <xsd:element name="foobarHistoryResponseParam">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element minOccurs="1" maxOccurs="1" name="result" type="typens:foobarHistoryEntityArray" />
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>

(Expected) Output

object(stdClass)[5]
  public 'result' => 
    object(stdClass)[6]
      public 'complexObjectArray' => 
        array (size=68)
          0 => 
            object(stdClass)[7]
              public 'name' => string 'Shiny Wallet' (length=12)
              public 'created_at' => string '2014-05-20 07:19:42' (length=19)
              public 'qty_ordered' => int 1
              public 'price' => string '399.99' (length=6)
              public 'base_currency_code' => string 'AUD' (length=3)
          1 => 
            object(stdClass)[8]
              public 'name' => string 'Shiny Shoes' (length=11)
              public 'created_at' => string '2014-05-21 07:20:24' (length=19)
              public 'qty_ordered' => int 1
              public 'price' => string '399.99' (length=6)
              public 'base_currency_code' => string 'AUD' (length=3)
          2 => 
            object(stdClass)[9]
              public 'name' => string 'Hamburger' (length=9)
              public 'created_at' => string '2014-05-21 07:20:24' (length=19)
              public 'qty_ordered' => int 1
              public 'price' => string '9.99' (length=3)
              public 'base_currency_code' => string 'AUD' (length=3)

The expected output is very similar to the output of customerCustomerList() when WS-I compliant mode is on. It's very hard to figure out how my $result should be structured. complexObjectArray is probably something I need to look into – maybe also wsiArrayPacker()?

Any help is appreciated.

Best Answer

I wasn't far off the correct answer. Here's the final function:

public function history($customerId)
{
    $collection = Mage::getModel("sales/order")->getCollection()->addFieldToFilter('customer_id', $customerId);
    $result = array();

    foreach ($collection as $order) {
        $orderID = $order->getId();
        $order = Mage::getModel("sales/order")->load($orderID);
        $orderedItems = $order->getAllItems();

        foreach ($orderedItems as $item) {
            $row = array(
                "name"                  => $item->getName(),
                "created_at"            => $item->getCreatedAt(),
                "qty_ordered"           => $item->getQtyOrdered(),
                "price"                 => $item->getPrice(),
                "base_currency_code"    => $order->getBaseCurrencyCode()
            );
            $result[] = $row;
        }

    }
    return $result;
}

This gives me the correct output. What I should probably mention is that, it may be important to clear the WSDL cache in your OS temporary directory - for *nix that is /tmp