php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #39179 Abstract types not handled by SoapClient in WSDL mode
Submitted: 2006-10-17 17:47 UTC Modified: 2006-10-31 01:00 UTC
Votes:53
Avg. Score:4.8 ± 0.4
Reproduced:51 of 51 (100.0%)
Same Version:5 (9.8%)
Same OS:5 (9.8%)
From: jchernia at netsuite dot com Assigned: dmitry (profile)
Status: No Feedback Package: SOAP related
PHP Version: 5.1.6 OS: Windows XP
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: jchernia at netsuite dot com
New email:
PHP Version: OS:

 

 [2006-10-17 17:47 UTC] jchernia at netsuite dot com
Description:
------------
This is very similar to bug 36575 http://bugs.php.net/bug.php?id=36575), but I still see this in the latest code.

If an operation takes an abstract type, I can not get SoapClient (in WSDL mode) to produce one of the subclass instances of it, even if I set type, etc.

Both Axis and .NET generated client classes will send the correct subclass if you specify it.

NuSoap does not, but allows you to specify additional attributes in WSDL mode.




Reproduce code:
---------------
Operation
<complexType name="GetRequest">
 <sequence>
  <element name="baseRef" type="platformCore:BaseRef"/>
 </sequence>
 </complexType>
<element name="get" type="platformMsgs:GetRequest"/>

XSD:
<complexType name="BaseRef" abstract="true">

<sequence>
<element name="name" type="xsd:string" minOccurs="0"/>
<!-- record name -->
</sequence>
</complexType>
<element name="baseRef" type="platformCore:BaseRef"/>
 <complexType name="RecordRef">
 <complexContent>
 <extension base="platformCore:BaseRef">
  <attribute name="internalId" type="xsd:string"/>
  <attribute name="externalId" type="xsd:string"/>
  <attribute name="type" type="platformCoreTyp:RecordType"/>
  </extension>
 </complexContent>
</complexType>

Expected result:
----------------
<ns1:get>
<ns1:baseRef internalId="17" type="customer" xsi:type="ns1:RecordRef"/>
</get>

Either this, or the ability to set these attributes in WSDL mode.

Actual result:
--------------
<ns1:get>
 <ns1:baseRef/>
</ns1:get>

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2006-10-17 17:52 UTC] tony2001@php.net
Please try using this CVS snapshot:

  http://snaps.php.net/php5.2-latest.tar.gz
 
For Windows:
 
  http://snaps.php.net/win32/php5.2-win32-latest.zip


 [2006-10-18 22:24 UTC] jchernia at netsuite dot com
Still fails with 5.2. Is there a way to indicate that you want the subclass, not the abstract class? I don't see any in the documentation and I've tried lots of things.
 [2006-10-23 05:38 UTC] dmitry@php.net
Could you provide full WSDL file and SOAP request or reeponce that ext/soap cannot handle correct.
 [2006-10-31 01:00 UTC] php-bugs at lists dot php dot net
No feedback was provided for this bug for over a week, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
 [2008-09-30 07:47 UTC] stuart at stuartherbert dot com
Looks like jchernia is trying to access Netsuite's web service (Netsuite is a popular hosted ERP solution).  You can't access their SOAP service w/out a valid account, but if you had such an account, the following code triggers the error:

<?php

class GetRequest
{
	public $baseRef = null;
}

class LoginRequest
{
	public $passport = null;
}

class Passport
{
	public $email = null;
        public $password = null;
        public $account = null;
        public $role = null;
}

class BaseRef
{
	public $name = null;
}

class RecordRef extends BaseRef
{
	public $internalId = null;
        public $externalId = null;
        public $type       = null;
}

$user = new Passport();
$user->email='<your netsuite login>';
$user->password='<your netsuite password>';
$user->account='<your netsuite account ID>';
$user->role=new RecordRef;
$user->role->internalId=<your role ID>;

$loginRequest = new LoginRequest;
$loginRequest->passport = $user;

$soapClient = new SoapClient('https://webservices.netsuite.com/wsdl/v2008_1_0/netsuite.wsdl', array('trace' => 1));
$result = $soapClient->login($loginRequest);

$requestRef = new RecordRef;
$requestRef->externalId = 200;
$requestRef->type = 'issue';

try
{
        $issue = $soapClient->get(array('recordRef' => $requestRef));
        var_dump($issue);
}
catch (Exception $e)
{
        var_dump($e);
	var_dump($soapClient->__getLastRequest());
        var_dump($soapClient->__getLastResponse());
}

?>

