Как создать SOAP веб-сервис в контроллере Symfony
Дата обновления перевода 2023-07-20
Как создать SOAP веб-сервис в контроллере Symfony
Настройка контроллера таким образом, чтобы он вёл себя, как веб-сервис SOAP - это легко с помощью некоторых инструментов. Конечно же, у вас должно быть установлено расширение PHP SOAP. Так как расширение PHP SOAP не может на данный момент сгенерировать WSDL, то вы должны либо создать его с нуля, либо использовать сторонний генератор.
Note
Существует несколько доступных к использованию реализаций SOAP-сервера с PHP. Zend SOAP и NuSOAP являются двумя примерами. Несмотря на то, что в этих примерах используется расширение PHP SOAP, общая идея должна быть применима к другим реализациям.
SOAP работает путём раскрытия методов PHP-объекта внешней сущности (т.е.
пользователю, использующему SOAP-сервис). Для начала, создайте класс
HelloService
, представляющий функциональность, которую вы раскроете в
вашем SOAP-сервисе. В этом случае, SOAP-сервис позволит клиенту вызывать
метод по имени hello
, который отправляет электронное письмо:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
// src/Service/HelloService.php
namespace App\Service;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Email;
class HelloService
{
private MailerInterface $mailer;
public function __construct(MailerInterface $mailer)
{
$this->mailer = $mailer;
}
public function hello(string $name): string
{
$email = (new Email())
->from('admin@example.com')
->to('me@example.com')
->subject('Hello Service')
->text($name.' says hi!');
$this->mailer->send($email);
return 'Hello, '.$name;
}
}
Далее, убедитесь в том, что ваш новый класс зарегистрирован как сервис. Если вы используете конфигурацию сервисов по умолчанию , то вам ничего не надо делать!
Наконец, ниже вы увидите пример контроллера, способного обработать SOAP-запрос.
Так как index()
доступен через /soap
, документ WSDL можетбыть вызван
через /soap?wsdl
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
// src/Controller/HelloServiceController.php
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;
}
}
Отметьте вызовы к ob_start()
и ob_get_clean()
. Эти методы контролируют
буферизацию вывода, что позволяет вам "поймать в ловушку" отражённый вывод
$server->handle()
. Это необходимо, так как Symfony ждёт, что ваш контроллер
вернёт объект Response
с выводом в качестве "содержания". Вы также должны
не забыть установить заголовок "Content-Type" (тип содержимого) как "text/xml",
так как это то, чего будет ожидать клиент. Таким образом, вы используете ob_start()
,
чтобы начать буферизацию STDOUT и используете ob_get_clean()
, чтобы сбросить
отражённый вовод в содержимое Ответа и очистить буфер вывода. Наконец, вы готовы
вернуть Response
.
Ниже показан пример вызова сервиса с использованием клиента NuSOAP. Этот
пример предполагает, что метод index()
в контроллере выше доступен по
маршруту /soap
:
1 2 3
$client = new \Soapclient('http://example.com/index.php/soap?wsdl');
$result = $client->call('hello', array('name' => 'Scott'));
Пример WSDL ниже.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
<?xml version="1.0" encoding="ISO-8859-1"?>
<definitions xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="urn:arnleadservicewsdl"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="urn:helloservicewsdl">
<types>
<xsd:schema targetNamespace="urn:hellowsdl">
<xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/" />
<xsd:import namespace="http://schemas.xmlsoap.org/wsdl/" />
</xsd:schema>
</types>
<message name="helloRequest">
<part name="name" type="xsd:string" />
</message>
<message name="helloResponse">
<part name="return" type="xsd:string" />
</message>
<portType name="hellowsdlPortType">
<operation name="hello">
<documentation>Hello World</documentation>
<input message="tns:helloRequest"/>
<output message="tns:helloResponse"/>
</operation>
</portType>
<binding name="hellowsdlBinding" type="tns:hellowsdlPortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="hello">
<soap:operation soapAction="urn:arnleadservicewsdl#hello" style="rpc"/>
<input>
<soap:body use="encoded" namespace="urn:hellowsdl"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output>
<soap:body use="encoded" namespace="urn:hellowsdl"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
</operation>
</binding>
<service name="hellowsdl">
<port name="hellowsdlPort" binding="tns:hellowsdlBinding">
<soap:address location="http://example.com/index.php/soap" />
</port>
</service>
</definitions>