.. index:: single: Web Services; SOAP .. _how-to-create-a-soap-web-service-in-a-symfony2-controller: How to Create a SOAP Web Service in a Symfony Controller ======================================================== Setting up a controller to act as a SOAP server is aided by a couple tools. Those tools expect you to have the `PHP SOAP`_ extension installed. As the PHP SOAP extension cannot 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. `Laminas 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/Service/HelloService.php namespace App\Service; class HelloService { private $mailer; public function __construct(\Swift_Mailer $mailer) { $this->mailer = $mailer; } public function hello($name) { $message = new \Swift_Message('Hello Service') ->setTo('me@example.com') ->setBody($name.' says hi!'); $this->mailer->send($message); return 'Hello, '.$name; } } Next, make sure that your new class is registered as a service. If you're using the :ref:`default services configuration `, you don't need to do anything! Finally, below is an example of a controller that is capable of handling a SOAP request. Because ``index()`` is accessible via ``/soap``, the WSDL document can be retrieved via ``/soap?wsdl``:: namespace App\Controller; use App\Service\HelloService; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; class HelloServiceController extends AbstractController { /** * @Route("/soap") */ public function index(HelloService $helloService) { $soapServer = new \SoapServer('/path/to/hello.wsdl'); $soapServer->setObject($helloService); $response = new Response(); $response->headers->set('Content-Type', 'text/xml; charset=ISO-8859-1'); ob_start(); $soapServer->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 ``index()`` method in the controller above is accessible via the route ``/soap``:: $soapClient = new \SoapClient('http://example.com/index.php/soap?wsdl'); $result = $soapClient->call('hello', ['name' => 'Scott']); An example WSDL is below. .. code-block:: xml Hello World .. _`PHP SOAP`: https://www.php.net/manual/en/book.soap.php .. _`NuSOAP`: https://sourceforge.net/projects/nusoap .. _`output buffering`: https://www.php.net/manual/en/book.outcontrol.php .. _`Laminas SOAP`: https://docs.laminas.dev/laminas-soap/server/