__getLastRequest() reports:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:messages_2008_2.platform.webservices.netsuite.com"><SOAP-ENV:Body><ns1:get><ns1:baseRef/></ns1:get></SOAP-ENV:Body></SOAP-ENV:Envelope>

and __getLastResponse() reports:

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soapenv:Body>
    <soapenv:Fault>
      <faultcode>soapenv:Server.userException</faultcode>
      <faultstring>org.xml.sax.SAXException: {urn:core_2008_2.platform.webservices.netsuite.com}BaseRef is an abstract type and cannot be instantiated</faultstring>
      <detail>
        <ns1:hostname xmlns:ns1="http://xml.apache.org/axis/">partners-java001.svale.netledger.com</ns1:hostname>
      </detail>
    </soapenv:Fault>
  </soapenv:Body>
</soapenv:Envelope>

Note the empty <ns1:baseRef/> in the request.  baseRef is an abstract type, in this case extended the recordRef.  The correct SOAP request is listed by the original poster.

Hope that helps.  If you need a Netsuite account for testing purposes, contact me privately and I'll sort one out for you.

Best regards,
Stu
--
 [2009-02-20 04:40 UTC] jchernia at netsuite dot com
Full WSDL - 

https://webservices.netsuite.com/wsdl/v2008_2_0/netsuite.wsdl

The code that Stu submitted will cause the problem. When making the 
get() request you will get

<baseRef/> 
instead of 
<baseRef internalId="17" type="customer" xsi:type="ns1:RecordRef"/>

where internalId and type are properties of the subclass (RecordRef) 
and not of BaseRef.

-John
 [2009-06-16 06:07 UTC] dasteph+forum at gmail dot com
Hi,

I have pretty the same problem.
Reproducing code: http://castex.de/stuff/php-bug.txt

expected result (in error log)
------------------------------
[15-Jun-2009 16:47:29] client
[15-Jun-2009 16:47:29] server
[15-Jun-2009 16:47:29] TestAbstractRequest Object
(
    [element] => Child Object
        (
            [name] => test
        )

)

actual result
-------------
[15-Jun-2009 16:47:29] client
[15-Jun-2009 16:47:29] server
[15-Jun-2009 16:47:29] TestAbstractRequest Object
(
    [element] => Father Object
        (
            [name] => test
            [number] => 5
        )

)


Regards

Stephan
 [2009-08-05 17:54 UTC] styx31 at gmail dot com
This bug is still present in the last version.

SoapClient does not honor polymorphism correctly, with or without abstract types

Sample WSDL :

<complexType name="PersonIdentity">
  <sequence>
    <element name="Id" type="xsd:string" />
  </sequence>
</complexType>
<complexType name="Person">
  <complexContent extends="PersonIdentity">
    <sequence>
      <element name="Name" type="xsd:string" />
      <element name="FirstName" type="xsd:string" />
    </sequence>
  </complexContent>
</complexType>

Operation contract :

<complexType name="CheckPerson">
 <sequence>
  <element name="Person" type="PersonIdentity"/>
 </sequence>
</complexType>

The operation CheckPerson accepts both Person and PersonIdentity.

Despite the fact that you can create a class which correponds in PHP :

class PersonIdentity {
  public $Id;
}

class Person extends PersonIdentity {
  public $Name;
  public $FirstName;
}

If you use a Person instance when you call CheckPerson() :
- the Person will be serialized as a PersonIdentity,
- no i:type="Person" attribute will be added to the <Person> element,
- the properties belonging to the Person class will be dropped
 [2012-05-08 12:05 UTC] marius dot orcsik at avangate dot com
This problem is still present in PHP 5.3.12.
 [2015-03-26 09:34 UTC] bpolaszek at gmail dot com
Hi there,

PHP 5.6 is out, PHP 7 is on its way, and a decade later, the bug's still here. 
I encounter it today and it's very annoying. The only way for me to communicate with a partner is its soap server, and I'm just stuck currently.

May you have a look at it ?

Thanks,
Beno!t POLASZEK
http://b.polaszek.fr
 [2018-12-04 09:15 UTC] shamot at neonus dot sk
This bug is still present in PHP 7.2.12. Does anyone actually working on this?
 [2020-04-09 00:44 UTC] virann20 at gmail dot com
I faced with this issue too, but after all it turns out that it's not a bug.
It works when all types are declared in classmap option for SoapClient constructor.

$classmap = array( 'abstractType' => abstractType::class, 'subAbstractType' => subAbstractType::class );
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Mar 28 10:01:26 2024 UTC