WsdlToPhp / PackageGenerator

Generates a PHP SDK based on a WSDL, simple and powerful, WSDL to PHP
https://providr.io
MIT License
425 stars 73 forks source link

TypeError: Cannot assign array to property #289

Open mwolff-fn opened 1 year ago

mwolff-fn commented 1 year ago

Prerequisites

We have a SOAP method getProduct() where the response contains property "externalAttributes", which is defined as a Map struct in the WSDL: <element name="externalAttributes" nillable="true" type="apachesoap:Map"/>

In the generated proxy class for the response, I see the property generated with the appropriate typehint:

/**
 * The externalAttributes
 * Meta information extracted from the WSDL
 * - nillable: true
 * @var \My\Namespace\Struct\Map|null
 */
protected ?\My\Namespace\Struct\Map $externalAttributes = null;

The Map struct class is properly generated and extends WsdlToPhp\PackageBase\AbstractStructBase.

Error message

Now, when I call the method doing the actual SOAP call, I'm getting this exception:

TypeError Cannot assign array to property My\Namespace\Struct\ProductAttribute::$externalAttributes of type ?My\Namespace\Struct\Map

SOAP response

In the raw SOAP response, I see the data represented like this:

<externalAttributes href="#id55"/>
...a gazillion nodes later...
<multiRef xmlns:ns31="http://xml.apache.org/xml-soap" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" id="id55" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns31:Map">\n
  <item>\n
    <key xsi:type="soapenc:string">LNG</key>\n
    <value href="#id97"/>\n
  </item>\n
  <item>\n
    <key xsi:type="soapenc:string">CDB</key>\n
    <value href="#id98"/>\n
  </item>\n
</multiRef>

Expectation

I would have expected the data to be parsed into the Map class.

What actually happens

While trying to interpret the response and hydrating the proxy class, the client seems to fail identifying the Map struct as such and simply converts the data into an associative array.

When I remove the type hints from the response struct class, the error message goes away and I can see the parsed data structure, which looks like this:

"externalAttributes": [
        "LNG" => SoapVar {#2857
          +enc_type: 0
          +enc_value: My\Namespace\Struct\ExternalAttribute^ {#2856
            #ID: 44
            #attributeId: 103
            #attributeName: "realaccount"
            #attributeType: "String"
            #productAttribute: My\Namespace\Struct\ProductAttribute^ {#2855}
            #systemId: "LNG"
          }
          +enc_stype: "ExternalAttribute"
          +enc_ns: "//productcatalog/beans"
          +enc_name: null
          +enc_namens: null
        }
        "CDB" => SoapVar {#2859
          +enc_type: 0
          +enc_value: My\Namespace\Struct\ExternalAttribute^ {#2858
            #ID: 517
            #attributeId: 103
            #attributeName: "realaccount"
            #attributeType: "String"
            #productAttribute: My\Namespace\Struct\ProductAttribute^ {#2855}
            #systemId: "CDB"
          }
          +enc_stype: "ExternalAttribute"
          +enc_ns: "//productcatalog/beans"
          +enc_name: null
          +enc_namens: null
        }
      ]

I am currently using PHP8.1, wsdltophp/packagebase:5.0.3 and PackageGenerator 4.1.7.

Is there a possible workaround other than to deactivate strict typing?

mikaelcom commented 1 year ago

Intriguing!

Can you provide the Map class declaration? From my point of view, the Map should contain an array-typed property or something like this.

Let me know, feel free, if possible, to send me the WSDL at contact@mikael-delsol.fr

mwolff-fn commented 1 year ago

Thanks for the quick reply - sent you the files earlier today.

mikaelcom commented 1 year ago

From my point of view, the generated classes match the WSDL definition.

I'm wondering if the SOAP response is well defined and if it does match the WSDL definition.

Maybe if I was able to send the request by myself, maybe I would be able to understand where the issue comes from and if it can be worked around.

Let me know then.

mwolff-fn commented 1 year ago

Thanks for looking into it. Unfortunately, the service is within a private network, so you can't access it from the outside. But if it helps, I could probably provide you with a complete protocol of a request/response cycle in private.

mikaelcom commented 1 year ago

Thanks for looking into it. Unfortunately, the service is within a private network, so you can't access it from the outside. But if it helps, I could probably provide you with a complete protocol of a request/response cycle in private.

If you can provide the full XML response, I could work with it I think