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.

IOT

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
120na80.cz: Superpotraviny. Jaké to jsou?

Superpotraviny. Jaké to jsou?

Podnikatel.cz: Prodá jen 15 obědů denně. Co dělá špatně?

Prodá jen 15 obědů denně. Co dělá špatně?

120na80.cz: Pánové, odřené bradavky při běhu nejsou nutné

Pánové, odřené bradavky při běhu nejsou nutné

Vitalia.cz: Vědci: Svět vegetariánů by byl zdravější, bohatší a...

Vědci: Svět vegetariánů by byl zdravější, bohatší a...

Vitalia.cz: Maurer: Nechci Jamieho Olivera za pět miliónů

Maurer: Nechci Jamieho Olivera za pět miliónů

Podnikatel.cz: Když si reklamou "zabíjíte" zákazníky

Když si reklamou "zabíjíte" zákazníky

Vitalia.cz: Podmínky pro dárcovství kostní dřeně

Podmínky pro dárcovství kostní dřeně

Podnikatel.cz: Google PageRank nadobro zmizel

Google PageRank nadobro zmizel

Podnikatel.cz: Poděs, Slibotechna a další. Ty berte obloukem

Poděs, Slibotechna a další. Ty berte obloukem

Podnikatel.cz: Upravuje se použití paušálních výdajů

Upravuje se použití paušálních výdajů

Podnikatel.cz: Stahujte přehledy pro všechny pojišťovny

Stahujte přehledy pro všechny pojišťovny

Vitalia.cz: Asijský LI-WU vařil z prošlého masa

Asijský LI-WU vařil z prošlého masa

Lupa.cz: Jaký je Průvodce světem Arduina?

Jaký je Průvodce světem Arduina?

Lupa.cz: Státní ICT systémy musí být „opendata ready“

Státní ICT systémy musí být „opendata ready“

DigiZone.cz: Přechod na DVB-T2 nabírá zpoždění

Přechod na DVB-T2 nabírá zpoždění

Lupa.cz: Další útok: po webu ČSSD je pod palbou i ČTK

Další útok: po webu ČSSD je pod palbou i ČTK

Vitalia.cz: Tyhle dorty se prostě nepovedly

Tyhle dorty se prostě nepovedly

120na80.cz: Konopí: každá rostlina je jinak účinná

Konopí: každá rostlina je jinak účinná

DigiZone.cz: Böhmen und Mähren v režii Ondřeje Trojana

Böhmen und Mähren v režii Ondřeje Trojana

Vitalia.cz: 7 situací, kdy ženy škodí svým ňadrům

7 situací, kdy ženy škodí svým ňadrům

Ušetřete