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