| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495 |
- <sect1 id="zend.xmlrpc.server">
- <title>Zend_XmlRpc_Server</title>
- <sect2 id="zend.xmlrpc.server.introduction">
- <title>Wprowadzenie</title>
- <para>Klasa Zend_XmlRpc_Server jest przeznaczona do użycia jako
- pełnofunkcjonalny serwer XML-RPC, zgodny ze
- <ulink url="http://www.xmlrpc.com/spec">specyfikacją przedstawioną
- na www.xmlrpc.com</ulink>. Dodatkowo implementuje ona metodę
- system.multicall(), pozwalającą na wywołanie wielu metod podczas
- jednego żądania.
- </para>
- </sect2>
- <sect2 id="zend.xmlrpc.server.usage">
- <title>Podstawowe użycie</title>
- <para>
- Przykład najbardziej podstawowego przypadku użycia:
- </para>
- <programlisting role="php"><![CDATA[
- $server = new Zend_XmlRpc_Server();
- $server->setClass('My_Service_Class');
- echo $server->handle();
- ]]>
- </programlisting>
- </sect2>
- <sect2 id="zend.xmlrpc.server.structure">
- <title>Struktura serwera</title>
- <para>
- Zend_XmlRpc_Server składa się z wielu różnych komponentów, od
- samego serwera, przez obiekty żądania, obiekty odpowiedzi aż do
- obiektów błędów.
- </para>
- <para>
- Aby uruchomić serwer Zend_XmlRpc_Server, programista musi dołączyć
- jedną lub więcej klas albo funkcji do serwera, za pomocą metod
- <code>setClass()</code> oraz <code>addFunction()</code>.
- </para>
- <para>
- Kiedy jest to już zrobione, możesz przekazać obiekt
- <code>Zend_XmlRpc_Request</code> do metody
- <code>Zend_XmlRpc_Server::handle()</code>, lub zostanie utworzona
- instancja obiektu <code>Zend_XmlRpc_Request_Http</code> w przypadku
- gdy nie zostanie zapewniony żaden obiekt -- spowoduje to pobieranie
- żądań z <code>php://input</code>.
- </para>
- <para>
- <code>Zend_XmlRpc_Server::handle()</code> próbuje wtedy uruchomić
- odpowiednią klasę obsługującą, zależnie od użytej metody dostępu.
- Zwraca wtedy obiekt oparty na <code>Zend_XmlRpc_Response</code> lub
- obiekt <code>Zend_XmlRpc_Server_Fault</code>. Oba te obiekty mają
- dostępne metody <code>__toString()</code>, ktore tworzą poprawne
- odpowiedzi XML-RPC, pozwalając na bezpośrednie ich wyświetlenie.
- </para>
- </sect2>
- <sect2 id="zend.xmlrpc.server.conventions">
- <title>Konwencje</title>
- <para>
- Zend_XmlRpc_Server pozwala programiście dołączać funkcje oraz metody
- klas jako uruchamialne metody XML-RPC. Poprzez Zend_Server_Reflection,
- przeprowadzana jest introspekcja dla wszystkich dołączanych metod,
- używając bloków dokumentacji funkcji i metod do określenia opisów
- pomocy dla metod oraz sygnatur metod.
- </para>
- <para>
- XML-RPC nie mają w typach PHP dokładnych odpowiedników. Jednak skrypt
- spróbuje dopasować najlepszy typ na podstawie wartości znajdujących
- się w polach @param oraz @return. Niektóre typy XML-RPC nie mają
- dokładnych odpowiedników w typach PHP, więc powinny być rzutowane
- używając typów XML-RPC w komentarzach phpdoc. Są to:
- </para>
- <itemizedlist>
- <listitem><para>dateTime.iso8601, łańcuch znaków sformatowany jako
- YYYYMMDDTHH:mm:ss</para></listitem>
- <listitem><para>base64, dane zakodowane jako base64</para></listitem>
- <listitem><para>struct, dowolna tablica asocjacyjna</para></listitem>
- </itemizedlist>
- <para>
- Przykład wywołania przykładowej funkcji:
- </para>
- <programlisting role="php"><![CDATA[
- /**
- * To jest przykładowa funkcja
- *
- * @param base64 $val1 Dane zakodowane jako Base64
- * @param dateTime.iso8601 $val2 Data ISO
- * @param struct $val3 Tablica asocjacyjna
- * @return struct
- */
- function myFunc($val1, $val2, $val3)
- {
- }
- ]]>
- </programlisting>
- <para>
- PhpDocumentor nie przeprowadza weryfikacji typów określonych dla
- parametrów lub zwracanych wartości, więc nie będzie to miało wpływu
- na twoją dokumentację API
- Providing the hinting is necessary, however, when the
- server is validating the parameters provided to the method call.
- </para>
- <para>
- Poprawne jest określenie wielu typów zarówno dla parametrów jak i
- dla zwracanych wartości; specyfikacja XML-RPC sugeruje nawet, że
- metoda system.methodSignature powinna zwracać tablicę wszystkich
- możliwych sygnatur metody (np. wszystkie możliwe kombinacje
- parametrów i zwracanych wartości). Możesz to zrobić tak jak robisz
- to w PhpDocumentor, używając operatora '|':
- </para>
- <programlisting role="php"><![CDATA[
- /**
- * To jest przykładowa funkcja
- *
- * @param string|base64 $val1 Łańcuch znaków lub dane zakodowane jako base64
- * @param string|dateTime.iso8601 $val2 Łańcuch znaków lub data ISO
- * @param array|struct $val3 Normalnie indeksowana tablica lub tablica asocjacyjna
- * @return boolean|struct
- */
- function myFunc($val1, $val2, $val3)
- {
- }
- ]]>
- </programlisting>
- <para>
- Jedna uwaga: dopuszczanie do utworzenia wielu różnych sygnatur może
- doprowadzić do dezorientacji programistów używających serwisów;
- W zasadzie metoda XML-RPC powinna mieć tylko jedną sygnaturę.
- </para>
- </sect2>
- <sect2 id="zend.xmlrpc.server.namespaces">
- <title>Używanie przestrzeni nazw</title>
- <para>
- XML-RPC posiada system przestrzeni nazw; najprościej mówiąc, pozwala
- to na grupowanie metod XML-RPC w przestrzenie nazw oddzielone
- znakiem kropki. Ułatwia to zapobieganie konfliktom pomiędzy metodami
- pochodzącymi z rożnych klas. Przykładowo, serwer XML-RPC powinien
- udostępniać kilka metod w przestrzeni nazw 'system':
- </para>
- <itemizedlist>
- <listitem><para>system.listMethods</para></listitem>
- <listitem><para>system.methodHelp</para></listitem>
- <listitem><para>system.methodSignature</para></listitem>
- </itemizedlist>
- <para>
- Wewnątrz odpowiada to metodom o tych samych w obiekcie
- Zend_XmlRpc_Server.
- </para>
- <para>
- Jeśli chcesz dodać przestrzenie nazw do metod, które oferujesz, po
- prostu podaj przestrzeń nazw do odpowiedniej metody wtedy, gdy
- dołączasz funkcję lub klasę:
- </para>
- <programlisting role="php"><![CDATA[
- // Wszystkie publiczne metody klasy My_Service_Class będą dostępne jako
- // myservice.METHODNAME
- $server->setClass('My_Service_Class', 'myservice');
- // Funkcja 'somefunc' będzie dostępna jako funcs.somefunc
- $server->addFunction('somefunc', 'funcs');
- ]]>
- </programlisting>
- </sect2>
- <sect2 id="zend.xmlrpc.server.request">
- <title>Własny obiekt żądania</title>
- <para>
- W większości przypadków będziesz używał domyślnego obiektu żądania
- dostarczanego przez Zend_XmlRpc_Server, którym jest obiekt
- Zend_XmlRpc_Request_Http. Jednak czasem możesz chcieć aby usługa
- XML-RPC była dostępna przez CLI, GUI lub inne środowisko, lub możesz
- chcieć zapisywać informacje o przychodzących żądaniach. Aby to
- zrobić, możesz utworzyć własny obiekt żądania, który rozszerza
- obiekt Zend_XmlRpc_Request. Najważniejszą rzeczą jest zapamiętanie
- aby zawsze implementować metody getMethod() oraz getParams() co
- pozwoli na to, że serwer XML-RPC będzie mógł pobrać te informacje w
- celu uruchomienia żądania.
- </para>
- </sect2>
- <sect2 id="zend.xmlrpc.server.response">
- <title>Własne odpowiedzi</title>
- <para>
- Podobnie jak obiekty żądania, Zend_XmlRpc_Server może zwracać własne
- obiekty odpowiedzi; domyślnie zwracany jest obiekt
- Zend_XmlRpc_Response_Http, który wysyła odpowiedni nagłówek HTPP
- Content-Type do użycia z XML-RPC. Możliwym powodem użycia własnego
- obiektu może być potrzeba logowania odpowiedzi, lub wysyłanie
- odpowiedzi spowrotem do STDOUT.
- </para>
- <para>
- Aby użyć własnej klasy odpowiedzi, użyj metody
- Zend_XmlRpc_Server::setResponseClass() przed wywołaniem handle().
- </para>
- </sect2>
- <sect2 id="zend.xmlrpc.server.fault">
- <title>Obsługa wyjątków poprzez odpowiedzi błędów</title>
- <para>
- Obiekt Zend_XmlRpc_Server łapie wyjątki wyrzucone przez uruchomioną
- metodę i generuje odpowiedź błędu (fault) wtedy gdy taki wyjątek
- zostanie złapany. Domyślnie informacje o wyjątkach i ich kody nie są
- używane w odpowiedzi błędu. Jest to celowe zachowanie chroniące twój
- kod; wiele wyjątków ujawnia dużo informacji o kodzie oraz środowisku,
- czemu programista powinien zapobiec (dobrym przykładem mogą być
- informacje o wyjątkach związanych z bazą danych)
- </para>
- <para>
- Klasy wyjątków, które mają być użyte jako odpowiedzi błędów mogą być
- dodane do listy dozwolonych wyjątków. Aby to zrobić wystarczy użyć
- metody Zend_XmlRpc_Server_Fault::attachFaultException() w celu
- przekazania klasy wyjątku do listy dozwolonych wyjątków:
- </para>
- <programlisting role="php"><![CDATA[
- Zend_XmlRpc_Server_Fault::attachFaultException('My_Project_Exception');
- ]]>
- </programlisting>
- <para>
- Jeśli dodasz do listy wyjątków klasę wyjątku z którego dziedziczą
- inne wyjątki, możesz w ten sposób dodać do listy całą rodzinę
- wyjątków za jednym razem. Wyjątki Zend_XmlRpc_Server_Exceptions
- zawsze znajdują się na liście dozwolonych wyjątków, aby pozwolić na
- informowanie o specyficznych wewnętrznych błędach (niezdefiniowanie
- metody itp.).
- </para>
- <para>
- Każdy wyjątek spoza listy dozwolonych wyjątków spowoduje
- wygenerowanie odpowiedzi błędu o kodzie '404' i informacji
- 'Unknown error' (Nieznany błąd).
- </para>
- </sect2>
- <sect2 id="zend.xmlrpc.server.caching">
- <title>Buforowanie definicji serwera pomiędzy żądaniami</title>
- <para>
- Dołączanie wielu klas do instancji serwera XML-RPC może zajmować
- wiele zasobów; za pomocą Reflection API (przez Zend_Server_Reflection)
- musi być dokonana introspekcja każdej klasy co w rezultacie wygeneruje
- listę wszystkich możliwych sygnatur metod w celu przekazania jej
- do klasy serwera.
- </para>
- <para>
- Aby zredukować straty wydajności, możemy użyć obiektu
- Zend_XmlRpc_Server_Cache do buforowania definicji serwera pomiędzy
- żądaniami. Gdy połączymy to z funkcją __autoload(), może to mocno
- zwiększyć wydajność.
- </para>
- <para>
- Przykładowe użycie:
- </para>
- <programlisting role="php"><![CDATA[
- function __autoload($class)
- {
- Zend_Loader::loadClass($class);
- }
- $cacheFile = dirname(__FILE__) . '/xmlrpc.cache';
- $server = new Zend_XmlRpc_Server();
- if (!Zend_XmlRpc_Server_Cache::get($cacheFile, $server)) {
- require_once 'My/Services/Glue.php';
- require_once 'My/Services/Paste.php';
- require_once 'My/Services/Tape.php';
- $server->setClass('My_Services_Glue', 'glue'); // przestrzeń nazw glue
- $server->setClass('My_Services_Paste', 'paste'); // przestrzeń nazw paste
- $server->setClass('My_Services_Tape', 'tape'); // przestrzeń nazw tape
- Zend_XmlRpc_Server_Cache::save($cacheFile, $server);
- }
- echo $server->handle();
- ]]>
- </programlisting>
- <para>
- Powyższy przykład próbuje pobrać definicję serwera z pliku bufora
- xmlrpc.cache znajdującego się w tym samym katalogu co skrypt. Jeśli
- się to nie uda, załaduje on potrzebne klasy serwisu, dołączy do
- instancji serwera i spróbuje utworzyć nowy plik bufora z definicją
- sderwera.
- </para>
- </sect2>
- <sect2 id="zend.xmlrpc.server.use">
- <title>Przykład użycia</title>
- <para>
- Poniżej znajduje się kilka przykładów użycia, pokazując pełne
- spektrum opcji dostępnych dla programistów. Każdy z przykładów
- użycia jest oparty na poprzednich przykładach.
- </para>
- <sect3 id="zend.xmlrpc.server.use.case1">
- <title>Podstawowe użycie</title>
- <para>
- Poniższy przykład dołącza funkcję jaką uruchamialną przez
- XML-RPC metodę i obsługuje przychodzące wywołania.
- </para>
- <programlisting role="php"><![CDATA[
- /**
- * Zwraca sumę MD5 zadanej wartości
- *
- * @param string $value wartość do obliczenia sumy md5
- * @return string MD5 suma wartości
- */
- function md5Value($value)
- {
- return md5($value);
- }
- $server = new Zend_XmlRpc_Server();
- $server->addFunction('md5Value');
- echo $server->handle();
- ]]>
- </programlisting>
- </sect3>
- <sect3 id="zend.xmlrpc.server.use.case2">
- <title>Dołączanie klasy</title>
- <para>
- Poniższy przykład pokazuje dołączanie publicznych metod klasy
- jako uruchamialnych metod XML-RPC.
- </para>
- <programlisting role="php"><![CDATA[
- $server = new Zend_XmlRpc_Server();
- $server->setClass('Services_Comb');
- echo $server->handle();
- ]]>
- </programlisting>
- </sect3>
- <sect3 id="zend.xmlrpc.server.use.case3">
- <title>Dołączanie wielu klas używając przestrzeni nazw</title>
- <para>
- Poniższy przykład pokazuje dołączanie kilku klas, każdej z
- własną przestrzenią nazw.
- </para>
- <programlisting role="php"><![CDATA[
- $server = new Zend_XmlRpc_Server();
- $server->setClass('Services_Comb', 'comb'); // metody wywoływane jako comb.*
- $server->setClass('Services_Brush', 'brush'); // metody wywoływane jako brush.*
- $server->setClass('Services_Pick', 'pick'); // metody wywoływane jako pick.*
- echo $server->handle();
- ]]>
- </programlisting>
- </sect3>
- <sect3 id="zend.xmlrpc.server.use.case4">
- <title>Określenie wyjątków dla odpowiedzi błędów</title>
- <para>
- Poniższy przykład pozwala dowolnej klasie pochodzącej od
- Services_Exception na przekazywanie informacji o wyjątkach w
- postaci kodu i wiadomości w odpowiedzi błędu.
- </para>
- <programlisting role="php"><![CDATA[
- // Pozwala na wyrzucanie wyjątku Services_Exceptions dla odpowiedzi błędu
- Zend_XmlRpc_Server_Fault::attachFaultException('Services_Exception');
- $server = new Zend_XmlRpc_Server();
- $server->setClass('Services_Comb', 'comb'); // metody wywoływane jako comb.*
- $server->setClass('Services_Brush', 'brush'); // metody wywoływane jako brush.*
- $server->setClass('Services_Pick', 'pick'); // metody wywoływane jako pick.*
- echo $server->handle();
- ]]>
- </programlisting>
- </sect3>
- <sect3 id="zend.xmlrpc.server.use.case5">
- <title>Użycie własnego obiektu żądania</title>
- <para>
- Poniższy przykład tworzy instancję własnego obiektu żądania i
- przekazuje go do obiektu serwera.
- </para>
- <programlisting role="php"><![CDATA[
- // Pozwala na wyrzucanie wyjątku Services_Exceptions dla odpowiedzi błędu
- Zend_XmlRpc_Server_Fault::attachFaultException('Services_Exception');
- $server = new Zend_XmlRpc_Server();
- $server->setClass('Services_Comb', 'comb'); // metody wywoływane jako comb.*
- $server->setClass('Services_Brush', 'brush'); // metody wywoływane jako brush.*
- $server->setClass('Services_Pick', 'pick'); // metody wywoływane jako pick.*
- // Tworzenie obiektu żądania
- $request = new Services_Request();
- echo $server->handle($request);
- ]]>
- </programlisting>
- </sect3>
- <sect3 id="zend.xmlrpc.server.use.case6">
- <title>Użycie własnego obiektu odpowiedzi</title>
- <para>
- Poniższy przykład pokazuje określanie własnej klasy odpowiedzi
- dla zwracanej odpowiedzi.
- </para>
- <programlisting role="php"><![CDATA[
- // Pozwala na wyrzucanie wyjątku Services_Exceptions dla odpowiedzi błędu
- Zend_XmlRpc_Server_Fault::attachFaultException('Services_Exception');
- $server = new Zend_XmlRpc_Server();
- $server->setClass('Services_Comb', 'comb'); // metody wywoływane jako comb.*
- $server->setClass('Services_Brush', 'brush'); // metody wywoływane jako brush.*
- $server->setClass('Services_Pick', 'pick'); // metody wywoływane jako pick.*
- // Utwórz obiekt żądania
- $request = new Services_Request();
- // Użyj własnego obiektu żądania
- $server->setResponseClass('Services_Response');
- echo $server->handle($request);
- ]]>
- </programlisting>
- </sect3>
- <sect3 id="zend.xmlrpc.server.use.case7">
- <title>Buforowanie definicji serwera pomiędzy żądaniami</title>
- <para>
- Poniższy przykład pokazuje buforowanie definicji serwera pomiędzy
- żądaniami.
- </para>
- <programlisting role="php"><![CDATA[
- // Określ plik cache
- $cacheFile = dirname(__FILE__) . '/xmlrpc.cache';
- // Pozwala na wyrzucanie wyjątku Services_Exceptions dla odpowiedzi błędu
- Zend_XmlRpc_Server_Fault::attachFaultException('Services_Exception');
- $server = new Zend_XmlRpc_Server();
- // Spróbuj pobrać definicje serwera z bufora
- if (!Zend_XmlRpc_Server_Cache::get($cacheFile, $server)) {
- $server->setClass('Services_Comb', 'comb'); // metody wywoływane jako comb.*
- $server->setClass('Services_Brush', 'brush'); // metody wywoływane jako brush.*
- $server->setClass('Services_Pick', 'pick'); // metody wywoływane jako pick.*
- // Zapisz cache
- Zend_XmlRpc_Server_Cache::save($cacheFile, $server));
- }
- // Utwórz obiekt żądania
- $request = new Services_Request();
- // Użyj własnej klasy odpowiedzi
- $server->setResponseClass('Services_Response');
- echo $server->handle($request);
- ]]>
- </programlisting>
- </sect3>
- </sect2>
- </sect1>
|