Webové služby v PHP: XML-RPC a SOAP

Jakub Vrána 10. 8. 2007

Koncept webových služeb umožňuje protokolem HTTP volat funkce na vzdáleném serveru, předávat jim parametry a pracovat s vrácenými výsledky. Je přitom úplně jedno, v jakém programovacím jazyce je webová služba napsaná i z jakého jazyka ji voláme. Rozdíly se smývají ve formátu výměny dat, kterým je obvykle XML.

Webové služby lze použít všude tam, kde potřebujeme partnerům předávat nějaká data nebo tato data naopak získávat. Může jít o seznam produktů, aktuální počasí, výsledky vyhledávání, …

Jako protokol pro práci s webovými službami se nejčastěji používá buď jednodušší XML-RPC, nebo komplexnější SOAP. K webové službě v protokolu SOAP lze navíc připojit tzv. WSDL dokument, který popisuje veškerou funkčnost webové služby, a ze kterého tedy můžeme zjistit, jaké funkce s jakými parametry a jakou návratovou hodnotou lze přes tuto webovou službu volat.

Požadavky a odpovědi můžeme zpracovávat stejně jako jakékoliv XML, PHP navíc pro oba nejběžnější druhy služeb nabízí extenze, které nás od přenosového formátu zcela odstíní: XML-RPC a SOAP (v PHP 4 lze použít knihovnu NuSOAP). V tomto článku si ukážeme, jak lze vytvářet požadavky v obou protokolech. Poměrně jednoduše lze na požadavky i odpovídat (vytvořit server), tomu se tento článek ale nevěnuje.

XML-RPC

Extenze XML-RPC pracuje na nižší úrovni a poskytuje pouze základní funkce zakódování požadavku a jeho dekódování. O samotné zavolání se musíme postarat sami:

<?php
/** Položení XML-RPC požadavku
* @param string $url URL webové služby
* @param string $method funkce, která se má zavolat
* @param string $params parametry, které se mají funkci předat
* @param string [$encoding] kódování odpovědi, výchozí je utf-8
* @return mixed data vrácená funkcí
*/
function xmlrpc($url, $method, $params, $encoding = 'utf-8') {
    $context = stream_context_create(array('http' => array(
        'method' => "POST",
        'header' => "Content-Type: text/xml",
        'content' => xmlrpc_encode_request($method, $params, array('encoding' => $encoding))
    )));
    return xmlrpc_decode(file_get_contents($url, false, $context), $encoding);
}
?> 

Funkce předpokládá zapnutou direktivu allow_url_fopen, která dovoluje pracovat se vzdálenými soubory. Pokud je tento požadavek splněn, dá se s XML-RPC pomocí této funkce velice jednoduše pracovat, jinak je potřeba funkci přepsat buď na extenzi CURL nebo na funkci fsockopen.

SOAP

Extenze SOAP umožňuje pracovat na vyšší úrovni a po zaregistrování webové služby už můžeme přímo volat její funkce. Práci s touto extenzí si ukážeme na službě Live Search, která nabízí vyhledávání přes protokol SOAP. Pro použití této služby se musíme zaregistrovat, čímž získáme klíč umožňující položení až 25 000 dotazů denně. Díky připravenému WSDL dokumentu můžeme službu začít ihned používat.

Nejprve zjistíme, jaké funkce můžeme používat. To lze zjistit buď z dokumentace nebo přímo z WSDL dokumentu:

<?php
$soap = new SoapClient('http://soap.search.msn.com/webservices.asmx?wsdl');
print_r($soap->__getFunctions()); // array('SearchResponse Search(Search $parameters)')
?> 

Dozvíme se, že existuje jediná funkce Search s parametrem typu Search a návratovou hodnotou typu SearchResponse. Co jednotlivé typy znamenají, můžeme zjistit zavoláním funkce SoapClient::__get­Types. Dozvíme se, že typ Search je struktura s jediným prvkem Request typu SearchRequest. SearchRequest je zase struktura s prvky jako AppID (náš klíč), Query (dotaz, který pokládáme), CultureInfo (informace o jazyku a místu vyhledávání, hodnota cs-CZ ale bohužel zatím není podporována) nebo Requests (oblast, kterou chceme prohledávat). V PHP se struktury předávají buď jako objekty s odpovídajícími vlastnostmi nebo jednoduše jako asociativní pole:

<?php
define("LIVE_APP_ID", "zaregistrovaný identifikátor aplikace");
$limit = 10;
$site = "php.vrana.cz";
$query = $_GET["query"];

$soap = new SoapClient('http://soap.search.msn.com/webservices.asmx?wsdl');
$SourceRequest = array(
    "Source" => "Web",
    "Offset" => intval($_GET["offset"]),
    "Count" => $limit,
    "ResultFields" => "All",
);
$Search = array(
    "AppID" => LIVE_APP_ID,
    "Query" => "site:$site $query",
    "CultureInfo" => "en-US",
    "SafeSearch" => "Off",
    "Flags" => "None",
    "Requests" => array("SourceRequest" => $SourceRequest),
);
$SearchResponse = $soap->Search(array("Request" => $Search));
?> 

