SoapVar
在线手册:中文 英文
PHP手册

SoapVar::SoapVar

(PHP 5 >= 5.0.1)

SoapVar::SoapVarSoapVar constructor

说明

SoapVar::SoapVar ( mixed $data , string $encoding [, string $type_name [, string $type_namespace [, string $node_name [, string $node_namespace ]]]] )

Constructs a new SoapVar object.

参数

data

The data to pass or return.

encoding

The encoding ID, one of the XSD_... constants.

type_name

The type name.

type_namespace

The type namespace.

node_name

The XML node name.

node_namespace

The XML node namespace.

范例

Example #1 SoapVar::SoapVar() example

<?php
class SOAPStruct {
    function 
SOAPStruct($s$i$f
    {
        
$this->varString $s;
        
$this->varInt $i;
        
$this->varFloat $f;
    }
}
$client = new SoapClient(null, array('location' => "http://localhost/soap.php",
                                     
'uri'      => "http://test-uri/"));
$struct = new SOAPStruct('arg'34325.325);
$soapstruct = new SoapVar($structSOAP_ENC_OBJECT"SOAPStruct""http://soapinterop.org/xsd");
$client->echoStruct(new SoapParam($soapstruct"inputStruct"));
?>

参见


SoapVar
在线手册:中文 英文
PHP手册
PHP手册 - N: SoapVar constructor

用户评论:

tcell (01-Mar-2012 02:53)

One potential gotcha with this is that if the XML you are passing in has the <?xml... declaration, it may cause problems on the server side. It's best to strip this out with str_replace.

jbbrunsveld at gmail dot com (20-May-2011 03:05)

It took me more than one day to figure out how to use the SoapVar object in a multilevel/complex SOAP request.
If you want to set-up a multilevel/complex SOAP call with parameters in subnodes, you can use the following methods:

<?php
/* Simple example with array as parameter */
$wsdl_url = '';
$client     = new SoapClient($wsdl_url, array('trace' => true));       
$parameters = array(
   
'FromCurrency' => 'EUR',
   
'ToCurrency' => 'AUD',
);

$client->ConversionRate($parameters);     
echo
htmlentities($client->__getLastRequest());

/* Simple example with stdClass object as parameter */
$wsdl_url  = '';
$client = new SoapClient($wsdl_url, array('trace' => true));

$parameters = new stdClass();
$parameters->FromCurrency = 'EUR';
$parameters->ToCurrency = 'AUD';

$client->ConversionRate($parameters);     
echo
htmlentities($client->__getLastRequest());

/* Example with complex/nested node structure using an array as param*/
$wsdl_url = "http://yourwsdlfile";
$client  = new SoapClient($wsdl_url, array('trace' => true));
$client->YourCall(array(
   
'YourContainerNodeName' => array(
       
'Level1NodeFoo' => '100',
       
'Level1NodeBar' => '100',
       
'Subnodes' => array(
           
'NodeLevel2' => 'test'
       
)
    )
));

/* Example with complex/nested node structure using an stdClass as param */
$wsdl_url = "http://yourwsdlfile";
$client  = new SoapClient($wsdl_url, array('trace' => true));
$params = new stdClass();
$params->YourContainerNodeName = new stdClass();
$params->YourContainerNodeName->Level1NodeFoo = 100;
$params->YourContainerNodeName->Level1NodeBar = 100;
$params->YourContainerNodeName->Subnodes = new stdClass();
$params->YourContainerNodeName->Subnodes->NodeLevel2 = 'test';

$client->YourCall($params);

/* Example with complex/nested node structure using an stdClass and SoapVars as param */
$wsdl_url = "http://yourwsdlfile";
$client  = new SoapClient($wsdl_url, array('trace' => true));

$params = new stdClass();
$params->YourContainerNodeName = new stdClass();
$params->YourContainerNodeName->Level1NodeFoo = 100;
$params->YourContainerNodeName->Level1NodeBar = 100;
$params->YourContainerNodeName->Subnodes = new stdClass();
$params->YourContainerNodeName->Subnodes->NodeLevel2 = new SoapVar(3, XSD_INT, 'xsd:int');
$params->YourContainerNodeName->Subnodes->NodeLevel3 = new SoapVar("<ns1:AdText><![CDATA[hallo<br><br>test]]></ns1:AdText>", XSD_ANYXML);
$params->YourContainerNodeName->Subnodes->NodeLevel4 = array(
    new
SoapVar(1, XSD_INT, 'xsd:int'),
    new
SoapVar(2, XSD_INT, 'xsd:int'),
    new
SoapVar(3, XSD_INT, 'xsd:int')
);   
?>

Krzych (03-Dec-2010 02:54)

It might be obvious to some but not to everyone
if you ever wondered how to encode attribute in soap object, use proper coding and not hacking by passing xml and flag XSD_ANYXML

try using this
<?php
 $amount
['_'] = 25;
 
$amount['currencyId'] = 'GBP';
 
$encodded = new SoapVar($amount, SOAP_ENC_OBJECT);

?>
and end result wound be
<amount currencyId="GBP">25</amount>

hope that helps someone

cb at wasteland dot org (02-Jul-2009 10:01)

If you need to add attributes XML entities in your SOAP query like this:

"<FilterBy Column="Id" FilterOperator="=" FilterValue="NUMBER" Table="Case">"

Use SoapVar() with the type XSD_ANYXML as shown below.  Example uses __soapCall and other SoapParams.

<?php
$response
= $client->__soapCall('GetFilteredRecordList',
    array(new
SoapParam($DSToken, 'Token'),
          new
SoapParam('Slide', 'TableName'),
          new
SoapVar('<FilterBy Column="Id" FilterOperator="=" FilterValue="NUMBER" Table="Case"/>', XSD_ANYXML)),
    array(
'soapaction' => 'http://www.example.com/webservices/GetFilteredRecordList'));
?>

Use this so you don't waste HOURS looking around:

clement006 at gmail dot com (08-Sep-2008 01:23)

I spent hours trying to send an XML document
(in XSD_ANYXML format) to a .NET webservice...

I don't know if it's always the case with .NET webservices,
but I had to use a little trick with the SoapVar object
to finally get this thing working.

Here is the code that works for me;
Hope it will help someone!

<?php

// xml content
$xmlDocument = '<Result>
    <Product id="12345" language="fr-BE">
        <Data>
            <Brand>BrandName</Brand>
            <ProductName>Bag</ProductName>
        </Data>
    </Product>
</Result>'
;

// initiate soap client
ini_set("soap.wsdl_cache_enabled", "0");
$client = new SoapClient(
           
"http://dotnetwebservice.com/Products.asmx?wsdl",
            array(
               
'trace' => 1,
               
'exceptions' => 1,
               
'soap_version' => SOAP_1_1,
               
'encoding' => 'ISO-8859-1',
               
'features' => SOAP_SINGLE_ELEMENT_ARRAYS
           
)
);

// prepare xml
// I debugged using $client->__getLastRequest() and
// then saw that the node around the XML was missing.
// So the trick here is to manually add the parameter
// (see the WSDL to catch the right parameter name of course).
$xmlvar = new SoapVar(
           
'<ns1:xmlDocument>'.$xmlDocument.'</ns1:xmlDocument>',
           
XSD_ANYXML
);

// send xml
try {
   
$params->xmlDocument = (object)$xmlvar;
   
$save_result = $client->SaveProduct($params);
    echo
"<pre>\n\n";
    echo
"Result :\n";
   
var_dump($save_result);
    echo
"</pre>";
} catch (
SoapFault $e) {
    echo
"SOAP Fault: ".$e->getMessage()."<br />\n";
}

//* DEBUG
echo "<pre>\n\n";
echo
"Request :\n";
echo
htmlspecialchars($client->__getLastRequest())."\n";
echo
"</pre>";
//*/

?>

OrionI (11-Jul-2005 03:30)

This class is useful when dealing with the "anyType" type (generic object reference): it lets you specify the xsd type to provide "late binding" type information.

Here's a really simple example: I have a .NET service that can take a string, a date, and integer, or other types, so I use the .NET "object" type. Here's an example of such a service--this one just tells me what type I passed in. (It's nice to use when checking to see if PHP passed in the type information the way .NET expects it.)

//inside a service.asmx.cs file...
[WebMethod]
public string WhatTypeIsThis(object ObjectParameter)
{
   return "You passed in a " + ObjectParameter.GetType().Name
     + ": " + ObjectParamter.ToString();
}

To call this service with a string from PHP, I used this code:
<?php
//set up the service client using WSDL
$client = new SoapClient("http://localhost/folder/service.asmx?WSDL");

//This is the variable that will be typed as an XSD string
$typedVar = new SoapVar("mystring", XSD_STRING, "string", "http://www.w3.org/2001/XMLSchema");
//This is the wrapper object for incoming parameters
$wrapper->ObjectParameter = $typedVar;
//This is the named parameter object that will be passed in to the service
$params = new SoapParam($wrapper, "WhatTypeIsThis");

//call the service with the string
$result = $client->WhatTypeIsThis($params);
//show the result
echo $result->WhatTypeIsThisResult;
?>

The output from this should be:
"You passed in a String: mystring"

The SOAP message that is passed in looks like this:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns1="http://tempuri.org/">
    <SOAP-ENV:Body>
        <ns1:WhatTypeIsThis>
            <ns1:ObjectParameter xsi:type="xsd:string">mystring</ns1:ObjectParameter>
        </ns1:WhatTypeIsThis>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

It's that xsi:type="xsd:string" that gives .NET the heads up that though the ObjectParameter is being passed in as an object, it is also a string.

When trying other types, it's helpful to see exactly what is being sent to the service--to see the SOAP messages like the one above, use the trace option when making your SOAP client and then call the $client->__getLastRequest() function. (See http://www.php.net/soap_soapclient_getlastrequest)  You may need to use try/catch constructs if you're generating errors.

Another helpful function is var_dump($client->__getTypes())--it shows how PHP parsed the WSDL file to create types to pass back and forth.