Web services are software systems designed to support interoperable machine-to-machine interaction over a network. Nowadays if you want to connect external systems, you probably want or have to use web services. What I will discuss here is how to get your own SOAP web service up in minutes.
SOAP(Simple Object Access Protocol ) is probably the most used web service protocol today. It relies on XML as its message format, and it uses HTTP for message transmission. The SOAP server uses WSDL(Web Services Description Language ) to describe its services to external clients. WSDL is simply an XML-based language that provides a model for describing Web services.
Back in the old days you had to know a lot about SOAP and WSDL create a web service. Have a look at http://www.php.net/soap to see what I mean. Definitely not very good looking. Luckily Zend Framework has a nice component, Zend_Soap, that handles all the SOAP hard work you would be supposed to do.
So without further ado, here's the code(discussing a Zend Framework component, the code presented here uses the Zend MVC, but you can use it without the Zend MVC):
This is the source code for the controller:
You can also download the full project here.
As you can see you don't have to write a lot of code to back up the web service.
Let's discuss the controller first, because there's where the “magic” happens. The index action handles two types of requests: the request for the WSDL, handled by the hadleWSDL() method and the actual SOAP request, handled by the handleSOAP() method.
You can go ahead and try to see how your WSDL looks by accessing http://URL_TO_WEB_SERVICE/soap?wsdl , where URL_TO_WEB_SERVICE is the URL where you have deployed the example. Now imagine that you would have to construct and maintain this yourself, by hand, as old school bearded guys would. Well you don't, because this is handled by Zend_Soap_AutoDiscover which will create the WSDL file for you. The only thing that Zend_Soap_AutoDiscover needs to know is the class you want to use for the web service. Also, because PHP is not strongly typed, you will have to put PHPDoc blocks, because SOAP needs to know what types you are using as parameters and what types you are returning. Have a look here if PHPDoc does not ring a bell .
The SOAP server is handled by the Zend_Soap_Server class, and all it needs is the class you intend to use for the web service, and the URI to your WSDL file. Remember when you checked out how the WSDL file looks? That's exactly the URI you will have to use. In the example you will have to put that into the $_WSDL_URI variable, defined in the SoapController.
That was the SOAP server. Simple, right? Now let's have some tests on the server by implementing a simple SOAP client. The client is handled by the Zend_Soap_Client class that is constructed in the same manner as the server class, it needs just the URI to the WSDL file. After you have constructed the client, you can access the methods defined by the SOAP server in the same way you would access the methods of an object. In the example above you have a simple class, called Soaptest, that defines three very simple methods. Feel free to change the class and test your own methods. While you are playing with the server, you might notice that the WSDL file is cached, so if you change something into the Soaptest.php file, you might not get the expected result. Just delete the cached WSDL file from /tmp/wsdl-* while you do your tests.
You definitely want to have a look at the Zend Framework documentation located here.
That was it, as promissed: your SOAP web service up in minutes.
SOAP(Simple Object Access Protocol ) is probably the most used web service protocol today. It relies on XML as its message format, and it uses HTTP for message transmission. The SOAP server uses WSDL(Web Services Description Language ) to describe its services to external clients. WSDL is simply an XML-based language that provides a model for describing Web services.
Back in the old days you had to know a lot about SOAP and WSDL create a web service. Have a look at http://www.php.net/soap to see what I mean. Definitely not very good looking. Luckily Zend Framework has a nice component, Zend_Soap, that handles all the SOAP hard work you would be supposed to do.
So without further ado, here's the code(discussing a Zend Framework component, the code presented here uses the Zend MVC, but you can use it without the Zend MVC):
This is the source code for the controller:
require_once realpath(APPLICATION_PATH .
'/../library/').'/Soaptest.php';
class SoapController extends Zend_Controller_Action
{
//change this to your WSDL URI!
private $_WSDL_URI="http://192.168.188.128:8081/soap?wsdl";
public function indexAction()
{
$this->_helper->viewRenderer->setNoRender();
if(isset($_GET['wsdl'])) {
//return the WSDL
$this->hadleWSDL();
} else {
//handle SOAP request
$this->handleSOAP();
}
}
private function hadleWSDL() {
$autodiscover = new Zend_Soap_AutoDiscover();
$autodiscover->setClass('Soaptest');
$autodiscover->handle();
}
private function handleSOAP() {
$soap = new Zend_Soap_Server($this->_WSDL_URI);
$soap->setClass('Soaptest');
$soap->handle();
}
public function clientAction() {
$client = new Zend_Soap_Client($this->_WSDL_URI);
$this->view->add_result = $client->math_add(11, 55);
$this->view->not_result = $client->logical_not(true);
$this->view->sort_result = $client->simple_sort(
array("d" => "lemon", "a" => "orange",
"b" => "banana", "c" => "apple"));
}
}
And the code for the Soaptest.php class:
class Soaptest {
/**
* Add method
*
* @param Int $param1
* @param Int $param2
* @return Int
*/
public function math_add($param1, $param2) {
return $param1+$param2;
}
/**
* Logical not method
*
* @param boolean $param1
* @return boolean
*/
public function logical_not($param1) {
return !$param1;
}
/**
* Simple array sort
*
* @param Array $array
* @return Array
*/
public function simple_sort($array) {
asort($array);
return $array;
}
}
You can also download the full project here.
As you can see you don't have to write a lot of code to back up the web service.
Let's discuss the controller first, because there's where the “magic” happens. The index action handles two types of requests: the request for the WSDL, handled by the hadleWSDL() method and the actual SOAP request, handled by the handleSOAP() method.
You can go ahead and try to see how your WSDL looks by accessing http://URL_TO_WEB_SERVICE/soap?wsdl , where URL_TO_WEB_SERVICE is the URL where you have deployed the example. Now imagine that you would have to construct and maintain this yourself, by hand, as old school bearded guys would. Well you don't, because this is handled by Zend_Soap_AutoDiscover which will create the WSDL file for you. The only thing that Zend_Soap_AutoDiscover needs to know is the class you want to use for the web service. Also, because PHP is not strongly typed, you will have to put PHPDoc blocks, because SOAP needs to know what types you are using as parameters and what types you are returning. Have a look here if PHPDoc does not ring a bell .
The SOAP server is handled by the Zend_Soap_Server class, and all it needs is the class you intend to use for the web service, and the URI to your WSDL file. Remember when you checked out how the WSDL file looks? That's exactly the URI you will have to use. In the example you will have to put that into the $_WSDL_URI variable, defined in the SoapController.
That was the SOAP server. Simple, right? Now let's have some tests on the server by implementing a simple SOAP client. The client is handled by the Zend_Soap_Client class that is constructed in the same manner as the server class, it needs just the URI to the WSDL file. After you have constructed the client, you can access the methods defined by the SOAP server in the same way you would access the methods of an object. In the example above you have a simple class, called Soaptest, that defines three very simple methods. Feel free to change the class and test your own methods. While you are playing with the server, you might notice that the WSDL file is cached, so if you change something into the Soaptest.php file, you might not get the expected result. Just delete the cached WSDL file from /tmp/wsdl-* while you do your tests.
You definitely want to have a look at the Zend Framework documentation located here.
That was it, as promissed: your SOAP web service up in minutes.
thank you for your tutorial, but i have a problem with this. i get this error:
ReplyDelete"Message: SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://localhost/ZfSoapTest/public/soap?wsdl' : Premature end of data in tag html line 2"
can u help me ?
Can you post the result of your wsdl URI, htp://..../soap?wsdl ? You can access that directly from the browser. I think something is wrong with your WSDL file.
ReplyDeleteI found the problem.
ReplyDeletethis is related to charset :)
thank you anyway.
this article was very helpful 4 me.
This comment has been removed by the author.
ReplyDeleteGreat post¡¡
ReplyDeleteIf you try to stick on ZF modular structure, you can try my soap webservice example. It also makes automatic documetation and test forms by reflection methods. Try it here http://www.fordnox.com/blog/2009/05/zf-18-soap-server-example-module
ReplyDeletegreat article, thanks for taking the time to write it.
ReplyDeleteI am thinking of adding a Soap Service on a project i am curently working on and this come just in time
Muito bom o post, valeu!
ReplyDeleteParabens
This comment has been removed by a blog administrator.
ReplyDeleteThis comment has been removed by a blog administrator.
ReplyDeleteGreat post :)
ReplyDeleteI am trying to consume a web service and it is giving me an error
ReplyDeleteMessage: SOAP extension is not loaded.
I am new to Zend Framework and dont know how to proceed
For Pali: You have to enable the PHP SOAP extension first. See here http://uk3.php.net/manual/en/soap.installation.php
ReplyDeleteThis comment has been removed by a blog administrator.
ReplyDeleteVery good article to quickly get started with SOAP web services.
ReplyDeleteHI, thanks for this quick start guide to SOAP.
ReplyDeleteI have set up your soapcontroller in an existing site and the wsdl is working, but I have a series of Zend_Loader errors when I point my browser to the soap service. (this results in my app throwing the error page and the xml presented is malformed).
I have tried placing the file Soaptest.php in different locations, everytime the same error, and in the last try I put it in the models directory and I should not need to require Soaptest.php in the SoapController, but even if I do I get the same error.
My the url to wsdl is
http://adamz.casa/soap?wsdl
(adamz.casa is on my local machine)
The xml response from the service contains no data but all the tags are there and the NameSpace is http://adamz.casa/index.php
Warning Zend_Loader::include_once(Array.php) and
Zend_loader::include_once(Int.php) cannot be found in path.
I notice that you use Zend_Application which my installation of Zend Framework does not have. Should the Soap service not work anyway?
I would be very grateful if you could point me in the right direction to fix this error.
I will need a SOAP service on my app by the end of next week.
Try getting the latest Zend Framework, if you don't have Zend_Application it means you miss the nice features in the latest releases. I would even suggest installing Zend Server Community Edition - http://www.zend.com/en/products/server/ . It comes preconfigured with the latest Zend Framework and everything you need to use it. The example posted should work out of the box, with minor changes of the actual WSDL url.
ReplyDeleteYour example worked great out of the box. But then I tried to duplicate one of your methods. say math_add and called it math_add_two I get the following error when I try calling it the Zend_Soap_Client
ReplyDeleteMessage: Function ("math_add_two") is not a valid method for this service.
I don't really under stand what the issue could be. I was using Version 1.9.2 so I updated to 1.9.5 and got the same error.
Try removing the wsdl cache files. On Linux PHP will create cache files into /tmp/wsdl-* , on Windows most of the times the files are in Windows\Temp.
ReplyDeleteNot really a useful comment. Just a thanks!
ReplyDeleteThank you for your tutorial. On local server all work good. But on provide server has errors with wsdl:
ReplyDelete1) output hasnt type information - everywhere "anyType"
2) return parts are missing
class has docblock and it works on my local server
I type http://localhost:10088/soap/public/soap?wdsl and the result is
ReplyDeleteSenderInvalid XML
what's wrong?
I only download your zip.
Decompress it.
And change $_WSDL_URI of course!
ohoh, I obtain the following error:
ReplyDeleteMessage: Unsupported Media Type
my code is pretty simple while trying to consume a web service:
public function soapAction() {
$ws = new Zend_Soap_Client($_WSDL_URI);
$this->view->resultado = $ws->getPrecioProducto(2);
}
and my WSDL: http://joaquinlrobles.redirectme.net:8080/Pelopincho/PelopinchoService?WSDL
This comment has been removed by the author.
ReplyDeleteI should add that, if you define another parameter name for the ws-operations diff than param*, you must specify this name in the function call on the client side like this:
ReplyDelete$resultado = $ws->getStockProducto(array('idProducto' => $idProducto));
if the operation parameter was called idProducto instead of param1...
To anyone who has problems with adding new methods to the project. Remember to put comments with 'param' and 'return', as those are take while creating WSDL.
ReplyDeleteHi,
ReplyDeleteI am currently using ZF 1.10.2, my wsdl works well ( if I call http://my-project-url/soap?wsdl I get the xml ), but if I call the client action I get an exception "[WSDL] SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://xxx/soap?wsdl' .
I also tried to save the generated xml file and edit the WSDL path to point this file, didn't work as well.
Any advices?
What version of PHP are you using? There are some bugs in the PHP Soap Client that were solved quite recently, so if you don't have the latest version I suggest an update.
ReplyDeleteHello,
ReplyDeleteI have this exception when I'm running my php code on an Apache 2.2.3 server and php 5.1.6. It uses a Zend_Soap_Client.
PHP Fatal error: Uncaught SoapFault exception: [3001] Invalid Session in ...... Zend/Soap/Client.php on line 1113
Have you ever seen this type of exception?
Changing the soap_version back and forth did not work. The worst is that I have the exact same code on my localhost and it works. I checked the php settings and they are the same, but I guess I miss somethig. Any ideas? Thanks.
PHP 5.1.6 is really old, try to get the latest version if possible. Probably you have a more recent version on your localhost, that's why it works.
ReplyDeleteHi.I just came across this site.Please send me the sample soap wsdl file.I noticed its not on the download sample.
ReplyDeleteThe WSDL is dynamic and you can access it at http://URL_TO_WEB_SERVICE/soap?wsdl
ReplyDeletethanks . useful information especially create this service with zend framework
ReplyDeleteregards,
Riki Risnandar
Thanks for the nice post and sample code. I tried it and it runs good but... when I try to do my self a new project with zf tool it doesn't work, the SOAP extension is not loaded! Why? I've created also with the zf tool a model and a soap controller and inserted your code inside. Regards.
ReplyDeleteThanks, it works! I needed only to disable the layout too... you can do this adding the following line in the indexAction method:
ReplyDelete$this->_helper->layout->disableLayout();
Hello,
ReplyDeletegreat post.
But if I add some more parameters to math_add($p1,$p2,$p3,$p4) e.g., only the first 2 parameters ($p1,$p2) are set, others are null in clientAction.
???
You can find some additional information about zend_soap and web-services here http://plutov.by/post/web_service_soap
ReplyDeletehi i create web services by seeing your example..my web services used by some third party.. in client we are sending data in array, parameter format.but my third party has to send in xml format. and result also want in xml format.please can u help on this ...
ReplyDeleteHi
ReplyDeleteCan you please show me how to run the client?
Thanks
This comment has been removed by the author.
ReplyDeleteHello,
ReplyDeleteI am new to ZF and when I run your project I get the following warnings followed by an "Maximum execution time error":
Warning: SoapClient::SoapClient(http://localhost/soap/public/soap?wsdl) [function.SoapClient-SoapClient]: failed to open stream: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. in D:\xampp\htdocs\soap\library\Zend\Soap\Client\Common.php on line 51
Warning: SoapClient::SoapClient() [function.SoapClient-SoapClient]: I/O warning : failed to load external entity "http://localhost/soap/public/soap?wsdl" in D:\xampp\htdocs\soap\library\Zend\Soap\Client\Common.php on line 51
Fatal error: Maximum execution time of 60 seconds exceeded in D:\xampp\htdocs\soap\library\Zend\Soap\Client\Common.php on line 52
Can you help me out?
Tx
What does "Invalid XML"? What's the problem?
ReplyDeleteThis comment has been removed by a blog administrator.
DeleteThis comment has been removed by the author.
ReplyDeleteI am hoping that by my next post here, I will have the links up to Book Locker, as well as Amazon, where this new novel will be available for sale.
ReplyDeleteLiterature Review
What if i use basic http authentication while creating soap client?
ReplyDelete$client = new Zend_Soap_Client($this->_WSDL_URI, array("login" => "user", "password" => "password"));
This comment has been removed by the author.
ReplyDeleteyour information very helpful and great work webs service
ReplyDeleteBest Casinos Near Hollywood (CO) Casino in - Mapyro
ReplyDeleteFind the best 김천 출장안마 Casinos 양산 출장안마 near Hollywood (CO) Casino in Hollywood, Indiana (CO) with real users 시흥 출장샵 reviews, 당진 출장안마 ratings, 제주도 출장샵 latest pictures, opening hours and a map of
كيف استثمر في امازون؟ هو سؤال شاغر للعديد من الاشخاص
ReplyDelete