API:Strategie implementace
| Tato stránka je součástí dokumentace k API Action MediaWiki. |
Vysvětluje implementaci MediaWiki API v jádru. Pokud chcete ve svém kódu poskytnout rozhraní API pro klienty k použití, přečtěte si API:Rozšíření.
Struktura souboru/modulu
api.phpje vstupní bod umístěný v kořenovém adresáři wiki. Viz API:Hlavní stránka#Koncový bod.ApiEntryPointis the implementation of the entry point (factored out in Gerrit change 959047).includes/apibude obsahovat všechny soubory související s API, ale žádný z nich nebude povolen jako vstupní bod.- Všechny třídy API jsou odvozeny od společné abstraktní třídy
ApiBase. Základní třída poskytuje běžné funkce, jako je analýza parametrů, profilování a zpracování chyb. ApiMainje hlavní třída vytvořená pomocíApiEntryPoint. Určuje, který modul se má spustit, na základě parametruaction=XXX.ApiMaintaké vytvoří instanci třídyApiResult, která obsahuje pole výstupních dat a související pomocné funkce. NakonecApiMainvytvoří instanci formátovací třídy, která klientovi vyvede data zApiResultve formátu XML/JSON/PHP nebo v jiném formátu.- Jakýkoli modul odvozený z
ApiBaseobdrží během vytváření instance odkaz na instanciApiMain, takže během provádění může modul získat sdílené prostředky, jako je výsledný objekt.
Moduly dotazů
ApiQueryse chová podobně jakoApiMainv tom, že spouští submoduly. Každý submodul je odvozen odApiQueryBase(kromě samotnéhoApiQuery, což je modul nejvyšší úrovně). Během vytváření instance obdrží submoduly odkaz na instanci ApiQuery.- Všechny moduly dotazů rozšíření by měly používat 3 nebo více písmenných předpon. Základní moduly používají 2 písmenné předpony.
- Realizační plán
ApiQuery:- Získejte sdílené parametry dotazu
list/prop/metak určení potřebných submodulů. - Vytvořte objekt
ApiPageSeta naplňte jej z parametrůtitles/pageids/revids. Objektpagesetobsahuje seznam stránek nebo revizí, se kterými budou moduly dotazů pracovat. - Na požádání se spustí modul generátoru k vytvoření dalšího
ApiPageSet. Podobné jako piping streams v UNIXu. Dané stránky jsou vstupem do generátoru, který vytváří další sadu stránek pro všechny ostatní moduly, na kterých mohou pracovat.
- Získejte sdílené parametry dotazu
- Požadavky na pokračování dotazu:
- SQL dotaz musí být zcela uspořádaný. Jinými slovy, dotaz musí používat všechny sloupce nějakého jedinečného klíče buď jako konstanty v klauzuli
WHEREnebo v klauzuliORDER BY.- V MySQL se jedná o exclusive or až do bodu, kdy se dotazování Foo a Bar musí řadit podle názvu, ale nikoli jmenného prostoru (jmenný prostor je konstantní 0), Foo a Talk:Foo se musí řadit podle jmenného prostoru, ale ne podle názvu (název je konstantní "Foo") a Foo a Talk:Bar se musí řadit podle jmenného prostoru i názvu.
- SQL dotaz nesmí řadit soubory.
- Hodnota přidělená
setContinueEnumParameter()musí zahrnovat všechny sloupce v klauzuliORDER BY. - Při pokračování by měla být do klauzule
WHEREpřidána jedna složená podmínka. Pokud má dotazORDER BY column_0, column_1, column_2, měla by tato podmínka vypadat nějak takto:
- SQL dotaz musí být zcela uspořádaný. Jinými slovy, dotaz musí používat všechny sloupce nějakého jedinečného klíče buď jako konstanty v klauzuli
(column_0 > value_0 OR (column_0 = value_0 AND (column_1 > value_1 OR (column_1 = value_1 AND (column_2 >= value_2) )) ))
Samozřejmě, vyměňte ">" za "<", pokud vaše sloupce ORDER BY používají DESC. Ujistěte se, že se v hodnotách vyhnete vkládání SQL.
Vnitřní datové struktury
- Query API má velmi úspěšnou strukturu jedné globální vnořené struktury
array(). Různé moduly by přidávaly kusy dat do mnoha různých bodů tohoto pole, až by je nakonec pro klienta vykreslila jedna z tiskáren (výstupní moduly). Pro rozhraní API doporučujeme zabalit toto pole jako třídu s pomocnými funkcemi pro připojení jednotlivých listových uzlů.
Hlášení chyb/stavu
Prozatím jsme se rozhodli zahrnout informace o chybě do stejného strukturovaného výstupu jako normální výsledek (možnost #2).
Ve výsledku můžeme buď použít standardní chybové kódy HTTP nebo vždy vrátit správně naformátovaná data:
- Pomocí HTTP kódu
void header( string reason_phrase [, bool replace [, int http_response_code]] )
header() lze použít k nastavení návratového stavu operace. Můžeme definovat všechny možné hodnoty reason_phrase, takže za neúspěšné přihlášení můžeme vrátit code=403 a phrase="BadPassword", zatímco v případě úspěchu bychom jednoduše vrátili odpověď beze změny hlavičky.
Výhody: Je to standard. Klient se vždy musí vypořádat s chybami HTTP, takže použití kódu HTTP pro výsledek by odstranilo jakékoli samostatné zpracování chyb, které by klient musel provést. Vzhledem k tomu, že klient může požadovat data ve více formátech, neplatný parametr formátu by byl stále správně zpracován, protože by to byl jednoduše další kód chyby http.
Nevýhody: ...
- Zahrnuje informace o chybě do správné odpovědi
Tato metoda by vždy vrátila správně formátovaný objekt odpovědi, ale chybový stav/popis budou jediné hodnoty uvnitř tohoto objektu. Je to podobné způsobu, jakým aktuální Query API vrací stavové kódy.
Výhody: Chybové kódy HTTP se používají pouze pro problémy se sítí, nikoli pro data (logické chyby). Nejsme vázáni na stávající kódy chyb HTTP.
Nevýhody: Pokud parametr formátu dat není správně zadán, jaký je formát výstupních dat? Aplikace musí objekt analyzovat, aby věděla o chybě (výkon?). Kód kontroly chyb bude muset být na úrovni připojení i analýzy dat.
Kód Boilerplate
Bylo navrženo, aby tato stránka nebo sekce byla sloučena s API:Extensions#ApiSampleApiExtension.php.(Diskuse) |
| Jednoduchý modul API |
|---|
<?php class Api<název modulu> extends ApiBase { public function __construct( $main, $action ) { parent::__construct( $main, $action ); } public function execute() { } public function getAllowedParams() { return array( '<název parametru>' => array( ApiBase::PARAM_TYPE => array( 'foo', 'bar', 'baz' ), ), ); } public function getParamDescription() { return array( '<název parametru>' => '<popis parametru>', ); } public function getDescription() { return '<Popis modulu zde>'; } public function getExamples() { return array( 'api.php?action=<název modulu>&<název parametru>=foo' ); } public function getHelpUrls() { return ''; } } |