2010-09-23 28 views
12

Usando PHP y SoapClient.Cómo pasar una matriz a una llamada de PHP SoapClient

Necesito pasar el siguiente XML en una solicitud de jabón - es decir, <stay>'s múltiples dentro de <stays>.

<reservation> 
    <stays> 
     <stay> 
      <start_date>2011-01-01</start_date> 
      <end_date>2011-01-15</end_date> 
     </stay> 
     <stay> 
      <start_date>2011-01-16</start_date> 
      <end_date>2011-01-30</end_date> 
     </stay> 
    </stays> 
</reservation> 

El problema es que estoy pasando los datos en forma de matriz:

$xml = array('reservation' => array(
    'stays' => array(
     array(
      'start_date' => '2011-01-01', 
      'end_date' => 2011-01-15 
     ), 
     array(
      'start_date' => '2011-01-16', 
      'end_date' => 2011-01-30 
     ) 
    ) 
); 

Lo anterior no funciona, como <stay> no está definido. Por lo que la alternativa es:

$xml = array('reservation' => array(
    'stays' => array(
     'stay' => array(
      'start_date' => '2011-01-01', 
      'end_date' => 2011-01-15 
     ), 
     'stay' => array(
      'start_date' => '2011-01-01', 
      'end_date' => 2011-01-15 
     ) 
    ) 
); 

Pero eso da lugar a duplicados de las llaves, por lo que sólo uno de los <stay> 's se envía.

Me estoy quedando esta como:

$soapClient->saveReservation($xml); 

¿Alguna idea sobre cómo puedo estructurar la matriz de manera que se genera el XML anterior?


Alguna información adicional. Los ejemplos anteriores fueron súper simplificados, así que aquí hay un ejemplo de uso real de lo que estoy haciendo, con la sugerencia de benjy implementada.

$options = $this->api->getDefaultOptions(); 
$options['baseProductCode'] = '123'.$basket->accommodation['feed_primary_identifier']; 
#        ^^^^^ just to ensure it fails and doesn't process 
$reservation = new stdClass(); 

$reservation->external_id = $order->pb_ref; 
$reservation->etab_id = $basket->accommodation['feed_primary_identifier']; 
$reservation->reservation_type = 'gin'; 
$reservation->firstname = $order->forename; 
$reservation->lastname = $order->surname; 
$reservation->birthdate = date('Y-m-d', strtotime('- 21 YEAR')); 
$reservation->stays = array(); 
$details = $basket->getDetailedBasketContents(); 
foreach ($details['room_types'] as $roomTypeId => $roomType) { 
    foreach($roomType['instances'] as $instance) { 
    $stay = new stdClass(); 
    $stay->nb_rooms = 1; 
    $stay->room_type_code = $roomTypeId; 
    $stay->start_date = date('Y-m-d', strtotime($order['checkin'])); 
    $stay->end_date = date('Y-m-d', strtotime($order['checkout'])); 
    $stay->occupants = array(); 
    foreach($instance['occupancy']['occupants'] as $key => $occupantData) { 
     if ($occupantData['forename'] and $occupantData['surname']) { 
     $occupant = new stdClass(); 
     $occupant->firstname = $occupantData['forename']; 
     $occupant->lastname = $occupantData['surname']; 
     $occupant->pos = 100; 
     $occupant->birthdate = date('Y-m-d', strtotime('- 21 YEAR')); 
     $stay->occupants[] = $occupant; 
     } 
    } 
    $reservation->stays[] = $stay; 
    } 
} 

$options['reservation'] = new stdClass(); 
$options['reservation']->reservation = $reservation; 


//echo XmlUtil::formatXmlString($this->api->); 

try { 
    $this->parsePlaceOrderResponse($this->api->__soapCall('saveDistribReservation2', $options)); 
} catch (Exception $e) { 
    echo $e->getMessage(); 
    echo XmlUtil::formatXmlString($this->api->__getLastRequest()); 
    echo XmlUtil::formatXmlString($this->api->__getLastResponse()); 
} 
exit; 

esto falla, con el mensaje object hasn't 'stay' property que se debe a la misma cuestión, que la etiqueta debe contener <stays> 1 o más <stay> etiquetas. Si fijo $reservation->stays['stay'] = $stay; entonces se acepta, pero que de nuevo sólo me permite tener un único <stay> dentro <stays>

Además, la solicitud SOAP se parece a esto:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:hom="homingwns" xmlns:v1="..."> 
    <soapenv:Header/> 
    <soapenv:Body> 
     <hom:saveDistribReservation2> 
     <base_id>?</base_id> 
     <username>?</username> 
     <password>?</password> 
     <partnerCode>?</partnerCode> 
     <baseProductCode>?</baseProductCode> 
     <reservation> 
      <v1:reservation> 
       <v1:external_id>?</v1:external_id> 
       <v1:etab_id>?</v1:etab_id> 
       <v1:reservation_type>?</v1:reservation_type> 
       <!--Optional:--> 
       <v1:option_date>?</v1:option_date> 
       <!--Optional:--> 
       <v1:gender>?</v1:gender> 
       <!--Optional:--> 
       <v1:firstname>?</v1:firstname> 
       <v1:lastname>?</v1:lastname> 
       <!--Optional:--> 
       <v1:birthdate>?</v1:birthdate> 
       <!--Optional:--> 
       <v1:stays> 
        <v1:stay> 
        <v1:nb_rooms>?</v1:nb_rooms> 
        <v1:room_type_code>?</v1:room_type_code> 
        <v1:start_date>?</v1:start_date> 
        <v1:end_date>?</v1:end_date> 
        <!--Optional:--> 
        <v1:occupants> 
         <!--Optional:--> 
         <v1:occupant> 
          <!--Optional:--> 
          <v1:gender>?</v1:gender> 
          <!--Optional:--> 
          <v1:firstname>?</v1:firstname> 
          <v1:lastname>?</v1:lastname> 
          <!--Optional:--> 
          <v1:birthdate>?</v1:birthdate> 
          <v1:pos>?</v1:pos> 
         </v1:occupant> 
        </v1:occupants> 
        </v1:stay> 
       </v1:stays> 
      </v1:reservation> 
     </reservation> 
     </hom:saveDistribReservation2> 
    </soapenv:Body> 
</soapenv:Envelope> 
+0

¿Por qué no serializar el array 'estancias' y asignar el contenido al elemento XML . En el lado de recepción, puede deserializarlo fácilmente. – stillstanding

+0

No tengo control sobre el punto final de soap. Tiene que ser XML según el wsdl. Pero esta es una estructura XML bastante estándar, por lo que debe haber una forma de representarla. – Colin

+0

Vea también http://stackoverflow.com/questions/577795/passing-array-to-soap-function-in-php –

Respuesta

18

'stay' tiene que definirse solo una vez. Esta debería ser la respuesta correcta:

$xml = array('reservation' => array(
'stays' => array(
    'stay' => array(
        array(
          'start_date' => '2011-01-01', 
          'end_date' => 2011-01-15 
        ), 
        array(
          'start_date' => '2011-01-01', 
          'end_date' => 2011-01-15 
        ) 
      ) 
    ) 
)); 
+0

Gracias, pero esta pregunta tiene 2 años y medio, y no estoy en el trabajo, y mucho menos en el mismo proyecto, por lo que no puedo probar/verificar. Gracias por contribuir sin embargo. – Colin

+0

Señor, ¡usted es un genio! Esto es exactamente lo que estaba buscando ... funciona como un encanto. Muchas gracias! – incutonez

+1

Al haber respondido tres años después de la pregunta, parece apropiado que lo acepto durante tres años más: p - Parece que incutonez verificó la solución. – Colin

3

Suponiendo que cuando se haya instanciado $soapClient, se También lo hizo en el modo de WSDL, lo siguiente debería funcionar:

$stay1 = new stdClass(); 
$stay1->start_date = "2011-01-01"; 
$stay1->end_date = "2011-01-15"; 
$stay2 = new stdClass(); 
$stay2->start_date = "2011-01-01"; 
$stay2->end_date = "2011-01-15"; 
$stays = array(); 
$stays[0] = $stay1; 
$stays[1] = $stay2; 
$soapClient->saveReservation(
    array("reservation" => array("stays" => $stays)) 
); 
+0

Gracias. Lo intentaré, aunque la base de datos en el punto final está desactivada por el momento, así que no puedo probarla, pero lo haré lo antes posible. – Colin

+0

No veo cómo obtendrá las múltiples etiquetas , pero supongo que sabe algo que yo no. Lo intentaré una vez que pueda. – Colin

+1

Re: no ves cómo funcionará esto - créeme, nadie más lo hace. El cliente SOAP de PHP apesta. – benjy

0

Prueba esto:

$xml = array(
    'stays' => array(
    'stay' => array(
     array(/* start end */), 
     array(/* start end */), 
     array(/* start end */) 
    ) 
) 
); 
0

También tuve este problema y encontré la solución. Estancias tiene que ser una matriz con teclas ascendente empezando por 0.

$client = new SoapClient('http://myservice.com?wsdl'); 
$stays[] = array('startDate'=>'01-01-2013', 'endDate'=>'02-02-2013'); 
$stays[] = array('startDate'=>'02-02-2013', 'endDate'=>'03-03-2013'); 
$params = array(
    'reservation' => array('stays'=>$stays) 
); 
$client->saveReservation($params); 

encontré mi respuesta en esta página: https://bugs.php.net/bug.php?id=45284

Cuestiones relacionadas