14.6.1. ProblemYou need to explicitly set an XML Schema type, but there's no way to tell ext/soap how to set that value through a normal PHP data structure. 14.6.2. SolutionCreate a SOAPVar and pass the type and namespace in the constructor: $ns = 'https://adwords.google.com/api/adwords/v2'; $job = new SOAPVar($data, SOAP_ENC_OBJECT, 'CustomReportJob', $ns); $response = $client->scheduleReportJob(array('job' => $job)); This creates XML that looks like: <ns1:job xsi:type="ns1:CustomReportJob"> ... </ns1:job> Where the ns1 namespace prefix is https://adwords.google.com/api/adwords/v2. 14.6.3. DiscussionThe SOAP extension exposes a number of classes to help you create the data that you pass into SOAP clients. These are rarely necessary when you're using a WSDL file. However, sometimes it's unavoidable. One such case is when you must set an XML Schema type attribute. SOAP uses XML Schema as its behind-the-scenes way of encoding data using XML. One feature of XML Schema is the ability to define the type of structure. Normally, this is one of the built-in XML Schema types, such as a string, integer, or object. However, you can extend XML Schema to create custom types. When a service requires a custom type, you must set it using the SOAPVar class. This class takes six parameters. The first four are most important here. They are the data to be sent, the general class of XML Schema type, the name of the value assigned to the xsi:type attribute, and the namespace that value lives in. For example, here's a piece of code that creates a CustomReportJob for the Google AdWords reporting web services: $ns = 'https://adwords.google.com/api/adwords/v2'; $job = new SOAPVar($data, SOAP_ENC_OBJECT, 'CustomReportJob', $ns); $response = $client->scheduleReportJob(array('job' => $job)); You can ignore the specific details as to what information is actually being passed into the service (it's stored in $data), or that it's an object (so you pass in SOAP_ENC_OBJECT as the second parameter). They're important, but not relevant to the XML Schema type. For that, you must look at the third and fourth parameters to the SOAPVar constructor: 'CustomReportJob' and $ns. In this example, you're creating a job of type CustomReportJob that lives under the XML namespace https://adwords.google.com/api/adwords/v2, which is the value of $ns. Now when ext/soap serializes the data into XML, it adds the necessary attribute: <ns1:job xsi:type="ns1:CustomReportJob"> ... </ns1:job> Depending on the number of XML namespaces your code is using, you may or may not get the same prefix of ns1. The specific prefix string doesn't matter, what does matter is that your prefix is mapped to https://adwords.google.com/api/adwords/v2 in the SOAP-Envelope element, as it is here: <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="https://adwords.google.com/api/adwords/v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 14.6.4. See AlsoRecipe 14.5 for using complex SOAP types. |