NuSOAP (link in archive.org) is a library that allows you to quickly and easily create SOAP-based webservices in PHP. The problem that you may encounter, however, is the fact that there is no obvious way to put some common code that you want to run in all (or almost all) of your SOAP functions. Think eg. about connecting to a database, or checking some username and password (token) or doing some logging. I’ll explain in this post how you may achieve that. I was using NuSOAP 0.9.5.
Let’s start with some slightly modified PHP code from NuSOAP intro page (archive.org). Obviously, it is all about server-side, so we’ll be dealing with nusoap_server class.
<?php // Pull in the NuSOAP code require_once('lib/nusoap.php'); // Create the server instance $server = new nusoap_server; // Register the method to expose $server->register('hello1'); $server->register('hello2'); $server->register('hello3'); // Define the methods as a PHP functions function hello1() { return 'Hello1'; } function hello2() { return 'Hello2'; } function hello3() { return 'Hello3'; } // Use the request to (try to) invoke the service $HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : ''; $server->service($HTTP_RAW_POST_DATA);
OK, so we have three SOAP functions: hello1, hello2 and hello3. Nothing special. However, what to do if you want to run some common code on the beginning of all these three functions? Sure, you can put it in some another function (let’s call it ini_code()) and then just to call it from each function, ie. put ini_code();
after opening parenthesis of each function. The problem with this approach is twofold, however:
- you will have to remember to add this line in each new SOAP function that you implement
- you can’t return from SOAP function without checking for errors returned from ini_code which will make common code even bigger
- it is ugly, unelegant and just simply lame (OK, this is a third reason).
The solution is to extend nusoap_server class and override its invoke_method method. If you open the file require
d in our example above (ie. lib/nusoap.php) you will notice that invoke_method is the place where your implemented SOAP functions are actually called from (near end of the method, via call_user_func_array
or some more perverse methods if you are using PHP version without this function). So let’s create the file “nusoap_server_wrapper.php” and put the following code in it:
<?php // see https://bartlomiejb.wordpress.com/2014/03/11/common-code-in-nusoap-soap-functions/ /* * We use this class to overwrite invoke_method() method * in order to put some common code in all of our implemented SOAP functions. */ class nusoap_server_wrapper extends nusoap_server { public function invoke_method() { // our common code here // you can use in it: // - $this->methodname - name of the called function // - $this->methodparams - parameters of the called function; it is an associative // array with parameters' names as keys and actual values as array values // - $this->methodreturn - use it as an lvalue (ie. write to it) and then // just |return;| to return from implemented SOAP function with a given value // as an example, let's write a called function name to a file $fp = fopen('nusoap-ext-test.txt', 'a'); // in production check for errors etc. fwrite($fp, 'called method is: ' . $this->methodname . "\n"); fclose($fp); // invoke original NuSOAP code to handle our function parent::invoke_method(); } }
Read comments in this piece of code and all will be – hopefully – clear. You should now modify your server-side code to use this class instead of nusoap_server. So, assuming that “nusoap_server_wrapper.php” is in the same directory as our example from the top of the page, you would have to add require_once('nusoap_server_wrapper.php');
after require
‘ing NuSOAP lib and then replace new nusoap_server
with new nusoap_server_wrapper
.
After running your client and calling all three SOAP functions you’ll notice not only that they work as usual, but that also their names are written to a file (obviously, you have to check write permissions etc. first) which proves that this code is indeed executed each time a SOAP function is called.
You should replace fopen/fwrite/fclose
with your code, of course.
That’s it! We extended NuSOAP and run common code in an elegant and easily maintainable way.
Update (2014-12-09): added links to archive.org as it seems that NuSOAP page is gone.