One of the recent projects required integrating a 3rd party application. The backend was developed using CodeIgniter v3 running on PHP v5+. I emphasized on standards and chose SOAP as the integration technology. Although PHP v5 has native support for SOAP server and client, I wanted to prevent re-inventing the wheel. That’s when I bumped on to NuSOAP library, provided by NuSphere and Dietrich Ayala. There are two variations, old and new. I decided to go with the latest.
- NuSOAP old : http://sourceforge.net/projects/nusoap/
- NuSOAP new : http://sourceforge.net/projects/nusoapforphp53/
The web is full of “HowTo”s about integrating NuSOAP with CodeIgniter. Careful observation revealed that most of them are copied from one or two sources ! After reading few, I decided to make my hands dirty. This is my experience. Upon running the library as is, I encountered several errors. They are mostly to do with PHP v5.5 compatibility issues. Looks like the developers were too busy to upgrade it. I hope this post will be useful for someone trying to do a similar activity. You are free to use anything from this page, and don’t forget to post your experience in the comments section below.
The beginning
- Download NuSOAP new version and copy the /lib folder to codeigniter’s application\libraries folder (I used v1.114 2007/11/06 15:17:46)
- Create a custom library wrapper in the same application\libraries folder (make sure the filename is Nusoap_lib.php – CodeIgniter v3 requires file names to start with a capital letter)
<?php class Nusoap_lib { function Nusoap_lib() { require_once('lib/nusoap.php'); } }
Patches
These are the patches I made (my version available at the bottom of this page)
- Line 2673 : original : set_magic_quotes_runtime(0);
replace with : ini_set(‘magic_quotes_runtime’, 0); - Line 3314 : original : $data = split(‘;’, $cookie_str);
replace with : $data = explode(‘;’, $cookie_str); - Line 5328 : remove this line <br><br>
- After Line 5456 add this line: if (isset($attrs[‘operations’])) {
- After Line 5484 add this line: }
- After Line 7389 add this line: unset($this->wsdl);
Server
Although I wanted to use try-catch for error management I realized that I can’t use:
throw new SoapFault("Server", "Some error message");
instead I used this:
return new soap_fault('-1', 'Server', 'Some error message', 'Some details here');
Here’s the server controller, at: application\controllers\MySoapServer.php
<?php if (!defined('BASEPATH')) exit('No direct script access allowed'); class MySoapServer extends CI_Controller { function __construct() { parent::__construct(); //$this->load->model(''); //load your models here $this->load->library("Nusoap_lib"); //load the library here $this->nusoap_server = new soap_server(); $this->nusoap_server->configureWSDL("MySoapServer", "urn:MySoapServer"); $this->nusoap_server->register( "echoTest", array("tmp" => "xsd:string"), array("return" => "xsd:string"), "urn:MySoapServer", "urn:MySoapServer#echoTest", "rpc", "encoded", "Echo test" ); /** * To test whether SOAP server/client is working properly * Just echos the input parameter * @param string $tmp anything as input parameter * @return string returns the input parameter */ function echoTest($tmp) { if (!$tmp) { return new soap_fault('-1', 'Server', 'Parameters missing for echoTest().', 'Please refer documentation.'); } else { return "from MySoapServer() : $tmp"; } } } function index() { $this->nusoap_server->service(file_get_contents("php://input")); //shows the standard info about service } }
Once the server is running you can test it by calling the controller class. Here’s the result.
Click on the wsdl link to see the auto-generated WSDL file; and click on the echoTest link to see the details of our first test function.
[Not a valid template]
Client
Here’s the client controller, at: application\controllers\MySoapClient.php
Always use try-catch blocks to prevent bad error messages shown to users.
<?php if (!defined('BASEPATH')) exit('No direct script access allowed'); class MySoapClient extends CI_Controller { private $wsdl, $client; public function __construct() { parent::__construct(); global $wsdl, $client; $this->load->library("Nusoap_lib"); $proxyhost = isset($_POST['proxyhost']) ? $_POST['proxyhost'] : ''; $proxyport = isset($_POST['proxyport']) ? $_POST['proxyport'] : ''; $proxyusername = isset($_POST['proxyusername']) ? $_POST['proxyusername'] : ''; $proxypassword = isset($_POST['proxypassword']) ? $_POST['proxypassword'] : ''; $wsdl = base_url() . 'MySoapServer?wsdl'; $client = new nusoap_client($wsdl, 'wsdl', $proxyhost, $proxyport, $proxyusername, $proxypassword); $err = $client->getError(); if ($err) { echo '<h2>Constructor error</h2><pre>' . $err . '</pre>'; } } public function index() { global $wsdl, $client; try { $param = array('tmp' => 'XYZ'); $result = $client->call('echoTest', $param, '', '', false, true); echo '<h2>Result</h2><pre>'; print_r($result); echo '</pre>'; } catch (SoapFault $exception) { echo $exception; } echo '<h2>Request</h2><pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>'; echo '<h2>Response</h2><pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>'; //echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->debug_str, ENT_QUOTES) . '</pre>'; //this generates a lot of text! } }
These are the function call prototypes (from nusoap.php)
function nusoap_client($endpoint, $wsdl = false, $proxyhost = false, $proxyport = false, $proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30) function call($operation, $params = array(), $namespace = 'http://tempuri.org', $soapAction = '', $headers = false, $rpcParams = null, $style = 'rpc', $use = 'encoded') function soap_fault(faultcode, faultactor, faultstring, detail)
Here’s the output from the browser:
Testing
I used the SOAPui, to test the communication. There are many browser-plugins, but nothing can be compared to SOAPui’s functionality. It has test cases, asserts, authentication, headers etc…
First try with an input and then without. You should see soap_fault is generated.
What is NOT shown here
My intention is to show you the bare minimum to implement a successful SOAP activity. If you read the server code carefully, the action method lives inside the constructor. This is not good, you can easily move it out but that requires using $this-> to refer the instance. But it is NOT available inside the constructor, we need to use $CI = & get_instance();
I also have not used any authentication here, although you must at least use “HTTP Basic Auth”.
Links
Use following links to extend your journey.
- Patched and tested library and other code in codeigniter folder structure
- The best tool for SOAP communication testing – SOAPui
- XSD data types list
- Custom data structure example – in case you need to send/receive arrays or records
- HTTP authentication with PHP
- Using HTTP Basic Authentication
hai, im really new with soap. i try this and looks like the server is working and give the same result on test function. but when i try the soapclient its didnt show anything and give no error. can you help what maybe wrong?
i have try fixing with adding .htaccess but still its only give request but the result and response didnt show anything
I try using this function in my CI 3.15 and PHP 7. It return empty in response.. What seem to be the problem?
what if you want to save the data from the soap envelope to a database?
well, there’s is nothing unusual. You can use standard database access code.
Thanks man! Your code about the constructors helped me get nuSOAP going with PHP7. Great!
Awesome! Pretty much all other code out there is copied from one source. Thank you for the clear breakdown.
As a follow-up to my previous question, I echoed the debug and I got these:
2016-02-20 21:45:58.535868 soap_transport_http: HTTP request: GET /cinusoap53/index.php/MySoapServer?wsdl HTTP/1.1
2016-02-20 21:45:58.535891 soap_transport_http: HTTP header: Host: localhost
2016-02-20 21:45:58.535918 soap_transport_http: HTTP header: User-Agent: NuSOAP/0.7.3 (1.114)
2016-02-20 21:45:58.535938 soap_transport_http: HTTP header: Accept-Encoding: gzip, deflate
2016-02-20 21:45:58.535956 soap_transport_http: HTTP header: Connection: close
2016-02-20 21:45:58.535975 soap_transport_http: HTTP header: Content-Length: 0
2016-02-20 21:45:58.536073 soap_transport_http: wrote data to socket, length = 177
2016-02-20 21:45:58.539164 soap_transport_http: read line of 24 bytes: HTTP/1.1 404 Not Found
:
:
2016-02-20 21:45:58.541226 wsdl: HTTP ERROR: Unsupported HTTP response status 404 Not Found (soapclient->response has contents of the response)
2016-02-20 21:45:58.541282 nusoap_client: checkWSDL
2016-02-20 21:45:58.541303 nusoap_client: got wsdl error: HTTP ERROR: Unsupported HTTP response status 404 Not Found (soapclient->response has contents of the response)
What could be my problem? I’m expecting this Result
from MySoapServer() : XYZ
but I got nothing.
Same for the Request and Response. I got nothing, unlike what you have in your sample output from the browser.
Hope to get a reply from you. Thanks!
I tried your codes however I got nothing printed from Result, Request, and Response unlike the picture of the browser output you’ve shown here. Why is this so?