Zend_XmlRpc_Server.xml 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. <sect1 id="zend.xmlrpc.server">
  2. <title>Zend_XmlRpc_Server</title>
  3. <sect2 id="zend.xmlrpc.server.introduction">
  4. <title>Wprowadzenie</title>
  5. <para>Klasa Zend_XmlRpc_Server jest przeznaczona do użycia jako
  6. pełnofunkcjonalny serwer XML-RPC, zgodny ze
  7. <ulink url="http://www.xmlrpc.com/spec">specyfikacją przedstawioną
  8. na www.xmlrpc.com</ulink>. Dodatkowo implementuje ona metodę
  9. system.multicall(), pozwalającą na wywołanie wielu metod podczas
  10. jednego żądania.
  11. </para>
  12. </sect2>
  13. <sect2 id="zend.xmlrpc.server.usage">
  14. <title>Podstawowe użycie</title>
  15. <para>
  16. Przykład najbardziej podstawowego przypadku użycia:
  17. </para>
  18. <programlisting role="php"><![CDATA[
  19. $server = new Zend_XmlRpc_Server();
  20. $server->setClass('My_Service_Class');
  21. echo $server->handle();
  22. ]]>
  23. </programlisting>
  24. </sect2>
  25. <sect2 id="zend.xmlrpc.server.structure">
  26. <title>Struktura serwera</title>
  27. <para>
  28. Zend_XmlRpc_Server składa się z wielu różnych komponentów, od
  29. samego serwera, przez obiekty żądania, obiekty odpowiedzi aż do
  30. obiektów błędów.
  31. </para>
  32. <para>
  33. Aby uruchomić serwer Zend_XmlRpc_Server, programista musi dołączyć
  34. jedną lub więcej klas albo funkcji do serwera, za pomocą metod
  35. <code>setClass()</code> oraz <code>addFunction()</code>.
  36. </para>
  37. <para>
  38. Kiedy jest to już zrobione, możesz przekazać obiekt
  39. <code>Zend_XmlRpc_Request</code> do metody
  40. <code>Zend_XmlRpc_Server::handle()</code>, lub zostanie utworzona
  41. instancja obiektu <code>Zend_XmlRpc_Request_Http</code> w przypadku
  42. gdy nie zostanie zapewniony żaden obiekt -- spowoduje to pobieranie
  43. żądań z <code>php://input</code>.
  44. </para>
  45. <para>
  46. <code>Zend_XmlRpc_Server::handle()</code> próbuje wtedy uruchomić
  47. odpowiednią klasę obsługującą, zależnie od użytej metody dostępu.
  48. Zwraca wtedy obiekt oparty na <code>Zend_XmlRpc_Response</code> lub
  49. obiekt <code>Zend_XmlRpc_Server_Fault</code>. Oba te obiekty mają
  50. dostępne metody <code>__toString()</code>, ktore tworzą poprawne
  51. odpowiedzi XML-RPC, pozwalając na bezpośrednie ich wyświetlenie.
  52. </para>
  53. </sect2>
  54. <sect2 id="zend.xmlrpc.server.conventions">
  55. <title>Konwencje</title>
  56. <para>
  57. Zend_XmlRpc_Server pozwala programiście dołączać funkcje oraz metody
  58. klas jako uruchamialne metody XML-RPC. Poprzez Zend_Server_Reflection,
  59. przeprowadzana jest introspekcja dla wszystkich dołączanych metod,
  60. używając bloków dokumentacji funkcji i metod do określenia opisów
  61. pomocy dla metod oraz sygnatur metod.
  62. </para>
  63. <para>
  64. XML-RPC nie mają w typach PHP dokładnych odpowiedników. Jednak skrypt
  65. spróbuje dopasować najlepszy typ na podstawie wartości znajdujących
  66. się w polach @param oraz @return. Niektóre typy XML-RPC nie mają
  67. dokładnych odpowiedników w typach PHP, więc powinny być rzutowane
  68. używając typów XML-RPC w komentarzach phpdoc. Są to:
  69. </para>
  70. <itemizedlist>
  71. <listitem><para>dateTime.iso8601, łańcuch znaków sformatowany jako
  72. YYYYMMDDTHH:mm:ss</para></listitem>
  73. <listitem><para>base64, dane zakodowane jako base64</para></listitem>
  74. <listitem><para>struct, dowolna tablica asocjacyjna</para></listitem>
  75. </itemizedlist>
  76. <para>
  77. Przykład wywołania przykładowej funkcji:
  78. </para>
  79. <programlisting role="php"><![CDATA[
  80. /**
  81. * To jest przykładowa funkcja
  82. *
  83. * @param base64 $val1 Dane zakodowane jako Base64
  84. * @param dateTime.iso8601 $val2 Data ISO
  85. * @param struct $val3 Tablica asocjacyjna
  86. * @return struct
  87. */
  88. function myFunc($val1, $val2, $val3)
  89. {
  90. }
  91. ]]>
  92. </programlisting>
  93. <para>
  94. PhpDocumentor nie przeprowadza weryfikacji typów określonych dla
  95. parametrów lub zwracanych wartości, więc nie będzie to miało wpływu
  96. na twoją dokumentację API
  97. Providing the hinting is necessary, however, when the
  98. server is validating the parameters provided to the method call.
  99. </para>
  100. <para>
  101. Poprawne jest określenie wielu typów zarówno dla parametrów jak i
  102. dla zwracanych wartości; specyfikacja XML-RPC sugeruje nawet, że
  103. metoda system.methodSignature powinna zwracać tablicę wszystkich
  104. możliwych sygnatur metody (np. wszystkie możliwe kombinacje
  105. parametrów i zwracanych wartości). Możesz to zrobić tak jak robisz
  106. to w PhpDocumentor, używając operatora '|':
  107. </para>
  108. <programlisting role="php"><![CDATA[
  109. /**
  110. * To jest przykładowa funkcja
  111. *
  112. * @param string|base64 $val1 Łańcuch znaków lub dane zakodowane jako base64
  113. * @param string|dateTime.iso8601 $val2 Łańcuch znaków lub data ISO
  114. * @param array|struct $val3 Normalnie indeksowana tablica lub tablica asocjacyjna
  115. * @return boolean|struct
  116. */
  117. function myFunc($val1, $val2, $val3)
  118. {
  119. }
  120. ]]>
  121. </programlisting>
  122. <para>
  123. Jedna uwaga: dopuszczanie do utworzenia wielu różnych sygnatur może
  124. doprowadzić do dezorientacji programistów używających serwisów;
  125. W zasadzie metoda XML-RPC powinna mieć tylko jedną sygnaturę.
  126. </para>
  127. </sect2>
  128. <sect2 id="zend.xmlrpc.server.namespaces">
  129. <title>Używanie przestrzeni nazw</title>
  130. <para>
  131. XML-RPC posiada system przestrzeni nazw; najprościej mówiąc, pozwala
  132. to na grupowanie metod XML-RPC w przestrzenie nazw oddzielone
  133. znakiem kropki. Ułatwia to zapobieganie konfliktom pomiędzy metodami
  134. pochodzącymi z rożnych klas. Przykładowo, serwer XML-RPC powinien
  135. udostępniać kilka metod w przestrzeni nazw 'system':
  136. </para>
  137. <itemizedlist>
  138. <listitem><para>system.listMethods</para></listitem>
  139. <listitem><para>system.methodHelp</para></listitem>
  140. <listitem><para>system.methodSignature</para></listitem>
  141. </itemizedlist>
  142. <para>
  143. Wewnątrz odpowiada to metodom o tych samych w obiekcie
  144. Zend_XmlRpc_Server.
  145. </para>
  146. <para>
  147. Jeśli chcesz dodać przestrzenie nazw do metod, które oferujesz, po
  148. prostu podaj przestrzeń nazw do odpowiedniej metody wtedy, gdy
  149. dołączasz funkcję lub klasę:
  150. </para>
  151. <programlisting role="php"><![CDATA[
  152. // Wszystkie publiczne metody klasy My_Service_Class będą dostępne jako
  153. // myservice.METHODNAME
  154. $server->setClass('My_Service_Class', 'myservice');
  155. // Funkcja 'somefunc' będzie dostępna jako funcs.somefunc
  156. $server->addFunction('somefunc', 'funcs');
  157. ]]>
  158. </programlisting>
  159. </sect2>
  160. <sect2 id="zend.xmlrpc.server.request">
  161. <title>Własny obiekt żądania</title>
  162. <para>
  163. W większości przypadków będziesz używał domyślnego obiektu żądania
  164. dostarczanego przez Zend_XmlRpc_Server, którym jest obiekt
  165. Zend_XmlRpc_Request_Http. Jednak czasem możesz chcieć aby usługa
  166. XML-RPC była dostępna przez CLI, GUI lub inne środowisko, lub możesz
  167. chcieć zapisywać informacje o przychodzących żądaniach. Aby to
  168. zrobić, możesz utworzyć własny obiekt żądania, który rozszerza
  169. obiekt Zend_XmlRpc_Request. Najważniejszą rzeczą jest zapamiętanie
  170. aby zawsze implementować metody getMethod() oraz getParams() co
  171. pozwoli na to, że serwer XML-RPC będzie mógł pobrać te informacje w
  172. celu uruchomienia żądania.
  173. </para>
  174. </sect2>
  175. <sect2 id="zend.xmlrpc.server.response">
  176. <title>Własne odpowiedzi</title>
  177. <para>
  178. Podobnie jak obiekty żądania, Zend_XmlRpc_Server może zwracać własne
  179. obiekty odpowiedzi; domyślnie zwracany jest obiekt
  180. Zend_XmlRpc_Response_Http, który wysyła odpowiedni nagłówek HTPP
  181. Content-Type do użycia z XML-RPC. Możliwym powodem użycia własnego
  182. obiektu może być potrzeba logowania odpowiedzi, lub wysyłanie
  183. odpowiedzi spowrotem do STDOUT.
  184. </para>
  185. <para>
  186. Aby użyć własnej klasy odpowiedzi, użyj metody
  187. Zend_XmlRpc_Server::setResponseClass() przed wywołaniem handle().
  188. </para>
  189. </sect2>
  190. <sect2 id="zend.xmlrpc.server.fault">
  191. <title>Obsługa wyjątków poprzez odpowiedzi błędów</title>
  192. <para>
  193. Obiekt Zend_XmlRpc_Server łapie wyjątki wyrzucone przez uruchomioną
  194. metodę i generuje odpowiedź błędu (fault) wtedy gdy taki wyjątek
  195. zostanie złapany. Domyślnie informacje o wyjątkach i ich kody nie są
  196. używane w odpowiedzi błędu. Jest to celowe zachowanie chroniące twój
  197. kod; wiele wyjątków ujawnia dużo informacji o kodzie oraz środowisku,
  198. czemu programista powinien zapobiec (dobrym przykładem mogą być
  199. informacje o wyjątkach związanych z bazą danych)
  200. </para>
  201. <para>
  202. Klasy wyjątków, które mają być użyte jako odpowiedzi błędów mogą być
  203. dodane do listy dozwolonych wyjątków. Aby to zrobić wystarczy użyć
  204. metody Zend_XmlRpc_Server_Fault::attachFaultException() w celu
  205. przekazania klasy wyjątku do listy dozwolonych wyjątków:
  206. </para>
  207. <programlisting role="php"><![CDATA[
  208. Zend_XmlRpc_Server_Fault::attachFaultException('My_Project_Exception');
  209. ]]>
  210. </programlisting>
  211. <para>
  212. Jeśli dodasz do listy wyjątków klasę wyjątku z którego dziedziczą
  213. inne wyjątki, możesz w ten sposób dodać do listy całą rodzinę
  214. wyjątków za jednym razem. Wyjątki Zend_XmlRpc_Server_Exceptions
  215. zawsze znajdują się na liście dozwolonych wyjątków, aby pozwolić na
  216. informowanie o specyficznych wewnętrznych błędach (niezdefiniowanie
  217. metody itp.).
  218. </para>
  219. <para>
  220. Każdy wyjątek spoza listy dozwolonych wyjątków spowoduje
  221. wygenerowanie odpowiedzi błędu o kodzie '404' i informacji
  222. 'Unknown error' (Nieznany błąd).
  223. </para>
  224. </sect2>
  225. <sect2 id="zend.xmlrpc.server.caching">
  226. <title>Buforowanie definicji serwera pomiędzy żądaniami</title>
  227. <para>
  228. Dołączanie wielu klas do instancji serwera XML-RPC może zajmować
  229. wiele zasobów; za pomocą Reflection API (przez Zend_Server_Reflection)
  230. musi być dokonana introspekcja każdej klasy co w rezultacie wygeneruje
  231. listę wszystkich możliwych sygnatur metod w celu przekazania jej
  232. do klasy serwera.
  233. </para>
  234. <para>
  235. Aby zredukować straty wydajności, możemy użyć obiektu
  236. Zend_XmlRpc_Server_Cache do buforowania definicji serwera pomiędzy
  237. żądaniami. Gdy połączymy to z funkcją __autoload(), może to mocno
  238. zwiększyć wydajność.
  239. </para>
  240. <para>
  241. Przykładowe użycie:
  242. </para>
  243. <programlisting role="php"><![CDATA[
  244. function __autoload($class)
  245. {
  246. Zend_Loader::loadClass($class);
  247. }
  248. $cacheFile = dirname(__FILE__) . '/xmlrpc.cache';
  249. $server = new Zend_XmlRpc_Server();
  250. if (!Zend_XmlRpc_Server_Cache::get($cacheFile, $server)) {
  251. require_once 'My/Services/Glue.php';
  252. require_once 'My/Services/Paste.php';
  253. require_once 'My/Services/Tape.php';
  254. $server->setClass('My_Services_Glue', 'glue'); // przestrzeń nazw glue
  255. $server->setClass('My_Services_Paste', 'paste'); // przestrzeń nazw paste
  256. $server->setClass('My_Services_Tape', 'tape'); // przestrzeń nazw tape
  257. Zend_XmlRpc_Server_Cache::save($cacheFile, $server);
  258. }
  259. echo $server->handle();
  260. ]]>
  261. </programlisting>
  262. <para>
  263. Powyższy przykład próbuje pobrać definicję serwera z pliku bufora
  264. xmlrpc.cache znajdującego się w tym samym katalogu co skrypt. Jeśli
  265. się to nie uda, załaduje on potrzebne klasy serwisu, dołączy do
  266. instancji serwera i spróbuje utworzyć nowy plik bufora z definicją
  267. sderwera.
  268. </para>
  269. </sect2>
  270. <sect2 id="zend.xmlrpc.server.use">
  271. <title>Przykład użycia</title>
  272. <para>
  273. Poniżej znajduje się kilka przykładów użycia, pokazując pełne
  274. spektrum opcji dostępnych dla programistów. Każdy z przykładów
  275. użycia jest oparty na poprzednich przykładach.
  276. </para>
  277. <sect3 id="zend.xmlrpc.server.use.case1">
  278. <title>Podstawowe użycie</title>
  279. <para>
  280. Poniższy przykład dołącza funkcję jaką uruchamialną przez
  281. XML-RPC metodę i obsługuje przychodzące wywołania.
  282. </para>
  283. <programlisting role="php"><![CDATA[
  284. /**
  285. * Zwraca sumę MD5 zadanej wartości
  286. *
  287. * @param string $value wartość do obliczenia sumy md5
  288. * @return string MD5 suma wartości
  289. */
  290. function md5Value($value)
  291. {
  292. return md5($value);
  293. }
  294. $server = new Zend_XmlRpc_Server();
  295. $server->addFunction('md5Value');
  296. echo $server->handle();
  297. ]]>
  298. </programlisting>
  299. </sect3>
  300. <sect3 id="zend.xmlrpc.server.use.case2">
  301. <title>Dołączanie klasy</title>
  302. <para>
  303. Poniższy przykład pokazuje dołączanie publicznych metod klasy
  304. jako uruchamialnych metod XML-RPC.
  305. </para>
  306. <programlisting role="php"><![CDATA[
  307. $server = new Zend_XmlRpc_Server();
  308. $server->setClass('Services_Comb');
  309. echo $server->handle();
  310. ]]>
  311. </programlisting>
  312. </sect3>
  313. <sect3 id="zend.xmlrpc.server.use.case3">
  314. <title>Dołączanie wielu klas używając przestrzeni nazw</title>
  315. <para>
  316. Poniższy przykład pokazuje dołączanie kilku klas, każdej z
  317. własną przestrzenią nazw.
  318. </para>
  319. <programlisting role="php"><![CDATA[
  320. $server = new Zend_XmlRpc_Server();
  321. $server->setClass('Services_Comb', 'comb'); // metody wywoływane jako comb.*
  322. $server->setClass('Services_Brush', 'brush'); // metody wywoływane jako brush.*
  323. $server->setClass('Services_Pick', 'pick'); // metody wywoływane jako pick.*
  324. echo $server->handle();
  325. ]]>
  326. </programlisting>
  327. </sect3>
  328. <sect3 id="zend.xmlrpc.server.use.case4">
  329. <title>Określenie wyjątków dla odpowiedzi błędów</title>
  330. <para>
  331. Poniższy przykład pozwala dowolnej klasie pochodzącej od
  332. Services_Exception na przekazywanie informacji o wyjątkach w
  333. postaci kodu i wiadomości w odpowiedzi błędu.
  334. </para>
  335. <programlisting role="php"><![CDATA[
  336. // Pozwala na wyrzucanie wyjątku Services_Exceptions dla odpowiedzi błędu
  337. Zend_XmlRpc_Server_Fault::attachFaultException('Services_Exception');
  338. $server = new Zend_XmlRpc_Server();
  339. $server->setClass('Services_Comb', 'comb'); // metody wywoływane jako comb.*
  340. $server->setClass('Services_Brush', 'brush'); // metody wywoływane jako brush.*
  341. $server->setClass('Services_Pick', 'pick'); // metody wywoływane jako pick.*
  342. echo $server->handle();
  343. ]]>
  344. </programlisting>
  345. </sect3>
  346. <sect3 id="zend.xmlrpc.server.use.case5">
  347. <title>Użycie własnego obiektu żądania</title>
  348. <para>
  349. Poniższy przykład tworzy instancję własnego obiektu żądania i
  350. przekazuje go do obiektu serwera.
  351. </para>
  352. <programlisting role="php"><![CDATA[
  353. // Pozwala na wyrzucanie wyjątku Services_Exceptions dla odpowiedzi błędu
  354. Zend_XmlRpc_Server_Fault::attachFaultException('Services_Exception');
  355. $server = new Zend_XmlRpc_Server();
  356. $server->setClass('Services_Comb', 'comb'); // metody wywoływane jako comb.*
  357. $server->setClass('Services_Brush', 'brush'); // metody wywoływane jako brush.*
  358. $server->setClass('Services_Pick', 'pick'); // metody wywoływane jako pick.*
  359. // Tworzenie obiektu żądania
  360. $request = new Services_Request();
  361. echo $server->handle($request);
  362. ]]>
  363. </programlisting>
  364. </sect3>
  365. <sect3 id="zend.xmlrpc.server.use.case6">
  366. <title>Użycie własnego obiektu odpowiedzi</title>
  367. <para>
  368. Poniższy przykład pokazuje określanie własnej klasy odpowiedzi
  369. dla zwracanej odpowiedzi.
  370. </para>
  371. <programlisting role="php"><![CDATA[
  372. // Pozwala na wyrzucanie wyjątku Services_Exceptions dla odpowiedzi błędu
  373. Zend_XmlRpc_Server_Fault::attachFaultException('Services_Exception');
  374. $server = new Zend_XmlRpc_Server();
  375. $server->setClass('Services_Comb', 'comb'); // metody wywoływane jako comb.*
  376. $server->setClass('Services_Brush', 'brush'); // metody wywoływane jako brush.*
  377. $server->setClass('Services_Pick', 'pick'); // metody wywoływane jako pick.*
  378. // Utwórz obiekt żądania
  379. $request = new Services_Request();
  380. // Użyj własnego obiektu żądania
  381. $server->setResponseClass('Services_Response');
  382. echo $server->handle($request);
  383. ]]>
  384. </programlisting>
  385. </sect3>
  386. <sect3 id="zend.xmlrpc.server.use.case7">
  387. <title>Buforowanie definicji serwera pomiędzy żądaniami</title>
  388. <para>
  389. Poniższy przykład pokazuje buforowanie definicji serwera pomiędzy
  390. żądaniami.
  391. </para>
  392. <programlisting role="php"><![CDATA[
  393. // Określ plik cache
  394. $cacheFile = dirname(__FILE__) . '/xmlrpc.cache';
  395. // Pozwala na wyrzucanie wyjątku Services_Exceptions dla odpowiedzi błędu
  396. Zend_XmlRpc_Server_Fault::attachFaultException('Services_Exception');
  397. $server = new Zend_XmlRpc_Server();
  398. // Spróbuj pobrać definicje serwera z bufora
  399. if (!Zend_XmlRpc_Server_Cache::get($cacheFile, $server)) {
  400. $server->setClass('Services_Comb', 'comb'); // metody wywoływane jako comb.*
  401. $server->setClass('Services_Brush', 'brush'); // metody wywoływane jako brush.*
  402. $server->setClass('Services_Pick', 'pick'); // metody wywoływane jako pick.*
  403. // Zapisz cache
  404. Zend_XmlRpc_Server_Cache::save($cacheFile, $server));
  405. }
  406. // Utwórz obiekt żądania
  407. $request = new Services_Request();
  408. // Użyj własnej klasy odpowiedzi
  409. $server->setResponseClass('Services_Response');
  410. echo $server->handle($request);
  411. ]]>
  412. </programlisting>
  413. </sect3>
  414. </sect2>
  415. </sect1>