I am all new to php and all lost in doing a soap request. I have this other question How to send a SOAP request in javascript, like in SoapUI, which I have just got answered, but I have now decided to work in php instead of Node.js. As I want my php code to do the exact same, I will repeat my earlier question down below:
I have this WSDL site that I need to get some answers from. I have figured out how to do this in SoapUI, but I have no idea how to do it in php. The request that I am sending in soapUI looks like this:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:uni="https://uni-login.dk">
<soap:Header/>
<soap:Body>
<uni:hentDataAftaler>
<uni:wsBrugerid>?</uni:wsBrugerid>
<uni:wsPassword>?</uni:wsPassword>
</uni:hentDataAftaler>
</soap:Body>
</soap:Envelope>
I also have the wsdl-link: https://wsiautor.uni-login.dk/wsiautor-v4/ws?WSDL
I hope you I have some suggestions and tell me if you need any more information to answer my question :)
The answer for my previous question was the following
const soapRequest = require('easy-soap-request');
const url = 'https://wsiautor.uni-login.dk/wsiautor-v4/ws';
const headers = {
'Content-Type': 'application/soap+xml;charset=UTF-8',
'soapAction': 'https://wsiautor.uni-login.dk/hentDataAftaler',
};
// example data
const xml = `
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:uni="https://uni-login.dk">
<soap:Header/>
<soap:Body>
<uni:hentDataAftaler>
<uni:wsBrugerid>?</uni:wsBrugerid>
<uni:wsPassword>?</uni:wsPassword>
</uni:hentDataAftaler>
</soap:Body>
</soap:Envelope>
`;
// usage of module
soapRequest(url, headers, xml).then(({response: {body, statusCode}}) => {
console.log(body);
console.log(statusCode);
}).catch((errorBody) => {
console.error(errorBody);
});
There are at least two extensions you can use to enable that.
I would recommend the old and good curl
extension.
Another tip is that with Postman you can generate code for HTTP requests using curl
or http-request
. You can find it in the right up corner, near the send button.
Certify you install the extension first (in my case, installed using apt):
sudo apt-get install php-curl
Anyway, I believe you can use this code to accomplish it:
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_PORT => "80",
CURLOPT_URL => "https://wsiautor.uni-login.dk/wsiautor-v4/ws",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"
xmlns:uni=\"https://uni-login.dk\">
<soapenv:Header/>
<soapenv:Body>
<uni:hentDataAftaler>
<uni:wsBrugerid>?</uni:wsBrugerid>
<uni:wsPassword>?</uni:wsPassword>
</uni:hentDataAftaler>
</soapenv:Body>
</soapenv:Envelope>",
CURLOPT_HTTPHEADER => array(
"Content-Type: application/soap+xml;charset=UTF-8",
"soapAction: https://wsiautor.uni-login.dk/hentDataAftaler"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
you can use the native PHP SoapClient class to achieve your plan. In your case it 's even easier to do it with SoapClient because the code will be less complex and easier to understand.
$client = null;
try {
$client = new SoapClient(
'https://wsiautor.uni-login.dk/wsiautor-v4/ws?WSDL',
[
'cache_wsdl' => WSDL_CACHE_NONE,
'encoding' => 'utf-8',
'exceptions' => true,
'soap_version' => SOAP_1_1,
'trace' => true,
],
);
} catch (SoapFault $e) {
echo "<pre>";
var_dump($e->getMessage());
echo "</pre>";
if ($client instanceof SoapClient) {
echo "<pre>";
var_dump($client->__getLastRequest(), $client->__getLastResponse());
echo "</pre>";
}
}
If we look at that code example, we instantiate a simple SoapClient with your wsdl url and some options, that grant access to some really cool debugging functions. The trace
option enables the functions __getLastRequest()
and __getLastResponse()
so you can easily look at what has been send and what was the response, if the client is alive. You should set this option to false. Also the cache_wsdl
option should be removed, when the development process has ended.
Sending Data with the PHP SoapClient class
If we have a look into your wsdl file, we can see the exact definition for the function and the types this function needs. So let us see, what hentDataAftaler
needs.
<message name="hentDataAftalerIn">
<part name="parameters" element="uni:hentDataAftaler"/>
</message>
This is the definition for the hentDataAftaler
request. It says that this function requres an attribute type uni:hentDataAftaler
. In this case uni
ist the namespace in which hentDataAftaler
is defined. Your wsdl file also says, that the type definitions for the uni
namespace are defined in a seperated xsd file, which imports another xsd file. After a deep dive into the xsd definitions your request paramter is defined as follows.
<xs:complexType name="Credentials">
<xs:sequence>
<xs:element name="wsBrugerid" type="xs:string"/>
<xs:element name="wsPassword" type="xs:string"/>
</xs:sequence>
</xs:complexType>
With this knowledge you can easily call your webservice method with php. As defined your parameter is a complex type which equals a PHP object.
class Credentials
{
public $wsBrugerid;
public $wsPassword;
public function __construct(SoapVar $wsBrugerid, SoapVar $wsPassword)
{
$this->wsBrugerid = $wsBrugerid;
$this->wsPassword = $wsPassword;
}
}
$parameters = new Credentials(
new SoapVar('brugerid', XSD_STRING, null, null, 'wsBrugerid', 'https://uni-login.dk'),
new SoapVar('password', XSD_STRING, null, null, 'wsPassword', 'https://uni-login.dk')
);
$result = $client->hentDataAftaler($parameters);
What have we done here? We 've adapted the complex type from the xsd definition into a PHP class. This class takes two parameters as SoapVar objects, in which we define the value and namespace stuff. At the end we can take this object as the parameter and call the webservice method hentDataAftaler
. The function name is known automatically by the soap client, because the soap client takes this information directly from the wsdl file.
Hope this helps a little bit.