PHP-ben az xmlrpc bővítménnyel tudunk XML-RPC szolgáltatást készíteni. A bővítmény előnye, hogy C nyelven íródott, így biztosan jobb teljesítményt nyújt, mint más PHP-ben írt XML-RPC könyvtárak. Annak ellenére, hogy már négy éve létezik, sajnos még mindig "experimental" státuszban van. A PHP oldalán elég gyenge dokumentáció olvasható róla, ezért megpróbálom azokat az információkat röviden felsorolni, amelyek nekem hiányoztak.

Az RPC protokollok közül a legismertebbek az XML-RPC és a SOAP.
A távoli eljáráshívás (RPC) lehetővé teszi programunkból más rendszerek API-ját használni. Távoli eljáráshívás alatt azt értjük, hogy meghívunk egy eljárást. Az eljárásnak paramétereket adhatunk át. A távolí eljáráshívás annyiban különbözik a helyi eljáráshívástól, hogy a meghívott eljárást egy másik rendszer valósítja meg, általában egy távoli számítógépen. Az XML-RPC párbeszéd két részből áll: az ügyfél kérelméből és a kiszolgáló válaszából. A kérelmet át kell alakítani egy szabványos nyelvre, el kell küldeni, majd a kiszolgálónak a kérelmet át kell alakítania a számára érthető formára. Ezt a folyamatot “marshalling”-nak nevezzük. Ez természetesen meglehetős lassulással jár.

A kommunikáció HTTP protokollon keresztül történik, az üzenetváltás pedig XML formában. A PHP-hez írt xmlrpc bővítmény csak a kérelem dokumentumok előallítására és a válasz dekódolására szolgál.

Lássunk példát egy egyszerű kérelemdokumentumra:

A válasz szintén XML formátumú:

Hiba esetén ilyen XML dokumentumot kapunk vissza:

Az xmlrpc bővítmény szerencsére elvégzi helyettünk az XML-dokumentumok előállítását és visszaalakítását (dekódolását)
az xmlrpc_encode_request() és xmlrpc_decode() függvények segítségével.

string xmlrpc_encode_request(string method, mixed params [, array output_options])
mixed xmlrpc_decode(string $xml [, string $encoding])

XML-RPC kiszolgáló létrehozása

Az XML-RPC kérések mindig HTTP POST-ként vannak elküldve. A következő módon tudjuk elérni a nyers POST adatot:

Második lépésben létrehozzuk a kiszolgálót:

A harmadik lépés során visszahívott függvényeket (callback) írunk és meghatározzuk, hogy az egyes bejövő kérelmeket melyik visszahívott függvények fogják ellátni.

Lássunk erre egy példát:

Mielőtt visszaküldenénk valamit is a kliensnek, be kell állítanunk az adat adattartalom típusát (content type).

Utolsó lépésben feldolgozzuk a kérelmet és visszaadjuk a kigenerált XML-dokumentumot.

A kliens megírása

Egy távoli eljárás meghívása a következő lépésekre bontható:

  1. Az xmlrpc_encode_request() függvénnyel legyártatjuk az XML-lekérést.
  2. A legyártott XML-dokumentumot elküldjük a távoli kiszolgálónak (a letölthető forráskódban az XmlRpc_Client osztály valósítja ezt meg).
  3. A visszakapott választ az xmlrpc_decode függvénnyel alakítjuk át a PHP saját adattípusára

Az XML-RPC szolgáltatás leírása (Introspection)

Van néhány rezervált függvénynév, amelyeknek speciális feladata van. Ezek a függvények arra szolgálnak, hogy információkat kérjünk le a tagfüggvényekről (függvények paraméterlistái, a paraméterek adattípusai, a függvény visszatérési értéke, stb.). Lényegében a WSDL-hez hasonló célt szolgálnak. Az XML-RPC szolgáltatások automatikus felderítését teszik lehetővé.

system.listMethods
Visszaadja a kiszolgáló által megvalósított összes tagfüggvény nevét.
system.methodHelp
A tagfüggvény neve alapján megadja a lehetséges prototípusokat.
system.methodSignature
Fogadja a tagfüggvény nevét, és a leírásával tér vissza.
system.describeMethods
fully describes the methods and types implemented by this XML-RPC server.
system.multiCall
executes multiple methods in sequence and returns the results
system.getCapabilities
returns a list of capabilities supported by this server

