2014-07-21 8 views
5

Sto cercando di aggiungere alcuni attributi a una richiesta di sapone. commento nominale superiore su PHP.net (http://php.net/manual/en/soapvar.soapvar.php) e here e here su SO tutti dicono la stessa cosa:php SoapVar non imposta gli attributi

$param = array(
    "_" => 'value', 
    'attrName' => 'attributeName' 
); 
$p = new SoapVar($param, SOAP_ENC_OBJECT); 

dovrebbe tornare

<param attrName="attributeName">value</param> 

che sarebbe fantastico, tranne quando ho eseguito quel blocco di codice, ottengo questo XML:

<param> 
    <_>value</_> 
    <attrName>attributeName</attrName> 
</param> 

che è chiaramente sbagliato. Sicuramente non sono l'unica persona al mondo ad avere questo problema? La documentazione su quel po 'di funzionalità è cambiata dal 2011?

risposta

0

Per il momento sto utilizzando l'oggetto DOMDocument per creare il nodo. Vorrei che ci fosse un modo più semplice, ma nell'interesse di rispondere a questa domanda e di fornire una soluzione, qui va:

$dom = new DOMDocument("1.0", "utf-8"); 
$dom->preserveWhiteSpace = false; 
$dom->formatOutput = true; 
$param = $dom->createElement('param'); 
$paramAttr = $dom->createAttribute('attrName'); 
$paramAttr->value = "attributeName"; 
$param->value = "value"; 
$param->appendChild($paramAttr); 
$dom->appendChild($param); 
$soap->param = new SoapVar($dom->saveXML($dom->documentElement), XSD_ANYXML); 

Quindi non è l'ideale. Un altro modo per farlo sarebbe quello di scrivere il codice XML da soli:

$soap->param = new SoapVar("<param attrName='attributeName'>value</param>", XSD_ANYXML); 

non mi piace in entrambi i casi, ma quando hai una scadenza, è andare con ciò che funziona.

0

So che questa è una vecchia domanda, ma volevo fornire una risposta per chiunque altro incappasse in questo post. Mi sono imbattuto nello stesso problema di mounty e sono stato in grado di aggirarlo utilizzando una soluzione che non richiede XSD_ANYXML. Non sono riuscito a ottenere il SoapVar con un approccio array funzionante, ma sono riuscito a farlo funzionare utilizzando gli stessi tasti delle proprietà di classe. Ad esempio, utilizzando il codice qui sotto:

class MyParam { 
    public $_; 
    public $attrName; 

    public function __construct($paramValue, $attrValue) 
    { 
    $this->_ = $paramValue; 
    $this->attrName = $attrValue; 
    } 
} 

$soap->param = new MyParam("value", "attributeName"); 

sono stato in grado di capire questo fuori dopo aver utilizzato la libreria wsdl2phpgenerator per generare classi PHP da un WSDL che contiene i tipi di dati che necessitano di attributi solo e ho visto questo modello in uso.

+0

come ha sottolineato Vladimir, questo funzionerà solo in modalità WSDL! – jfx

2

Sì, non sei l'unico ad avere questo problema - Ho visto un numero infinito di post in cui le persone affermano che l'array è passato a SoapVar con SOAP_ENC_OBJECT risolve il problema mentre altre persone rivendicano il contrario sugli stessi post. E la documentazione non è chiara sui motivi (a parte il mio post anno fa nella sezione commenti di php.net).

Di fronte allo stesso problema, ho letto le fonti dell'estensione PHP SOAP. Fondamentalmente la sintassi che avete usato è assolutamente corretto:

$param = array(
    "_" => 'value', 
    'attrName' => 'attributeName' 
); 
$p = new SoapVar($param, SOAP_ENC_OBJECT); 

Che la documentazione non dice: questa sintassi può produrre due risultati diversi (e in realtà anche di più: SOAP PHP può esprimere in otto modi diversi). E come puoi vedere il codice sopra è ambiguo: cosa nel codice sopra dice che 'attrName' è un attributo e non un elemento? Niente. Il codice qui sopra non ha una quantità sufficiente di informazioni per SoapClient per decidere cosa sia 'attrName' e quindi è impostato su "un elemento".

SoapClient può funzionare in due modalità: non WSDL e WSDL. Nella precedente modalità non si otterrebbe mai il risultato desiderato: SoapClient si basa sulle informazioni sul tipo per trasformare l'elemento dell'array in attributo. Poiché le informazioni sul tipo non sono presenti in modalità non WSDL, SoapClient rappresenta l'array fornito come set di elementi, esattamente ciò che hai ottenuto.In modalità WSDL sono presenti le informazioni sul tipo e quindi SoapClient conosce gli elementi e i nomi degli attributi e può associarli agli indici di array. Quindi DEVI avere il tuo SoapClient in modalità WSDL se vuoi i tuoi attributi.

sostanza al fine di ottenere ciò che si vuole è necessario disporre di file WSDL in modalità documento/literal con < xsd: attributo name = tipo "attrName" = "xsd: string" /> nella sezione appropriata di < xsd: schema > blocco.

Il motivo per cui alcune persone affermano il successo dell'uso di array per attributi e altre persone dicono "Non funziona" si trova solo nella loro configurazione: alcune persone hanno file WSDL da consumare, alcune persone cercano solo di fare un nuovo SoapClient (null , matrice (...)); (che naturalmente fallisce le loro aspettative)

+0

ottimo punto, solo per aggiungere questo funziona anche per gli oggetti, è sufficiente aggiungere la proprietà e sarà * automaticamente * mappato all'attributo in base al wsdl. funzionalità netta - in questo modo è possibile utilizzare solo strutture oggetto e farle mappare automaticamente su nodi/attributi. – jfx