Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [SOAP] Problem z zagnieżdżonymi tablicami
Forum PHP.pl > Forum > XML, AJAX > XML
prond
Mam problem z biblioteka PEAR:SOAP w php 5 kiedy chcę przekazać jako argument zagnieżdżoną tablicę :

  1. <?php
  2. $arguments = array(
  3. 'proc' => 'COSTAM',
  4. 'args' => array(
  5. 'LOGIN' => '111',
  6. 'PASSWORD' => '111',
  7. )
  8. );
  9.  
  10. #...
  11.  
  12. $params = array (
  13. 'namespace' => 'JAKIS_SYSTEM',
  14. 'soapaction' => false,
  15. 'timeout' => 120
  16. );
  17.  
  18. #...
  19.  
  20. $this->soap_client = new SOAP_Client($strHost);
  21.  
  22. #...
  23.  
  24. $this->soap_client->call('login', $arguments, $params, -1);
  25.  
  26. #...
  27. ?>


Biblioteka traktuje to tak :

  1. <ns4:login>
  2. <proc xsi:type="xsd:string">COSTAM</proc>
  3. <args xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:string[2]" SOAP-ENC:offset="[0]">
  4. <item xsi:type="xsd:string">111</item>
  5. <item xsi:type="xsd:string">111</item></args></ns4:login>


Czyli traktuje $arguments['args'] jako array, a nie hash.
Próbowałem to rozwiązać przekazując argumenty jako obiekt (z tym samym efektem).

Wcześniej ta procedura śmigała na serwerze z PHP 4.3.11, po zmianie PHP na 5.2.0 zachowuje się tak jak wyżej.

Udało mi się rozwiązać problem wykorzystując wbudowaną bibliotekę z PHP 5.2.0 :
  1. <?php
  2. class DiaSoapClient extends SoapClient
  3. {
  4.  
  5. public function __construct($strHost, $strNamespace = '#', $strWSDL = null, $arrOptions = array())
  6. {
  7. parent::__construct($strWSDL, array(
  8. "location" => $strHost,
  9. "uri" => $strNamespace,
  10. "trace" => true
  11. ));
  12. }
  13.  
  14. public function getLocation()
  15. {
  16. return $this->location;
  17. }
  18.  
  19. public function setLocation($strLocation)
  20. {
  21. $this->location = $strLocation;
  22. }
  23.  
  24. public function getNamespace()
  25. {
  26. return $this->uri;
  27. }
  28.  
  29. public function setNamespace($strNamespace)
  30. {
  31. $this->uri = $strNamespace;
  32. }
  33.  
  34. /**
  35.  * Przeciazenie pobierania atrybutow obiektu umozliwiajace latwe operowanie przestr
    zeniami nazw
  36.  **/
  37. private function __get($strNamespace)
  38. {
  39. $this->uri = $strNamespace;
  40.  
  41. return $this;
  42. }
  43.  
  44. /**
  45.  * Przeciazenie wywolywania metod
  46.  *
  47.  * @todo  Dodac inne mozliwosci wywolywania procedur
  48.  * @todo  Rozszerzyc obsluge bledow
  49.  * @todo  Dodac obsluge roznych typow zwracanych przez serwer
  50.  **/
  51. public function __call($strMethodName, &$arrArguments)
  52. {
  53. $_arrArguments = array();
  54.  
  55. //
  56. // Przekazano tablice
  57. //
  58. if (count($arrArguments) === 1 && is_array($arrArguments[0]))
  59. {
  60. foreach($arrArguments[0] as $argumentName => $argumentValue)
  61. {
  62. $_arrArguments[] = (is_string($argumentName)) ? new SoapParam($argumentValue, $argumentName) : $argumentValue;
  63. }
  64. }
  65.  
  66. //
  67. // Wywolanie procedury
  68. //
  69. try {
  70. $result = parent::__soapCall($strMethodName, $_arrArguments);
  71. } catch (SoapFault $fault) {
  72. $result = null;
  73. }
  74.  
  75. return $result;
  76. }
  77. }
  78. ?>
splatch
Czy w XML Schema mapujesz odpowiednio typ? Widzę, że klientowi nie przekazujesz nawet położenia pliku WSDL. Być może to jest źródłem problemów?
Sh4dow
z tego co wiem to zmienne to zmienne i przez klienta SOAP w php musisz użyć obiektu SoapVar gdzie ustala sie czy to jest obiekt, tablica czy string itd. Jesli nie podasz nic i przekażesz parametr to potraktuje to jako string.
splatch
@Sh4dow - Twierdzę, że przyczyną błędu jest brak pliku WSDL. Może się mylę, ale korzystając z pliku WSDL unika się wielu problemów, tym bardziej, że SOAP to nie swawolny REST a definicje typów w XSD to podstawa.

Co do problemu - w pracy wykorzystujemy zdefiniowany typ dla każdej operacji, dzięki czemu nie ma problemów z ich obsługą. Swoją drogą SOAP:Array to jest lista, żeby w PHP dostać hash trzeba dać complexType:
  1. <xsd:complexType name="LoginRequest">
  2.    <xsd:sequence>
  3.        <xsd:element name="login" type="xsd:string" />
  4.        <xsd:element name="pass" type="xsd:string" />
  5.    </xsd:sequence>
  6. </xsd:complexType>
  7.  
  8. <wsdl:message name="LoginRequest">
  9.    <wsdl:part name="request" type="tns:LoginRequest" />
  10. </wsdl:message>


Listę można zrobić w bardzo prosty sposób, bez korzystania z dodatkowych przestrzeni nazw:
  1. <xsd:complexType name="LoginRequest">
  2.    <xsd:sequence>
  3.        <xsd:element name="item" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
  4.    </xsd:sequence>
  5. </xsd:complexType>
Sh4dow
splatch ja osobiscie na chwile obecna nie uzywam wsdl'a i nie mam problemow z przesylaniem tablic obiektow czy innych wartosc. Wszystko co wysylam daje jako obiekt SoapVar to ze wsdl jest pomocny przy walidacji to jedno, ale jego brak nie podejzewam zeby powodowal tyle problemow.
splatch
Problem polega na tym że, jak słusznie zauważył prond, biblioteka na podstawie typu deklaruje argument jako SOAP-ENC:Array w połączeniu z SOAP-ENC:arrayType=xsd:string, co oznacza listę a nie mapę.
W rozszerzeniu z PHP5 takie dane otrzymywaliśmy w postaci obiektów klasy stdClass.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.