Як створити вед-сервіс SOAP у контролері Symfony
Дата оновлення перекладу 2023-05-27
Як створити вед-сервіс 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
$soapClient = new \SoapClient('http://example.com/index.php/soap?wsdl');
$result = $soapClient->__soapCall('hello', ['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:helloservicewsdl"
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>