During my latest project I was faced with the need to access a PHP class with all its methods and properties from another server. This lead to some research and an astonishingly simple solution…
Your first thought might be: Why not simply copy the class file(s) to the second machine? Well, my class uses a database and generates images and I had to consolidate all these functions on a single machine while offering the methods of the class to multiple systems on other servers.
My research started with the possibilities to issue remote procedure calls (RPC) in PHP and I quickly found that the modern way to do it is the Simple Object Access Protocol (SOAP). While I was aware of this protocol, I had not realized that it would provide exactly what I needed for my task. But it soon became clear to me that this was the way to go and that I had to build a SOAP server around my class.
Ok, this sounded like a full day job. And it actually was. But only because I needed so much time and so many trials to find the best way to implement SOAP for my needs. In the end it was all incredibly simple.
You may skip to the “Go, Forrest!” section, if you want to get your hands dirty right away. But if you want to know about the rocky road to enlightenment, here is a quick summary of the detours that I had to take…
The SCA_SDO package?
My further research lead me to the PECL package SCA_SDO for PHP that basically creates a SOAP server only from PHPDocumentor compliant comments in the class file. That sounded like a great way to go and I also found some nice tutorials on the web.
But… while I tried to install the SCA_SDO package I found that it has not been maintained since 2008. The package is probably dying. It is also not compatible with PHP 5.3 although there are patches available if you are willing and able to compile the package yourself. I was not.
The NuSOAP class set?
NuSOAP is a SOAP implementation in pure PHP. It is probably the best way to go if you do not have access to your PHP.ini and cannot install PHP extensions. I do not have these restrictions. Beside that the native PHP SOAP extension that I finally chose to work with is available on most shared hosting solutions.
The PHP SOAP extension!
PHP SOAP is a native PHP extension that adds SOAP server and client capabilities to PHP. I quickly found some great tutorials on the web and after I finally decided to go this way, I actually transformed my existing PHP class with several public methods, database manipulation and image generation into a fully functional SOAP service within some 10 minutes(!). Another 5 minutes went into transforming an existing PHP testing page for that class into a SOAP client that would test against my server.
I could hardly believe how fast it all was done and how simple and stable it worked. I did not create a WSDL file for my SOAP server though – simply because I don’t need one. WSDL stands for Web Services Description Language and is a means of announcing your SOAP service’s capabilities and interface to the public in the form of a standardized XML file. As I did not intend to open up my web service to anybody but myself I did not need to create a WSDL file. SOAP works perfectly without it if you know the names and parameters of your methods (which you hopefully do). See the very last section if you still want some hints on WSDL creation.
Go, Forrest!
Now, here is a quick summary of what you have to do to install the SOAP extension, create a SOAP server from any existing class and transform a PHP testing file for that class into a corresponding SOAP client:
Install the SOAP extension
It’s a simple PHP extensions and it comes bundled with PHP 5.x. You can activate it with the usual statement in your PHP.ini file.
Windows:
extension=php_soap.dll
Linux:
extension=php_soap.so
On Linux you additionally will have to start PHP with the –enable-soap switch.
If SOAP is running you will find a dedicated soap block in the output of phpinfo(). This is also the easiest way to see if your shared hosting provider has the SOAP extension enabled:
As usual the configuration of the extension can be done in PHP.ini. You will most likely find a preconfigured block that you do not need to change for your first trials:
[soap] ; Enables or disables WSDL caching feature. ; http://php.net/soap.wsdl-cache-enabled soap.wsdl_cache_enabled=1 ; Sets the directory name where SOAP extension will put cache files. ; http://php.net/soap.wsdl-cache-dir soap.wsdl_cache_dir="/tmp" ; (time to live) Sets the number of second while cached file will be used ; instead of original one. ; http://php.net/soap.wsdl-cache-ttl soap.wsdl_cache_ttl=86400 ; Sets the size of the cache limit. (Max. number of WSDL files to cache) soap.wsdl_cache_limit = 5
Missing PHP SOAP extension on Windows?
When the SOAP extension DLL for Windows is not available in your PHP /ext/ path, here are some hints to download the correct version:
The complete set of extension DLLs is usually contained in the Windows ZIP file distributions of PHP. You will have to choose between VC6 and VC9 versions and between Thread Safe and Non Thread Safe versions. Use phpinfo() to find the compiler version used for your PHP (VC6, VC9) and the Thread Safety of your PHP version:
After the extension is up and running, let’s finally see some hard facts and coding!
Building a SOAP server from a PHP class
Let’s say you have a normal class file /myPath/class/MyClass.php that you want to turn into a SOAP service. To do that, you build a very simple PHP wrapper file /myPath/myClassSoapServer.php which will load the class and act as SOAP server to offer the class methods. Here is the wrapper code:
<?php // *** The SOAP class wrapper: myClassSoapServer.php *** require_once('class/MyClass.php'); $options = array('uri' => 'http://www.mydomain.com/myPath/'); $SOAPServer = new SoapServer(null, $options); $SOAPServer->setClass('MyClass'); $SOAPServer->handle(); ?>
That’s all! You have built a SOAP server from your class!
Building a SOAP client from a PHP file
My next assumption is that together with your class you have a PHP testing file on your webserver. It includes/requires your class, instantiates it, calls a method and echos the result so you can check it in your webbrowser:
<html> <head></head> <body> <?php // *** The usual way: using a class locally *** require_once('class/MyClass.php'); $hdl = new MyClass(); $data = $hdl->myClassMethod($param1, $param2); echo $data; ?> </body> </html>
And here is the same code converted into a SOAP client:
<html> <head></head> <body> <?php // *** The SOAP way: using a class remotely *** $options = array( 'location' => 'http://www.mydomain.com/myPath/myClassSoapServer.php', 'uri' => 'http://www.mydomain.com/myPath/' ); $hdl = new SoapClient(null, $options); $data = $hdl->myClassMethod($param1, $param2); echo $data; ?> </body> </html>
So basically all you have to do is to replace the require_once statement and the instantiation of the class. Instead you instantiate the SOAP class and provide the constructor with some simple options in an array. The big difference between the two code versions is that the first one has to be located on the same machine and in the same filesystem as the class file, while the second one can be located on any other server somewhere else in the world!
Done!
That’s it. You have created a SOAP server and client with minimal effort.
The SoapClient instance (stored in $hdl) works very much like the original class instance in the local version. All the communication between the client machine and the server machine is handled transparently through the SOAP extension. On the other hand there is nothing to be said against placing the SOAP server and client scripts on the same machine and same domain, e.g. for testing purposes.
The icing on the cake: WSDL
As said, a WSDL service description is only needed if you want to announce and open your web service to the public. This is not subject of this discussion. In fact it was one of my major findings that I do not need such a file to distribute PHP classes over multiple servers with SOAP. Anyway here are some quick remarks if you still want to create a WSDL file for your web service:
There are multiple approaches for semi-automatic generation of WSDL files. The main advantage of the SCA_SDO package discussed above would have been, that it automatically creates the WSDL file from the comments in your class file. This is a great approach, but as mentioned before, the package is obviously dying. As a replacement you will find similar tools on the web that analyze your code and/or comments and generate WSDL file skeletons for you. Some PHP IDEs also include WSDL editors and/or generators (e.g. ZEND). And – if all fails – you can still write your WSDL manually. Look out for the many nice tutorials on the web!