Как работает преобразование классов PHP SOAP и как получить согласованные результаты списка? - PullRequest
0 голосов
/ 01 октября 2018

Итак, я сейчас пытаюсь реализовать внешний вызов API с помощью PHP SoapClient - и обнаружил, что он работает довольно странным образом.

Допустим, у меня есть следующий WSDLопределение:

<xs:element name="someParamList">
  <xs:complexType>
    <xs:sequence>
      <xs:element maxOccurs="unbounded" minOccurs="0" name="someParam" type="someParam"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>

, которое может возвращать либо:

<someParamList>
  <someParam>foo</someParam>
  <someParam>bar</someParam>
</someParamList>

, либо:

<someParamList>
  <someParam>foo</someParam>
</someParamList>

Я сопоставил someParamList с SomeParamListClass и someParam с SomeParamClass используя атрибут classmap.В целом это работает нормально, НО , в зависимости от результата, я не всегда получаю array из SomeParamClass.Если в списке только 1 результат, PHP будет непосредственно устанавливать объект вместо массива с одним объектом в нем.

Я пытался преобразовать данные в __construct __set или в обычный установщикно ни один из них не вызывается.

Итак: почему SoapClient действует так странно и почему он никогда не вызывает конструктор или сеттеры?И как мне получить согласованные списки?

1 Ответ

0 голосов
/ 01 октября 2018

Подобно различным подпрограммам десериализации, SoapClient не передает значения конструктору или установщику, которые вы можете перехватить, он просто создает объекты внутренне со значениями, «магически» настроенными.

Что вы можетевместо этого используется опция typemap вместо classmap, которая позволяет назначать обратные вызовы для преобразования типов, а не имен классов.

Однако «умное» форматирование списка может быть легче пропущеноиспользование параметра $options:

features является битовой маской из ... SOAP_SINGLE_ELEMENT_ARRAYS ...

На самом деле это нигде не описано, ноон заставляет каждый элемент декодированного XML быть массивом, а не пытаться угадать, какие из них единичные, а какие - множественные.Это может означать, что вам придется много писать $response[0]['foo'][0]['bar'][0], но по крайней мере это предсказуемо.

Итак:

$client = new SoapClient(
    $wsdl,
    [
        // other options which you're already passing here...
        'features' => SOAP_SINGLE_ELEMENT_ARRAYS
    ]
);
...