Matthew Brown
Matthew Brown

Reputation: 5116

SOAP PHP & Array of Types

I'll be the first to admit I rarely use SOAP, but I generally can make do. I am seriously struggling with something, hopefully someone can shed some light on this.

I have a WSDL, that I am connecting to and getting a sessionToken that is used for future requests, all well and good.

I am trying to call a VmifCreateVisitor method now that according to SOAP UI, should look something like the following:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:vmif="http://www.gallagher.co/security/commandcentre/vmifws" xmlns:web="http://www.gallagher.co/security/commandcentre/webservice">
   <soapenv:Header/>
   <soapenv:Body>
      <vmif:VmifCreateVisitor>
         <!--Optional:-->
         <vmif:sessionToken>
            <web:Value>?</web:Value>
         </vmif:sessionToken>
         <!--Optional:-->
         <vmif:vmConfigDivisionId>
            <web:Value>?</web:Value>
         </vmif:vmConfigDivisionId>
         <!--Optional:-->
         <vmif:visitor>
            <!--Optional:-->
            <vmif:DetailFields>
               <!--Zero or more repetitions:-->
               <web:PdfValue>
                  <!--Optional:-->
                  <web:IsUsedForNotification>?</web:IsUsedForNotification>
                  <web:Name>?</web:Name>
                  <web:Type>?</web:Type>
               </web:PdfValue>
            </vmif:DetailFields>
            <vmif:FirstName>?</vmif:FirstName>
            <vmif:LastName>?</vmif:LastName>
            <!--Optional:-->
            <vmif:DivisionId>
               <web:Value>?</web:Value>
            </vmif:DivisionId>
            <!--Optional:-->
            <vmif:Id>
               <web:Value>?</web:Value>
            </vmif:Id>
            <!--Optional:-->
            <vmif:UserCode>?</vmif:UserCode>
            <vmif:VisitorTypeIds>
               <!--Zero or more repetitions:-->
               <vmif:VmifVisitorTypeId>
                  <web:Value>?</web:Value>
               </vmif:VmifVisitorTypeId>
            </vmif:VisitorTypeIds>
         </vmif:visitor>
      </vmif:VmifCreateVisitor>
   </soapenv:Body>
</soapenv:Envelope>

I can create a visitor OK if I leave out the DetailFields section:

<vmif:DetailFields>
  <!--Zero or more repetitions:-->
  <web:PdfValue>
    <!--Optional:-->
    <web:IsUsedForNotification>?</web:IsUsedForNotification>
    <web:Name>?</web:Name>
    <web:Type>?</web:Type>
  </web:PdfValue>
</vmif:DetailFields>

But this is not something I can do, I need to send some personal details in the POST request. This is where it gets weird. When I send the following SOAP DetailFields Params, I get "Cannot create abstract class"

// ... (Truncated for Brevity)
$params->visitor->FirstName = $request->firstname;
$params->visitor->LastName = $request->lastname;

# ▼▼ Works if commented out. ▼▼
$mobile = new PdfValue();
$mobile->IsUsedForNotification = null;
$mobile->Name = 'Mobile Number';
$mobile->Type = 'Mobile';
$mobile->Value = $request->mobile;

$address = new PdfValue();
$address->IsUsedForNotification = null;
$address->Name = 'Address';
$address->Type = 'Address';
$address->Value = $request->address;

$params->visitor->DetailFields = [
    $address,
    $mobile
];
# ▲▲ Works if commented out. ▲▲

$visitorId = new VmifVisitorTypeId();
$visitorId->Value = $request->visitor_type_id;
$params->visitor->VisitorTypeIds = [
    $visitorId
];
// ... (Truncated for Brevity)

The Generated PHP WSDL Class created the following PdfValue() Class:

class PdfValue {
    public $IsUsedForNotification; // boolean
    public $Name; // string
    public $Type; // PdfType
}

But I notice its missing Value parameter, same with SOAP structure from SOAP UI. (Adding it to class makes no difference).

If you're curious, here is the VmifVisitor class the WSDL generated:

class VmifVisitor {
    public $DivisionId; // VmifDivisionId
    public $Id; // VmifVisitorId
    public $UserCode; // string
    public $VisitorTypeIds; // ArrayOfVmifVisitorTypeId
}

As shown above - its missing the DetailFields parameter, even the the SOAP API Docs clearly show its required, (Adding it manually to class still doesn't help)

The Actual documentation shows the following structure for PdfValue:

SOAP API Documentation for PdfValue

As you can see it clearly shows Value as an object. What is it expecting me to send it in an object?

For completion, this is the documentation for the Visitor object:

Visitor object API Documentation

So we can see its expecting an array of PdfValue, which I believe I am sending. Any Ideas?

TL;DR I am getting "Cannot create abstract class" when I send an array of PdfValue() in DetailFields for VmifVisitorCreate method. The auto-generated php class for PdfValue is missing Value parameter, and the SOAP API Docs expects a Value parameter and says it should be an object, Adding the Value param to my PdfValue class still yields same error, which confuses me.

Upvotes: 1

Views: 317

Answers (1)

Matthew Brown
Matthew Brown

Reputation: 5116

I feel silly, this basically boiled down to a namespace issue. The Type was not being found due to my assumption that all types were in the same namespace. Simply changing:

$params->visitor->DetailFields = [
    $address,
    $mobile
];

to

$params->visitor->DetailFields = [
    new \SoapVar($address, SOAP_ENC_OBJECT, 'PdfGeneralValue', 'http://www.domain.co/security/namespacepath/webservice'),
    new \SoapVar($mobile, SOAP_ENC_OBJECT, 'PdfGeneralValue', 'http://www.domain.co/security/namespacepath/webservice'),
];

This allowed it to work. Notice I also changed the type_name to PdfGeneralValue, this was also key in getting it to work. Thanks all.

Upvotes: 1

Related Questions