За последние 24 часа нас посетили 20305 программистов и 1010 роботов. Сейчас ищут 367 программистов ...

SoapServer: как отдавать нормальный тег вместо item

Тема в разделе "Прочие вопросы по PHP", создана пользователем tmnv, 22 окт 2018.

  1. tmnv

    tmnv Новичок

    С нами с:
    21 окт 2018
    Сообщения:
    3
    Симпатии:
    0
    Здравствуйте, форумчане.

    Я пишу веб-сервис используя стандартный класс SoapServer и файл WSDL, с описание функций и типов данных. В общем-то всё работает, но есть один маленький нюанс, который меня сильно раздражает, т.к. я не могу найти на него ответ в Интернете.

    При возврате массивов объектов сервер ставит тегам имя "item" вместо того имени, что я указывал в WSDL. Можно ли это как-нибудь исправить?

    Хотелось бы так:
    HTML:
    1. <Services>
    2.     <Service>
    3.         <Name>PAYMENT_CASH</Name>
    4.         <Enabled>true</Enabled>
    5.     </Services>
    6.     <Service>
    7.         <Name>PAYMENT_CARD</Name>
    8.         <Enabled>true</Enabled>
    9.     </Services>
    10. </Services>
    А получается так:
    HTML:
    1. <Services>
    2.     <item>
    3.         <Name>PAYMENT_CASH</Name>
    4.         <Enabled>true</Enabled>
    5.     </item>
    6.     <item>
    7.         <Name>PAYMENT_CARD</Name>
    8.         <Enabled>true</Enabled>
    9.     </item>
    10. </Services>
    Вот часть WSDL с описанием типов:
    HTML:
    1. <xsd:complexType name="Services">
    2.     <xsd:complexContent>
    3.         <xsd:restriction base="SOAP-ENC:Array">
    4.             <xsd:attribute ref="SOAP-ENC:arrayType" wsdl:arrayType="tns:Service[]" />
    5.         </xsd:restriction>
    6.     </xsd:complexContent>
    7. </xsd:complexType>
    8.  
    9. <xsd:complexType name="Service">
    10.     <xsd:all>
    11.         <xsd:element name="Name" type="xsd:string" />
    12.         <xsd:element name="Enabled" type="xsd:boolean" />
    13.     </xsd:all>
    14. </xsd:complexType>
    PHP:

    PHP:
    1. function getServices() {
    2.     $Response = new stdClass();
    3.     ...
    4.     $Response->Services = [];
    5.     $Services = ServiceManager->getAll();
    6.     foreach ($Services as $Service) {
    7.         // $Service - экземпляр класса Service, подробно описывающий предоставляемую услугу.
    8.         $Response->Services[] = (object) ['Name' => $Service->getName(), 'Enabled' => $Service->isEnabled()];
    9.     }
    10.     ...
    11.  
    12.     return $Response;
    13. }
     
    #1 tmnv, 22 окт 2018
    Последнее редактирование: 22 окт 2018
  2. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.237
    Адрес:
    там-сям
    нет
     
  3. tmnv

    tmnv Новичок

    С нами с:
    21 окт 2018
    Сообщения:
    3
    Симпатии:
    0
    Спасибо за столь развёрнутый и обоснованный ответ...)) Но хотелось бы больше конкретики.

    И ещё. В документации по конструктору класса SoapServer ( https://php.ru/manual/soapserver.soapserver.html ) очень мало информации по использованию опции features и константам SOAP_WAIT_ONE_WAY_CALLS, SOAP_SINGLE_ELEMENT_ARRAYS и SOAP_USE_XSI_ARRAY_TYPE.

    Использование SOAP_SINGLE_ELEMENT_ARRAYS в клиенте SoapClient понятно, он позволяет вернуть элемент, содержащий массив именно как массив, даже если в нём самом всего один элемент массива:

    В клиенте БЕЗ опции SOAP_SINGLE_ELEMENT_ARRAYS:
    Код (Text):
    1. object(stdClass)#1 (1) {
    2.     [ 'Services'] =>
    3.     object(stdClass)#2 (1) {
    4.         [ 'Service'] =>
    5.         object(stdClass)#3 (2) {
    6.             [ 'Name'] =>
    7.             string(12) "PAYMENT_CARD"
    8.             ['Enabled'] =>
    9.             boolean true
    10.         }
    11.     }
    12. }
    В клиенте С опцией SOAP_SINGLE_ELEMENT_ARRAYS:
    Код (Text):
    1. object(stdClass)#1 (1) {
    2.     [ 'Services'] =>
    3.     object(stdClass)#2 (1) {
    4.         [ 'Service'] =>
    5.         array(1) {
    6.             [0]=>
    7.             object(stdClass)#3 (2) {
    8.                 [ 'Name'] =>
    9.                 string(12) "PAYMENT_CARD"
    10.                 ['Enabled'] =>
    11.                 boolean true
    12.             }
    13.         }
    14.     }
    15. }
    По поводу влияния остальных констант я не знаю, в особенности их влияния на SoapServer. Поясните пожалуйста, кто в курсе.
     
  4. tmnv

    tmnv Новичок

    С нами с:
    21 окт 2018
    Сообщения:
    3
    Симпатии:
    0
    Ладно. Видимо вопрос для многих нерешённый или совсем ненужный. Попробую сам разобраться. Может кому тоже пригодится. Вот что нашёл ( https://stackoverflow.com/questions...difference-between-soapserver-features-option ):

    SOAP_WAIT_ONE_WAY_CALLS
    Without this, SOAP will not wait for a response on one way calls. It will just continue on and assume that all is well in the world. A one way call is anything that does not have a response in the WSDL.

    SOAP_SINGLE_ELEMENT_ARRAYS
    Your SOAP call may return a single value, or it may return an array of values. However, if you enable this flag, then it will force that single value to be an array with just the single value. You'll know what your data looks like without having to check it.

    SOAP_USE_XSI_ARRAY_TYPE
    This sets the deserialization type. If an error like this comes up "No deserializer defined for array type {http://www.w3.org/2001/XMLSchema}", then look to enable this feature.