ugrás a tartalomhoz

SOAP: Együttműködés távoli szolgáltatásokkal

Anonymous · 2004. Szep. 7. (K), 22.00
SOAP: Együttműködés távoli szolgáltatásokkal
Néhány hete jelent meg - a Kiskapu gondozásában magyar fordításban is elérhető - Advanced PHP Programming című könyv távoli szolgáltatások használatával foglalkozó fejezetének első része webhelyünkön. A PHP fejlesztés felsőfokon címen megjelent könyv ezen fejezete a SOAP technológia ismertetésével folytatódik, rátérve a WSDL praktikáira, majd végül összehasonlítja az XML-RPC és SOAP megoldásokat.

SOAP

A sorozatban megjelent

A SOAP eredetileg a Simple Object Access Protocol (egyszerű objektumelérési protokoll) rövidítése volt, de az 1.1-es változattól önállósult. A SOAP egy olyan protokoll, amely alkalmas változatos környezetbeli adatcserék lebonyolítására. Az XML-RPC-től eltérően, ami kifejezetten az RPC-k kezelésére hivatott, a SOAP általános üzenetkezelésre készült, így az RPC-k ügye csak egyike a számos alkalmazásának. Mindazonáltal, fejezetünk az RPC-kről szól, így most csak a SOAP 1.1 hozzájuk kapcsolódó részéről szólunk.

Hogy is néz ki a SOAP? Íme egy SOAP boríték, amely az xmethods.net tőzsdei árfolyam- lekérdező SOAP szolgáltatását alkalmazza a hivatalos bemutató példa megvalósítására, vagyis az IBM tőzsdei árfolyamának lekérdezésére (azért hivatalos , mert ez a példa szerepel a SOAP bemutató leírásában):
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"  
  3.   xmlns:xsd="http://www.w3.org/2001/XMLSchema"  
  4.   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  5.   xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/"  
  6.   soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">  
  7.   <soap:Body>  
  8.     <getQuote xmlns="http://www.themindelectric.com/wsdl/net.xmethods.services.stockquote.StockQuote/">  
  9.       <symbol xsi:type="xsd:string">ibm</symbol>  
  10.     </getQuote>  
  11.   </soap:Body>  
  12. </soap:Envelope>  
Íme a válasz:
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <soap:Envelope  
  3.   xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"  
  4.   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  5.   xmlns:xsd="http://www.w3.org/2001/XMLSchema"  
  6.   xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"  
  7.   soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">  
  8.   <soap:Body>  
  9.     <n:getQuoteResponse xmlns:n="urn:xmethods-delayed-quotes">  
  10.       <Result xsi:type="xsd:float">90.25</Result>  
  11.     </n:getQuoteResponse>  
  12.   </soap:Body>  
  13. </soap:Envelope>  
A SOAP esete jól példázza azt, hogy egy egyszerű elgondolás nem feltétlenül jár együtt egyszerű megvalósítással. A SOAP üzenet egy borítékból áll, ami egy fejlécet és egy üzenettörzset tartalmaz. Minden elem névtereken található, ami nagyszerű gondolat, de nehézkessé teszi az XML olvasását.

A legkülső címke neve Envelope - ez tartalmazza magát a SOAP üzenetet. Ez az elem az xmlsoap névtérben található, amit teljes minősített nevéből (<soap:Envelope>) és e névtér meghatározásából is láthatunk:

xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
Ez kapcsolatot teremt a soap és az alábbi névtér-URI között:
http://schemas.xmlsoap.org/soap/envelope/

A SOAP és a Schema

A SOAP belső működéseihez igénybe veszi a Schema segítségét, ami egy XML alapú nyelv adatszerkezetek meghatározására és ellenőrzésére. A közmegegyezés szerint egy elem teljes névtere (például http://schemas.xmlsoap.org/soap/envelope/) egy, a névteret leíró Schema dokumentum. Ez a meghatározás azonban nem kötelező érvényű - a névtérnek még csak URL-nek sem kell lennie -, de a teljesség kedvéért ezt alkalmazzák.

A névterek ugyanazt a szerepet töltik be az XML-ben, amit más programozási nyelvekben: Segítenek elkerülni az ütközéseket két megvalósítás neve között. Vegyük a legfelső szintű címkét (<soap-env:Envelope>). Az Envelope tulajdonságnév eszerint a soap-env névtérben található. Így hát, ha a FedEX valamilyen okból egy XML formátumot határoz meg, amely az Envelope tulajdonságot használja, ezt nyugodtan megteheti a teljes <FedEX:Envelope> névvel, és semmi baj nem történik.

A SOAP Envelope-on belül négy névtér létezik:
  • xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" - A SOAP boríték Schema meghatározása leírja az alapvető SOAP objektumokat - ez a névtér szerepel minden SOAP kérelemben.
  • xmlns:xsi="http://www.w3.org/21/XMLSchema-instance" - Az xsi:type elemtulajdonság gyakran használatos az elemek típusának megadásánál.
  • xmlns:xsd="http://www.w3.org/21/XMLSchema" - A Schema megad néhány alapvető adattípust, melyeket adataink meghatározásánál és az ellenőrzésnél használhatunk.
  • xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding" - Ez a típuskódolások meghatározása, melyek a szabványos SOAP kérelmekben megjelennek.
A <GetQuote> elem szintén egy névtérben található - ez esetben egy meglehetősen hosszú nevűben:
http://www.themindelectric.com/wsdl/net.xmethods.services.stockquote.StockQuote
Figyeljük meg a Schema használatát a tőzsdei azonosító típusmeghatározásában és elrendezésében:
  1. <symbol xsi:type="xsd:string">ibm</symbol>  
A <symbol> karakterlánc típusú.

Hasonlóan, a válaszban is látható az árfolyam típusának meghatározása:
  1. <Result xsi:type="xsd:float">90.25</Result>  
Itt láthatjuk, hogy az eredmény egy lebegőpontos szám. Mindez hasznunkra lehet, hiszen a Schema érvényességi eszközeivel ellenőrizhetjük dokumentumunkat. Így például, ha a válasz a következő alakban érkezik, érvénytelennek tekintik, mivel a foo nem érvényes lebegőpontos szám:
  1. <Result xsi:type="xsd:float">foo</Result>  

WSDL

A SOAP méltó párja a WSDL (Web Services Description Language - webszolgáltatás-leíró nyelv). Ez egy XML alapú nyelv, ami kifejezetten arra szolgál, hogy a webszolgáltatások (leggyakrabban a SOAP) lehetőségeit és tagfüggvényeit leírjuk. Íme egy WSDL fájl, amely a korábban már alkalmazott tőzsdei szolgáltatás leírását adja:
  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2. <definitions name="net.xmethods.services.stockquote.StockQuote"  
  3.   targetNamespace"http://www.themindelectric.com/wsdl/net.xmethods.services.stockquote.   StockQuote/"  
  4.   xmlns:tns"http://www.themindelectric.com/wsdl/net.xmethods.services.stockquote.   StockQuote/"  
  5.   xmlns:electric="http://www.themindelectric.com/"  
  6.   xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"  
  7.   xmlns:xsd="http://www.w3.org/2001/XMLSchema"  
  8.   xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"  
  9.   xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/">  
  10.   <message name="getQuoteResponse1">  
  11.     <part name="Result" type="xsd:float" />  
  12.   </message>  
  13.   <message name="getQuoteRequest1">  
  14.     <part name="symbol" type="xsd:string" />  
  15.   </message>  
  16.   <portType name="net.xmethods.services.stockquote.StockQuotePortType">  
  17.     <operation name="getQuote" parameterOrder="symbol">  
  18.       <input message="tns:getQuoteRequest1" />  
  19.       <output message="tns:getQuoteResponse1" />  
  20.     </operation>  
  21.   </portType>  
  22.   <binding name="net.xmethods.services.stockquote.StockQuoteBinding"  
  23.     type="tns:net.xmethods.services.stockquote.StockQuotePortType">  
  24.     <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />  
  25.     <operation name="getQuote">  
  26.       <soap:operation soapAction="urn:xmethods-delayed-quotes#getQuote" />  
  27.       <input>  
  28.         <soap:body use="encoded" namespace="urn:xmethods-delayed-quotes"  
  29.           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />  
  30.       </input>  
  31.       <output>  
  32.         <soap:body use="encoded" namespace="urn:xmethods-delayed-quotes"  
  33.           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />  
  34.       </output>  
  35.     </operation>  
  36.   </binding>  
  37.   <service name="net.xmethods.services.stockquote.StockQuoteService">  
  38.     <documentation>  
  39.       net.xmethods.services.stockquote.StockQuote web service  
  40.     </documentation>  
  41.     <port name="net.xmethods.services.stockquote.StockQuotePort"  
  42.       binding="tns:net.xmethods.services.stockquote.StockQuoteBinding">  
  43.       <soap:address location="http://66.28.98.121:9090/soap" />  
  44.     </port>  
  45.   </service>  
  46. </definitions>  
Látható, hogy a WSDL sem takarékoskodik a névterek használatával, szerkezete pedig kissé felrúgni látszik a logika szabályait.

A kód első vizsgálatra érdemes része a <portType> címke, amely meghatározza a végrehajtható műveleteket, valamint a ki- és bevitt üzeneteket. Esetünkben a getQuote műveletet adja meg, amely a getQuoteRequest1 kérelmet fogadja, és a getQuoteResponse1 választ adja vissza.

A getQuoteResponse1 <message> címkéi szerint tartalma egyetlen, float típusú Result elem. Hasonlóképpen, a getQuoteRequest1 egyetlen string típusú symbol elemet tartalmaz.

Következik a <binding> címke. A <portType>-hoz a type tulajdonságon keresztül kapcsolódik egy kötés, amely megegyezik a <portType> nevével. A kötések a protokoll és az adatátvitel tulajdonságait határozzák meg (például a SOAP üzenet törzsében elhelyezett adatok kódolását), de a címeket nem. Egy kötés egyetlen protokollhoz tartozhat - esetünkben a HTTP-hez, kapcsolatukat az alábbi kód adja meg:
  1. <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />  
Végezetül, a <service> címke felsorol néhány kaput, és címeket határoz meg számukra. Mivel esetünkben csak egyetlen kaput használunk, a következő kóddal hivatkozunk rá és kötjük a http://66.28.98.121:9090/soap címhez:
  1. <port name="net.xmethods.services.stockquote.StockQuotePort"  
  2.   binding="tns:net.xmethods.services.stockquote.StockQuoteBinding">  
  3.   <soap:address location="http://66.28.98.121:9090/soap" />  
  4. </port>  
Érdemes megjegyeznünk, hogy semmi sem köti a SOAP-ot a HTTP protokollhoz, és választ sem kell feltétlenül visszaadnia. Ez egy rugalmas, általános célú protokoll, melynek a HTTP felett működő RPC csak egyik megvalósítása. A WSDL fájl arról tájékoztat, hogy milyen szolgáltatások érhetők el, és ezt hogyan és hogyan férhetünk hozzájuk. A kérelmet és a választ ezután a SOAP valósítja meg.

Szerencsére a PEAR SOAP osztályai elvégzik a munka nagyobb részét. Egy SOAP kérelem kiadásához először egy új SOAP_Client ügyfélobjektumot kell készítenünk, és át kell adnunk a WSDL fájlt az elérni kívánt szolgáltatásokkal. A SOAP_Client ezután elkészíti az összes szükséges helyettes kódot a közvetlenül végrehajtott kérelmekhez, legalábbis olyan esetekben, amikor az adatok mind egyszerű Schema típusoknak feleltethetők meg. Az alábbiakban bemutatunk egy teljes ügyfélkérelmet az xmethods.net tőzsdei szolgáltatásához:
  1. <?php  
  2. require_once "SOAP/Client.php";  
  3. $url = "http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl";  
  4. $soapclient = new SOAP_Client($url, true);  
  5. $price = $soapclient->getQuote("ibm")->deserializeBody();  
  6. print "Current price of IBM is $price\n";  
  7. ?>  
A SOAP_Client ezután átvállalja a helyettes objektum készítésének terhét, mellyel közvetlenül futtathatjuk a WSDL-ben megadott tagfüggvényeket. A getQuote() hívását követően a rendszer kicsomagolja az eredményt, és a PHP saját típusaiba írja a deserializeBody() segítségével. A futtatáskor az alábbi eredményt kapjuk:

> php delayed-stockquote.php
Current price of IBM is 90.25

A sysem.load átírása SOAP szolgáltatássá

SOAP programozói tudásunkat nyomban próbára is tehetjük - kíséreljük meg SOAP alatt megvalósítani az XML-RPC sysem.load szolgáltatását.

Először is, SOAP szolgáltatásunkat a SOAP_Service különleges célú változataként kell megvalósítanunk. Ehhez legalább az alábbi négy függvény megvalósítására szükség van:
  • public static function getSOAPServiceNamespace(){} - Vissza kell adnunk az általunk meghatározott szolgáltatás névterét.
  • public static function getSOAPServiceName(){} - Vissza kell adnunk szolgáltatásunk nevét.
  • public static function getSOAPServiceDescription(){} - Vissza kell adnunk szolgáltatásunk leírását egy karakterlánc alakjában.
  • public static function getWSDLURI(){} - Vissza kell adnunk a szolgáltatást leíró WSDL fájl URL-jét.
Ezeken felül természetesen meg kell határoznunk saját tagfüggvényeinket is.

Íme az új SOAP SystemLoad megvalósítás osztályának meghatározása:
  1. <?php   
  2. require_once 'SOAP/Server.php';  
  3.   
  4. class ServerHandler_SystemLoad implements SOAP_Service {  
  5.   public static function getSOAPServiceNamespace()  
  6.     { return 'http://example.org/SystemLoad/'; }  
  7.   public static function getSOAPServiceName()  
  8.     { return 'SystemLoadService'; }  
  9.   public static function getSOAPServiceDescription()  
  10.     { return 'Return the one-minute load avergae.'; }  
  11.   public static function getWSDLURI()  
  12.     { return 'http://localhost/soap/tests/SystemLoad.wsdl'; }  
  13.     
  14.   public function SystemLoad()  
  15.   {  
  16.     $uptime = `uptime`;  
  17.     if(preg_match("/load averages?: ([\d.]+)/"$uptime$matches)) {  
  18.       return array'Load' => $matches[1]);  
  19.     }  
  20.   }  
  21. }  
  22. ?>  
Az XML-RPC-től eltérően a SOAP_Service tagfüggvények paramétereiket hagyományos PHP változók alakjában kapják meg. Visszatéréskor mindössze a válaszüzenet patamétereinek tömbjét kell megadnunk. A névterek választásánál szabad kezet kapunk, de a rendszer ellenőrzi azokat a megadott WSDL fájl alapján, így egymással összhangban kell legyenek.

Ha meghatároztunk egy szolgáltatást, az XML-RPC-hez hasonlóan be kell jegyeztetnünk. A következő példában készítünk egy új SOAP_Server objektumot, csatoljuk az új szolgáltatást, és utasítjuk a kiszolgálópéldányt a bejövő kérelmek kezelésére:
  1. <?php  
  2. $server = new SOAP_Server;  
  3. $service = new ServerHandler_System_Load;  
  4. $server->addService($service);  
  5. $server->service('php://input');  
  6. ?>  
Van tehát egy teljes értékű kiszolgálónk, de nincs még meg a WSDL fájl, melyből az ügyfelek megtudhatnák, hogyan férhetnek hozzá ehhez a kiszolgálóhoz. Ennek elkészítése nem nehéz feladat - csak sok időbe telik. Lássuk, milyen eredményre számíthatunk:
  1. <?xml version='1.0' encoding='UTF-8'?>  
  2. <definitions name='SystemLoad'  
  3.   targetNamespace='http://example.org/SystemLoad/'  
  4.   xmlns:tns='http://example.org/SystemLoad/'  
  5.   xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/'  
  6.   xmlns:xsd='http://www.w3.org/2001/XMLSchema'  
  7.   xmlns:soapenc='http://schemas.xmlsoap.org/soap/encoding/'  
  8.   xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/'  
  9.   xmlns='http://schemas.xmlsoap.org/wsdl/'>  
  10.   <message name='SystemLoadResponse'>  
  11.     <part name='Load' type='xsd:float'/>  
  12.   </message>  
  13.   <message name='SystemLoadRequest'/>  
  14.   <portType name='SystemLoadPortType'>  
  15.     <operation name='SystemLoad'>  
  16.       <input message='tns:SystemLoadRequest'/>  
  17.       <output message='tns:SystemLoadResponse'/>  
  18.     </operation>  
  19.   </portType>  
  20.   <binding name='SystemLoadBinding' type='tns:SystemLoadPortType'>  
  21.     <soap:binding style='rpc' transport='http://schemas.xmlsoap.org/soap/http'/>  
  22.     <operation name='SystemLoad'>  
  23.       <soap:operation soapAction='http://example.org/SystemLoad/'/>  
  24.       <input>  
  25.         <soap:body use='encoded'  
  26.           namespace='http://example.org/SystemLoad/'  
  27.           encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>  
  28.       </input>  
  29.       <output>  
  30.         <soap:body use='encoded'  
  31.           namespace='http://example.org/SystemLoad/'  
  32.           encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>  
  33.       </output>  
  34.     </operation>  
  35.   </binding>  
  36.   <service name='SystemLoadService'>  
  37.     <documentation>System Load web service</documentation>  
  38.     <port name='SystemLoadPort' binding='tns:SystemLoadBinding'>  
  39.       <soap:address location='http://localhost/soap/tests/SystemLoad.php'/>  
  40.     </port>  
  41.   </service>  
  42. </definitions>  
Nos, itt nem sok újdonság bukkant fel. Figyeljük meg, hogy a névterek egybecsengenek azzal, amit a ServerHandler_SystemLoad-nál láthattunk, továbbá a SystemLoad prototípusa szerint egy Load nevű lebegőpontos számmal tér vissza.

A szolgáltatáshoz tartozó ügyfél hasonlít a tőzsdés példában látotthoz:
  1. <?php  
  2. include("SOAP/Client.php");  
  3. $url = "http://localhost/soap/tests/SystemLoad.wsdl";  
  4. $soapclient = new SOAP_Client($url, true);  
  5. $load = $soapclient->SystemLoad()->deserializeBody();  
  6. print "One minute system load is $load\n";  
  7. ?>  

Amazon webszolgáltatások és összetett típusok

A SOAP egyik legnagyobb előnye az XML-RPC-vel szemben, hogy támogatja a felhasználók által meghatározott típusokat, melyeket a Schema segítségével készíthetnek el és ellenőrizhetnek. A PEAR SOAP-megvalósítása pedig képes automatikusan átírni e saját változókat a PHP típusaira.

Mindennek bemutatására lássuk, miként kereshetünk meg egy szerzőt az Amazon.com webszolgáltatási API-jával. Az Amazon nagy hangsúlyt fektet webszolgáltatásainak megfelelő működésére, és elérhetővé teszi minden keresési lehetőségét a SOAP-on keresztül. Az Amazon API használatához fejlesztőként kell bejegyeztetnünk magunkat az Amazon webhelyén, a http://www.amazon.com/gp/aws/landing.html címen. Ha belepillantunk az Amazon WSDL fájljába, láthatjuk, hogy a szerző keresésének művelete az alábbi blokkban található (http://soap.amazon.com/schemas2/Amazon-WebServices.wsdl):
  1. <operation name="AuthorSearchRequest">  
  2.   <input message="typens:AuthorSearchRequest" />  
  3.   <output message="typens:AuthorSearchResponse" />  
  4. </operation>  
A kimeneti és bemeneti üzenetek típusát itt az alábbiak szerint határozzák meg:
  1. <message name="AuthorSearchRequest">  
  2.   <part name="AuthorSearchRequest" type="typens:AuthorRequest" />  
  3. </message>  
és
  1. <message name="AuthorSearchResponse">  
  2.   <part name="return" type="typens:ProductInfo" />  
  3. </message>  
Mindkettő saját, a Schema-ban meghatározott típus. Íme az AuthorRequest típusos meghatározása:
  1. <xsd:complexType name="AuthorRequest">  
  2.   <xsd:all>  
  3.     <xsd:element name="author" type="xsd:string" />  
  4.     <xsd:element name="page" type="xsd:string" />  
  5.     <xsd:element name="mode" type="xsd:string" />  
  6.     <xsd:element name="tag" type="xsd:string" />  
  7.     <xsd:element name="type" type="xsd:string" />  
  8.     <xsd:element name="devtag" type="xsd:string" />  
  9.     <xsd:element name="sort" type="xsd:string" minOccurs="0" />  
  10.     <xsd:element name="variations" type="xsd:string" minOccurs="0" />  
  11.     <xsd:element name="locale" type="xsd:string" minOccurs="0" />  
  12.   </xsd:all>  
  13. </xsd:complexType>  
Ahhoz, hogy ezt a típust PHP-ben is megjeleníthessük, készítenünk kell egy erre a célra szolgáló osztályt, amely a SchemaTypeInfo felületet is megvalósítja. Ehhez két műveletet kell megírnunk:
  • public static function getTypeName() {} - Visszaadja a típus nevét.
  • public static function getTypeNamespace() {} - Visszaadja a típus névterét.
Esetünkben az osztály egyszerűen a tulajdonságok tárolójaként viselkedik. Mivel ezek a Schema alaptípusai, nincs szükség további erőfeszítésre.

Lássuk tehát az AuthorRequest burkolóosztályát:
  1. <?php  
  2. class AuthorRequest implements SchemaTypeInfo {  
  3.   public $author;  
  4.   public $page;  
  5.   public $mode;  
  6.   public $tag;  
  7.   public $type;  
  8.   public $devtag;  
  9.   public $sort;  
  10.   public $variations;  
  11.   public $locale;  
  12.     
  13.   public static function getTypeName()  
  14.     { return 'AuthorRequest';}  
  15.   public static function getTypeNamespace()  
  16.     { return 'http://soap.amazon.com';}  
  17. }  
A szerző szerinti keresés megvalósításához először készítenünk kell egy SOAP_Client helyettes objektumot az Amazon WSDL fájlból:
  1. <?php  
  2. require_once 'SOAP/Client.php';  
  3. $url = 'http://soap.amazon.com/schemas2/AmazonWebServices.wsdl';  
  4. $client = new SOAP_Client($url, true);  
  5. ?>  
Ezután hozzunk létre egy AuthorRequest objektumot, és töltsük fel a keresés adataival:
  1. <?php  
  2. $authreq = new AuthorRequest;  
  3. $authreq->author = 'schlossnagle';  
  4. $authreq->mode = 'books';  
  5. $authreq->type = 'lite';  
  6. $authreq->devtag = 'DEVTAG';  
  7. ?>  
Az eredményt a ProductInfo típusban kapjuk vissza, ami túlzottan összetett ahhoz, hogy a felépítésével itt foglalkozzunk. Mindazonáltal az alábbi rövid kóddal gyorsan utánajárhatunk, mely könyvek szerzőit hívták Schlossnagle-nek:
  1. <?php  
  2. $result = $client->AuthorSearchRequest($authreq)->deserializeBody();  
  3. foreach ($result->Details as $detail) {  
  4.   print "Title: $detail->ProductName, ASIN: $detail->Asin\n";  
  5. }  
  6. ?>  
Futtatása után az alábbi eredményt kapjuk:

Title: Advanced PHP Programming, ASIN: 0672325616

Helyettes kód készítése

Nem nehéz feladat olyan kódot írni, ami dinamikusan elkészíti a helyettes (proxy) objektumokat a WSDL-ből, de ez a folyamat meglehetősen sok értelmezési munkával jár, amit jobb elkerülni, különösen, ha egy webszolgáltatást gyakran hívnak. A SOAP WSDLkezelője képes elkészíteni a PHP kódot, így közvetlenül is lebonyolíthatjuk a hívásokat, anélkül, hogy újra és újra át kellene vizsgálni a WSDL fájlt.

A helyettes kód elkészítésének érdekében töltsük be az URL-t az MSDLManager::get() tagfüggvénnyel, és hívjuk meg a generateProxyCode() függvényt. Mindezt most a SystemLoad WSDL fájl példáján mutatjuk be:
  1. <?php  
  2. require_once 'SOAP/WSDL.php';  
  3. $url = "http://localhost/soap/tests/SystemLoad.wsdl";  
  4. $result = WSDLManager::get($url);  
  5. print $result->generateProxyCode();  
  6. ?>  
A futtatás után az alábbi kódhoz jutunk:
  1. <?php  
  2. class WebService_SystemLoadService_SystemLoadPort extends SOAP_Client {  
  3.   public function __construct()  
  4.   {  
  5.     parent::_ _construct("http://localhost/soap/tests/SystemLoad.php", 0);  
  6.   }  
  7.   function SystemLoad()  
  8.   {  
  9.     return $this->call("SystemLoad",  
  10.                        $v = array(),  
  11.                  array('namespace'=>'http://example.org/SystemLoad/',  
  12.                        'soapaction'=>'http://example.org/SystemLoad/',  
  13.                        'style'=>'rpc',  
  14.                        'use'=>'encoded' ));  
  15.   }  
  16. }  
Mostantól a WSDL fájl értelmezése helyett közvetlenül ezt az osztályt hívhatjuk.

A SOAP és az XML-RPC összehasonlítása

Melyik RPC protokollt alkalmazzuk - a SOAP vagy az XML-RPC mellett tegyük le voksunkat? Nos, sok esetben a körülmények nem hagynak túlzottan nagy mozgásteret. Ha olyan szolgáltatást valósítunk meg, ami meglevő ügyfelekkel vagy kiszolgálókkal érintkezik, elvesztjük a döntés lehetőségét. Így a SOAP felület használata webnaplónkban érdekes kísérlet lehet, de valószínűleg nem képes együttműködni más, már eleve meglevő eszközökkel. Ha az Amazon vagy a Google API-jaival szeretnénk együttműködni, ismét csak egyértelmű a válasz: a SOAP-ot kell használnunk.

Ha azonban új szolgáltatást telepítünk, és szabad kezet kapunk a választásban, az alábbiakat érdemes megfontolnunk:
  • A megvalósítás szemszögéből nézve az XML-RPC sokkal kevesebb kezdeti erőfeszítést igényel, mint a SOAP.
  • Az XML-RPC kisebb dokumentumokat készít, melyek értelmezése kevésbé költséges, mint a SOAP-pal készítetteké.
  • A SOAP lehetővé teszi a Schema segítségével meghatározott saját típusok használatát. Ez módot ad az adatok érvényességének hatékonyabb ellenőrzésére, valamint az automatikus típusátalakításra az XML és a PHP között. Az XML-RPC-ben mindenféle összetettebb adatcsomagolást kézzel kell elvégeznünk.
  • A WSDL nagyszerű eszköz. A SOAP automatikus felderítési és helyetteskód-készítési képességei jobbak az XML-RPC-ben elérhetőknél.
  • A SOAP jelentős támogatást kap az IBM-től, a Microsofttól, valamint számos, a sikerében érdekelt internetes vállalattól. Mindez azt jelenti, hogy e cégek a múltban és a jövőben is jelentős anyagi erőforrásokat és időt szentelnek arra, hogy javítsák a SOAP együttműködési készségét és a SOAP-hoz kötődő segédeszközöket fejlesszenek.
  • A SOAP általános, bővíthető eszköz, míg az XML-RPC célirányos protokoll, viszonylag merev meghatározással.
Az XML-RPC-t vonzóan egyszerű megoldásnak tartom olyankor, amikor a megvalósítandó RPC mindkét oldala felett befolyásom van. Ilyen esetekben a helyes automatikus felderítés és a helyettes kód készítésének hiánya nem okoz fejfájást. Ha azonban olyan szolgáltatást telepítek, melyet mások is támogatnak, mindenképpen a SOAP választását tartom jobbnak széleskörű támogatottsága és hatékony segédeszközei miatt.

További olvasmányok

A távoli szolgáltatásokkal való együttműködés témaköre igen széles, sokkal szélesebb annál, mint amennyit e fejezet átfogni képes. A SOAP különösen érdekes, fejlődő szabvány; maga is megérdemelne egy külön könyvet. A következőkben néhány hasznos forrásmunkát mutatunk be, témakörök szerint csoportosítva.

SOAP

A SOAP leírása megtalálható a http://www.w3.org/TR/SOAP/ címen.

A http://www.soapware.org/bdg nagyszerű bevezetést ad a SOAP használatába.

Shane Caraveo webszolgáltatásokról adott előadásainak anyaga a http://talks.php.net címen segít megérteni, mi szükséges a SOAP sikeres használatához a PHP-ben. Jó tudnunk, hogy Shane a PHP 5 SOAP-megvalósításának vezető fejlesztője.

XML-RPC

Az XML-RPC leírása megtalálható a http://www.xmlrpc.com/spec címen.

Dave Winer, az XML-RPC megalkotója egy kellemes bevezető írását a következő címen lelhetjük meg: http://davenet.scripting.com/1998/07/14/xmlRpcForNewbies.

Webnaplózás

A Blogger API leírását a http://www.blogger.com/developers/api/1_docs címen találhatjuk meg.

A MetaWeblog API leírása a http://www.xmlrpc.com/metaWeblogApi címen található.

A MovableType bővítményeket kínál mind a MetaWeblog, mind a Blogger API-hez. Leírásuk a http://www.movabletype.org/docs/mtmanual_programmatic.html címen megtalálható.

Az RSS egy nyílt XML formátum tartalom-közzétételhez. Leírását a http://blogs.law.harvard.edu/tech/rss címen lelhetjük meg.

Az XML-RPC példáinkban szereplő Serendipity webnaplózó rendszer a http://www.s9y.org címen érhető el.

Nyilvánosan elérhető webszolgáltatások

A http://xmethods.net kifejezetten a webszolgáltatások fejlesztéséhez (elsősorban a SOAP és a WSDL alkalmazásokhoz) nyújt segítséget. Itt ingyenesen elérhető webszolgáltatások garmadáját találhatjuk, a szerkesztők pedig az együttműködési képességek próbára tételére hívnak fel.

Az Amazon rendelkezik egy szabad SOAP felülettel. A részletekről a http://www.amazon.com/gp/aws/landing.html címen érdeklődhetünk.

A Google is rendelkezik szabad SOAP keresőfelülettel. Erről a http://www.google.com/apis címen olvashatunk.

Zárszó

Kétrészes sorozatunk a PHP fejlesztés felsőfokon című könyvből ezennel végetért. Aki kíváncsi a folytatásra, illetve a könyv más érdekes tippjeire, az mindenképpen látogasson el egy közeli könyvesboltba, és lapozzon bele a könyvbe élőben is.