Az xmlrpc bővítményünk szerencsére (majdnem) automatikusan létrehozza helyettünk ezeket a tagfüggfényeket. Mivel a PHP nyelv nem típusos nyelv, ezért saját magunknak kell megadni a típusokat. Ehhez egy XML dokumentumot kell írnunk, amiben az általunk megvalósított tagfüggvényeket írjuk le.

Ezután meg kell irnunk PHP-ben egy függvényt, ami beolvassa a diszkről ezt az XML-fájlt és visszaadja.

Az xmlrpc_server_register_introspection_callback() függvénnyel regisztráljuk az előbb megírt tagfüggvényt. Ez a módszer azért jó, mert az XML-fájl csak akkor lesz beolvasva és feldolgozva, ha tényleg szükség van rá (on demand), azaz amikor egy kliens érdeklődik a webszolgáltatásunk tagfüggvényeiről.

Ezekkel a speciális függvényekkel az a baj, hogy szinte egyik XMLRPC webszolgáltatás sem implementálta őket (például a Flickr és a WordPress sem). Valószínűleg semmilyen szabvány sem írja ezt elő. Mindenesetre én jó ötletnek tartom, hiszen nem sok munkába kerül, és lehetséges automatikus úton dokumentációt generálni belőle (lásd lentebb a linkeket) a webszolgáltatásunkat használni kivánó fejlesztők részére.

Tagfüggvényeinknek akár többféle paraméterezése (signature - szignatúrája) is lehetséges (egyfajta method overloading). Sajnos az XMLRPC bővítmény nem jól adja vissza a túlterhelt tagfüggvények paraméterezését. Ezt az észrevételemet ezen a fórumon írtam le XMLRPC introspection hiba. Ez azért nem jó hír, mert ha automatikusan szeretnénk kigenerálni a webszolgáltatásunk tagfüggvényeinek listáját automatikus felderítéssel, akkor a túlterhelt tagfüggvények paraméterezése nem lesz jó. Kerülő megoldásnak megírhatunk egy XSLT stíluslapot, ami a meta.xml fájlból készítene dokumentációt.

Letölthető példakód

Megírtam egy rövid, de hasznos példaalkalmazást, amely jó kiindulópont lehet azoknak, akiknek gyorsan kell XML-RPC webszolgáltatást készíteni.
Kipróbálható online is:

És mi a helyzet a SOAP-al?

Egy webszolgáltatás megírása előtt el kell döntenünk, hogy SOAP-ot, vagy XML-RPC-t használjunk-e. Ilyenkor figyelembe kell vennünk a következő tényezőket:

  • programozási nyelv
  • milyen programozási nyelven íródott kliensek fogják használni a webszolgáltatást
  • enterprise méretű webszolgáltatást írunk-e

A SOAP mellett szól, hogy W3C-szabványos leírónyelven kommunikál, és kliens-alkalmazások megírása is egyszerűbb.
Ha PHP-ben egyszerű lenne SOAP kiszolgáló megírása, gondolkodás nélkül a SOAP-ot választanám. ASP.NET-ben például egy SOAP szerver létrehozása gyerekjáték, szinte semmivel sem kell törődnünk, mindenről a .NET gondoskodik. PHP-be azonban egyáltalán nem könnyű és fáradságmentes egy SOAP szerver megírása. Magunknak kell megírni a WSDL (Web Services Description Language - webszolgáltatás-leíró nyelv) fájlt, ami jónéhány hosszú W3C-ajánlás elolvasását követeli meg. Erre meglehetősen sok idő elmegy, így sokan az XML-RPC-t használják PHP-ben.

Ha webszolgáltatásunkat csak PHP kliensek fogják használni, nyugodtan használjunk XMLRPC-t. Komoly méretű webszolgáltatáshoz mindenképpen a SOAP-ot tudom javasolni. A WSDL fájl megírásában esetleg segítségünkre lehet a Zend Studio WSDL generátora. Más ötletem nincsen, hogyan lehetne megúszni a WSDL fájl fáradságos megírását.

Remélem ez a rövid összefoglalás hasznos útmutatást adott azoknak, akik most tervezik saját webszolgáltatás írását.

A témához kapcsolódó linkek

Leave a Reply