Exemple de wsdl pentru serviciul web PHP. Toți pașii necesari pentru a vă conecta la un serviciu web (exemplu WSDL și exemplu SOAP). Aceasta este ceea ce trebuie să faci

Sunt obișnuit să scriu cod PHP, dar nu folosesc des codificare orientată pe obiecte. Acum trebuie să interacționez cu SOAP (ca client) și nu pot obține corect sintaxa. Am un fișier WSDL care îmi permite să configurez corect o nouă conexiune folosind clasa SoapClient. Cu toate acestea, nu reușesc să efectuez apelul corect și să recuperez datele. Trebuie să trimit următoarele date (simplificate):

  • ID de contact
  • Nume de contact
  • Descriere generală
  • Sumă

Există două funcții în documentul WSDL, dar am nevoie doar de una ("FirstFunction" de mai jos). Iată scriptul pe care îl rulez pentru a obține informații despre funcțiile și tipurile disponibile:

$client = new SoapClient("http://example.com/webservices?wsdl"); var_dump($client->__getFunctions()); var_dump($client->__getTypes());

Și iată rezultatul pe care îl generează:

Array( => "FirstFunction Function1(FirstFunction $parametri)", => "SecondFunction Function2(SecondFunction $parametri)",); array( => struct Contact ( id id; nume nume; ) => șir „descriere șir” => șir „cantitate int” )

Să presupunem că vreau să apelez FirstFunction cu date:

  • ID de contact: 100
  • Persoana de contact: Ioan
  • Descriere generală: Baril de petrol
  • Suma: 500

Care ar fi sintaxa corectă? Am încercat tot felul de variante, dar se pare că structura săpunului este destul de flexibilă, așa că există doar atâtea moduri de a face acest lucru. Nu am putut să-mi dau seama din manual...

UPDATE 1: Exemplu de probă de la MMK:

$client = new SoapClient("http://example.com/webservices?wsdl"); $params = array("id" => 100, "name" => "Ioan", "descriere" => "Baril de petrol", "cantitate" => 500,); $răspuns = $client->__soapCall(„Funcția1”, matrice($params));

Dar primesc acest răspuns: Obiectul nu are nicio proprietate „Contact”. După cum puteți vedea în rezultatul getTypes() , există o structură numită Contact , așa că cred că trebuie să clarific cumva că parametrii mei includ datele de contact, dar întrebarea este: cum?

UPDATE 2: Am încercat și aceste structuri, aceeași eroare.

$params = array(array("id" => 100, "nume" => "Ioan",), "Baril de petrol", 500,);

De asemenea, ca:

$params = array("Contact" => array("id" => 100, "nume" => "Ioan",), "descriere" => "Baril de petrol", "cantitate" => 500,);

Eroare în ambele cazuri: obiectul nu are proprietatea „Contact”.

8 răspunsuri

Aceasta este ceea ce trebuie să faci.

Doar ca să știu, am încercat să refac situația ta...

  • În acest exemplu, am creat un serviciu web .NET folosind o WebMethod numită Function1 și aceștia sunt parametrii:

Funcția1 (pin pin, descriere șir, număr int)

    În care Contact are doar o clasă bean care are getters și setters pentru id și nume, ca în cazul dvs.

    Puteți încărca acest serviciu web .NET cu:

Cod.

Acesta este ceea ce trebuie să faci în lateral PHP:

(Testat și funcțional)

id = $id;

$acest->nume = $nume;

  • ) ) /* Inițializați serviciul web cu WSDL dvs. */ $client = new SoapClient("http://localhost:10139/Service1.asmx?wsdl"); /* Completați obiectul dvs. de contact */ $contact = new Contact(100, "John"); /* Setează-ți parametrii pentru cerere */ $params = array("Contact" => $contact, "description" => "Baril de petrol", "cantitate" => 500,); /* Invocă metoda webservice cu parametrii tăi, în acest caz: Function1 */ $response = $client->__soapCall("Function1", array($params)); /* Tipăriți răspunsul serviciului web */ var_dump($response); ?>

De unde știu că funcționează?

  • Dacă faci print_r($params); veți vedea această ieșire deoarece serviciul dvs. web așteaptă:

Array ([Contact] => Obiect de contact ( => 100 => Ioan) [descriere] => Tambur de ulei [cantitate] => 500)

  • Când am depanat exemplul de serviciu web .NET, am primit următoarele:

(După cum puteți vedea, obiectul Contact nu este nul, la fel ca și alți parametri, aceasta înseamnă că solicitarea dvs. a fost finalizată cu succes din partea PHP).

Răspunsul de la serviciul web .NET a fost cel așteptat și afișat pe partea PHP:

obiect (stdClass) public "Function1Result" => string "Detaliile cererii dvs.! id: 100, nume: John, descriere: Baril de petrol, cantitate: 500" (lungime = 98)

Sper ca asta sa ajute :-)

De asemenea, puteți utiliza serviciile SOAP:

„Spania”, „CityName” => „Alicante”); $răspuns = $soapclient->getWeather($params); var_dump($răspuns); // Obțineți orașele după țară $param = array("CountryName" => "Spania"); $răspuns = $soapclient->getCitiesByCountry($param); var_dump($răspuns);

Acesta este un exemplu cu un serviciu real și funcționează.

Sper că acest lucru ajută.

Mai întâi inițializați serviciile web:

$client = new SoapClient("http://example.com/webservices?wsdl");

Rețineți că numele metodei este disponibil în WSDL ca nume de operație, de exemplu:

Nu știu de ce serviciul meu web are aceeași structură ca a ta, dar nu are nevoie de o clasă pentru parametru, ci doar de o matrice.

De exemplu:- WSDL-ul meu:

5390a7006cee11e0ae3e0800200c9a66 831f8c1ad25e1dc89cf2d8f23d2af...fa85155f5c67627 VITS-STALENS Zoethout tine 0.100 10K24 2012-12-31 Gladys Roldan de Moras

Calle General Oraá 26 (4º izda) 28006 Madrid ES
[email protected] es

Var_dump($client->getFunctions()); var_dump($client->getTypes());

Iată rezultatul:

Matrice 0 => șir "OrderConfirmation createOrder(OrderRequest $createOrder)" (lungime=56) matrice 0 => șir "struct OrderRequest ( Identificare de identificare; Livrare livrare; Colet; Destinatar destinatar; șir de referință; )" (lungime=130) 1 => șir "struct Identification (șir expeditor; șir hash; șir de origine; )" (lungime=75) 2 => șir "struct Delivery ( Nod from; Node to; )" (lungime=41) 3 => șir " struct Node ( țara șirului; nodul șirului; )" (lungime=46) 4 => șir "struct Parcel ( descriere șir; greutate zecimală; număr ordine șir; data ordineData; )" (lungime=93) 5 => șir "struct Receiver ( string firstName; string prenume; Adresa adresa; string email; string language; )" (lungime=106) 6 => string "struct Adresa ( string line1; string line2; string postalCode; string city; string country; )" (lungime =99) 7 => șir „struct OrderConfirmation (string trackingNumber; șir de referință; )” (lungime=71) 8 => șir „struct OrderServiceException ( șir de cod;

OrderServiceException faultInfo;

mesaj șir; )" (lungime=97) [email protected]", "limba" => "es")); $rezultat = $client->createOrder($params); var_dump($rezultat);

dar a reusit!

Acesta este un exemplu bun pentru funcția SOAP „__call”. Cu toate acestea, este depășit.

Envio Internacional: "; $vem = $client->__call("CustoEMSInternacional",array($int_zona, $int_peso)); print $vem; print "

"; ?>

Fundal:

Construiesc un site de servicii web care va oferi multe tipuri de servicii simple pe lângă SOAP și, eventual, alte protocoale. Scopul este de a ușura lucrurile, cum ar fi conversiile, analiza RSS, verificările spamului și multe alte tipuri de muncă. Site-ul va fi destinat în principal dezvoltatorilor începători.

Problema mea:

Nu am dezvoltat niciodată în C# sau .NET. Am spart niște VB6 acum câțiva ani, dar asta este. Acum am nevoie de mai multe exemple de efectuare a apelurilor RPC prin SOAP în C#. Am încercat să caut pe web și Stack Overflow pentru a găsi acest lucru, dar nu am găsit multe resurse și nu am idee cum să clasific resursele (care sunt vechi?, care sunt incorecte? etc.).

Am creat un exemplu de serviciu simplu numit acesta în PHP:

getCurrentYear(); //Această metodă returnează un număr întreg, numit „an” ?>

Acum vreau să numesc această metodă cât mai simplu posibil în C#. Toate linkurile și exemplele sunt binevenite. De unde ar trebui să încep? Ce clase/module/ce pot folosi?

Soluția nu trebuie să includă deloc SOAP dacă există un cadru de comunicare mai bun (back-end-ul este menit să fie extensibil), dar rețineți că partea de server este implementată în PHP pe Unix, astfel încât soluțiile proprietare ale Microsoft sunt în afara întrebare pe partea serverului.

Rețineți că am nevoie de acest lucru pentru a putea scrie documentația pe care J. Random Web Developer o poate urma (chiar dacă se află pe o gazdă web partajată). Deci, cred că cea mai bună abordare ar trebui să fie să o faceți numai în cod, dar chiar și alte moduri de a face acest lucru sunt binevenite.

6 răspunsuri

După cum am înțeles, doriți să vă apelați serviciul web dintr-o aplicație client C#. Aveți deja un serviciu și un fișier WSDL publicat (corectați-mă dacă greșesc). Acum, cel mai simplu mod este să creați clase proxy în aplicația dvs. C# (acest proces se numește adăugarea unei legături de serviciu). Există două modalități principale de a face acest lucru: .NET oferă servicii ASP.NET, care este vechea modalitate de SOA și WCF, așa cum a sugerat John, care este cel mai recent cadru de la MS și oferă multe protocoale, inclusiv aplicații open source și MS.

Acum destulă teorie și hai să o facem pas cu pas

Service1Client service = nou Service1Client();

int year = service.getCurrentYear();

Sper că vă va ajuta, dacă întâmpinați vreo problemă, vă rugăm să ne anunțați.

Am făcut destul de mult din ceea ce vorbești, iar compatibilitatea SOAP între platforme are o regulă de bază: CONTRACT FIRST. Nu deduceți WSDL din cod și apoi încercați să creați un client pe o altă platformă. Orice lucru mai mare decât funcțiile de tip „Hello World” probabil nu va reuși să genereze cod, nu va putea vorbi în timpul rulării sau (preferatul meu) nu va putea trimite sau primi toate datele corect fără a genera o eroare.

Cu toate acestea, WSDL este lucruri complexe, urâte și evit să-l scriu de la zero ori de câte ori este posibil. Mai jos sunt câteva recomandări pentru comunicarea de încredere a serviciului (folosind link-uri web, WCF, Axis2/Java, WS02, Ruby, Python etc.):

Dacă îl puteți face să funcționeze în browser, atunci ceva simplu este cum funcționează

Var webRequest = WebRequest.Create(@"http://webservi.se/year/getCurrentYear"); folosind (var răspuns = webRequest.GetResponse()) ( folosind (var rd = new StreamReader(response.GetResponseStream())) ( var soapResult = rd.ReadToEnd(); ) )

Uită-te și la NuSOAP. Dacă sunteți acum, acesta este un set de instrumente care vă permite să vă conectați de la PHP la un serviciu WCF.

În acest exemplu vom vedea un exemplu de client SOAP care comunică cu un server. SOAP este una dintre multele definiții de protocol de servicii web. Un serviciu web este o tehnologie care utilizează un protocol (SOAP în acest exemplu) pentru schimbul de date între aplicații prin intermediul rețelei.

Dacă dezvoltăm un client pentru consumarea unui serviciu web, trebuie să ne uităm la protocolul pe care îl folosește serviciul. Acest exemplu este pentru a analiza resursele oferite de PHP pentru dezvoltarea unui client pentru un serviciu web care implementează protocolul SOAP.

Pentru acest exemplu, vom folosi:

  • Ubuntu (14.04) ca sistem de operare.
  • Server HTTP Apache (2.4.7).
  • PHP (5.5.9).

1. Pregătirea mediului

1.1. Instalare

Mai jos, sunt afișate comenzile pentru instalarea Apache și PHP:

Sudo apt-get update sudo apt-get install apache2 php5 libapache2-mod-php5 sudo service apache2 restart

1.2. Configurare PHP

Chiar dacă nu este necesar, se recomandă dezactivarea memoriei cache SOAP WSDL pentru mediile de dezvoltare. În fișierul /etc/php5/apache2/php.ini, setați directiva soap.wsdl_cache_enabled la 0:

php.ini

Soap.wsdl_cache_enabled=0

Nu uitați să reporniți Apache după orice modificare.

Nota: dacă doriți să utilizați Windows, instalarea XAMPP este cea mai rapidă și mai ușoară modalitate de a instala un server web complet care îndeplinește cerințele prealabile.

2. Ce este SAPUNUL?

SOAP (Simple Object Access Protocol) este un protocol standard care definește modul în care două obiecte diferite în procese diferite pot comunica între ele, prin schimbul de date în format XML. Este unul dintre cele mai largi protocoale utilizate în serviciile web.

Cu alte cuvinte, acest protocol permite apelarea metodei obiectelor care sunt definite în mașini la distanță.

3. Exemplu PHP de clienți SOAP

Serverul care oferă serviciile SOAP le poate defini în două moduri diferite:

  • Cu WSDL (Web Services Definition Language)
  • Fără WSDL

Din punctul de vedere al clientului, există foarte puține diferențe, dar să vedem cum să procedăm pentru fiecare.

Vom lua în considerare următorul scenariu, destul de tipic: un serviciu web care inserează și citește dintr-o bază de date (simulat cu un fișier text simplu), pentru care vom dezvolta un client.

Este responsabilitatea serverului care oferă serviciul să anunțe protocolul utilizat, la fel ca și definițiile metodelor disponibile, pentru a permite clienților să știe cum să se ocupe de serviciu.

Chiar dacă acest tutorial este despre clientul în sine, vom vedea și partea serverului, pentru a testa dacă clientul funcționează efectiv.

3.1. Structura directorului de lucru

Pentru acest exemplu, vom folosi următoarea structură:

Php_soapclient_example/ ├── simple_soap_client_class.php ├── simple_soap_server_class.php ├── handle_soap_request.php ├── no_wsdl ─ ─ ─ server ─ ─ ─ php ├── server_endpoint.php └── simple_service_definition.wsdl

Unde directorul rădăcină, php_soapclient_example , va fi în directorul rădăcină al serverului web, care este implicit /var/www/html/.

Explicat pe scurt fiecare fișier:

  • simple_soap_client_class.php este clasa definită pentru metodele client SOAP.
  • simple_soap_server_class.php este clasa definită pentru metodele serverului SOAP.
  • handle_soap_request.php este pentru instanțierea și utilizarea clasei SimpleSoapClient definită în simple_soap_client_class.php .
  • În directoarele wsdl și no_wsdl , este oferit serviciul definit în simple_soap_server_class.php, în modul în care se acordă fiecăruia dintre moduri. Nu vom intra în detalii pentru acestea, deoarece nu este scopul acestui exemplu. Singurul lucru pe care trebuie să-l știm este că într-unul dintre directoare există un serviciu oferit în modul WSDL, iar în celălalt, fără modul WSDL; sunt două servicii web independente care folosesc codul definit în simple_soap_server_class.php .

Nota: modul WSDL are nevoie de un fișier .wsdl, unde este definit serviciul web. Nu îl vom vedea în acest exemplu, deoarece scopul nu este să vedem cum să construim un fișier de definiție WSDL, dar este disponibil și pentru descărcare în ultima secțiune a exemplului.

3.2. Serverul

După cum sa spus, serverul nostru va citi și scrie datele într-un fișier text. Să vedem:

simple_soap_server_class.php

", FILE_APPEND); if ($writtenBytes) ( $response = "$writtenBytes au fost inserati octeți."; ) else ( $response = "Eroare de date introduse."; ) return $response; ) /** * Citește datele. Invocat de la distanță de la clientul SOAP * * @return Datele fișierului */ public function readData() ( $contents = file_get_contents(self::FILENAME); return $contents; ) )

Atât de simplu, despre citirea și scrierea într-un fișier text.

Observați funcțiile pe care le implementează acest server, în rândurile 16 și 33. Aceste funcții vor fi cele invocate de client.

3.3. Clientul

După cum am spus mai sus, în funcție de mod (WSDL sau nu WSDL), clientul trebuie să gestioneze conexiunea într-un mod diferit, dar, odată stabilită, procedura este aceeași. Deci, să codificăm o clasă care funcționează pentru ambele moduri, gestionând instanțiarea clasei SoapClient în conformitate cu modul:

simple_soap_client_class.php

initializeClient($soapMode, $serverLocation);

) /** * Instanțiază SoapClient, în funcție de modul specificat.

  • * * Pentru WSDL, trebuie doar să fie instanțiat cu locația serviciului, care de fapt trebuie să fie locația * .wsdl. * * Pentru non-WSDL, primul parametru al constructorului trebuie să fie nul; iar al doilea, o matrice care specifică * atât locația, cât și URI (care poate fi același, parametrul important este locația)..
  • */ funcția protejată initializeClient($soapMode, $serverLocation) ( switch ($soapMode) (case self::MODE_WSDL: $this->client = new SoapClient($serverLocation); break; case self::MODE_NO_WSDL: $opțiuni = matrice ("location" => $serverLocation, "uri" => $serverLocation $this->client = new SoapClient(NULL, $options break default: throw new Exception("Eroare: mod SOAP furnizat." )); ; break ) ) /** * Inserează datele de la distanță în serviciul SOAP. * * @param $data Date de inserat de la distanță..

* @return Răspuns de la serviciul de la distanță.

Dacă nu credeți, să vedem un script pentru a utiliza acest client.

3.4. Utilizarea clientului

Următorul script ne permite să folosim clientul pentru a comunica cu serviciul, prin parametrii GET. Aceștia sunt parametrii disponibili:

  • „mode” , pentru a specifica modul (WSDL sau non WSDL).
  • „acțiune” , pentru a specifica acțiunea de efectuat. Valorile disponibile sunt „inserați” și „citiți”.
  • „valoare” , ​​pentru a specifica valoarea de inserat, necesar doar atunci când acțiunea este „inserare”.

handle_soap_request.php

getMessage());
) returnează $soapClient; ) // Fluxul începe aici. checkGETParametersOrDie(["mod", "acțiune"]); $mode = $_GET["modul"]; $acțiune = $_GET[„acțiune”]; $soapClient = instantiateSoapClient($mod); switch($action) (case ACTION_INSERT: checkGETParametersOrDie(); $value = $_GET; încercați ( $response = $soapClient->insertData($value); echo "Răspuns de la serviciul SOAP: $răspuns)
"; ) catch (Excepție $excepție) ( die("Eroare la inserarea în serviciul SOAP: " . $exception->getMessage()); ) break; caz ACTION_READ: încercați ( $date = $soapClient->readData(); echo „Date primite de la serviciul SOAP:

"; echo $date; ) catch (Excepție $excepție) ( die("Eroare la citirea de la serviciul SOAP: " . $excepție->getMessage()); ) break; implicit: die ("Acțiunea" specificată nevalidă.") ;" , and the following will be printed:!}

Dacă introducem în browser http://127.0.0.1/php_soapclient_example/handle_soap_request.php?mode=no_wsdl&action=insert&value=testing_no_wsdl , serviciul va crea un fișier no_wsdl/data.txt (dacă nu există deja), scriind valoarea furnizată „testing_no_wsdl

Răspuns de la serviciul SOAP: au fost introduși 19 octeți.
(Cei 4 octeți suplimentari corespund cu suplimentar

caractere introduse în fișier).

Serviciul oferă o metodă de citire a tuturor datelor, așa că, dacă introducem în browser http://127.0.0.1/php_soapclient_example/handle_soap_request.php?mode=no_wsdl&action=read , se vor tipări următoarele:
Date primite de la serviciul SOAP:

testing_no_wsdl

Îl putem verifica și pentru modul WSDL, setând mode=wsdl în parametri.

După cum sa spus în secțiunea 3, atunci când dezvoltăm un client de servicii web (indiferent dacă SOAP, REST, etc.), furnizorul de servicii trebuie să furnizeze și documentație despre metodele disponibile; trebuie să știm definiția acestora: ce parametri se așteaptă, dacă returnează ceva. Din acest motiv, cel mai obișnuit mod de a dezvolta un serviciu web SOAP este utilizarea fișierelor WSDL, pentru a furniza documentație cu privire la metodele disponibile. În orice caz, SoapClient are o metodă pentru a obține metodele disponibile, în scopuri de depanare, numită __getFunctions() . Deci, am putea vedea metodele oferite de serviciu cu următoarele:

Var_dump($soapClient->__getFunctions())

Presupunând că $soapClient a fost instanțat corect.

De asemenea, rețineți că, dacă serviciul nu oferă o conexiune criptată, comunicarea dintre client și server se va face în text simplu. Deci, dacă trebuie să dezvoltăm un client care trebuie să se ocupe de informații sensibile, ar trebui să ne asigurăm că comunicarea cu serverul poate fi considerată sigură.

5. Rezumat

Am văzut cum să dezvoltăm un client pentru un serviciu web SOAP folosind clasa PHP SoapClient. Serverul poate oferi serviciul folosind WSDL sau nu, ceva de luat în considerare atunci când instanțiem clasa SoapClient. Apoi, pentru a folosi metodele oferite de serviciu, trebuie doar să apelăm acele metode în instanța SoapClient, așa cum erau ale noastre.

SOAP (Simple Object Access Protocol) este un protocol bazat pe XML conceput pentru a face schimb de informații structurate între aplicații distribuite prin protocoalele web existente, cum ar fi HTTP. Specificația SOAP definește formatul utilizat de mesajele XML, modul în care acestea trebuie procesate, un set de reguli de codificare pentru standard, tipuri de date și convenții pentru apelurile de procedură de la distanță și răspunsurile la apeluri.

Serviciile web sunt o tehnologie la modă și modernă. Lista tehnologiilor legate de serviciile web crește aproape zilnic, dar SOAP este probabil cea mai importantă dintre ele. Acesta devine rapid protocolul standard pentru accesarea serviciilor web. Utilizează mesaje XML pentru a face schimb de informații între punctele finale, oferind în același timp unele dintre beneficiile protocoalelor binare.

Extensia SOAP pentru PHP 5 este prima încercare de a organiza suportul SOAP în PHP în C. Are mai multe avantaje față de implementările SOAP existente scrise în PHP, dintre care cel mai important este viteza. În prezent, extensia este considerată experimentală, dar treptat va deveni din ce în ce mai fiabilă și mai stabilă.

Extensia SOAP implementează subseturi mari ale specificațiilor SOAP 1.1, SOAP 1.2 și WSDL 1.1. Scopul principal este de a profita la maximum de capabilitățile RPC ale SOAP. WSDL este folosit ori de câte ori este posibil pentru a simplifica implementarea serviciilor web.

Primul client SOAP

Pentru a demonstra crearea unui client SOAP simplu, folosim serviciul demonstrativ „Delayed Stock Quote” de pe site-ul web XMethods. Înainte de a începe să scriem cod PHP, trebuie să colectăm următoarele informații despre acest serviciu special:

  • Numele metodei
  • URL unde se află acest serviciu
  • Valoarea antetului metodei SOAPAction
  • Spațiul de nume al metodei
  • Nume și tipuri de parametrii de intrare și de ieșire ale metodei

Din fericire, toate aceste informații sunt disponibile pe site-ul XMethods la http://www.xmethods.com/ din profilul RPC al serviciului:

Numele metodei getQuote
Adresa URL a serviciului http://66.28.98.121:9090/soap
SAAPUNActiune urn:xmethods-delayed-quotes#getQuote
Spațiul de nume al metodei urn:xmethods-delayed-quotes
Parametrii de intrare Simbol (șir)
Parametrii de ieșire Rezultat (float)

Exemplul 1 (client1.php)

$client = SoapClient nou (NULL,
matrice(
„locație” => „http://66.28.98.121:9090/soap”,
"uri" =>
"style" => SOAP_RPC ,
„utilizați” => SOAP_ENCODED
));

Print($client -> __call (
/* Numele metodei SOAP */
"getQuote"
/* Parametri */
matrice(
SoapParam nou(
/* Valoarea parametrului */
"ibm"
/* Numele parametrului */
"simbol"
)),
/* Opțiuni */
matrice(
/* Spațiul de nume al metodei SOAP */
"uri" => "urn:xmethods-delayed-quotes" ,
/* Antet HTTP SOAPAction pentru metoda SOAP */
"sapaction" => „urn:xmethods-delayed-quotes#getQuote”
)). „\n” );
?>

După cum puteți vedea, rezolvarea acestei probleme simple a necesitat destul de multă muncă.

Din fericire, serviciile web se pot descrie clienților folosind WSDL, ceea ce este în general destul de convenabil. WSDL pentru serviciul „Cotație întârziată” este prezentat pe pagina sa de informații de pe site-ul xmethods.com - http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl.

Iată o versiune a aceluiași client, rescrisă pentru a funcționa folosind acest document WSDL. Aici nu mai trebuie să specificăm URI-ul serverului, spațiul de nume, antetul SOAPAction, metoda de codificare și tipurile de parametri. Toate aceste informații sunt preluate din fișierul WSDL.

Exemplul 2 (client2.php)

$client = nou
SoapClient(
„http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl”
);

Print($client -> getQuote("ibm" ));
?>

E puțin mai ușor așa, nu?

Ce probleme apar la utilizarea WSDL?

Singurul argument împotriva utilizării acestuia este că clientul trebuie să citească WSDL de pe server înainte de a putea fi apelată orice procedură, iar pe web acest lucru poate dura destul de mult. Pentru a accelera munca, extensia SOAP oferă următorii parametri de configurare: soap.wsdl_cache_enabled, soap.wsdl_cache_dir și soap.wsdl_cache_ttl. Ele pot fi setate în fișierul php.ini sau folosind ini_set() (vezi Exemplul 4). În mod implicit, memorarea în cache WSDL este activată, iar fișierele WSDL sunt stocate în cache timp de 1 zi.

Aici este secțiunea SOAP a fișierului php.ini cu valorile implicite. Le puteți copia în php.ini.

[săpun]
; Săpun. wsdl_cache_enabled = „1”

activează sau dezactivează stocarea în cache WSDL
; Săpun. wsdl_cache_dir = "/tmp"- specifică numele directorului în care SOAP

extensia va stoca fișiere stocate în cache
Săpun. wsdl_cache_ttl = "86400" ; (durata de viață) stabilește ora (în secunde)

ce fișiere din cache pot fi utilizate

Primul server SOAP

Să încercăm să scriem propriul nostru serviciu web SOAP care va face același lucru ca serviciul „Cotație întârziată” cu XMethods.

Primul lucru pe care trebuie să-l facem este să creăm un document WSDL care să descrie serviciul nostru într-un format pe care clienții îl pot înțelege. Pentru a face acest lucru, va trebui să modificați ușor documentul original preluat de pe site-ul web Xmethods, așa că vom începe prin a-l privi mai detaliat.

Secțiunea de mesaje definește două mesaje. Primul este getQuoteRequest, care transmite mesajul getQuote și acceptă un parametru de o linie numit simbol. Al doilea mesaj este getQuoteResponse, un răspuns la o solicitare getQuote care transmite o singură valoare flotantă numită Result.

Secțiunea de legare definește modul în care mesajul ar trebui să fie codificat și transmis. În acest caz, se precizează că vom trimite o solicitare RPC prin HTTP folosind codificare SOAP. De asemenea, definește spațiul de nume și valoarea antetului SOAPAction pentru metoda getQuote.

În cele din urmă, secțiunea de servicii definește adresa URL la care se află serviciul.

Exemplul 3 (stockquote.wsdl)


targetNamespace="http://example.org/StockQuote"
xmlns:tns=" http://example.org/StockQuote "
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns="http://schemas.xmlsoap.org/wsdl/">












transport="http://schemas.xmlsoap.org/soap/http"/>



encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>


encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>








Notă: Memorarea în cache WSDL este activată în mod implicit. În timpul dezvoltării și depanării WSDL-ului, este mai bine să dezactivați stocarea în cache.

Acum este momentul să începem crearea serverului nostru.

În primul rând, vom dezvolta o funcție getQuote() care va gestiona cererile primite de pe web. În continuare, vom crea un obiect al clasei SoapServer și vom atașa funcția noastră utilizând metoda SoapServer::addFunction(). După cum veți vedea mai târziu, constructorul SoapServer() are un singur parametru - calea către documentul WSDL care descrie serviciul.

Exemplul 4 (server1.php)

$ghilimele = matrice(
"ibm" => 98.42
);


global $ghilimele ;
returnează $ghilimele [ $simbol ];
}

Ini_set ( "soap.wsdl_cache_enabled" , "0" ); // dezactivează memoria cache WSDL
$server = new SoapServer("stockquote1.wsdl");
$server -> addFunction("getQuote");
$server -> handle();
?>

SoapServer poate funcționa fără WSDL, la fel ca un client, dar nu există avantaje în utilizarea acestei opțiuni care să merite să fie folosită. Dacă tot doriți să lucrați în acest fel, trebuie să vă asigurați că valorile returnate sunt obiecte ale claselor SoapParam și SoapVar (ca în primul exemplu.

Iată un client pentru a accesa serverul nostru SOAP. În comparație cu exemplul anterior, a fost adăugat doar linkul de locație WSDL. Se presupune că fișierul „stockquote1.wsdl” se află în același director cu serverul SOAP.

Exemplul 5 (client3.php)

$client = new SoapClient("stockquote1.wsdl");
print($client -> getQuote("ibm" ));
?>

Care sunt principalele probleme cu clientul și serverul nostru?

Pentru început, nu se ocupă de erori. Ce se întâmplă când serverul nu găsește un rezultat potrivit pentru valoarea variabilei simbol transmisă acestuia? SOAP are un format de mesaj special pentru mesajele de eroare - SoapFault Pentru a genera un astfel de mesaj, serverul trebuie să lanseze o excepție folosind obiectul SoapFault. Primul parametru al constructorului SoapFault() este un șir cu un cod de eroare, al doilea este un șir cu o descriere a erorii. Clientul trebuie să fie scris pentru a gestiona excepțiile SoapFault.

În al doilea rând, este mai bine să încapsulați funcționalitatea serviciului web într-o clasă PHP. În acest caz, nu va trebui să folosim variabile globale și să adăugăm fiecare metodă SOAP la server separat. În schimb, vom putea adăuga întreaga clasă și toate metodele acesteia vor fi disponibile prin SOAP. Iată versiunile modificate corespunzător ale clientului și serverului.

Exemplul 6 (server2.php)

clasa QuoteService(
private $quotes = array("ibm" => 98.42 );

Funcția getQuote ($simbol) (
if (isset($this -> ghilimele [ $simbol ])) (
returnează $acest -> ghilimele [ $simbol ];
) altfel (
arunca noua
SoapFault("Server" , "Simbol necunoscut "$simbol"." );
}
}
}

$server = new SoapServer("stockquote2.wsdl");
$server -> setClass("QuoteService");
$server -> handle();
?>

După cum puteți vedea, am folosit metoda SoapServer::setClass() pentru a conecta obiectul SoapServer la clasa QuoteService.

Exemplul 7 (client4.php)

$client = new SoapClient("stockquote2.wsdl");
incearca (
ecou"

\n" ; 
print($client -> getQuote("ibm" ));
ecou „\n” ;
print($client -> getQuote("microsoft" ));
ecou „\n
\n" ;
) catch (SoapFault $exception ) (
echo $exceptie ;
}
?>

Ce este înăuntru?

Dacă doriți să înțelegeți formatul mesajelor SOAP sau doriți să depanați singur un client SOAP, atunci această secțiune este pentru dvs.

După cum ați văzut în primul exemplu, constructorul SoapClient() ia ca al doilea parametru o matrice asociativă. Cu această matrice putem apela diverse opțiuni pe server.

Să ne uităm la două dintre ele:

  • urmă - permite clientului să salveze cererile și răspunsurile SOAP (dezactivate implicit).
  • excepții - permite clientului să controleze mecanismul de excepție (activat implicit).

Să ne uităm la următorul exemplu de client SOAP. Aceasta este o extindere a clientului din Exemplul 5, care arată exact ceea ce este transmis între client și server. Pentru a obține aceste informații, sunt utilizate metodele __getLastRequest() și __getLastResponse().

Exemplul 8 (client5.php)

$client = new SoapClient("stockquote1.wsdl" ,array(
"urme" => 1 ,
„excepții” => 0 ));
$client -> getQuote("ibm");
printeaza "

\n" ; 
imprimați „Interogare:\n” . htmlspecialchars ($client -> __getLastRequest ()) . „\n” ;
imprimați „Răspuns:\n” . htmlspecialchars($client -> __getLastResponse()). „\n” ;
printeaza "
" ;
?>

Iată rezultatul scriptului. A fost ușor modificat pentru a fi mai ușor de înțeles.

Cerere:



xmlns:xsd="http://www.w3.org/2001/XMLSchema"

SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">


ibm


Răspuns:


xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="urn:xmethods-delayed-quotes"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">


98.42


Alte implementări SOAP pentru PHP

Toate sunt scrise în PHP, nu în C.

Relua

În acest articol, am descris doar funcțiile de bază ale extensiei SOAP. De fapt, poate face mult mai mult, dar este pur și simplu imposibil să-și demonstreze toate capacitățile într-un articol scurt. Iată o listă cu cele principale:

  1. Suport pentru tipuri de date complexe (matrice, obiecte)
  2. Suport antet SOAP
  3. Suport dinamic pentru SOAP 1.1 și SOAP 1.2

Poate că acestea vor fi discutate mai detaliat în articolele următoare.

Documentația detaliată despre extensia SOAP se găsește la http://www.php.net/manual/en/ref.soap.php.

Dezvoltarea acestei extensii este în fazele sale incipiente, astfel încât feedbackul dvs. va ajuta să o faceți mai stabilă, fiabilă, convenabilă și mai rapidă. Vă rugăm să raportați orice problemă pe care o întâlniți când îl utilizați la http://bugs.php.net/.

Legături

Despre autor

(9)

Sunt obișnuit să scriu cod PHP, dar nu folosesc des codificare orientată pe obiecte. Acum trebuie să interacționez cu SOAP (ca client) și nu pot obține corect sintaxa. Am un fișier WSDL care îmi permite să configurez corect o nouă conexiune folosind clasa SoapClient. Cu toate acestea, nu reușesc să efectuez apelul corect și să recuperez datele. Trebuie să trimit următoarele date (simplificate):

  • ID de contact
  • Persoana de contact
  • Descriere generală
  • Cantitate

Există două funcții în documentul WSDL, dar am nevoie doar de una ("FirstFunction" de mai jos). Iată scriptul pe care îl rulez pentru a obține informații despre funcțiile și tipurile disponibile:

$client = new SoapClient("http://example.com/webservices?wsdl"); var_dump($client->__getFunctions()); var_dump($client->__getTypes());

Și iată rezultatul pe care îl generează:

Array( => "FirstFunction Function1(FirstFunction $parametri)", => "SecondFunction Function2(SecondFunction $parametri)",); array( => struct Contact ( id id; nume nume; ) => șir „descriere șir” => șir „cantitate int” )

Să presupunem că vreau să apelez FirstFunction cu date:

  • ID de contact: 100
  • Persoana de contact: Ioan
  • Descriere generală: Baril de petrol
  • Cantitate: 500

Care ar fi sintaxa corectă? Am încercat tot felul de variante, dar se pare că structura săpunului este destul de flexibilă, așa că există doar atâtea moduri de a face acest lucru. Nu am putut să-mi dau seama din manual...

UPDATE 1: Probă încercată de la MMK:

$client = new SoapClient("http://example.com/webservices?wsdl"); $params = array("id" => 100, "name" => "Ioan", "descriere" => "Baril de petrol", "cantitate" => 500,); $răspuns = $client->__soapCall(„Funcția1”, matrice($params));

Dar primesc acest răspuns: Obiectul nu are nicio proprietate „Contact”. După cum puteți vedea în rezultatul getTypes() , există o structură numită Contact , așa că cred că trebuie să clarific cumva că parametrii mei includ datele de contact, dar întrebarea este: cum?

UPDATE 2: Am încercat și aceste structuri, aceeași eroare.

$params = array(array("id" => 100, "nume" => "Ioan",), "Baril de petrol", 500,);

Precum si:

$params = array("Contact" => array("id" => 100, "nume" => "Ioan",), "descriere" => "Baril de petrol", "cantitate" => 500,);

Eroare în ambele cazuri: obiectul nu are proprietatea „Contact”.

Răspunsuri

Cod.

Acesta este ceea ce trebuie să faci în lateral PHP :

(Testat și funcțional)

id = $id;

$acest->nume = $nume;

  • Dacă faceți print_r($params); veți vedea acest rezultat deoarece serviciul dvs. web așteaptă:

Array ( => Contact Object ( => 100 => John) => Butoi de petrol => 500)

  • Dacă faci print_r($params); veți vedea această ieșire deoarece serviciul dvs. web așteaptă:

(După cum puteți vedea, obiectul Contact nu este nul, precum și alți parametri, ceea ce înseamnă că solicitarea dvs. a fost finalizată cu succes din partea PHP).

  • Când am depanat exemplul de serviciu web .NET, am primit următoarele:

obiect (stdClass) public "Function1Result" => string "Detaliile cererii dvs.! id: 100, nume: John, descriere: Baril de ulei, cantitate: 500" (lungime = 98)

Sper ca asta sa ajute :-)

De exemplu:

Require_once „WSDLInterpreter-v1.0.0/WSDLInterpreter.php”; $wsdlLocation = " ?wsdl"; $wsdlInterpreter = nou WSDLInterpreter($wsdlLocation); $wsdlInterpreter->savePHP(".");

Nu știu de ce serviciul meu web are aceeași structură ca a ta, dar nu are nevoie de o clasă pentru parametru, ci doar de o matrice.

De exemplu:- WSDL-ul meu:

5390a7006cee11e0ae3e0800200c9a66 831f8c1ad25e1dc89cf2d8f23d2af...fa85155f5c67627 VITS-STALENS Zoethout tine 0.100 10K24 2012-12-31 Gladys Roldan de Moras

Calle General Oraá 26 (4º izda) 28006 Madrid ES
es

Var_dump($client->getFunctions()); var_dump($client->getTypes());

Iată rezultatul:

Matrice 0 => șir "OrderConfirmation createOrder(OrderRequest $createOrder)" (lungime=56) matrice 0 => șir "struct OrderRequest ( Identificare de identificare; Livrare livrare; Colet; Destinatar destinatar; șir de referință; )" (lungime=130) 1 => șir "struct Identification (șir expeditor; șir hash; șir de origine; )" (lungime=75) 2 => șir "struct Delivery ( Nod from; Node to; )" (lungime=41) 3 => șir " struct Node ( țara șirului; nodul șirului; )" (lungime=46) 4 => șir "struct Parcel ( descriere șir; greutate zecimală; număr ordine șir; data ordineData; )" (lungime=93) 5 => șir "struct Receiver ( string firstName; string prenume; Adresa adresa; string email; string language; )" (lungime=106) 6 => string "struct Adresa ( string line1; string line2; string postalCode; string city; string country; )" (lungime =99) 7 => șir „struct OrderConfirmation (string trackingNumber; șir de referință; )” (lungime=71) 8 => șir „struct OrderServiceException ( șir de cod;

OrderServiceException faultInfo;

mesaj șir; )" (lungime=97)

Deci, în codul meu:

obiect (stdClass) public "Function1Result" => string "Detaliile cererii dvs.! id: 100, nume: John, descriere: Baril de petrol, cantitate: 500" (lungime = 98)

$client = new SoapClient("http://packandship-ws.kiala.com/psws/order?wsdl");

De asemenea, puteți utiliza serviciile SOAP:

$params = array("reference" => $orderId, "identification" => array ("sender" => param ("kiala", "sender_id"), "hash" => hash ("sha512", $orderId . param("kiala", "sender_id") , param("kiala", "parolă"), "originator" => null,), "delivery" => array ("de la" => matrice ("țară" =. > "es", "nod" => "",), "to" => array("country" => "es", "node" => "0299"),), "parcel" => array( "description" => "Descriere", "greutate" => 0.200, "orderNumber" => $orderId, "orderDate" => data ("A-m-d")), "receiver" => array ("firstName" => " Prenume client", "surname" => "Nume de familie client", "address" => array("line1" => "Linia 1 Adresa", "line2" => "Linia 2 Adresa", "postalCode" => 28006, "city" => "Madrid", "country" => "es",), "email" => " ", "language" => "es"));

$rezultat = $client->createOrder($params);

var_dump($rezultat);

Mai întâi inițializați serviciile web:

$params = array("arg0" => $contactid, "arg1" => $desc, "arg2" => $nume contact); $răspuns = $client->__soapCall(„numemetodă”, matrice($params));

Rețineți că numele metodei este disponibil în WSDL ca nume de operație, de exemplu:

Aveți nevoie de o matrice multidimensională, puteți încerca asta:

$params = array(array("id" => 100, "nume" => "Ioan",), "Baril de petrol", 500);

în PHP o matrice este o structură și este foarte flexibilă. De obicei, cu apeluri de săpun folosesc învelișul XML, așa că nu sunt sigur dacă va funcționa.

EDITA:

Ceea ce ați putea dori să încercați este să creați o solicitare json pentru a o trimite sau să utilizați aceasta pentru a crea un xml de achiziție urmând ceea ce este pe această pagină: http://onwebdev.blogspot.com/2011/08/ php-converting-rss-to- json.html

Trebuie să declari acord clasă

Contract de clasă ( public $id; public $nume; ) $contract = contract nou(); $contract->id = 100; $contract->nume = "Ioan"; $params = array("Contact" => $contract, "descriere" => "Baril de petrol", "cantitate" => 500,);

$params = array($contract, "description" => "Baril de petrol", "amount" => 500,);

$răspuns = $client->__soapCall(„Funcția1”, matrice(„Prima funcție” => $params));

$răspuns = $client->__soapCall(„Funcția1”, $params);

Întrebare mare, deoarece mulți dezvoltatori, chiar și cei experimentați, sunt derutați de modul în care PHP gestionează matricele în buclele foreach. Într-o buclă standard foreach, PHP creează o copie a matricei care este utilizată în buclă. Copia este eliminată imediat după finalizarea buclei. Acest lucru este transparent pentru funcționarea unei bucle simple foreach. De exemplu:

$set = array("mar", "banana", "nuca de cocos"); foreach ($set AS $item) ( echo "($item)\n"; )

Aceste rezultate:

Nucă de cocos mere banană

Deci o copie este creată, dar dezvoltatorul nu observă, deoarece matricea originală nu este referită în buclă sau după ce bucla se termină. Cu toate acestea, când încercați să schimbați elementele din buclă, veți descoperi că acestea nu sunt modificate când se încheie:

$set = array("mar", "banana", "nuca de cocos"); foreach ($set AS $item) ( $item = strrev ($item); ) print_r($set);

Aceste rezultate:

Matrice ( => mere => banane => nucă de cocos)

Orice modificare față de original nu poate fi marcată, de fapt nu se fac modificări la original, chiar dacă i-ați atribuit în mod explicit o valoare $item. Acest lucru se datorează faptului că lucrați la $item așa cum apare în copia $set la care lucrează. Puteți suprascrie acest lucru prin capturarea $item prin referință, astfel:

$set = array("mar", "banana", "nuca de cocos"); foreach ($set AS &$item) ( $item = strrev($item); ) print_r($set);

Aceste rezultate:

Array ( => elppa => ananab => tunococ)

Deci, este evident și observabil că atunci când $item este rulat prin referință, modificările aduse $item sunt făcute membrilor setului $original. Utilizarea $item prin referință împiedică, de asemenea, PHP să creeze o copie a matricei. Pentru a testa acest lucru, vom afișa mai întâi un script rapid care demonstrează copia:

$set = array("mar", "banana", "nuca de cocos"); foreach ($set AS $item) ( $set = ucfirst($item); ) print_r($set);

Aceste rezultate:

Array ( => mere => banane => nucă de cocos => Măr => Banane => Nucă de cocos)

După cum se arată în exemplu, PHP a copiat $set și l-a folosit pentru a itera peste el, dar când $set a fost folosit în buclă, PHP a adăugat variabilele la matricea originală și nu la matricea copiată. Practic, PHP folosește doar matricea copiată pentru a trece prin buclă și a atribui $item. Din acest motiv, bucla de mai sus rulează doar de 3 ori și de fiecare dată adaugă o valoare diferită la sfârșitul setului $ original, lăsând setul $ original cu 6 elemente, dar nu intră niciodată într-o buclă infinită.

Totuși, ce se întâmplă dacă am folosi $item prin referință, așa cum am menționat mai devreme? Un caracter adăugat la testul de mai sus:

$set = array("mar", "banana", "nuca de cocos"); foreach ($set AS &$item) ( $set = ucfirst($item); ) print_r($set);

Rezultă o buclă nesfârșită. Vă rugăm să rețineți că aceasta este efectiv o buclă infinită, va trebui fie să omorâți singur scriptul, fie să așteptați ca sistemul de operare să se închidă. Am adăugat următoarea linie la script-ul meu, astfel încât PHP să rămână fără memorie foarte repede, vă sugerez să faceți același lucru dacă aveți de gând să rulați aceste teste de buclă infinită:

Ini_set("memory_limit","1M");

Deci, în acest exemplu anterior de buclă infinită, vedem motivul pentru care PHP a fost scris, pentru a crea o copie a unui tablou pe care să o iterați. Când o copie este creată și utilizată numai de proiectarea construcției buclei în sine, matricea rămâne statică în timp ce bucla rulează, astfel încât nu veți avea niciodată probleme.