Home > desarrollo, Spanish, técnico > Retornar arrays con NuSOAP

Retornar arrays con NuSOAP

Christian escribió un artículo hace unos días sobre la manera de usar NuSOAP para crear un servicio web. El artículo describe en detalles el procedimiento. No obstante, probar de retornar un arreglo es un trabajo bastante complejo en NuSOAP, o por lo menos esta mal documentado. Una excelente referencia (en Inglés) sobre el tema se puede encontrar en el blog de Lyingonthecovers, pero el artículo faltaba (he puesto un comentario ahí) una noción importante que es que NuSOAP debe tener un ‘return’ => ‘xsd:Array’ en su método register() para retornar el formato correcto.

En este artículo, revisaremos como retornar arreglos.

Retornar arreglos simples

Primero, imaginamos, como en el artículo en Inglés de Lyingonthecovers, que queremos hacer un servicio web que retorna, en el caso de Dokeos, detalles sobre un curso.

La función que se encargar de recojer la información se llamará getCourseDetails(), tomará solo un parámetro  tipo string en entrada (para parametros complejos, ver el ejemplo de Christian) y retornará un arreglo del tipo siguiente:

Array(

[‘code’] => ‘ABC’,

[‘title’] => ‘English alphabet’,

[‘url’] => ‘http://www.example.com/ABC’,

[‘teacher’] => ‘Yannick Warnier’,

[‘language’] => ‘english’

)

Hemos definido nuestras necesidades, ahora vamos más adelante y registramos el servicio mismo y sus tipos de datos:

$server = new soap_server();

$server->configureWSDL(‘WSCourse’, ‘urn:WSCourse’);

// definimos el tipo complejo (arreglo asociativo, =’struct’) de detalles de curso

$server->wsdl->addComplexType(
‘courseDetails’,
‘complexType’,
‘struct’,
‘all’,
”,
array(
‘name’=>’code’  , ‘type’=>’xsd:string’,
‘name’=>’title’  , ‘type’=>’xsd:string’,
‘name’=>’url’    , ‘type’=>’xsd:string’,
‘name’=>’teacher’, ‘type’=>’xsd:string’,
‘name’=>’language’,’type’=>’xsd:string’,
)
);

Por favor apunten que declaramos un tipo, pero no hay ninguna relación, al nivél de esta declaración, entre el tipo y un método. Este tipo podrá ser reutilizado para otros métodos también.

// Registramos el método y su parámetro de entrada
$server->register(‘getCourseDetails’,           // nombre método
array(‘username’ => ‘xsd:string’),            //  parametros entrantes al servicio
array(‘return’ => ‘tns:courseDetails’),     // valor(es) retornado(s)
‘urn:WSCourse’,                                            // namespace (espacio de nombre)
‘urn:WSCourse#getCourseDetails’,         // acción SOAP
‘rpc’,                                                                 // estílo
‘encoded’,                                                       // tipo de uso
‘This service returns a list of courses’    // documentación
);

En este caso, usamos directamente un ‘struct’ como valor de retorno. Usamos el marcador ‘tns:’ (probablemente Type NameSpace o algo así) para decir que es un tipo complejo definido por otro lado, y definimos que tipo exactamente queremos usar.

Esto es lo que debería ocurir y, para este caso (no verificado), tal vez funcionaría. Si no funciona, prueben remplazar tns:courseDetails por xsd:Array, simplemente (vemos más abajo casos probados).

En el caso un poco más complejo en que tenga que devolver un arreglo de estos courseDetails, como hago?

Arreglos de arreglos

Una estructura a dos niveles no se puede definir en solo una definición de ComplexType. En sí, se tiene que definir cada nivel como un ComplexType:

$server->wsdl->addComplexType(
‘courseDetails’,
‘complexType’,
‘struct’,
‘all’,
”,
array(
‘name’=>’code’  , ‘type’=>’xsd:string’,
‘name’=>’title’  , ‘type’=>’xsd:string’,
‘name’=>’url’    , ‘type’=>’xsd:string’,
‘name’=>’teacher’, ‘type’=>’xsd:string’,
‘name’=>’language’,’type’=>’xsd:string’,
)
);

Nada cambia para esta primera parte. Ahora definimos el arreglo que va a contener estos structs:

$server->wsdl->addComplexType(
‘courseList’,
‘complexType’,
‘array’,
”,
‘SOAP-ENC:Array’,
array(),
array(
array(‘ref’=>’SOAP:ENC:arrayType’,
‘wsdl:arrayType’=>’tns:courseDetails[]’)
),
‘tns:courseDetails’
);

Bueno, hay mucho que todavía no hemos detallado ahí, pero no es directamente el objetivo de este artículo. Una cosa es importante: esto es la forma de declarar un arreglo (no asociativo, es decir con indices numéricos unicamente) del ComplexType courseDetails.

Una vez que tenemos esto listo, la lógica nos haría pensar que simplemente debería registrar este tipo complejo en mi servicio web:

// Registramos el método y su parámetro de entrada
$server->register(‘getCourseDetails’,           // nombre método
array(‘username’ => ‘xsd:string’),            //  parametros entrantes al servicio
array(‘return’ => ‘tns:courseList’),          // valor(es) retornado(s)
‘urn:WSCourse’,                                            // namespace (espacio de nombre)
‘urn:WSCourse#getCourseDetails’,         // acción SOAP
‘rpc’,                                                                 // estílo
‘encoded’,                                                       // tipo de uso
‘This service returns a list of courses’    // documentación
);

