.. index::
single: Web Services; SOAP
How to Create a SOAP Web Service in a Symfony2 Controller
=========================================================
Setting up a controller to act as a SOAP server is simple with a couple
tools. You must, of course, have the `PHP SOAP`_ extension installed.
As the PHP SOAP extension can not currently generate a WSDL, you must either
create one from scratch or use a 3rd party generator.
.. note::
There are several SOAP server implementations available for use with
PHP. `Zend SOAP`_ and `NuSOAP`_ are two examples. Although the PHP SOAP
extension is used in these examples, the general idea should still
be applicable to other implementations.
SOAP works by exposing the methods of a PHP object to an external entity
(i.e. the person using the SOAP service). To start, create a class - ``HelloService`` -
which represents the functionality that you'll expose in your SOAP service.
In this case, the SOAP service will allow the client to call a method called
``hello``, which happens to send an email::
// src/Acme/SoapBundle/Services/HelloService.php
namespace Acme\SoapBundle\Services;
class HelloService
{
private $mailer;
public function __construct(\Swift_Mailer $mailer)
{
$this->mailer = $mailer;
}
public function hello($name)
{
$message = \Swift_Message::newInstance()
->setTo('me@example.com')
->setSubject('Hello Service')
->setBody($name . ' says hi!');
$this->mailer->send($message);
return 'Hello, '.$name;
}
}
Next, you can train Symfony to be able to create an instance of this class.
Since the class sends an e-mail, it's been designed to accept a ``Swift_Mailer``
instance. Using the Service Container, you can configure Symfony to construct
a ``HelloService`` object properly:
.. configuration-block::
.. code-block:: yaml
# app/config/config.yml
services:
hello_service:
class: Acme\SoapBundle\Services\HelloService
arguments: ["@mailer"]
.. code-block:: xml
.. code-block:: php
// app/config/config.php
$container
->register('hello_service', 'Acme\SoapBundle\Services\HelloService')
->addArgument(new Reference('mailer'));
Below is an example of a controller that is capable of handling a SOAP
request. If ``indexAction()`` is accessible via the route ``/soap``, then the
WSDL document can be retrieved via ``/soap?wsdl``.
.. code-block:: php
namespace Acme\SoapBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
class HelloServiceController extends Controller
{
public function indexAction()
{
$server = new \SoapServer('/path/to/hello.wsdl');
$server->setObject($this->get('hello_service'));
$response = new Response();
$response->headers->set('Content-Type', 'text/xml; charset=ISO-8859-1');
ob_start();
$server->handle();
$response->setContent(ob_get_clean());
return $response;
}
}
Take note of the calls to ``ob_start()`` and ``ob_get_clean()``. These
methods control `output buffering`_ which allows you to "trap" the echoed
output of ``$server->handle()``. This is necessary because Symfony expects
your controller to return a ``Response`` object with the output as its "content".
You must also remember to set the "Content-Type" header to "text/xml", as
this is what the client will expect. So, you use ``ob_start()`` to start
buffering the STDOUT and use ``ob_get_clean()`` to dump the echoed output
into the content of the Response and clear the output buffer. Finally, you're
ready to return the ``Response``.
Below is an example calling the service using a `NuSOAP`_ client. This example
assumes that the ``indexAction`` in the controller above is accessible via the
route ``/soap``::
$client = new \Soapclient('http://example.com/app.php/soap?wsdl', true);
$result = $client->call('hello', array('name' => 'Scott'));
An example WSDL is below.
.. code-block:: xml
Hello World
.. _`PHP SOAP`: http://php.net/manual/en/book.soap.php
.. _`NuSOAP`: http://sourceforge.net/projects/nusoap
.. _`output buffering`: http://php.net/manual/en/book.outcontrol.php
.. _`Zend SOAP`: http://framework.zend.com/manual/en/zend.soap.server.html