1 <sect1 id="zend.xmlrpc.server">
2 <title>Zend_XmlRpc_Server</title>
4 <sect2 id="zend.xmlrpc.server.introduction">
5 <title>Wprowadzenie</title>
7 <para>Klasa Zend_XmlRpc_Server jest przeznaczona do użycia jako
8 pełnofunkcjonalny serwer XML-RPC, zgodny ze
9 <ulink url="http://www.xmlrpc.com/spec">specyfikacją przedstawioną
10 na www.xmlrpc.com</ulink>. Dodatkowo implementuje ona metodę
11 system.multicall(), pozwalającą na wywołanie wielu metod podczas
16 <sect2 id="zend.xmlrpc.server.usage">
17 <title>Podstawowe użycie</title>
20 Przykład najbardziej podstawowego przypadku użycia:
23 <programlisting role="php"><![CDATA[
24 $server = new Zend_XmlRpc_Server();
25 $server->setClass('My_Service_Class');
26 echo $server->handle();
31 <sect2 id="zend.xmlrpc.server.structure">
32 <title>Struktura serwera</title>
35 Zend_XmlRpc_Server składa się z wielu różnych komponentów, od
36 samego serwera, przez obiekty żądania, obiekty odpowiedzi aż do
41 Aby uruchomić serwer Zend_XmlRpc_Server, programista musi dołączyć
42 jedną lub więcej klas albo funkcji do serwera, za pomocą metod
43 <code>setClass()</code> oraz <code>addFunction()</code>.
47 Kiedy jest to już zrobione, możesz przekazać obiekt
48 <code>Zend_XmlRpc_Request</code> do metody
49 <code>Zend_XmlRpc_Server::handle()</code>, lub zostanie utworzona
50 instancja obiektu <code>Zend_XmlRpc_Request_Http</code> w przypadku
51 gdy nie zostanie zapewniony żaden obiekt -- spowoduje to pobieranie
52 żądań z <code>php://input</code>.
56 <code>Zend_XmlRpc_Server::handle()</code> próbuje wtedy uruchomić
57 odpowiednią klasę obsługującą, zależnie od użytej metody dostępu.
58 Zwraca wtedy obiekt oparty na <code>Zend_XmlRpc_Response</code> lub
59 obiekt <code>Zend_XmlRpc_Server_Fault</code>. Oba te obiekty mają
60 dostępne metody <code>__toString()</code>, ktore tworzą poprawne
61 odpowiedzi XML-RPC, pozwalając na bezpośrednie ich wyświetlenie.
65 <sect2 id="zend.xmlrpc.server.conventions">
66 <title>Konwencje</title>
68 Zend_XmlRpc_Server pozwala programiście dołączać funkcje oraz metody
69 klas jako uruchamialne metody XML-RPC. Poprzez Zend_Server_Reflection,
70 przeprowadzana jest introspekcja dla wszystkich dołączanych metod,
71 używając bloków dokumentacji funkcji i metod do określenia opisów
72 pomocy dla metod oraz sygnatur metod.
76 XML-RPC nie mają w typach PHP dokładnych odpowiedników. Jednak skrypt
77 spróbuje dopasować najlepszy typ na podstawie wartości znajdujących
78 się w polach @param oraz @return. Niektóre typy XML-RPC nie mają
79 dokładnych odpowiedników w typach PHP, więc powinny być rzutowane
80 używając typów XML-RPC w komentarzach phpdoc. Są to:
84 <listitem><para>dateTime.iso8601, łańcuch znaków sformatowany jako
85 YYYYMMDDTHH:mm:ss</para></listitem>
86 <listitem><para>base64, dane zakodowane jako base64</para></listitem>
87 <listitem><para>struct, dowolna tablica asocjacyjna</para></listitem>
91 Przykład wywołania przykładowej funkcji:
94 <programlisting role="php"><![CDATA[
96 * To jest przykładowa funkcja
98 * @param base64 $val1 Dane zakodowane jako Base64
99 * @param dateTime.iso8601 $val2 Data ISO
100 * @param struct $val3 Tablica asocjacyjna
103 function myFunc($val1, $val2, $val3)
110 PhpDocumentor nie przeprowadza weryfikacji typów określonych dla
111 parametrów lub zwracanych wartości, więc nie będzie to miało wpływu
112 na twoją dokumentację API
113 Providing the hinting is necessary, however, when the
114 server is validating the parameters provided to the method call.
118 Poprawne jest określenie wielu typów zarówno dla parametrów jak i
119 dla zwracanych wartości; specyfikacja XML-RPC sugeruje nawet, że
120 metoda system.methodSignature powinna zwracać tablicę wszystkich
121 możliwych sygnatur metody (np. wszystkie możliwe kombinacje
122 parametrów i zwracanych wartości). Możesz to zrobić tak jak robisz
123 to w PhpDocumentor, używając operatora '|':
126 <programlisting role="php"><![CDATA[
128 * To jest przykładowa funkcja
130 * @param string|base64 $val1 Łańcuch znaków lub dane zakodowane jako base64
131 * @param string|dateTime.iso8601 $val2 Łańcuch znaków lub data ISO
132 * @param array|struct $val3 Normalnie indeksowana tablica lub tablica asocjacyjna
133 * @return boolean|struct
135 function myFunc($val1, $val2, $val3)
142 Jedna uwaga: dopuszczanie do utworzenia wielu różnych sygnatur może
143 doprowadzić do dezorientacji programistów używających serwisów;
144 W zasadzie metoda XML-RPC powinna mieć tylko jedną sygnaturę.
148 <sect2 id="zend.xmlrpc.server.namespaces">
149 <title>Używanie przestrzeni nazw</title>
152 XML-RPC posiada system przestrzeni nazw; najprościej mówiąc, pozwala
153 to na grupowanie metod XML-RPC w przestrzenie nazw oddzielone
154 znakiem kropki. Ułatwia to zapobieganie konfliktom pomiędzy metodami
155 pochodzącymi z rożnych klas. Przykładowo, serwer XML-RPC powinien
156 udostępniać kilka metod w przestrzeni nazw 'system':
160 <listitem><para>system.listMethods</para></listitem>
161 <listitem><para>system.methodHelp</para></listitem>
162 <listitem><para>system.methodSignature</para></listitem>
166 Wewnątrz odpowiada to metodom o tych samych w obiekcie
171 Jeśli chcesz dodać przestrzenie nazw do metod, które oferujesz, po
172 prostu podaj przestrzeń nazw do odpowiedniej metody wtedy, gdy
173 dołączasz funkcję lub klasę:
176 <programlisting role="php"><![CDATA[
177 // Wszystkie publiczne metody klasy My_Service_Class będą dostępne jako
178 // myservice.METHODNAME
179 $server->setClass('My_Service_Class', 'myservice');
181 // Funkcja 'somefunc' będzie dostępna jako funcs.somefunc
182 $server->addFunction('somefunc', 'funcs');
187 <sect2 id="zend.xmlrpc.server.request">
188 <title>Własny obiekt żądania</title>
191 W większości przypadków będziesz używał domyślnego obiektu żądania
192 dostarczanego przez Zend_XmlRpc_Server, którym jest obiekt
193 Zend_XmlRpc_Request_Http. Jednak czasem możesz chcieć aby usługa
194 XML-RPC była dostępna przez CLI, GUI lub inne środowisko, lub możesz
195 chcieć zapisywać informacje o przychodzących żądaniach. Aby to
196 zrobić, możesz utworzyć własny obiekt żądania, który rozszerza
197 obiekt Zend_XmlRpc_Request. Najważniejszą rzeczą jest zapamiętanie
198 aby zawsze implementować metody getMethod() oraz getParams() co
199 pozwoli na to, że serwer XML-RPC będzie mógł pobrać te informacje w
200 celu uruchomienia żądania.
204 <sect2 id="zend.xmlrpc.server.response">
205 <title>Własne odpowiedzi</title>
208 Podobnie jak obiekty żądania, Zend_XmlRpc_Server może zwracać własne
209 obiekty odpowiedzi; domyślnie zwracany jest obiekt
210 Zend_XmlRpc_Response_Http, który wysyła odpowiedni nagłówek HTPP
211 Content-Type do użycia z XML-RPC. Możliwym powodem użycia własnego
212 obiektu może być potrzeba logowania odpowiedzi, lub wysyłanie
213 odpowiedzi spowrotem do STDOUT.
217 Aby użyć własnej klasy odpowiedzi, użyj metody
218 Zend_XmlRpc_Server::setResponseClass() przed wywołaniem handle().
222 <sect2 id="zend.xmlrpc.server.fault">
223 <title>Obsługa wyjątków poprzez odpowiedzi błędów</title>
226 Obiekt Zend_XmlRpc_Server łapie wyjątki wyrzucone przez uruchomioną
227 metodę i generuje odpowiedź błędu (fault) wtedy gdy taki wyjątek
228 zostanie złapany. Domyślnie informacje o wyjątkach i ich kody nie są
229 używane w odpowiedzi błędu. Jest to celowe zachowanie chroniące twój
230 kod; wiele wyjątków ujawnia dużo informacji o kodzie oraz środowisku,
231 czemu programista powinien zapobiec (dobrym przykładem mogą być
232 informacje o wyjątkach związanych z bazą danych)
236 Klasy wyjątków, które mają być użyte jako odpowiedzi błędów mogą być
237 dodane do listy dozwolonych wyjątków. Aby to zrobić wystarczy użyć
238 metody Zend_XmlRpc_Server_Fault::attachFaultException() w celu
239 przekazania klasy wyjątku do listy dozwolonych wyjątków:
242 <programlisting role="php"><![CDATA[
243 Zend_XmlRpc_Server_Fault::attachFaultException('My_Project_Exception');
248 Jeśli dodasz do listy wyjątków klasę wyjątku z którego dziedziczą
249 inne wyjątki, możesz w ten sposób dodać do listy całą rodzinę
250 wyjątków za jednym razem. Wyjątki Zend_XmlRpc_Server_Exceptions
251 zawsze znajdują się na liście dozwolonych wyjątków, aby pozwolić na
252 informowanie o specyficznych wewnętrznych błędach (niezdefiniowanie
257 Każdy wyjątek spoza listy dozwolonych wyjątków spowoduje
258 wygenerowanie odpowiedzi błędu o kodzie '404' i informacji
259 'Unknown error' (Nieznany błąd).
263 <sect2 id="zend.xmlrpc.server.caching">
264 <title>Buforowanie definicji serwera pomiędzy żądaniami</title>
266 Dołączanie wielu klas do instancji serwera XML-RPC może zajmować
267 wiele zasobów; za pomocą Reflection API (przez Zend_Server_Reflection)
268 musi być dokonana introspekcja każdej klasy co w rezultacie wygeneruje
269 listę wszystkich możliwych sygnatur metod w celu przekazania jej
273 Aby zredukować straty wydajności, możemy użyć obiektu
274 Zend_XmlRpc_Server_Cache do buforowania definicji serwera pomiędzy
275 żądaniami. Gdy połączymy to z funkcją __autoload(), może to mocno
281 <programlisting role="php"><![CDATA[
282 function __autoload($class)
284 Zend_Loader::loadClass($class);
287 $cacheFile = dirname(__FILE__) . '/xmlrpc.cache';
288 $server = new Zend_XmlRpc_Server();
290 if (!Zend_XmlRpc_Server_Cache::get($cacheFile, $server)) {
291 require_once 'My/Services/Glue.php';
292 require_once 'My/Services/Paste.php';
293 require_once 'My/Services/Tape.php';
295 $server->setClass('My_Services_Glue', 'glue'); // przestrzeń nazw glue
296 $server->setClass('My_Services_Paste', 'paste'); // przestrzeń nazw paste
297 $server->setClass('My_Services_Tape', 'tape'); // przestrzeń nazw tape
299 Zend_XmlRpc_Server_Cache::save($cacheFile, $server);
302 echo $server->handle();
306 Powyższy przykład próbuje pobrać definicję serwera z pliku bufora
307 xmlrpc.cache znajdującego się w tym samym katalogu co skrypt. Jeśli
308 się to nie uda, załaduje on potrzebne klasy serwisu, dołączy do
309 instancji serwera i spróbuje utworzyć nowy plik bufora z definicją
314 <sect2 id="zend.xmlrpc.server.use">
315 <title>Przykład użycia</title>
317 Poniżej znajduje się kilka przykładów użycia, pokazując pełne
318 spektrum opcji dostępnych dla programistów. Każdy z przykładów
319 użycia jest oparty na poprzednich przykładach.
321 <sect3 id="zend.xmlrpc.server.use.case1">
322 <title>Podstawowe użycie</title>
325 Poniższy przykład dołącza funkcję jaką uruchamialną przez
326 XML-RPC metodę i obsługuje przychodzące wywołania.
329 <programlisting role="php"><![CDATA[
331 * Zwraca sumę MD5 zadanej wartości
333 * @param string $value wartość do obliczenia sumy md5
334 * @return string MD5 suma wartości
336 function md5Value($value)
341 $server = new Zend_XmlRpc_Server();
342 $server->addFunction('md5Value');
343 echo $server->handle();
348 <sect3 id="zend.xmlrpc.server.use.case2">
349 <title>Dołączanie klasy</title>
352 Poniższy przykład pokazuje dołączanie publicznych metod klasy
353 jako uruchamialnych metod XML-RPC.
356 <programlisting role="php"><![CDATA[
357 $server = new Zend_XmlRpc_Server();
358 $server->setClass('Services_Comb');
359 echo $server->handle();
364 <sect3 id="zend.xmlrpc.server.use.case3">
365 <title>Dołączanie wielu klas używając przestrzeni nazw</title>
368 Poniższy przykład pokazuje dołączanie kilku klas, każdej z
369 własną przestrzenią nazw.
372 <programlisting role="php"><![CDATA[
373 $server = new Zend_XmlRpc_Server();
374 $server->setClass('Services_Comb', 'comb'); // metody wywoływane jako comb.*
375 $server->setClass('Services_Brush', 'brush'); // metody wywoływane jako brush.*
376 $server->setClass('Services_Pick', 'pick'); // metody wywoływane jako pick.*
377 echo $server->handle();
382 <sect3 id="zend.xmlrpc.server.use.case4">
383 <title>Określenie wyjątków dla odpowiedzi błędów</title>
386 Poniższy przykład pozwala dowolnej klasie pochodzącej od
387 Services_Exception na przekazywanie informacji o wyjątkach w
388 postaci kodu i wiadomości w odpowiedzi błędu.
391 <programlisting role="php"><![CDATA[
392 // Pozwala na wyrzucanie wyjątku Services_Exceptions dla odpowiedzi błędu
393 Zend_XmlRpc_Server_Fault::attachFaultException('Services_Exception');
395 $server = new Zend_XmlRpc_Server();
396 $server->setClass('Services_Comb', 'comb'); // metody wywoływane jako comb.*
397 $server->setClass('Services_Brush', 'brush'); // metody wywoływane jako brush.*
398 $server->setClass('Services_Pick', 'pick'); // metody wywoływane jako pick.*
399 echo $server->handle();
404 <sect3 id="zend.xmlrpc.server.use.case5">
405 <title>Użycie własnego obiektu żądania</title>
408 Poniższy przykład tworzy instancję własnego obiektu żądania i
409 przekazuje go do obiektu serwera.
412 <programlisting role="php"><![CDATA[
413 // Pozwala na wyrzucanie wyjątku Services_Exceptions dla odpowiedzi błędu
414 Zend_XmlRpc_Server_Fault::attachFaultException('Services_Exception');
416 $server = new Zend_XmlRpc_Server();
417 $server->setClass('Services_Comb', 'comb'); // metody wywoływane jako comb.*
418 $server->setClass('Services_Brush', 'brush'); // metody wywoływane jako brush.*
419 $server->setClass('Services_Pick', 'pick'); // metody wywoływane jako pick.*
421 // Tworzenie obiektu żądania
422 $request = new Services_Request();
424 echo $server->handle($request);
429 <sect3 id="zend.xmlrpc.server.use.case6">
430 <title>Użycie własnego obiektu odpowiedzi</title>
433 Poniższy przykład pokazuje określanie własnej klasy odpowiedzi
434 dla zwracanej odpowiedzi.
437 <programlisting role="php"><![CDATA[
438 // Pozwala na wyrzucanie wyjątku Services_Exceptions dla odpowiedzi błędu
439 Zend_XmlRpc_Server_Fault::attachFaultException('Services_Exception');
441 $server = new Zend_XmlRpc_Server();
442 $server->setClass('Services_Comb', 'comb'); // metody wywoływane jako comb.*
443 $server->setClass('Services_Brush', 'brush'); // metody wywoływane jako brush.*
444 $server->setClass('Services_Pick', 'pick'); // metody wywoływane jako pick.*
446 // Utwórz obiekt żądania
447 $request = new Services_Request();
449 // Użyj własnego obiektu żądania
450 $server->setResponseClass('Services_Response');
452 echo $server->handle($request);
457 <sect3 id="zend.xmlrpc.server.use.case7">
458 <title>Buforowanie definicji serwera pomiędzy żądaniami</title>
461 Poniższy przykład pokazuje buforowanie definicji serwera pomiędzy
465 <programlisting role="php"><![CDATA[
467 $cacheFile = dirname(__FILE__) . '/xmlrpc.cache';
469 // Pozwala na wyrzucanie wyjątku Services_Exceptions dla odpowiedzi błędu
470 Zend_XmlRpc_Server_Fault::attachFaultException('Services_Exception');
472 $server = new Zend_XmlRpc_Server();
474 // Spróbuj pobrać definicje serwera z bufora
475 if (!Zend_XmlRpc_Server_Cache::get($cacheFile, $server)) {
476 $server->setClass('Services_Comb', 'comb'); // metody wywoływane jako comb.*
477 $server->setClass('Services_Brush', 'brush'); // metody wywoływane jako brush.*
478 $server->setClass('Services_Pick', 'pick'); // metody wywoływane jako pick.*
481 Zend_XmlRpc_Server_Cache::save($cacheFile, $server));
484 // Utwórz obiekt żądania
485 $request = new Services_Request();
487 // Użyj własnej klasy odpowiedzi
488 $server->setResponseClass('Services_Response');
490 echo $server->handle($request);