Zend Framework Soap Server in WSDL-mode
Update: ZF version 1.7 offers a setUri() method that overrides the default endpoint. No hack needed.
I wanted to publish some web services over SOAP in an Zend Framework application of mine and tried out the ZF Soap classes. Getting this to work was not that obvious so I thought I would share my experiences. In a nutshell I wanted ZF to automatically generate an WSDL for me on the fly based on my class. Additionally it should work in a ZF application environment with URL rewriting. Current Zend_Soap documentation does not show this in a straightforward way.
You’re after the code anyway so here it is
:
-
* Zend Framework Soap Server in WSDL-mode
-
* This is a normal ZF controller class
-
* Get WSDL by calling http://yourserver.com/soap-server?WSDL
-
* @author Patrik Osteraker
-
*/
-
class SoapServerController extends Zend_Controller_Action {
-
/**
-
* Executed before any ..Action()
-
* Disable rendering and layout functionality
-
*/
-
public function preDispatch() {
-
$this->_helper->viewRenderer->setNoRender();
-
$this->_helper->layout()->disableLayout();
-
}
-
-
public function indexAction() {
-
// Check if we should serve the WSDL, http://yourserver.com/soap-server?WSDL
-
if (array_key_exists('WSDL',$this->getRequest()->getParams())) {
-
// Auto generate WSDL from existing class MyWebServices
-
$autodiscover = new Zend_Soap_AutoDiscover();
-
-
// Here comes a hack!
-
// The fourth parameter is a custom end point that overrides ZF's own end point logic, see explanation below
-
$autodiscover->setClass('MyWebServices', '', null, "http://yourserver.com/soap-server");
-
$autodiscover->handle();
-
} else {
-
$options=null;
-
$server = new Zend_Soap_Server("http://yourserver.com/soap-server?WSDL", $options);
-
$server->setClass('MyWebServices');
-
$server->handle();
-
}
-
}
-
}
That was our controller class. The hack stems from the current ZF end point definition in the setClass() method which is (Zend/Soap/AutoDiscover.php:74):
-
{
-
$uri = Zend_Uri::factory('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME']);
-
…continues
As you can see this won’t play nicely in a ZF application where URL rewriting is on. The SCRIPT_NAME will always be index.php and your SOAP client will shoot to the wrong end point (http://yourserver.com/index.php). So a small fix let’s you specify your own end point in full :
-
{
-
$uri = Zend_Uri::factory('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME']);
-
if ($endPoint!=null) {
-
$uri = Zend_Uri::factory($endPoint);
-
}
-
…continues
Alrighty then, we have a SOAP server, the only thing missing is the MyWebServices class. That class is a plain old PHP class with proper method documentation (!important, the autodiscovery logic uses the doc).
-
-
/**
-
* Echoes input string
-
* Test method
-
*
-
* @param string $str
-
* @return string
-
*/
-
public function hello($str) {
-
return $str;
-
}
-
}
Now you have a SOAP server that lives in the ZF application environment and can utilize it. Test and debug with the free tool soap UI
ZF version used is 1.6.1
September 30th, 2008 at 9:47 pm #Wil Sinclair
I’ll forward this to Alex so he can work out with you what additions need to be made to the reference guide. Hope Zend_Soap is treating you well now that you’ve figured out how to use it!
,Wil
November 27th, 2008 at 7:32 pm #beberlei
Zend_Soap_AutoDiscover has a setUri() function or takes an uri as second parameter of the constructor as of version 1.7 which can point to a different endpoint than the default one.
December 2nd, 2008 at 11:09 am #Patrik
Great! This solves the issue and is makes the rather ugly hack obsolete
August 28th, 2009 at 12:12 pm #Soap Webservices
Great job you copied the Example from the Zend Tutorial….
January 5th, 2010 at 12:13 pm #Amila
When i attempt the above code it generates a soapFault
SoapFault exception: [VersionMismatch] Wrong Version in C:\ZendFramework-1.9.4\library\Zend\Soap\Client.php:1063 Stack trace: #0 C:\ZendFramework-1.9.4\library\Zend\Soap\Client.php(1063): SoapClient->__soapCall(’GetAdminInfo’, Array, NULL, NULL, Array) #1 [internal function]: Zend_Soap_Client->__call(’GetAdminInfo’, Array)
what could be the fault ?