Použití výsledků vyhledávání záleží na naší fantazii – můžeme ho použít pro prohledávání na vlastních stránkách (přidáním operátoru site: přímo do dotazu) nebo třeba pro pravidelné zjišťování pozice našich stránek na vybrané dotazy (to se dá udělat i přímým rozebráním stránky s výsledky, použití webové služby je ale spolehlivější a hlavně v souladu s licencí).

Funkce Search vrátí hlubokou strukturu s výsledky pro jednotlivé zdroje vyhledávání (kromě webu lze prohledávat i reklamy, obrázky, telefonní seznam, opravy překlepů, …). My prohledáváme pouze web, takže s výsledkem můžeme přímo pracovat:

<?php
$SourceResponse = $SearchResponse->Response->Responses->SourceResponse;
if (!$SourceResponse->Results->Result) {
    echo "<p>Nic nebylo nalezeno.</p>\n";
} else {
    echo "<dl>\n";
    foreach ($SourceResponse->Results->Result as $Result) {
        echo '<dt><a href="' . htmlspecialchars($Result->Url) . '">';
        echo htmlspecialchars($Result->Title) . "</a></dt><dd>";
        echo htmlspecialchars($Result->Description) . "</dd>\n";
    }
    echo "</dl>\n";
}
if ($SourceResponse->Total > $_GET["offset"] + $limit) {
    echo "<p><a href='?query=" . urlencode($query) . "&amp;offset=" . ($_GET["offset"] + $limit);
    echo "'>Další</a> z celkem $SourceResponse->Total.</p>\n";
}
?> 

Nalezené výsledky zobrazíme v seznamu, a pokud jich je hodně, zobrazíme odkaz na další stránku.

Závěr

Díky existujícím extenzím se v PHP s webovými službami pracuje velice pohodlně – jsme zcela odstíněni od přenosového formátu a jednoduše voláme funkce a zpracováváme výsledky podobně, jako to děláme s lokálními knihovnami.


Podobně laděné texty můžete najít i na autorově weblogu PHP triky.

Anketa

Který protokol webových služeb preferujete?

Ohodnoťte jako ve škole:

Průměrná známka 2,92

Našli jste v článku chybu?
Zasílat nově přidané názory e-mailem
Vitalia.cz: Tetanus v USA – i po odřeninách

Tetanus v USA – i po odřeninách

Lupa.cz: Válka e-shopů. Alza končí s Heurekou

Válka e-shopů. Alza končí s Heurekou

120na80.cz: Tady se vaří padělané léky

Tady se vaří padělané léky

Vitalia.cz: Syndrom počítačového vidění: stačí dvě hodiny denně

Syndrom počítačového vidění: stačí dvě hodiny denně

120na80.cz: Co lidi tropí se sádrou

Co lidi tropí se sádrou

Podnikatel.cz: Přechod z OSVČ na firmu? Totální šok!

Přechod z OSVČ na firmu? Totální šok!

Vitalia.cz: Ministerstvo: tyto příbory jsou nebezpečné

Ministerstvo: tyto příbory jsou nebezpečné

120na80.cz: 5 triků, jak zastavit krvácení po holení

5 triků, jak zastavit krvácení po holení

Vitalia.cz: Taky ji kupujete? Je šizená

Taky ji kupujete? Je šizená

Podnikatel.cz: Když už je sexy, tak ať taky funguje

Když už je sexy, tak ať taky funguje

Root.cz: Zákon o hazardu je v rozporu s ústavou

Zákon o hazardu je v rozporu s ústavou

Podnikatel.cz: Rošáda v živnostech. Týká se vás?

Rošáda v živnostech. Týká se vás?

Podnikatel.cz: Konečně vývar. Skoro jako od Steva Jobse

Konečně vývar. Skoro jako od Steva Jobse

120na80.cz: Poznáte, který z léků je pravý?

Poznáte, který z léků je pravý?

DigiZone.cz: Šlágr TV: pokuta 100 tisíc za on-line

Šlágr TV: pokuta 100 tisíc za on-line

DigiZone.cz: Konec geoblokace online médií?

Konec geoblokace online médií?

DigiZone.cz: UPC umí televizi sedm dní nazpět

UPC umí televizi sedm dní nazpět

Vitalia.cz: Mražené ryby z Makra byly falšované

Mražené ryby z Makra byly falšované

Vitalia.cz: Před, nebo po snídani? Kdy je lepší čistit si zuby

Před, nebo po snídani? Kdy je lepší čistit si zuby

Lupa.cz: Přenos hokeje padal kvůli útoku, tvrdí O2

Přenos hokeje padal kvůli útoku, tvrdí O2