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 :) :

/**
  1. * Zend Framework Soap Server in WSDL-mode
  2. * This is a normal ZF controller class
  3. * Get WSDL by calling http://yourserver.com/soap-server?WSDL
  4. * @author Patrik Osteraker
  5. */
  6. class SoapServerController extends Zend_Controller_Action {
  7. /**
  8. * Executed before any ..Action()
  9. * Disable rendering and layout functionality
  10. */
  11. public function preDispatch()  {
  12. $this->_helper->viewRenderer->setNoRender();
  13. $this->_helper->layout()->disableLayout();
  14. }
  15.  
  16. public function indexAction() {
  17. // Check if we should serve the WSDL, http://yourserver.com/soap-server?WSDL
  18. if (array_key_exists('WSDL',$this->getRequest()->getParams())) {
  19. // Auto generate WSDL from existing class MyWebServices
  20. $autodiscover = new Zend_Soap_AutoDiscover();
  21.  
  22. // Here comes a hack!
  23. // The fourth parameter is a custom end point that overrides ZF's own end point logic, see explanation below
  24. $autodiscover->setClass('MyWebServices', '', null, "http://yourserver.com/soap-server");
  25. $autodiscover->handle();
  26. } else {
  27. $options=null;
  28. $server = new Zend_Soap_Server("http://yourserver.com/soap-server?WSDL", $options);
  29. $server->setClass('MyWebServices');
  30. $server->handle();
  31. }
  32. }
  33. }

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):

public function setClass($class, $namespace = '', $argv = null)
  1. {
  2. $uri = Zend_Uri::factory('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME']);
  3. 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 :

public function setClass($class, $namespace = '', $argv = null, $endPoint=null)
  1. {
  2. $uri = Zend_Uri::factory('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME']);
  3. if ($endPoint!=null) {
  4. $uri = Zend_Uri::factory($endPoint);
  5. }
  6. 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).

class MyWebServices {
  1.  
  2. /**
  3. * Echoes input string
  4. * Test method
  5. *
  6. * @param string $str
  7. * @return string
  8. */
  9. public function hello($str) {
  10. return $str;
  11. }
  12. }

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

Posted in Code at September 30th, 2008. Trackback URI: trackback
Tags: , , ,

5 Responses to “Zend Framework Soap Server in WSDL-mode”

  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

  2. 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.

  3. December 2nd, 2008 at 11:09 am #Patrik

    Great! This solves the issue and is makes the rather ugly hack obsolete :)

  4. August 28th, 2009 at 12:12 pm #Soap Webservices

    Great job you copied the Example from the Zend Tutorial….

  5. 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 ?

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>