Hlavní navigace

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

10. 8. 2007
Doba čtení: 4 minuty

Sdílet

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.

root_podpora

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.

Který protokol webových služeb preferujete?

Byl pro vás článek přínosný?

Autor článku

Autor se živí programováním v PHP, podílí se na jeho oficiální dokumentaci, vyučuje ho na MFF UK a vede odborná školení. Poznámky si zapisuje na weblog PHP triky.