If you are looking for english version of documentation, proceed directly to github.
Json Rpc 2
Kompletní RPC Klient/Server knihovna, pro komunikaci Nette aplikace s ostatními platformami, jako jsou mobilní aplikace či jiné instalace. Knihovna obsahuje automatické test-api a je dle specifikace json-rpc 2 (http://groups.google.com/…json-rpc-2-0?…)
| Verze | 1.0 |
|---|---|
| Github | foglcz/JSONRpc2 |
| Download 1.0 | https://github.com/…on%201.0.zip |
| Demo | – |
| Forum thread | http://forum.nette.org/…ent-a-server |
| Autor | Pavel Ptáček |
| Licence | New BSD |
Co je Json-Rpc 2
JSON-RPC verze 2 je specifikace, díky které je možné standartizovaně komunikovat mezi aplikacemi. Někteří z vás budou pamatovat SOAP → json-rpc2 je to samé, akorát postavené nad formátem JSON objektů, nikoliv nad XML jako je tomu u SOAP metod.
Komunikace se vždy skládá z request a response – ukázka komunikace by mohla vypadat takto:
--> {"jsonrpc": "2.0", "method": "odecist", "params": {"prvni": 23, "druhy": 42}, "id": 3}
<-- {"jsonrpc": "2.0", "result": 19, "id": 3}
--> {"jsonrpc": "2.0", "method": "odecist", "params": {"prvni": 42, "druhy": 23}, "id": 4}
<-- {"jsonrpc": "2.0", "result": 19, "id": 4}
Protokol je mnohem kompaktnější než je tomu u XML notace. Největší výhodou protokolu verze 2 je ale fakt, že je možné v rámci jednoho requestu zaslat více požadavků – a server na ně odpoví jednou response. Pro vykonání více funkcí nám tedy odpadá několik requestů, ale je možné vše zřetězit do jednoho:
--> [
{"jsonrpc": "2.0", "method": "sum", "params": [1,2,4], "id": "1"},
{"jsonrpc": "2.0", "method": "notify_hello", "params": [7]},
{"jsonrpc": "2.0", "method": "subtract", "params": [42,23], "id": "2"},
{"foo": "boo"},
{"jsonrpc": "2.0", "method": "foo.get", "params": {"name": "myself"}, "id": "5"},
{"jsonrpc": "2.0", "method": "get_data", "id": "9"}
]
<-- [
{"jsonrpc": "2.0", "result": 7, "id": "1"},
{"jsonrpc": "2.0", "result": 19, "id": "2"},
{"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request."}, "id": null},
{"jsonrpc": "2.0", "error": {"code": -32601, "message": "Method not found."}, "id": "5"},
{"jsonrpc": "2.0", "result": ["hello", 5], "id": "9"}
]
Pro více informací doporučuji buď specifikaci nebo příslušnou stránku na Wikipedii
Instalace Klient / Server
Instalace je jednoduchá – stáhněte .zip soubor (viz výše), rozbalte a nakopírujte obsah složky „lib“ do Vašeho projektu.
Doporučuji rovněž projít tento manuál step-by-step, nejde o nic složitého – spíše o „handy features.“
Rychlý start (klient)
Pokud již máte k dispozici server, který splňuje JSON-RPCv2 specifikaci, pak je nejjednodušší okamžitě začít vytvořením klienta a zavolání příslušné metody:
$client = new Lightbulb\Json\Rpc2\Client('http://example.com/rpc/json');
$user = $client->user->login('email@example.com', 'password');
// $user je nyní instance StdClass
Proč voláme user->login a co to dělá na pozadí? Klient i server předpokládají dělení aplikace do menších částí – uživatelské metody budou v „user“ class atp. Z pohledu klienta jde spíš o zjednodušení volání jednotlivých metod. Json-rpc metody jsou z principu vždy string, ale mohou obsahovat tečku.
A právě tečku v klientu i serveru nahrazujeme PHP „šipkou“. Volání vyššího příkazu tedy ve skutečnosti odeslalo požadavek na metodu „user.login“
Parametry metody vždy vycházejí z toho, jak je serverová část navržena. Proto budeme nadále pokračovat aspekty serverové aplikace, kde leží největší síla tohoto doplňku.
Rychlý start (server)
V rámci Nette aplikace budeme potřebovat Presenter, který se nám bude o obsluhu serverové části starat. Ten je možné najít například ve složce „example“ – nicméně pro skutečně rychlý start použijeme složku „test-suite.“
Postupujme tedy takto:
- Nakopírujte test-suite/JsonTestSuitePresenter.php do složky „presenters“ ve vašem Nette projektu
- Nakopírujte test-suite/jsonTestModule do složky „app“ ve vašem projektu
- Nakopírujte test-suite/jsonTest.css do složky „www/css“ ve vašem projektu
- Do bootstrap.php přidejte následující 3 cesty:
$router[] = new Route('rpc/test', 'jsonTest:Base:jsonAcessLogin');
$router[] = new Route('rpc/test/<presenter>[/<action=default>]', array('module' => 'jsonTest'));
$router[] = new Route('rpc/json', 'JsonTestSuite:default');
- Otevřete si adresu http://localhost/…ekt/rpc/test ve vašem prohlížeči. Měli by jste vidět něco podobného tomuto:

- Přihlašte se s uživatelským jménem „test“ a heslem „test“
Nyní jste se dostali do polo-generovaného test-suite. Jednotlivé presentery jsou v rámci složky „jsonTestModule“, o šablony se příliš starat nemusíte. Nás ale bude zajímat jiný soubor: a sice app/presenters/JsonTestSuitePresenter.php
Když si ho otevřeme, uvidíme presenter s jednou metodou „renderDefault.“ Z té metody nás ale zajímají pouze dva řádky – zbytek je stejný pro všechny instalace serverové části:
$server->access = new AccessHandler;
$server->user = new UserHandler;
Toto jsou dvě referenční implementace, které jsme vzali z našeho projektu, kde je tento doplněk použit pro komunikaci mezi Nette instalací a mobilní aplikací postavenou pro iPhone a Android telefony. Vycházíme z jednoduchého předpokladu, že do API mají přístup pouze přihlášení uživatelé – ale abychom neposílali uživatelská jména a hesla v rámci každého požadavku, používáme techniku Facebooku, kdy se uživatel přihlásí z telefonu pouze jednou, a aplikace nadále používá získaný access_token.
Tento předpoklad budeme používat i u dalších metod, které záhy implementujeme.
Login a logout
Nejdříve se zkusíme z test-suite přihlásit do API samotného. Klikněme tedy na odkaz „access.*“ a pokračujme do metody „access.login“. Následně by jsme měli vidět něco podobného:

Zde vyplníme e-mail a heslo – je jedno jaké – a klikneme na odeslat. Co se právě stalo? Odeslal se požadavek na náš „JsonTestSuitePresenter“, respektive server, který tento presenter obaluje. Ten nám vrátil vygenerovaný access_token.
Tento token byl následně uložen v session, abychom ho nemuseli neustále vyplňovat. Logika se nachází v souboru jsonTestModule/presenters/UserPresenter.php, takže si ji můžete jakkoli změnit právě tak, aby vyhovovala vašim potřebám.
Implementujeme matematiku
Teď už máme za sebou zavolání první metody nad naším serverem – ale to pořád není ono, protože zatím jsme si jenom hráli s tím, co jsme stáhli z githubu. No není to nuda?
Pojďme tedy na věc! Otevřeme si soubor app/presenters/JsonTestSuitePresenter.php a nakonec doplňme následující class:
class Matika {
public function secti($prvni, $druhy) {
return $prvni + $druhy;
}
}
Tím jsme vytvořili kolekci matematických funkcí a prozatím implementovali pouze součet. To ale samo o sobě nestačí, ještě musíme serveru říct, že nějaká matematika vůbec existuje. V metodě renderDefault tedy upravíme instanci serveru tak, aby zahrnoval i matematiku:
// Get server
$server = new Lightbulb\Json\Rpc2\Server;
$server->access = new AccessHandler;
$server->user = new UserHandler;
$server->matika = new Matika; // tento řádek přidejte
A je to! Ale… jak to vlastně poznáme?
Pozn: uvedený příklad by rovněž bylo možné definovat rovnou jako funkci serveru – $server->secti = function($prvni, $druhy) { … } → o tom ale níže..
Přidání matematiky do TEST-SUITE
Pro to, abychom poznali zda nám metoda správně funguje musíme metodu také přidat do jsonTestModule. Díky architektuře test-suite je toto veskrze jednoduché – stačí vytvořit presenter a správně napsat metodu.. a test-suite se postará o zbytek.
Vytvořme si tedy soubor jsonTestModule/presenters/MatikaPresenter.php a do něj vložme následující class:
namespace jsonTestModule;
class MatikaPresenter extends BasePresenter {
public function renderSecti() {
$this->template->formData = array(
'method' => 'matika.secti',
'params' => array(
'prvni' => null,
'druhy' => null,
)
);
}
}
Teď stačí obnovit test suite okno, a odkaz se nám na nový presenter automaticky objeví:
Awesome! Teď už se stačí proklikat do zavolání dané metody a vyzkoušet si, zda nám počítače umí.. počítat:

Implementace rozdílných parametrů
V předchozím bodě jsme vytvořili novou metodu na testování našeho JSON-API serveru. Generování test-suite probíhá tak, že se BasePresenter dotazuje na seznam presenterů v daném namespace – a vygeneruje na ně odkaz. Následně, v detailu daného presenteru se dotáže na render* metody a rovněž vygeneruje odkaz.
Nicméně vygenerování samotného formuláře na odesílání dat do serveru probíhá jednoduše na základě pole $formData, které vyplňujeme v rámci dané render metody.
Ale jaká je vlastně struktura pole?
array(
'method' => 'jméno volané metody, např. user.getInfo',
'params' => array(
// the array of parameters, eg:
'first' => null,
'second' => 'jménoParametru',
'third' => 'jménoParametru:datovýTyp',
'fourth' => array('a', 'b', 'c'), // takhle se generuje "select box"
'fifth' => false, // false / true na vygenerování checkboxu
'sixth' => '~array~', // "~array~" pokud chceme poslat pole - vygeneruje 5 inputů
'seventh' => $object, // a instance stdClass pro vygenerování parametru jako objektu
)
)
Všimněte si, že je možné poslat jako parametr objekt – nakonec, bez posílání objektů by skoro nemělo smysl API vytvářet. Systém automaticky pracuje nad StdClass (pro zachování kompatibility mimo Nette Framework) – nicméně je možné poslat instanci čehokoli, nad čím lze iterovat.
Objekty jako takové mají stejné parametry a mohou obsahovat další objekt – mají narozdíl od ostatních parametrů jednu podmínku: musí obsahovat parametr „_objectName“, který se použije pro vygenerování správného názvu v hlavičce metody.
Detailní ukázku můžete prostudovat v příkladech, jedná se o soubor jsonTestModule/presenters/UserPresenter.php , metoda store().
Implementace neseskupených metod
Jak je vidět ze struktury $formData, test-suite předpokládá možnost definovat a zavolat prakticky cokoliv – a jakkoliv setříděné, je to jen na vás.
Struktura vychází ze dvou předpokladů:
- Presenter = uskupení metod (nemusí nutně být stejné jako u server-u)
- render() = jedna metoda serveru
Pro přiblížení – předpokládejme, že nebudeme používat roztřídění do jednotlivých classes v rámci serveru, ale vše budeme mít rovnou jako samostatné metody v serveru (tj. metody „bez teček“) – prostě něco na tenhle způsob:
$server = new Lightbulb\Json\Rpc2\Server;
$server->prvniMetoda = function() {};
$server->druhaMetoda = function() {};
$server->tretiMetoda = function() {};
V našem případě (na kterém jsme knihovnu vyvíjeli) k tomu sice nedošlo, ale je možné i takovéto metody testovat. Doporučil bych vytvoření samostatného presenteru – něco na způsob „InlineMethodsPresenter“, který bude obsahovat odkaz na dané metody:
namespace jsonTestModule;
class InlineMethodsPresenter extends BasePresenter {
public function renderPrvni() {
$this->formData = array('method' => 'prvni', /* ... */);
}
public function renderDruhy() {
$this->formData = array('method' => 'druhy', /* ... */);
}
public function renderTreti() {
$this->formData = array('method' => 'treti', /* ... */);
}
}
Podpora
Případné chyby hlašte na fóru, na mailu nebo twitteru.
A samozřejmě – pokud nějakou najdete, ocením pull-request na gitu :-)
Historie
2011–09–12: Verze 1.0.