… y ahí es donde perdimos horas buscando. En realidad, parece que hay algo malo ahí, en la forma en que NuSOAP (a lo menos versión de Agosto de 2008) retorna este valor, que es incorrecto. Resulta que el cliente SOAP de PHP5 no entiende el valor retornado. Ni para este arreglo de structs, ni para el struct mismo.

Abandonar la definición de tipos complejos

La solución es de abandonar la idea de definir el tipo de valor retornado, y simplemente usar xsd:Array como valor de retorno:

// Registramos el método y su parámetro de entrada
$server->register(‘getCourseDetails’,           // nombre método
array(‘username’ => ‘xsd:string’),            //  parametros entrantes al servicio
array(‘return’ => ‘xsd:Array’),          // valor(es) retornado(s)
‘urn:WSCourse’,                                            // namespace (espacio de nombre)
‘urn:WSCourse#getCourseDetails’,         // acción SOAP
‘rpc’,                                                                 // estílo
‘encoded’,                                                       // tipo de uso
‘This service returns a list of courses’    // documentación
);

No hay lógica ahí, es cierto, pero a lo menos espero que les ayudarán. Me estoy comunicando con los desarrolladores de NuSOAP para averiguar el tema.

Advertisements
  1. Alejandra
    April 14, 2009 at 7:58 am

    Muchas gracias por la información. He estado mucho tiempo volteando con esto pero por lo visto es mejor dejar a un lado la idea de arreglo de arreglos…. :(

  2. Kaname
    April 22, 2009 at 9:48 am

    ufff,, estamos en la misma linea, se vuelve un infierno tener que devolver arreglo de arreglos

  3. May 23, 2009 at 10:34 am

    Exelente. Era justo lo que necesitaba.

    Exito.

  4. GLN
    May 29, 2009 at 8:05 am

    Estoy en un proyecto que tiene este problema, solo que el cliente consumidor del WS es en Java. Al generar las clases stub para conectarse al servicio me devuelve un error diciendo que no existe el tipo xsd:Array. ¿hay algo que puedo estar omitiendo?

    Muchas gracias.

  5. July 24, 2009 at 10:26 am

    Estimados, buenos días, a ver si alguien me puede ayudar… estoy trabajando con complextype un arreglo de arreglo. Y uno de los campos es un string donde debo almacenar un número, el problema que tengo es que al armar el array NuSoap o PHP me hacen una conversión implícita y me termina devolviendo un tipe integer. Qué pasa, el numero que debo almacenar desborda el rango de enteros, entonces siempre me almacena 2147483647, bueno, si alguien pudiera ayudarme le estaría agradecido.

    Saludos.
    El foro está de 10

    Fede

  6. José Luis
    October 17, 2009 at 1:00 pm

    Bueno el articulo, pero hay un error en los codigos.
    En la parte de complextype cada variable debe ir declarado como arreglo.

    Slds,
    José Luis

  7. October 4, 2012 at 2:50 am

    pleno el articulo ami me valio ‘xsd:Array’

  8. November 23, 2012 at 12:56 pm

    Gracias por la información, he tenido algunos dolores de cabeza por los tipos complejos de nusoap cuando se retornan en un Array, gracias por el dato del xsd:Array, me sirvió de mucho.

  9. November 27, 2012 at 11:04 pm

    Excelente! a mi me funciono sin especificando “tns:courseList” en vez de ‘xsd:Array’ como tu señalabas , porque mi cliente .NET me estaba exigiendo un tipo de datos declarado, en un cliente php funciona de las 2 maneras.

    Gracias hermano!! =)

  10. Jopsuey
    August 8, 2013 at 7:18 pm

    EXCELENTE, LLEVABA 2 DIAS INTENTANDO DEVOLVER UN ARRAY

    • man
      September 10, 2014 at 6:22 pm

      Como muestro un array en SOAP llamado en PHP?
      El array se encuentra $objRespuesta->ObtenerPadronResult->adeudo;
      como lo visualizo en php?

      • Yannick Warnier
        September 10, 2014 at 6:44 pm

        print_r($objRespuesta->ObtenerPadronResult->adeudo); ?

  11. Andres Benavides
    May 28, 2015 at 7:11 pm

    Amigo muchas gracias me salvo la vida me estaba volviendo loco este tema enserio muchísimas gracias

  12. Edd
    December 6, 2015 at 2:19 am

    Muchisimas gracias me salvaste con el array(‘return’ => ‘xsd:Array’), era exactamente lo que estaba buscando.

  13. Mike Ortiz
    November 1, 2016 at 6:04 pm

    Muuuuchas gracias llevaba muucho rato intentando retornar ese tipo de estructura y siempre me salia el error “Array to string conversion”, muchas gracias!

  14. edwin
    January 4, 2017 at 11:46 am

    Hay alguna limitante en cuanto a la cantidad de registros que se pueden enviar en un arreglo de arreglos? excelente articulo muchas gracias

    • Yannick Warnier
      June 28, 2017 at 6:35 pm

      No que sepamos, pero a partir de un cierto tamaño es importante asegurarte que no pases de ningún otro límite (memoria, tamaño de pedidos HTTP, etc).

  15. CARLOS
    May 15, 2017 at 5:08 pm

    En serio muchas gracias!!! Llevaba días intentando solucionar este problema

  1. April 22, 2013 at 1:00 am

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: