Exemple de clienți PHP soap. Scrierea unei aplicații SOAP client-server în PHP

Trebuie să mă conectez la un serviciu web și asta este tot ce am:

    Exemplu de apel:

    Nume de utilizator Parolă

    Știu că această funcție returnează un șir;

Iată ce am făcut până acum:

    A creat o referință de serviciu, adăugând doar adresa WSDL specificată la pasul 1.

    Am creat o instanță de serviciu web și am apelat funcția cu toți parametrii necesari, dar nu utilizatorul și parola pentru antet.

Cum ar trebui să continui? Mulţumesc anticipat.

1 raspuns

Acesta ar putea fi un loc bun pentru a începe dacă trebuie să vă adăugați acreditările; Cred că ar trebui să o faci din moment ce le-ai luat cumva. Partea în care vă adăugați acreditările este mai jos:

UsernameToken userToken = new UsernameToken (nume utilizator, parola, PasswordOption.SendHashed); Service1 serviceProxy = nou Service1(); SoapContext requestContext = serviceProxy.RequestSoapContext; requestContext.Security.Tokens.Add(userToken);

  1. Adăugați-vă acreditările inserându-le într-un anumit token - al cărui tip aparține spațiului de nume Microsoft.Web.Services2.Security.Tokens
  2. Creați un proxy pentru serviciul dvs. (în exemplul de mai sus serviceProxy)
  3. Accesați antetul solicitării dvs. prin serviciul dvs. RequestSoapContext
  4. Adăugați token la cerere

De asemenea, cred că ați putea sări peste partea „? Wsdl” din adresă, deoarece se referă la specificația serviciului web. Odată ce ați terminat, puteți încerca să apelați funcția și să vedeți cum funcționează totul: dacă funcția ar trebui să returneze ceva, verificați la ce vă așteptați.

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");

Apoi setați și transmiteți parametrii:

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

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 0.100 VITS-STALENS 2012-12-31 Zoethout tine 10K24

Gladys Roldan de Moras 28006 Calle General Oraá 26 (4º izda)
Madrid ES

[email protected]

es

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) Madrid Deci in codul meu:

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

$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" => "

", "limba" => "es")); $rezultat = $client->createOrder($params); var_dump($rezultat);

"; ?>

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.

Suportul RPC (Remote Procedure Calls) a fost una dintre caracteristicile minore ale protocolului SOAP la început, dar acum a devenit una dintre caracteristicile cele mai frecvent utilizate.

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 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,
„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 o metodă 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. Acestea 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

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 portType definește o singură operație, getQuote, care specifică care dintre cele descrise în secțiunea mesaj vor fi folosite pentru cerere și care pentru răspuns.

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 în același mod ca un client, dar nu există avantaje în utilizarea acestei opțiuni care să o facă 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ă atunci când serverul nu găsește un rezultat potrivit pentru valoarea variabilei simbol care i-a fost transmisă? 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 un tablou asociativ ca al doilea parametru. Cu această matrice putem apela diverse opțiuni pe server.

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

  • urmărire - 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, arătând exact ce se trece î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ă a celor 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

Pentru a crea un serviciu web SOAP în PHP, mai întâi trebuie să instalați și să configurați PHP, precum și un server HTTP local. În acest proiect, a fost folosit pachetul XAMP, care permite instalarea rapidă a serverului HTTP Apache și PHP.

Separat, trebuie să faceți modificări la fișierele de configurare Apache și PHP.

În fișierul de configurare a serverului HTTP Apache httpd.conf, trebuie să găsiți următorul fragment de cod:

Pentru a rula scripturi PHP pe un server local, trebuie să le stocați în directorul rădăcină al serverului Apache, în mod implicit, folderul htdocs din folderul rădăcină Apache.

Pentru a schimba directorul rădăcină al site-ului, trebuie să faceți modificări fișierului httpd.conf în linia de mai jos:

Pentru a activa suportul PHP, trebuie să adăugați următoarele linii în fișierul httpd.conf:


Pentru a lansa serverul Apache HTTP, puteți utiliza comenzile consolei sau panoul de control XAMMP, care vă permite să gestionați starea Apache și, de asemenea, să o configurați.

Aspectul acestui utilitar este prezentat în Figura 2.

Figura 2. - Utilitarul XAMMP Control Panel:


Pentru a crea un serviciu web SOAP, trebuie să scrieți documente PHP care implementează părțile client și server ale aplicației, precum și o pagină WSDL pentru a descrie serviciul web.

Să creăm un serviciu web care oferă un serviciu web care returnează clientului rezultatul unei operații aritmetice pe două numere. Elementele de intrare sunt două numere specificate de client, precum și o variabilă simbolică care definește o operație aritmetică.

Partea client este implementată de două documente PHP. În fișierul form.php folosind elementul

descrie forma în care utilizatorul introduce datele. Proprietățile formularului conțin metoda POST, care este folosită pentru a extrage informații din formular și a le transfera într-un fișier PHP. În acest caz, datele introduse de utilizator sunt transferate către afqk code.php. Elemente descrieți câmpurile de text pentru introducerea datelor și un buton, când se face clic, datele sunt transferate în fișierul code.php.

Fragmentul de cod care implementează fișierul form.php este mai jos:


În fișierul code.php, este creată o instanță a clasei de client și datele introduse de utilizator sunt primite și trimise într-un mesaj SOAP către server. Un fragment de cod care implementează crearea unei instanțe a clasei client este prezentat mai jos:

În acest fragment, este creată o instanță a clasei SoapClient $client, care execută un mesaj SOAP în conformitate cu fișierul de configurare cacl.wsdl.

Fișierul code.php atribuie și variabilelor $a, $b, $action valorile membrilor matricei asociative $_POST, care stochează datele primite de la form.php.

Un fragment de cod care implementează aceste operațiuni este prezentat mai jos:

Unde getCalcEntry() este operația descrisă în fișierul WSDL.

În acest serviciu web, rolul părții server este jucat de fișierul calc-server.php.

Acest fișier declară și apelează funcția getCalcEntry.

Această funcție verifică valoarea variabilei $acțiune și, conform acesteia, efectuează o operație asupra variabilelor $a și $b, scriind rezultatul în variabila $c. În acest fragment, metoda addFunction() oferă acces la funcția getCalcentry clientului de la distanță. Metoda handle() procesează cererea SOAP, apelează funcțiile necesare și trimite răspunsul SOAP. Fragmentul de cod care implementează această funcție este prezentat mai jos:


Fișierul de descriere calc.wsdl joacă un rol important în funcționarea acestui serviciu web SOAP.

Acest fișier definește principalii parametri ai mesajelor SOAP. Fragmentul de cod responsabil pentru implementarea acestui lucru este prezentat mai jos:


În acest fragment elementele getCalcRequest și getCalcResponse - cerere SOAP și, respectiv, răspuns SOAP. În imbricat în elemente definesc numele variabilelor transferate și tipurile acestora. De remarcat că este posibil să se transmită șiruri de caractere (de tip șir) care vor fi convertite în numere implicit, datorită tastării dinamice în PHP. Un alt element important al fișierului WSDL este descrierea interfeței serviciului web realizată de element

În acest fragment elementul descrie un anumit serviciu getCalcEntry constând din două acțiuni:

  • - prima acțiune getCalcRequest reprezintă trimiterea mesajului;
  • - a doua acțiune getCalcResponse - primirea unui răspuns.

Pentru a opera cu succes un serviciu web pe un server local, trebuie să:

  • 1) Creați un director separat pentru aplicația distribuită în directorul rădăcină al serverului Apache. Plasați fișierele form.php, code.php, calc-server.php și calc.wsdl în el;
  • 2) Lansați Apache folosind consola sau panoul de control XAMMP;
  • 3) În bara de adrese a browserului, introduceți adresa clientului serviciului web;
  • 4) Introduceți datele în câmpurile de text și faceți clic pe butonul Calculate;
  • 5) Ca rezultat, o pagină PHP cu rezultatul calculului afișat se va deschide într-o filă de browser.

Figura 3. - Rezultatul serviciului web modificat:


Pentru a considera mai detaliat funcționarea SOAP, modificăm codul fișierului code.php în așa fel încât listele cu ultimele mesaje SOAP - cerere și răspuns - să fie afișate în browser împreună cu rezultatul calculului.

Un fragment de cod care îndeplinește aceste funcții este prezentat mai jos:


programare server web

Acest fragment conține metode standard de sistem ale clasei:

Returnarea textului mesajelor SOAP. La examinarea mesajelor SOAP primite în acest fel, schimbul de date între client și server este clar vizibil. Dacă sunt solicitate, datele sunt conținute în fragmentul de cod de mai jos. Acest fragment conține corpul plicului SOAP, care conține elementul , care descrie un serviciu web.


Conține elemente care stochează valorile variabilelor transferate și tipurile de date ale acestora. Serverului i se trimit valorile numerelor 5 și 3, precum și simbolul operației de scădere efectuate asupra acestora.

Un fragment de cod similar pentru răspuns este mai jos:


În acest fragment de cod puteți vedea valoarea rezultatului scăderii trimis clientului - 2.

Salutare tuturor!
S-a întâmplat că recent am început să dezvolt servicii web. Dar astăzi subiectul nu este despre mine, ci despre cum putem scrie propriul nostru serviciu web XML bazat pe protocolul SOAP 1.2.

Sper că după ce ai citit subiectul vei putea:

  • scrieți propria implementare de server a unei aplicații web;
  • scrieți propria implementare client a unei aplicații web;
  • scrieți propria descriere a serviciului web (WSDL);
  • trimite matricele client de același tip de date către server.

După cum probabil ați ghicit, toată magia se va face folosind PHP și clasele încorporate SoapClient și SoapServer. Iepurele nostru va fi un serviciu de trimitere de mesaje SMS.

1 Declarația problemei

1.1 Limite

La început, îmi propun să ne ocupăm de rezultatul pe care îl vom obține la finalul subiectului. După cum am anunțat mai sus, vom scrie un serviciu de trimitere de mesaje SMS și, mai precis, vom primi mesaje din diferite surse prin protocolul SOAP. După care, vom lua în considerare sub ce formă ajung pe server. Procesul de a pune în coadă mesajele pentru livrare ulterioară către furnizor, din păcate, depășește scopul acestei postări din mai multe motive.

1.2 Ce date vom schimba?

Super, ne-am hotărât limitele! Următorul pas care trebuie făcut este să decidem ce date vom schimba între server și client. Pe acest subiect, vă sugerez să nu despărțiți părul prea mult timp și să răspundeți imediat la întrebările principale:

  • Ce date minime trebuie trimise către server pentru a trimite un mesaj SMS unui abonat?
  • Ce date minime trebuie trimise de la server pentru a satisface nevoile clientului?

Ceva îmi spune că pentru asta trebuie să trimiți următoarele:

  • numărul de telefon mobil și
  • textul mesajului SMS.

În principiu, aceste două caracteristici sunt suficiente pentru trimitere, dar îmi imaginez imediat cazul unui SMS cu felicitări de ziua de naștere care vin la tine la ora 3 dimineața, sau 4! În acest moment, voi fi foarte recunoscător tuturor pentru că nu au uitat de mine! Prin urmare, vom trimite și către server și

  • data trimiterii mesajului SMS.

Următorul lucru pe care aș dori să-l trimit pe server este:

  • Tipul mesajului.

Acest parametru nu este obligatoriu, dar ne poate fi foarte util dacă trebuie să îi spunem rapid șefului câți dintre clienții noștri ne-am „încântat” de știrile noastre și, de asemenea, să tragem câteva statistici frumoase pe această temă.

Și totuși, am uitat ceva! Dacă reflectăm puțin mai mult, este de remarcat faptul că clientul poate trimite fie un mesaj SMS, fie câteva dintre ele la server la un moment dat. Cu alte cuvinte, un pachet de date poate conține de la unu la infinit mesaje.

Drept urmare, obținem că pentru a trimite un mesaj SMS avem nevoie de următoarele date:

  • numarul de telefon mobil,
  • text mesaj SMS,
  • ora trimiterii mesajului SMS către abonat,
  • tipul mesajului.

Am răspuns la prima întrebare, acum trebuie să răspundem la a doua întrebare. Și poate îmi voi permite să fac un pic de încurcătură. Prin urmare, de pe server vom trimite doar date booleene, a căror semnificație are următoarea semnificație:

  • TRUE – pachetul a ajuns cu succes la server, a trecut autentificarea și a fost în coada de așteptare pentru a fi trimis la furnizorul de SMS-uri
  • FALSE – în toate celelalte cazuri

Aceasta încheie descrierea enunțului problemei! Și, în sfârșit, să trecem la partea distractivă - să ne dăm seama ce fel de fiară ciudată este acest SAPUN!

2 Ce este SAPUNUL?

În general, inițial nu am plănuit să scriu nimic despre ce este SOAP și am vrut să mă limitez la link-uri către site-ul w3.org cu specificațiile necesare, precum și link-uri către Wikipedia. Dar la final am decis să scriu o scurtă notă despre acest protocol.

Și îmi voi începe povestea cu faptul că acest protocol de schimb de date aparține unui subset de protocoale bazate pe așa-numita paradigmă RPC (Remote Procedure Call), al cărei antipod este REST (Representational State Transfer). Puteți citi mai multe despre acest lucru pe Wikipedia, linkurile către articole sunt la sfârșitul subiectului. Din aceste articole, trebuie să înțelegem următoarele: „Abordarea RPC permite utilizarea unui număr mic de resurse de rețea cu un număr mare de metode și un protocol complex. Cu abordarea REST, numărul de metode și complexitatea protocolului sunt strict limitate, ceea ce înseamnă că numărul de resurse individuale poate fi mare.” Adică, în raport cu noi, asta înseamnă că în cazul abordării RPC pe site va exista întotdeauna o intrare (link) către serviciu și ce procedură să apelăm pentru a procesa datele primite pe care le transmitem împreună cu datele, în timp ce cu abordarea REST în site-ul nostru are multe intrări (link-uri), fiecare dintre acestea acceptând și procesând doar anumite date. Dacă cineva care citește știe cum să explice diferența dintre aceste abordări și mai simplu, nu uitați să scrieți în comentarii!

Următorul lucru pe care trebuie să-l știm despre SOAP este că acest protocol folosește același XML ca transport, ceea ce, pe de o parte, este foarte bun, deoarece Arsenalul nostru include imediat întreaga putere a unui teanc de tehnologii bazate pe acest limbaj de marcare, și anume XML-Schema - un limbaj de descriere a structurii unui document XML (mulțumesc Wikipedia!), care permite validarea automată a datelor primite de server de la clientii.

Și așa, acum știm că SOAP este un protocol folosit pentru a implementa apeluri de procedură de la distanță și folosește XML ca transport! Dacă citiți articolul de pe Wikipedia, puteți afla și de acolo că poate fi folosit peste orice protocol la nivel de aplicație și nu doar în combinație cu HTTP (din păcate, în acest subiect vom lua în considerare doar SOAP peste HTTP). Și știi ce îmi place cel mai mult la toate astea? Dacă nu există ghiciri, atunci voi da un indiciu - SAPUN!... Încă nu ghiciți?... Ești sigur că ai citit articolul de pe Wikipedia?... În general, nu te voi mai tortura. Prin urmare, voi merge direct la răspunsul: „SOAP (din engleză Simple Object Access Protocol - simplu protocol acces la obiecte; până la specificația 1.2)". Cel mai remarcabil lucru la această linie este scrisul cu caractere cursive! Nu știu ce concluzii ați tras din toate acestea, dar văd următoarele - deoarece acest protocol nu poate fi în niciun fel numit „simplu” (și se pare că chiar și w3 este de acord cu asta), atunci de la versiunea 1.2 a încetat cumva să fie decriptat ! Și a devenit cunoscut sub numele de SOAP, doar SOAP, punct.

Ei bine, vă rog să mă scuzați, am luat-o puțin în lateral. După cum am scris mai devreme, XML este folosit ca transport, iar pachetele care călătoresc între client și server se numesc plicuri SOAP. Dacă luați în considerare structura generală a plicului, vi se va părea foarte familiar, deoarece... seamănă cu marcajul unei pagini HTML. Are o secțiune principală - Învălui, care include secțiuni AntetŞi Corp, sau Vina. ÎN Corp datele sunt transmise și este o secțiune obligatorie a plicului, în timp ce Antet este opțională. ÎN Antet pot fi transmise autorizarea sau orice alte date care nu au legătură directă cu datele de intrare ale procedurilor serviciului web. Despre Vina nu este nimic special de spus, cu excepția faptului că vine la client de pe server în cazul oricăror erori.

Aici se termină povestea mea de recenzie despre protocolul SOAP (ne vom uita la plicurile în sine și la structura lor mai detaliat când clientul și serverul nostru vor învăța în sfârșit să le ruleze unul pe celălalt) și începe una nouă - despre companionul SOAP numit WSDL(Limbajul de descriere a serviciilor web). Da, da, acesta este exact lucrul care ne sperie pe cei mai mulți dintre noi chiar și de a încerca să implementăm API-ul nostru pe acest protocol. Ca rezultat, de obicei ne reinventăm roata cu JSON ca transport. Deci, ce este WSDL? WSDL este un limbaj pentru descrierea serviciilor web și accesarea acestora, bazat pe limbajul XML (c) Wikipedia. Dacă această definiție nu vă explică întregul sens sacru al acestei tehnologii, atunci voi încerca să o descriu cu propriile mele cuvinte!

WSDL este conceput pentru a permite clienților noștri să comunice în mod normal cu serverul. Pentru a face acest lucru, fișierul cu extensia „*.wsdl” descrie următoarele informații:

  • Ce spații de nume au fost folosite?
  • Ce scheme de date au fost folosite?
  • Ce tipuri de mesaje așteaptă serviciul web de la clienți?
  • Ce date aparțin căror proceduri de servicii web,
  • Ce proceduri conține serviciul web?
  • Cum ar trebui clientul să apeleze procedurile serviciului web,
  • La ce adresă trebuie trimise apelurile clienților?

După cum puteți vedea, acest fișier este întregul serviciu web. Specificând adresa fișierului WSDL în client, vom ști totul despre orice serviciu web! Drept urmare, nu trebuie să știm absolut nimic despre locul în care se află serviciul web în sine. Tot ce trebuie să știți este locația fișierului său WSDL! Vom afla în curând că SOAP nu este atât de înfricoșător pe cât spun proverbele rusești.

3 Introducere în XML-Schema

Acum știm multe despre ce este SOAP, ce este în el și avem o privire de ansamblu asupra stivei de tehnologie care îl înconjoară. Întrucât, în primul rând, SOAP este o metodă de interacțiune între un client și un server, iar limbajul de markup XML este folosit ca transport pentru acesta, în această secțiune vom înțelege puțin despre modul în care are loc validarea automată a datelor folosind scheme XML.

Sarcina principală a diagramei este de a descrie structura datelor pe care urmează să le procesăm. Toate datele din schemele XML sunt împărțite în simplu(scalar) și complex(structuri) tipuri. Tipurile simple includ următoarele tipuri:

  • linia,
  • număr,
  • valoare booleană,
  • data.

Ceva foarte simplu care nu are extensii în interior. Antipodul lor este de tipuri complexe complexe. Cel mai simplu exemplu de tip complex care vine în minte tuturor sunt obiectele. De exemplu, o carte. Cartea constă din proprietăți: autor, Nume, preţ, numărul ISBN etc. Și aceste proprietăți, la rândul lor, pot fi fie tipuri simple, fie complexe. Și sarcina schemei XML este de a descrie acest lucru.

Vă sugerez să nu mergeți departe și să scrieți o schemă XML pentru mesajul nostru SMS! Mai jos este descrierea xml a mesajului SMS:

71239876543 Mesajul de testare 20-07-2013T12:00:00 12

Diagrama noastră de tip complex va arăta astfel:

Această intrare arată după cum urmează: Avem o variabilă " mesaj" tip " Mesaj„și există un tip complex numit „ Mesaj", care constă dintr-un set secvenţial de elemente" telefon" tip şir, « text" tip şir, « data" tip dateTime, « tip" tip zecimal. Aceste tipuri sunt simple și sunt deja definite în descrierea schemei. Felicitări! Tocmai am scris prima noastră schemă XML!

Cred că sensul elementelor " element" Și " complexType„Totul a devenit mai mult sau mai puțin clar pentru tine, așa că nu ne vom mai concentra asupra lor și hai să trecem direct la elementul compozitor” secvenţă" Când folosim elementul compozitor " secvenţă„Vă informăm că elementele incluse în acesta trebuie să fie întotdeauna amplasate în ordinea specificată în diagramă, iar toate sunt obligatorii. Dar nu dispera! Mai sunt două elemente de compoziție în schemele XML: " alegere" Și " toate" Compozitor " alegere" anunță că trebuie să existe unul dintre elementele enumerate în acesta, iar compozitorul " toate» – orice combinație a elementelor enumerate.

După cum vă amintiți, în prima secțiune a subiectului am convenit că de la unul la infinit mesajele SMS pot fi transmise într-un pachet. Prin urmare, îmi propun să înțelegem cum sunt declarate astfel de date în schema XML. Structura generală a pachetului ar putea arăta astfel:

71239876543 Mesajul de testare 1 20-07-2013T12:00:00 12 71239876543 Mesajul de testare N 20-07-2013T12:00:00 12

Diagrama pentru un astfel de tip complex va arăta astfel:

Primul bloc conține declarația familiară de tip complex „ Mesaj" Dacă ați observat, atunci în fiecare tip simplu inclus în " Mesaj", au fost adăugate noi atribute de clarificare" minApare" Și " maxApare" După cum ați putea ghici din nume, primul ( minApare) indică faptul că această secvență trebuie să conțină cel puțin un element de tip „ telefon», « text», « data" Și " tip", în timp ce următorul ( maxApare) atributul ne declară că există cel mult un astfel de element în secvența noastră. Ca rezultat, atunci când scriem propriile noastre scheme pentru orice date, ni se oferă cea mai largă alegere în ceea ce privește modul de configurare a acestora!

Al doilea bloc al diagramei declară elementul " listă de mesaje" tip " Listă de mesaje" Este clar că „ Listă de mesaje" este un tip complex care conține cel puțin un element " mesaj„, dar numărul maxim de astfel de elemente nu este limitat!

4 Scrieți WSDL

Vă amintiți că WSDL este serviciul nostru web? Sper să vă amintiți! Pe măsură ce îl scriem, micul nostru serviciu web va rula pe el. Prin urmare, vă sugerez să nu vă încurcați.

În general, pentru ca totul să funcționeze corect pentru noi, trebuie să transferăm clientului un fișier WSDL cu tipul MIME corect. Pentru a face acest lucru, trebuie să configurați serverul dvs. web în consecință, și anume, setați tipul MIME pentru fișierele cu extensia „*.wsdl” la următoarea linie:

Aplicație/wsdl+xml

Dar, în practică, de obicei trimiteam antetul HTTP prin PHP " text/xml»:

Antet ("Content-Type: text/xml; charset=utf-8");

și totul a funcționat excelent!

Vreau să vă avertizez imediat că serviciul nostru web simplu va avea o descriere destul de impresionantă, așa că nu vă alarmați, pentru că... Majoritatea textului este apă obligatorie și, după ce l-a scris o singură dată, îl poți copia constant de la un serviciu web la altul!

Deoarece WSDL este XML, trebuie să scrieți despre asta direct în prima linie. Elementul rădăcină al fișierului ar trebui să fie întotdeauna numit „ definiții»:

De obicei, WSDL constă din 4-5 blocuri principale. Primul bloc este definiția unui serviciu web sau, cu alte cuvinte, punctul de intrare.

Aici scrie că avem un serviciu numit - „ Serviciu SMS" În principiu, toate denumirile din fișierul WSDL pot fi schimbate de dvs. în orice doriți, pentru că nu joacă absolut niciun rol.

După aceasta vă anunțăm că în serviciul nostru web " Serviciu SMS" există un punct de intrare ("port") numit " SMSServicePort" La acest punct de intrare vor fi trimise toate cererile de la clienți către server. Și indicați în elementul „ adresa» link la fișierul de gestionare care va accepta cereri.

Odată ce am definit serviciul web și am specificat punctul de intrare pentru acesta, trebuie să le legăm procedurile acceptate:

Pentru a face acest lucru, listează ce operațiuni și sub ce formă vor fi numite. Aceste. pentru port" SMSServicePort" o legare este definită sub numele " SMSServiceBinding", care are un tip de apel " rpc„și HTTP este folosit ca protocol de transmisie. Astfel, am indicat aici că vom efectua un apel RPC prin HTTP. După aceasta, descriem ce proceduri ( operare) sunt acceptate în serviciul web. Vom sprijini o singură procedură – „ trimite SMS" Prin această procedură minunatele noastre mesaje vor fi trimise către server! După ce procedura a fost declarată, este necesar să se indice sub ce formă vor fi transmise datele. În acest caz, este indicat că vor fi folosite plicuri SOAP standard.

După aceea, trebuie să legăm procedura de mesaje:

Pentru a face acest lucru, precizăm că legarea noastră este de tipul " SMSServicePortType"și în elementul" portType„cu denumirea de același tip, indicăm legarea procedurilor de mesaje. Și astfel, mesajul primit (de la client la server) va fi numit „ trimiteSmsRequest", și de ieșire (de la server la client) " trimiteSmsResponse" Ca toate numele din WSDL, numele mesajelor de intrare și de ieșire sunt arbitrare.

Acum trebuie să descriem mesajele în sine, de ex. de intrare și de ieșire:

Pentru a face acest lucru adăugăm elementele " mesaj"cu nume" trimiteSmsRequest" Și " trimiteSmsResponse„, respectiv. În ele indicăm că intrarea ar trebui să fie un plic a cărui structură corespunde tipului de date " Cerere" După care se returnează de la server un plic care conține tipul de date - „ Răspuns».

Acum trebuie să facem doar puțin - adăugați o descriere a acestor tipuri în fișierul nostru WSDL! Și cum credeți că WSDL descrie datele de intrare și de ieșire? Cred că ai înțeles deja totul cu mult timp în urmă și ți-ai spus că folosind scheme XML! Și vei avea perfectă dreptate!

Ne poți felicita! Primul nostru WSDL a fost scris! Și suntem cu un pas mai aproape de a ne atinge obiectivul.
În continuare, ne vom uita la ce ne oferă PHP pentru dezvoltarea propriilor aplicații distribuite.

5 Primul nostru server SOAP

Mai devreme am scris că pentru a crea un server SOAP în PHP vom folosi clasa încorporată SoapServer. Pentru ca toate acțiunile ulterioare să se întâmple în același mod ca și pentru mine, va trebui să vă modificați puțin PHP. Pentru a fi și mai precis, trebuie să vă asigurați că aveți instalată extensia „php-soap”. Cel mai bine este să citiți cum să îl instalați pe serverul dvs. web de pe site-ul oficial PHP (vezi lista de referințe).

După ce totul a fost instalat și configurat, va trebui să creăm un fișier în folderul rădăcină al găzduirii dvs. „ smsservice.php» cu următorul conținut:

setClass("SoapSmsGateWay"); //Porniți serverul $server->handle();

Sper că nu este nevoie să explic ce este deasupra liniei cu funcția „ini_set”. Deoarece acolo se determină ce anteturi HTTP vom trimite de la server către client și se configurează mediul. În conformitate cu „ini_set”, dezactivăm memorarea în cache a fișierului WSDL, astfel încât modificările noastre să aibă efect imediat asupra clientului.

Acum ajungem la server! După cum puteți vedea, întregul server SOAP are doar trei linii! Pe prima linie, creăm o nouă instanță a obiectului SoapServer și transmitem adresa descrierii noastre WSDL a serviciului web constructorului său. Acum știm că va fi localizat în rădăcina găzduirii într-un fișier cu numele auto-explicativ „ smsservice.wsdl.php" În a doua linie, îi spunem serverului SOAP care clasă trebuie extrasă pentru a procesa plicul primit de la client și a returna plicul cu răspunsul. După cum probabil ați ghicit, singura noastră metodă va fi descrisă în această clasă trimite SMS. Pe a treia linie pornim serverul! Gata, serverul nostru este gata! Cu care ne felicit pe toti!

Acum trebuie să creăm fișierul WSDL. Pentru a face acest lucru, puteți fie să-i copiați pur și simplu conținutul din secțiunea anterioară, fie să vă luați libertăți și să-l „șablonați” puțin:

"; ?> /" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http:// schemas.xmlsoap.org/wsdl/http/" name="SmsWsdl" xmlns="http://schemas.xmlsoap.org/wsdl/"> /"> /smsservice.php" />

În această etapă, ar trebui să fim complet mulțumiți de serverul rezultat, deoarece Putem înregistra plicurile care vin la el și apoi analizăm cu calm datele primite. Pentru a primi ceva pe server, avem nevoie de un client. Deci să trecem la asta!

6 client SOAP pe drum

În primul rând, trebuie să creăm un fișier în care vom scrie clientul. Ca de obicei, îl vom crea în rădăcina gazdei și îl vom numi " client.php", iar în interior vom scrie următoarele:

MessageList = new MessageList(); $req->messageList->message = mesaj nou(); $req->messageList->message->phone = "79871234567"; $req->messageList->message->text = "Testează mesajul 1"; $req->messageList->message->date = "2013-07-21T15:00:00.26"; $req->messageList->message->type = 15; $client = new SoapClient("http://($_SERVER["HTTP_HOST"])/smsservice.wsdl.php", array("soap_version" => SOAP_1_2)); var_dump($client->sendSms($req));

Să ne descriem obiectele. Când am scris WSDL, acesta a descris trei entități pentru plicul primit pe server: Cerere, Listă de mesajeŞi Mesaj. În consecință, clasele Cerere, Listă de mesajeŞi Mesaj sunt reflectări ale acestor entități în scriptul nostru PHP.

Odată ce am definit obiectele, trebuie să creăm un obiect ( $req), pe care îl vom trimite către server. După care vin cele mai prețuite două replici pentru noi! Clientul nostru SOAP! Credeți sau nu, acest lucru este suficient pentru ca serverul nostru să înceapă să primească mesaje de la client, precum și pentru ca serverul nostru să le primească și să le proceseze cu succes! În primul dintre ele, creăm o instanță a clasei SoapClient și transmitem adresa locației fișierului WSDL constructorului acestuia, iar în parametri indicăm în mod explicit că vom lucra folosind protocolul SOAP versiunea 1.2. Pe linia următoare numim metoda trimite SMS obiect $clientși afișați imediat rezultatul în browser.
Hai să-l rulăm și să vedem ce avem în sfârșit!

Următorul obiect mi-a fost returnat de pe server:

Object(stdClass) public "status" => boolean adevărat

Și asta este grozav, pentru că... Acum știm sigur că serverul nostru funcționează și nu numai că funcționează, dar poate returna și câteva valori clientului!

Acum să ne uităm la jurnalul pe care îl păstrăm cu prudență pe partea serverului! În prima parte vedem datele brute care au ajuns la server:

79871234567 Mesajul de testare 1 2013-07-21T15:00:00.26 15

Acesta este plicul. Acum știi cum arată! Dar este puțin probabil să fim interesați să ne uităm la asta tot timpul, așa că haideți să deserializăm obiectul din fișierul jurnal și să vedem dacă totul este bine:

Object(stdClass) public "messageList" => object(stdClass) public "message" => object(stdClass) public "phone" => șir "79871234567" (lungime=11) public "text" => șir "Test mesaj 1 " (lungime=37) public "date" => șir "2013-07-21T15:00:00.26" (lungime=22) public "tip" => șir "15" (lungime=2)

După cum puteți vedea, obiectul a fost deserializat corect, pentru care vreau să ne felicit pe toți! Ceva mai interesant ne așteaptă în continuare! Și anume, vom trimite clientul către server nu doar un mesaj SMS, ci un pachet întreg (mai precis, trei)!

7 Trimiterea obiectelor complexe

Să ne gândim cum putem transfera o grămadă de mesaje pe server într-un singur pachet? Probabil cea mai ușoară modalitate ar fi să organizați o matrice în interiorul elementului messageList! Să facem asta:

// creăm un obiect de trimis la server $req = new Request(); $req->messageList = new MessageList(); $msg1 = mesaj nou(); $msg1->telefon = "79871234567"; $msg1->text = "Mesajul de testare 1"; $msg1->date = "2013-07-21T15:00:00.26"; $msg1->tip = 15; $msg2 = mesaj nou(); $msg2->telefon = "79871234567"; $msg2->text = "Test mesajul 2"; $msg2->date = "2014-08-22T16:01:10"; $msg2->tip = 16; $msg3 = mesaj nou(); $msg3->telefon = "79871234567"; $msg3->text = "Test mesajul 3"; $msg3->date = "2014-08-22T16:01:10"; $msg3->tip = 17; $req->messageList->message = $msg1; $req->messageList->message = $msg2; $req->messageList->message = $msg3;

Jurnalele noastre indică faptul că următorul pachet a fost primit de la client:

79871234567 Mesajul de testare 1 2013-07-21T15:00:00.26 15 79871234567 Mesajul de testare 2 22-08-2014T16:01:10 16 79871234567 Mesajul de testare 3 22-08-2014T16:01:10 17

Ce prostii, zici? Și vei avea dreptate într-un fel, pentru că... De îndată ce am aflat că un obiect a părăsit clientul, acesta a ajuns la serverul nostru exact în aceeași formă sub forma unui plic. Adevărat, mesajele SMS nu au fost serializate în XML așa cum aveam nevoie - trebuiau să fie împachetate în elemente mesaj, nu in Struct. Acum să vedem în ce formă un astfel de obiect vine la metodă trimite SMS:

Object(stdClass) public "messageList" => obiect(stdClass) public "message" => object(stdClass) public "Struct" => matrice (dimensiune=3) 0 => obiect(stdClass) public "telefon" => șir „79871234567” (lungime=11) public „text” => șir „Test mesajul 1” (lungime=37) public „date” => șir „2013-07-21T15:00:00.26” (lungime=22) public „ tip" => șir "15" (lungime=2) 1 => obiect(stdClass) public "telefon" => șir "79871234567" (lungime=11) public "text" => șir "Mesaj de testare 2" (lungime= 37) public „date” => șir „2014-08-22T16:01:10” (lungime=19) public „tip” => șir „16” (lungime=2) 2 => obiect(stdClass) public „telefon " => șir "79871234567" (lungime=11) public "text" => șir "Test mesaj 3" (lungime=37) public "date" => șir "2014-08-22T16:01:10" (lungime= 19) public „type” => șir „17” (lungime=2)

Ce ne oferă această cunoaștere? Doar că calea pe care am ales-o nu este corectă și nu am primit răspuns la întrebarea - „Cum putem obține structura corectă de date pe server?” Dar vă sugerez să nu disperați și să încercați să convertiți matricea noastră la tipul obiect:

$req->messageList->message = (obiect)$req->messageList->mesaj;

În acest caz, vom primi un alt plic:

79871234567 Mesajul de testare 1 2013-07-21T15:00:00.26 15 79871234567 Mesajul de testare 2 22-08-2014T16:01:10 16 79871234567 Mesajul de testare 3 22-08-2014T16:01:10 17

A intrat în metodă trimite SMS obiectul are următoarea structură:

Object(stdClass) public "messageList" => obiect(stdClass) public "message" => object(stdClass) public "BOGUS" => matrice (dimensiune=3) 0 => obiect(stdClass) public "telefon" => șir „79871234567” (lungime=11) public „text” => șir „Test mesajul 1” (lungime=37) public „date” => șir „2013-07-21T15:00:00.26” (lungime=22) public „ tip" => șir "15" (lungime=2) 1 => obiect(stdClass) public "telefon" => șir "79871234567" (lungime=11) public "text" => șir "Mesaj de testare 2" (lungime= 37) public „date” => șir „2014-08-22T16:01:10” (lungime=19) public „tip” => șir „16” (lungime=2) 2 => obiect(stdClass) public „telefon " => șir "79871234567" (lungime=11) public "text" => șir "Test mesaj 3" (lungime=37) public "date" => șir "2014-08-22T16:01:10" (lungime= 19) public „type” => șir „17” (lungime=2)

În ceea ce mă privește, „suma nu se schimbă din schimbarea locurilor termenilor” (c). Ce FALS, Ce Struct– încă nu ne-am atins scopul! Și pentru a realiza acest lucru, trebuie să ne asigurăm că în locul acestor nume de neînțeles este afișat cel nativ. mesaj. Dar autorul nu știe încă cum să realizeze acest lucru. Prin urmare, singurul lucru pe care îl putem face este să scăpăm de recipientul suplimentar. Cu alte cuvinte, acum ne vom asigura că în loc de mesaj devenit FALS! Pentru a face acest lucru, schimbați obiectul după cum urmează:

// creăm un obiect de trimis la server $req = new Request(); $msg1 = mesaj nou(); $msg1->telefon = "79871234567"; $msg1->text = "Mesajul de testare 1"; $msg1->date = "2013-07-21T15:00:00.26"; $msg1->tip = 15; $msg2 = mesaj nou(); $msg2->telefon = "79871234567"; $msg2->text = "Test mesajul 2"; $msg2->date = "2014-08-22T16:01:10"; $msg2->tip = 16; $msg3 = mesaj nou(); $msg3->telefon = "79871234567"; $msg3->text = "Test mesajul 3"; $msg3->date = "2014-08-22T16:01:10"; $msg3->tip = 17; $req->messageList = $msg1; $req->messageList = $msg2; $req->messageList = $msg3; $req->messageList = (obiect)$req->messageList;

Ce se întâmplă dacă avem noroc și numele corect iese din diagramă? Pentru a face acest lucru, să ne uităm la plicul care a sosit:

79871234567 Mesajul de testare 1 2013-07-21T15:00:00.26 15 79871234567 Mesajul de testare 2 22-08-2014T16:01:10 16 79871234567 Mesajul de testare 3 22-08-2014T16:01:10 17

Da, nu s-a întâmplat un miracol! FALS– nu vom câștiga! A venit la trimite SMS obiectul în acest caz va arăta astfel:

Object(stdClass) public "messageList" => object(stdClass) public "BOGUS" => array (size=3) 0 => object(stdClass) public "phone" => șir "79871234567" (lungime=11) public " text" => șir "Test mesajul 1" (lungime=37) public "date" => șir "2013-07-21T15:00:00.26" (lungime=22) public "type" => șir "15" (lungime =2) 1 => obiect(stdClass) public "telefon" => șir "79871234567" (lungime=11) public "text" => șir "Test mesaj 2" (lungime=37) public "date" => șir " 2014-08-22T16:01:10" (lungime=19) public "type" => șir "16" (lungime=2) 2 => obiect(stdClass) public "telefon" => șir "79871234567" (lungime= 11) public "text" => șir "Test mesajul 3" (lungime=37) public "date" => șir "2014-08-22T16:01:10" (lungime=19) public "type" => șir " 17" (lungime=2)

După cum se spune – „Aproape”! Pe această notă (puțin tristă), îmi propun să încheiem treptat lucrurile și să tragem niște concluzii pentru noi înșine.

8 Concluzie

In sfarsit am ajuns aici! Să ne dăm seama ce poți face acum:

  • puteți scrie fișierul WSDL necesar serviciului dvs. web;
  • puteți scrie cu ușurință propriul client care poate comunica cu serverul prin SOAP;
  • vă puteți scrie propriul server care comunică cu lumea exterioară prin SOAP;
  • puteți trimite matrice de același tip de obiecte către server de la clientul dvs. (cu unele restricții).

Am făcut și câteva descoperiri în timpul micii noastre cercetări:

  • clasa nativă SoapClient nu serializează corect structurile de date de același tip în XML;
  • atunci când serializează o matrice în XML, acesta creează un element suplimentar numit Struct;
  • atunci când serializează un obiect în XML, acesta creează un element suplimentar numit FALS;
  • FALS mai puțin rău decât Struct datorită faptului că plicul este mai compact (nu sunt adăugate spații de nume suplimentare la antetul XML al plicului);
  • Din păcate, clasa SoapServer nu validează automat datele plicului cu schema noastră XML (poate că nici alte servere nu fac acest lucru).

Vizualizări