<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-889576792288551864</id><updated>2012-02-07T14:41:58.214+01:00</updated><category term='IBM'/><category term='dokumentacje'/><category term='PHP'/><category term='DOM'/><category term='StAX'/><category term='SimpleXML'/><category term='Bazy Danych'/><category term='DB2'/><category term='Zend Framework'/><category term='XML'/><category term='Zend'/><category term='Java'/><category term='Ogólne'/><category term='SAX'/><title type='text'>Marcin Molak - w bezmiarze informacji</title><subtitle type='html'>O szeroko pojętej integracji, systemach BI, ... i życiu</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://mmolak.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/889576792288551864/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://mmolak.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Marcin 'frodo2000' Molak</name><uri>http://www.blogger.com/profile/11445820412848135632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='14' height='32' src='http://lh5.google.com/image/frodo2000/RhJvf1W7piI/AAAAAAAAAAk/R-TrBNFKJ5M/s144/ja.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>11</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-889576792288551864.post-4439898238995880457</id><published>2011-07-11T09:57:00.003+02:00</published><updated>2012-02-07T14:41:58.220+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DB2'/><category scheme='http://www.blogger.com/atom/ns#' term='IBM'/><title type='text'>Źródła wiedzy - IBM DB2</title><content type='html'>W poprzednim poście poruszyłem kwestie dokumentacji produktów IBM. Mimo, że są one najdokładniejszym (a przynajmniej powinny takim być) i użytecznym źródłem wiedzy, wielu z nas poszukuje łatwiej przyswajalnych alternatyw.&lt;br /&gt;O takie często pytany byłem w przypadku serwera IBM DB2. Jak się okazuje jest wiele (i to bezpłatnych) źródeł wiedzy dotyczących tego produktu. Poniżej przedstawiona jest ich lista:&lt;br /&gt;&lt;br /&gt;- polskie wydania magazynów SDJ Extra!:&lt;br /&gt;- &lt;a href="http://sdjournal.pl/magazine/1477-db2-9"&gt;SDJ Extra! - DB2 9&lt;/a&gt;&lt;br /&gt;- &lt;a href="http://sdjournal.pl/magazine/1351-db2-9-7"&gt;SDJ Extra! - DB2 9.7&lt;/a&gt;&lt;br /&gt;- książki z serii &lt;a href="http://www.ibm.com/developerworks/data/bestpractices/"&gt;Najlepsze praktyki DB2&lt;/a&gt;&lt;br /&gt;- książka &lt;a href="http://mysite.verizon.net/graeme_birchall/id1.html"&gt;DB2 SQL Cookbook&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;- blog &lt;a href="http://db2.com.pl/"&gt;Poznaj DB2&lt;/a&gt;&lt;br /&gt;- blog &lt;a href="http://www.db2ude.com/"&gt;DB2 UDE&lt;/a&gt;&lt;br /&gt;- portal &lt;a href="http://www.channeldb2.com/"&gt;Channel DB2&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;- książki z serii &lt;a href="https://www.ibm.com/developerworks/wikis/display/db2oncampus/FREE+eBooks"&gt;Getting started&lt;/a&gt;&lt;br /&gt;Wśród nich można znaleźć polską edycję "Wprowadzenie do DB2 Express-C 9.5", przygotowaną przez studentów Uniwersytetu im. Adama Mickiewicza w Poznaniu pod opieką Marcina Marczewskiego, kierownika zespołu migracyjnego w Laboratorium IBM.&lt;br /&gt;- magazyn &lt;a href="http://www.ibm.com/developerworks/data/dmmag/"&gt;IBM Data Management&lt;/a&gt;&lt;br /&gt;- dział &lt;a href="http://www.ibm.com/developerworks/data"&gt;Information Management&lt;/a&gt; na portalu Developerworks&lt;br /&gt;- książki z serii &lt;a href="http://redbooks.ibm.com/"&gt;IBM RedBooks&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Wśród płatnych publikacji warto wyróżnić:&lt;br /&gt;- książki Rogera Sandersa przygotowujące do certyfikatów IBM; Roger jest nota bene współautorem egzaminów z dziedziny administracji i programowania DB2&lt;br /&gt;- książkę Understanding DB2 zespołu w składzie: Raul F. Chong, Xiaomei Wang, Michael Dang, Dwaine R. Snow (w Polsce wydano również pierwszą edycje tej książki pod nazwą Zrozumieć DB2, jednak dotyczy ona już niewspieranej wersji 8 motoru)&lt;br /&gt;&lt;br /&gt;Dla klientów i business partnerów IBM dostępne są również bezpłatne warsztaty IBM Bootcamps. Ich listę można zobaczyć na &lt;a href="http://www.ibm.com/developerworks/wikis/display/im/Bootcamps+and+Education#BootcampsandEducation-bootcamps%22"&gt;stronie&lt;/a&gt;.&lt;br /&gt;Dodatkowo dział oprogramowania IBM Polska często organizuje niezależne warsztaty, np. Zostań ekspertem DB2.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/889576792288551864-4439898238995880457?l=mmolak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmolak.blogspot.com/feeds/4439898238995880457/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=889576792288551864&amp;postID=4439898238995880457' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/889576792288551864/posts/default/4439898238995880457'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/889576792288551864/posts/default/4439898238995880457'/><link rel='alternate' type='text/html' href='http://mmolak.blogspot.com/2011/07/zroda-wiedzy-ibm-db2.html' title='Źródła wiedzy - IBM DB2'/><author><name>Marcin 'frodo2000' Molak</name><uri>http://www.blogger.com/profile/11445820412848135632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='14' height='32' src='http://lh5.google.com/image/frodo2000/RhJvf1W7piI/AAAAAAAAAAk/R-TrBNFKJ5M/s144/ja.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-889576792288551864.post-8160199610140609381</id><published>2011-07-11T09:01:00.013+02:00</published><updated>2011-07-11T19:36:22.397+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DB2'/><category scheme='http://www.blogger.com/atom/ns#' term='IBM'/><category scheme='http://www.blogger.com/atom/ns#' term='dokumentacje'/><title type='text'>O dokumentacjach IBM słów kilka</title><content type='html'>Często w naszej pracy z produktami podstawowe źródło wiedzy stanowią ich dokumentacje. Nie inaczej wygląda pozyskiwanie informacji na temat oprogramowania sygnowanego marką IBM. Co więcej, &lt;b&gt;Centra informacyjne&lt;/b&gt; stanowią tak wygodny interfejs dostępu, że ich omówienie jest niekiedy elementem szkolenia (np. najlepszych moim zdaniem szkoleń Artura Wrońskiego na temat DB2).&lt;br /&gt;Aby znaleźć dokumentację interesującego nas produktu w ramach dowolnej wyszukiwarki wpisujemy jego nazwę dołączając frazę &lt;b&gt;Information Center&lt;/b&gt;. Dla przykładu będziemy posługiwać się dokumentacją najbliższego mi produktu IBM, czyli DB2. Wpiszmy zatem &lt;b&gt;IBM DB2 9.7 Information Center&lt;/b&gt;. Powinniśmy wówczas otrzymać rezultat podobny do poniższego:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-xImTxNgPmiI/ThqfyQnoT_I/AAAAAAAAAOM/M_5SBmqvlEk/s1600/search_result.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 241px;" src="http://2.bp.blogspot.com/-xImTxNgPmiI/ThqfyQnoT_I/AAAAAAAAAOM/M_5SBmqvlEk/s400/search_result.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5627986370156318706" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Wybieramy pierwszą pozycję, to jest odnośnik z adresem &lt;a href="http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/index.jsp"&gt;http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/index.jsp&lt;/a&gt;. Zanim jednak przejdziemy do omówienia interfejsu dokumentacji i jego użytecznych funkcji, warto pokusić się o pewną uwagę. W ramach adresu dokumentacji (prawie) każdego produktu określana jest jego wersja. W naszym przypadku widzimy zapis &lt;b&gt;v9r7&lt;/b&gt; co odpowiada wersji 9.7. Zmieniając go na &lt;b&gt;v9&lt;/b&gt; czy &lt;b&gt;v9r5&lt;/b&gt; możemy w łatwy sposób zmienić wcześniejszą wersję motoru danych.&lt;br /&gt;&lt;br /&gt;Niezależnie jednak od wersji (a nawet od produktu) otrzymujemy jednak taki sam, oparty na platformie Eclipse, interfejs:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-vdc5_xmdk5Q/Thqi-B5hPBI/AAAAAAAAAOU/bD7qaZYiJMY/s1600/doc.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 241px;" src="http://2.bp.blogspot.com/-vdc5_xmdk5Q/Thqi-B5hPBI/AAAAAAAAAOU/bD7qaZYiJMY/s400/doc.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5627989870898134034" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Po jego lewej stronie mamy zakładki ze spisem treści, indeksem oraz wynikami wyszukiwania. Po prawej zaś obszar treści z paskiem narzędzi. Zarówno lokalizacja interfejsu jak i samej zawartości są ściśle powiązane z ustawieniami językowymi przeglądarki. W przypadku języka polskiego należy jednak liczyć się z faktem, że nie wszystko jest obecnie przetłumaczone. Najczęściej jednak wszyscy i tak zmieniają język na angielski.&lt;br /&gt;&lt;br /&gt;Wyszukajmy w dokumentacji informacje o poleceniu &lt;b&gt;db2look&lt;/b&gt; i z otrzymanych wyników wybierzmy pierwszą pozycje:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-DrPdkXWeASY/Thqm47ja9AI/AAAAAAAAAOc/mF5IbUMCiNY/s1600/doc_search_result.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 241px;" src="http://2.bp.blogspot.com/-DrPdkXWeASY/Thqm47ja9AI/AAAAAAAAAOc/mF5IbUMCiNY/s400/doc_search_result.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5627994181342000130" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Widzimy, że wszystkie wystąpienia wyszukanej frazy są podświetlone w ramach treści. Czasem powoduje to jednak zmniejszenie czytelności wyświetlanego tekstu. Dlatego posłużymy się ikoną markera z paska narzędzi. Jednocześnie wybierzmy opcję wyszukania obecnie wyświetlanego tematu w spisie treści:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-TiSsKpRE36I/ThqpwouBR_I/AAAAAAAAAOk/13NxJ3emLiQ/s1600/toolbar.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 331px; height: 72px;" src="http://4.bp.blogspot.com/-TiSsKpRE36I/ThqpwouBR_I/AAAAAAAAAOk/13NxJ3emLiQ/s400/toolbar.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5627997337382111218" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Otrzymamy widok podobny do poniższego:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-3kz__Lyo340/ThqqM_-v9tI/AAAAAAAAAOs/5f2HHO7xHkk/s1600/doc_in_content.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 241px;" src="http://3.bp.blogspot.com/-3kz__Lyo340/ThqqM_-v9tI/AAAAAAAAAOs/5f2HHO7xHkk/s400/doc_in_content.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5627997824662632146" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Funkcjonalność wyszukiwania elementu w spisie treści wykorzystywana może być w przypadku, gdy nie potrzebujemy znaleźć element, którego nazwę zapomnieliśmy. W naszym przykładzie wyświetlenie komendy &lt;b&gt;db2look&lt;/b&gt; w spisie treści umożliwia znalezienie potrzebnego nam w danej chwili polecenia administracyjnego.&lt;br /&gt;&lt;br /&gt;Ostatnią kwestią jest przekazywanie hiperłącza do konkretnego elementu dokumentacji. W tej kwestii musimy otworzyć ten element korzystając z opcji Otwórz w nowej zakładce (nowym oknie) bądź użyć opcji Kopiowania łącza w przeglądarce. W przeciwnym wypadku skopiujemy początkowy adres dokumentacji produktu.&lt;br /&gt;&lt;br /&gt;Być może ktoś z Was zna jeszcze inne ciekawe funkcje dokumentacji IBM. Czekam na komentarze.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/889576792288551864-8160199610140609381?l=mmolak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmolak.blogspot.com/feeds/8160199610140609381/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=889576792288551864&amp;postID=8160199610140609381' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/889576792288551864/posts/default/8160199610140609381'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/889576792288551864/posts/default/8160199610140609381'/><link rel='alternate' type='text/html' href='http://mmolak.blogspot.com/2011/07/o-dokumentacjach-ibm-sow-kilka.html' title='O dokumentacjach IBM słów kilka'/><author><name>Marcin 'frodo2000' Molak</name><uri>http://www.blogger.com/profile/11445820412848135632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='14' height='32' src='http://lh5.google.com/image/frodo2000/RhJvf1W7piI/AAAAAAAAAAk/R-TrBNFKJ5M/s144/ja.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-xImTxNgPmiI/ThqfyQnoT_I/AAAAAAAAAOM/M_5SBmqvlEk/s72-c/search_result.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-889576792288551864.post-1195102168609533604</id><published>2011-07-05T09:04:00.003+02:00</published><updated>2011-07-05T12:29:13.060+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ogólne'/><title type='text'>Reaktywacja i zmiany...</title><content type='html'>"Jak ten czas leci" - tymi słowami chciałoby się podsumować przerwę w aktywności autora niniejszego blogu. Przerwę, która u wielu osób - z autorem włącznie - wywołała poczucie, iż nowe posty nie pojawią się już nigdy.&lt;br /&gt;&lt;br /&gt;W przyrodzie nic jednak nie ginie i również ten blog przeżywa swoją reinkarnacje. Nowe doświadczenia autora z zakresu zarządzania informacją, wywołały jednak chęć intensywnych zmian. Począwszy od samej nazwy, która odchodzi od zagadnień programowania na rzecz integracji informacji i systemów BI (wszak mamy mówić o Bezmiarze Informacji).&lt;br /&gt;&lt;br /&gt;Co więcej wpisy techniczne nie będą już miały tutaj wyłączności. Zobaczymy czy zmiany wyjdą na dobre. W każdym razie trzymajcie kciuki.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/889576792288551864-1195102168609533604?l=mmolak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmolak.blogspot.com/feeds/1195102168609533604/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=889576792288551864&amp;postID=1195102168609533604' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/889576792288551864/posts/default/1195102168609533604'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/889576792288551864/posts/default/1195102168609533604'/><link rel='alternate' type='text/html' href='http://mmolak.blogspot.com/2011/07/reaktywacja-i-zmiany.html' title='Reaktywacja i zmiany...'/><author><name>Marcin 'frodo2000' Molak</name><uri>http://www.blogger.com/profile/11445820412848135632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='14' height='32' src='http://lh5.google.com/image/frodo2000/RhJvf1W7piI/AAAAAAAAAAk/R-TrBNFKJ5M/s144/ja.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-889576792288551864.post-5925515943525807259</id><published>2008-11-28T08:16:00.002+01:00</published><updated>2008-11-28T11:24:21.096+01:00</updated><title type='text'>Software Developer's Journal 12/2008 - moje wrażenia</title><content type='html'>Nie sądziłem, iż po tak długi(e)j przerwie przyjdzie mi napisać kilka gorzkich słów na temat wydawnictwa, którego broniłem w komentarzach do artykułu na blogu Jacka Laskowskiego (patrz: &lt;a href="http://jlaskowski.blogspot.com/2008/10/wraenia-po-netbeans-day-2008-w-gdasku.html"&gt;Wrażenia po NetBeans Day 2008 w Gdańsku&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;Wówczas napisałem, iż powinniśmy wziąć się do roboty i przekazać własne artykuły do tegoż wydawnictwa zamiast narzekać. Siłę swojego apelu odczułem na sobie dzisiaj, gdy przyszło mi zapoznać się z najnowszym numerem - 12/2008.&lt;br /&gt;&lt;br /&gt;Początek nie był najgorszy - wśród aktualności udało mi się wyłuskać informacje o języku wspierającym proces projektowania aplikacji - Microsoft M, nowościach w MS Visual Studio 10 i premierze dacie premiery kolejnej wersji SQL Server'a. Pozostałe aktualności były raczej mało związane z programowaniem, ale traktuję ten dział jako możliwość poszerzenia horyzontów.&lt;br /&gt;&lt;br /&gt;Pierwszy artykuł (pomijając opis konferencji) dotyczył znanego w świecie Pythona szkieletu aplikacyjnego Django. Autor - Tomasz Kropiewnicki - w czytelny i ciekawy sposób wprowadza do opisywanej przez siebie technologii. Jedyne opisywana przez niego warstwa widoków mi przypomina raczej warstwę kontrolera, jako że jej funkcjonalność nie musi ograniczać się do generowania treści na stronie. Zaiste jednak artykuł warto przeczytać, traktując go jako odskocznie od świata Javy.&lt;br /&gt;&lt;br /&gt;Jednak kolejne artykuły wywołały we mnie zdziwienie. Po django jesteśmy bowiem uświadamiani jak założyć macierz typu mirror (RAID 1). Pomijam sam fakt, iż większość nowych płyt głównych obsługuje RAID w trybie fake-raid (realizowany programowo na poziomie BIOSu), a osoby które nie kupują drogich płyt głównych nie inwestują również w wiele dysków. Jednak wydaje się, iż ten artykuł jest świetnym materiałem na Linux+.&lt;br /&gt;&lt;br /&gt;Jeśli jednak pominiemy ten artykuł dalej czeka nas kolejna "niespodzianka" - 3 artykuły o grach. Rozumiem, iż nie samą pracą człowiek żyje. Sam lubię uruchomić jakąś grę od czasu do czasu, ale od informacji o tego typu oprogramowaniu nie szukam w SDJcie. Jako że i te gry są dla Linuksa to artykuły powinny znaleźć się znów w Linux+.&lt;br /&gt;&lt;br /&gt;Na szczęście dalej mamy już powrót do programowania. I takich artykułów programiści raczej oczekują. Więc jeśli ktoś z Nas wpadnie na ciekawy pomysł - przekazujmy naszą wiedzę innym :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/889576792288551864-5925515943525807259?l=mmolak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmolak.blogspot.com/feeds/5925515943525807259/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=889576792288551864&amp;postID=5925515943525807259' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/889576792288551864/posts/default/5925515943525807259'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/889576792288551864/posts/default/5925515943525807259'/><link rel='alternate' type='text/html' href='http://mmolak.blogspot.com/2008/11/software-developers-journal-122008-moje.html' title='Software Developer&apos;s Journal 12/2008 - moje wrażenia'/><author><name>Marcin 'frodo2000' Molak</name><uri>http://www.blogger.com/profile/11445820412848135632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='14' height='32' src='http://lh5.google.com/image/frodo2000/RhJvf1W7piI/AAAAAAAAAAk/R-TrBNFKJ5M/s144/ja.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-889576792288551864.post-3467234280968375422</id><published>2008-06-16T17:03:00.012+02:00</published><updated>2008-06-18T08:03:55.434+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DB2'/><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><title type='text'>DB2 w PHP (środowisko Windows)</title><content type='html'>Dość często tworząc aplikacje internetowe oparte na języku PHP ograniczamy się do platformy LAMP (Linux, Apache, MySQL i PHP). Czy jednak jest to jedyne rozwiązanie dostępne na rynku i czy nie mamy żadnej alternatywy?&lt;br /&gt;W ostatnich latach wielkie korporacje wydały bezpłatne alternatywy swoich serwerów baz danych. Ich licencje pozwalają na wykorzystanie zaawansowanych silników zarówno do niekomercyjnych jak i komercyjnych celów, stawiając jedynie ograniczenia na platformy sprzętowe (a dokładniej rzecz ujmując na wykorzystywane zasoby). Poniżej chciałbym skupić się na wykorzystaniu jednej z owych baz danych - IBM DB2 Express-C.&lt;br /&gt;&lt;br /&gt;W tej części skupimy się na instalacji całego środowiska na platformie systemowej Windows, natomiast w wolnym czasie postaram się dodać informacje na temat instalacji rozszerzenia php_ibm_db2 w środowisku Linux.&lt;br /&gt;&lt;br /&gt;Z czego będziemy korzystać:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Baza danych DB2 Express-C 9.5 - dostępna na stronie &lt;a href="http://www.ibm.com/db2/express"&gt;http://www.ibm.com/db2/express&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Serwer Apache HTTP 2 (u mnie 2.2.9) - dostępny na stronie &lt;a href="http://apache.org"&gt;http://apache.org&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Środowisko PHP (u mnie paczka php-5.2.6-Win32) - dostępne na stronie &lt;a href="http://www.php.net"&gt;http://www.php.net&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Rozszerzenie php_ibm_db2.dll (u mnie paczka pecl-5.2.6-Win32) - dostępne na stronie &lt;a href="http://www.php.net"&gt;http://www.php.net&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Po rozpakowaniu pliku z instalatorem serwera danych uruchamiamy program setup. Na ekranie pojawi się Setup Launchapd, w którym będziemy mogli zapoznać się z informacjami o nowej wersji, instrukcją migracji z poprzednich edycji DB2 czy wymaganiami systemowymi. Wybierając opcję Install a product możemy zainstalować nowe środowisko bazy danych. Po zaakceptowaniu licencji, wybieramy standardową opcję instalacji (Typical) i na 4 kolejnych ekranach zatwierdzamy domyślne wartości. Następnie będziemy poproszeni o podanie nazwy i hasła dla tak zwanego właściciela instancji. Warto zachować użytkownika dedykowanego - db2admin - i podać dla niego hasło zgodne z aktualną polityką bezpieczeństwa w systemie (bądź domenie).&lt;br /&gt;Po udanej instalacji przy pomocy konsoli Pierwsze Kroki (First Steps) będzie możliwe stworzenie przykładowej bazy danych SAMPLE.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;UWAGA&lt;/b&gt; Jeśli ktoś nie stworzy przykładowej bazy w tym miejscu będzie tego mógł dokonać z poziomu specjalnej powłoki systemowej (db2cmd) przy pomocy polecenia db2sampl -sql -xml&lt;br /&gt;&lt;br /&gt;Kolejnym krokiem będzie instalacja serwera Apache i PHP. W przypadku serwera WWW ogranicza się ona do zaakceptowania standardowych opcji instalacyjnych. Następnie należy rozpakować paczkę php-5.x.x-win32 do katalogu c:\PHP, a także z paczki pecl skopiować plik php_ibm_db2.dll do katalogu c:\PHP\ext.&lt;br /&gt;&lt;br /&gt;Czas na konfigurację całości. Tworzymy kopię pliku php.ini-dist o nazwię php.ini w katalogu c:\PHP i poddajemy ją edycji. W sekcji Paths and Directories ustawiamy wartość extension_dir na "c:\PHP\ext", w Dynamic Extensions dodajemy wpis&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;extension=php_ibm_db2.dll&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;a na końcu pliku&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;[IBM DB2]&lt;br /&gt;ibm_db2.instance_name=DB2&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;gdzie DB2 jest nazwą zainstalowanej przez nas instancji.&lt;br /&gt;&lt;br /&gt;Pozostało dołaczyć PHP do Apache. W tym celu przechodzimy do katalogu konfiguracyjnego Apache (u mnie C:\Program Files\Apache Software Foundation\Apache2.2\conf) i poddajemy edycji plik httpd.conf dodając na końcu:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# For PHP 5 do something like this:&lt;br /&gt;LoadModule php5_module "c:/php/php5apache2_2.dll"&lt;br /&gt;AddType application/x-httpd-php .php&lt;br /&gt;&lt;br /&gt;# configure the path to php.ini&lt;br /&gt;PHPIniDir "C:/php"&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Zanim wystartujemy serwer Apache warto przygotować sobie dwa pliki w katalogu htdocs (u mnie C:\Program Files\Apache Software Foundation\Apache2.2\htdocs). Pierwszy o nazwie test.php postaci:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?php&lt;br /&gt;   phpinfo();&lt;br /&gt;?&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;i plik db2test.php postaci:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?php&lt;br /&gt;  $database = 'SAMPLE';&lt;br /&gt;  $user = 'db2admin';&lt;br /&gt;  $password = 'twoje_haslo';&lt;br /&gt;  &lt;br /&gt;  $conn = db2_connect($database, $user, $password);&lt;br /&gt;  &lt;br /&gt;  if ($conn){&lt;br /&gt;    echo "Connected";&lt;br /&gt;    db2_close($conn);&lt;br /&gt;  }&lt;br /&gt;?&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Teraz pozostało jedynie uruchomienie serwera i sprawdzenie poprawności wyświetlania stron: http://localhost/test.php i http://localhost/db2test.php. Na pierwszej z nich powinny zostać wyświetlone zainstalowane moduły php, między innymi dodany przez nas ibm_db2. Na drugiej, jak łatwo się domyślić, wyświetli się napis Connected po nawiązaniu połączenia z bazą danych SAMPLE.&lt;br /&gt;&lt;br /&gt;Skoro mamy skonfigurowane środowisko możemy zapoznać się z listą funkcji, oferowanych przez moduł ibm_db2. Pełen spis znajdziemy na stronie &lt;a href="http://uk2.php.net/manual/pl/ref.ibm-db2.php"&gt;http://uk2.php.net/manual/pl/ref.ibm-db2.php&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Jednak jak mawiają dobry programista to leniwy programista. Pojawia się zatem pytanie czy nie można pominąć całego procesu konfiguracji i zainstalować gotowej paczki. Rozwiązaniem jest serwer Zend Core 2 for IBM dostępny na stronie &lt;a href="www.zend.com/en/products/core/downloads"&gt;www.zend.com/en/products/core/downloads&lt;/a&gt; . Pozwala on na dużo prostszą instalacje środowiska zawierającego Apache HTTP 2, PHP5 (z Zend Optimizerem) i DB2 Express-C 9.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/889576792288551864-3467234280968375422?l=mmolak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmolak.blogspot.com/feeds/3467234280968375422/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=889576792288551864&amp;postID=3467234280968375422' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/889576792288551864/posts/default/3467234280968375422'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/889576792288551864/posts/default/3467234280968375422'/><link rel='alternate' type='text/html' href='http://mmolak.blogspot.com/2008/06/db2-w-php-rodowisko-windows.html' title='DB2 w PHP (środowisko Windows)'/><author><name>Marcin 'frodo2000' Molak</name><uri>http://www.blogger.com/profile/11445820412848135632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='14' height='32' src='http://lh5.google.com/image/frodo2000/RhJvf1W7piI/AAAAAAAAAAk/R-TrBNFKJ5M/s144/ja.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-889576792288551864.post-1192137014437796047</id><published>2007-04-12T11:02:00.002+02:00</published><updated>2008-06-16T17:03:40.577+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Zend Framework'/><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='Zend'/><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><category scheme='http://www.blogger.com/atom/ns#' term='Bazy Danych'/><title type='text'>Zend Framework - obsługa baz danych</title><content type='html'>&lt;div style="text-align: justify; overflow: auto;"&gt;&lt;br /&gt;Przyznam szczerze, że na Zend Framework trafiłem dzięki praktykom w IBM, gdzie przyszło mi testować hybrydowy silnik baz danych (pureXML w DB2 9). Postanowiłem pobawić się bowiem serwerem Zend Core for IBM (dość szybko przerzuciłem się na Zend Core 2) i przy jego instalacji zauważyłem ZF.&lt;br /&gt;W dobie programowania obiektowego mamy szeroki wybór API, które zdeserializują nam rekord tablicy na obiekt klasy, pozwolą go zmodyfikować w łatwy sposób i dokonać ponownej serializacji. Sztandarowym przykładem jest na chwilę obecną zapewne Java Persistence API opisywana szczegółowo przez &lt;a href="http://jaceklaskowski.pl/"&gt;Jacka Laskowskiego&lt;/a&gt;, ale oczywiście takiej możliwości w Zend Framework zabraknąć nie mogło.&lt;br /&gt;Postanowiłem zatem omówić ten mechanizm i zwrócić uwagę na pewną ważną moim zdaniem kwestię - unikanie deserializacji do obiektów i wykorzystanie tablic bądź tablic asocjacyjnych tam (w Javie byłoby to używanie kolekcji lub tablic typów wbudowanych), gdzie istotne jest wydajne przetwarzanie informacji.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;W moim przykładzie posłużę się tabelą opisującą pęk promieni kosmicznych, podobną do tej z którą pracuję na co dzień:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;CREATE TABLE cosmic_rays(&lt;br /&gt;   id serial NOT NULL, -- Automatycznie generowany identyfikator&lt;br /&gt;   nix_date float8, -- Unix'owy stempel czasu&lt;br /&gt;   peak_particles float 8, -- Liczba zarejestrowanych cząstek&lt;br /&gt;   az float4, -- Położenie źródła we współrzędnych horyzontalnych - azymut&lt;br /&gt;   ze float4, -- Położenie źródła we współrzędnych horyzontalnych - odległość od zenitu&lt;br /&gt;   ra float4, -- Położenie źródła we współrzędnych niebieskich - rekt ascencja&lt;br /&gt;   dec float4, -- Położenie źródła we współrzędnych niebieskich - deklinacja&lt;br /&gt;   l float4, -- Położenie źródła we współrzędnych galaktycznych - szerokość gal&lt;br /&gt;   b float4, -- Położenie źródła we współrzędnych galaktycznych - długość gal&lt;br /&gt;   CONSTRAINT id PRIMARY KEY (id)&lt;br /&gt;) WITHOUT OIDS;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Jak łatwo się domyślić tabela jest przygotowana dla bazy opartej o PostgreSQL, ale nie trzeba wielu zabiegów, aby przystosować ją do innego systemu baz danych.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Struktura katalogów w projekcie&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Podobnie jak w poprzednim przykładzie opartym o Zend Framework struktura będzie wyglądać w następujący sposób:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;   &lt;li&gt;application&lt;ul&gt;&lt;br /&gt;         &lt;li&gt;controllers&lt;ul&gt;&lt;br /&gt;            &lt;li&gt;IndexController.php&lt;/li&gt;&lt;br /&gt;         &lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;         &lt;li&gt;models&lt;ul&gt;&lt;br /&gt;            &lt;li&gt;CosmicRays.php&lt;/li&gt;&lt;br /&gt;         &lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;         &lt;li&gt;views&lt;/li&gt;&lt;br /&gt;   &lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;configuration&lt;ul&gt;&lt;br /&gt;      &lt;li&gt;config.xml&lt;/li&gt;&lt;br /&gt;   &lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;library&lt;ul&gt;&lt;br /&gt;         &lt;li&gt;Zend&lt;/li&gt;&lt;br /&gt;         &lt;li&gt;Zend.php&lt;/li&gt;&lt;br /&gt;   &lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;public&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;.htaccess&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;index.php&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Plik .htaccess zawiera również jedynie informacje sterujące dla modułu rewrite:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;RewriteEngine on&lt;br /&gt;RewriteRule .* index.php&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Inicjalizacja połączenia z bazą danych&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Plik config.xml będzie zawierać niezbędne do zestawienia połączenia z bazą danych informacje:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="utf-8"&amp;gt;&lt;br /&gt;&amp;lt;configData&amp;gt;&lt;br /&gt;   &amp;lt;db&amp;gt;&lt;br /&gt;      &amp;lt;adapter&amp;gt;PDO_Pgsql&amp;lt;/adapter&amp;gt;&lt;br /&gt;      &amp;lt;configuration&amp;gt;&lt;br /&gt;         &amp;lt;host&amp;gt;localhost&amp;lt;/host&amp;gt;&lt;br /&gt;         &amp;lt;port&amp;gt;5432&amp;lt;/port&amp;gt;&lt;br /&gt;         &amp;lt;dbname&amp;gt;baza&amp;lt;/dbname&amp;gt;&lt;br /&gt;         &amp;lt;username&amp;gt;uzytkownik&amp;lt;/username&amp;gt;&lt;br /&gt;         &amp;lt;password&amp;gt;*****&amp;lt;/password&amp;gt;&lt;br /&gt;      &amp;lt;/configuration&amp;gt;&lt;br /&gt;   &amp;lt;/db&amp;gt;&lt;br /&gt;&amp;lt;/configData&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Możemy zatem przystąpić do konfiguracji bootstrapa w pliku index.php:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;//Ustawiamy ścieżki dostępu&lt;br /&gt;set_include_path('.' . PATH_SEPARATOR&lt;br /&gt;               . './library' . PATH_SEPARATOR&lt;br /&gt;               . './application/models/' . PATH_SEPARATOR&lt;br /&gt;               . get_include_path() );&lt;br /&gt;&lt;br /&gt;//Ładujemy klasę Zend_Loader&lt;br /&gt;require_once 'Zend/Loader.php';&lt;br /&gt;&lt;br /&gt;try{&lt;br /&gt;&lt;br /&gt;   //Ładujemy niezbędne klasy&lt;br /&gt;   &lt;b&gt;Zend_Loader::loadClass('Zend_Config_Xml');&lt;br /&gt;   Zend_Loader::loadClass('Zend_Db');&lt;br /&gt;   Zend_Loader::loadClass('Zend_Db_Table');&lt;/b&gt;&lt;br /&gt;   Zend_Loader::loadClass('Zend_Registry');&lt;br /&gt;   Zend_Loader::loadClass('Zend_View');&lt;br /&gt;   Zend_Loader::loadClass('Zend_Controller_Front');&lt;br /&gt;&lt;br /&gt;   //Ustalamy adres bazowy&lt;br /&gt;   $baseUrl = substr($_SERVER['PHP_SELF'], 0, &lt;br /&gt;                     strpos($_SERVER['PHP_SELF'], '/index.php'));&lt;br /&gt;&lt;br /&gt;   &lt;b&gt;//Ładujemy konfigurację bazy danych z pliku XML (gałąź db)&lt;br /&gt;   $config = new Zend_Config_Xml('./configuration/config.xml','db');&lt;br /&gt;   &lt;br /&gt;   //Tworzymy połączenie dla bazy danych i czynimy je domyślnym dla modeli tabel&lt;br /&gt;   $db = Zend_Db::factory($config-&gt;adapter, &lt;br /&gt;                          $config-&gt;configuration-&gt;asArray());&lt;br /&gt;   Zend_Db_Table::setDefaultAdapter($db);&lt;br /&gt;   &lt;/b&gt;&lt;br /&gt; &lt;br /&gt;   //Konfigurujemy klasę widoku&lt;br /&gt;   $view = new Zend_View();&lt;br /&gt;   $view-&gt;baseUrl = $baseUrl;&lt;br /&gt;   $view-&gt;setScriptPath('./application/views');&lt;br /&gt;   //Umieszczamy ją w rejestrze&lt;br /&gt;   Zend_Registry::set('view',$view);&lt;br /&gt;&lt;br /&gt;   //Inicjalizacja głównego kontrolera&lt;br /&gt;   $frontController = Zend_Controller_Front::getInstance();&lt;br /&gt;   $frontController-&gt;setRouter($router);&lt;br /&gt;   $frontController-&gt;setBaseUrl($baseUrl);&lt;br /&gt;   $frontController-&gt;setControllerDirectory(&lt;br /&gt;                               './application/controllers');&lt;br /&gt;   $frontController-&gt;throwExceptions(true);&lt;br /&gt;   $frontController-&gt;returnResponse(true);&lt;br /&gt;&lt;br /&gt;   //Inicjalizacja obiektu odpowiedzi&lt;br /&gt;   $response = $frontController-&gt;dispatch();&lt;br /&gt;   $response-&gt;renderExceptions(true);&lt;br /&gt;   $response-&gt;setHeader('Pragma', 'No-cache');&lt;br /&gt;   $response-&gt;setHeader('Cache-Control', 'no-cache');&lt;br /&gt;   &lt;br /&gt;   //Wyświetlenie strony&lt;br /&gt;   echo $response;&lt;br /&gt;&lt;br /&gt;} catch (Exception $e){&lt;br /&gt;   //Obsługa wyjątków&lt;br /&gt;   die($e-&gt;getMessage());&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Jak widać dodanie obsługi naszej bazy danych wymagało od nas 6 linijek kodu (wraz z importem plików odpowiednich bibliotek).&lt;br /&gt;Obiekt Zend_Config_Xml (dziedziczący po Zend_Config) jest obiektem pozwalającym na łatwe ładowanie plików konfiguracyjnych w postaci dokumentów XML. Jego użycie jest bardzo podobne do obsługi plików XML przy pomocy SimpleXML (patrz wcześniejszy post).&lt;br /&gt;Inicjalizacji połączenia dokonujemy przez statyczną metodę factory klasy Zend_Db, której podajemy typ adaptera (dla większości baz są to adaptery PDO, własne adaptery posiadają jedynie DB2, Oracle i Mysqli) oraz parametry konfiguracyjne.&lt;br /&gt;Z kolei statyczną metodą setDefaultAdapter klasy Zend_Db_Table ustawiamy utworzone połączenie dla wszystkich obiektów związanych z tabelami.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Nasz pierwszy model&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;W pliku CosmicRays.php umieścimy nasz model dla tabeli cosmic_rays:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   Zend_Loader::loadClass('Zend_Db_Table');&lt;br /&gt;&lt;br /&gt;   class CosmicRays extends Zend_Db_Table{&lt;br /&gt;      protected function _setup(){&lt;br /&gt;         //Standardowo ZF ustala nazwę tabeli jako łańcuch znaków występujący&lt;br /&gt;         //po ostatnim znaku _ w nazwie klasy modelu, więc musimy ją zmienić&lt;br /&gt;         $this-&gt;_name = 'cosmic_rays';&lt;br /&gt;         //Możemy również ustalić nazwę klucza głównego (jeśli inna niż id)&lt;br /&gt;         //oraz schemat tabeli (szczególnie ważne dla baz takich jak DB2 czy Oracle)&lt;br /&gt;&lt;br /&gt;         //Na koniec ładujemy ustawienia klasy bazowej&lt;br /&gt;         parent::_setup();&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I to by było na tyle. Musimy tylko stworzyć obiekt klasy CosmicRays i już możemy modyfikować jej obiekty. Do dyspozycji mamy metody (wymieniłem najważniejsze):&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;   &lt;li&gt;fetchNew() - tworzy nowy pusty "rekord"&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;fetchRow($where, $order) - zwraca pierwszy "rekord" z wyniku spełniającego warunek $where z uporządkowaniem $order&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;fetchAll($where, $order) - zwraca wszystkie "rekordy"&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;insert($data) - wstawia "rekord" na podstawie tablicy asocjacyjnej&lt;/li&gt;&lt;br /&gt;   &lt;li&gt;update($data, $where) - aktualizuje dane na podstawie tablicy asocjacyjnej&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;Warto zwrócić uwagę, iż metoda fetchAll zwraca nam obiekt typu Zend_Db_Table_Rowset z iteratorem dla obiektów Zend_Db_Table_Rows (dzięki temu możliwe jest przeglądanie kolekcji za pomocą pętli foreach). Metody fetchNew i fetchRow zwracają nam obiekt typu Zend_Db_Table_Row.&lt;br /&gt;Każdy z obiektów Zend_Db_Table_Row udostępnia nam dane w sposób podobny do obiektów stClass. Możemy zatem modyfikować je w łatwy sposób (niedopuszczalna jest jedynie modyfikacja klucza głównego), np.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   $cr  = new CosmicRays();&lt;br /&gt;   $row = $cr-&gt;fetchRow("id = 10");&lt;br /&gt;   $row-&gt;ra = 0;&lt;br /&gt;   $row-&gt;update();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Przytoczona powyżej metoda update() daje nam możliwość zaktualizowania obiektu. Istnieje również metoda save() pozwalająca na zapis nowego obiektu utworzonego za pomocą metody fetchNew().&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Problem wydajności&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Problemem na jaki natrafiłem było pobranie jedynie dwóch kolumn z całej tabeli. Oczywiście możemy stworzyć obiekt select. Jednak wymaga to umieszczenia obiektu $db w rejestrze, bądź wyłuskania go z obiektu modelu.&lt;br /&gt;Oczywiście dla zapytań łączących dane z wielu tabeli jest to praktycznie jedyna metoda. Co jeśli jednak chcemy dane wyłuskać TYLKO z jednej tabeli?&lt;br /&gt;&lt;br /&gt;Stwórzmy nową metodę w klasie modelu:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   public function fetchAllColumns(&lt;b&gt;$columns = null&lt;/b&gt;, $where = null, $order = null,&lt;br /&gt;   $count = null, $offset = null){&lt;br /&gt;   &lt;br /&gt;      // selection tool&lt;br /&gt;      $select = $this-&gt;_db-&gt;select();&lt;br /&gt;   &lt;br /&gt;      &lt;b&gt;//Set columns&lt;br /&gt;      $columns = (is_null($columns))?$this-&gt;_cols:$columns;&lt;/b&gt;&lt;br /&gt;           &lt;br /&gt;      // the FROM clause&lt;br /&gt;      $select-&gt;from($this-&gt;_name, $columns);&lt;br /&gt; &lt;br /&gt;      // the WHERE clause&lt;br /&gt;      $where = (array) $where;&lt;br /&gt;      foreach ($where as $key =&gt; $val) {&lt;br /&gt;         // is $key an int?&lt;br /&gt;         if (is_int($key)) {&lt;br /&gt;            // $val is the full condition&lt;br /&gt;            $select-&gt;where($val);&lt;br /&gt;         } else {&lt;br /&gt;            // $key is the condition with placeholder,&lt;br /&gt;            // and $val is quoted into the condition&lt;br /&gt;            $select-&gt;where($key, $val);&lt;br /&gt;         }&lt;br /&gt;      }&lt;br /&gt; &lt;br /&gt;      // the ORDER clause&lt;br /&gt;      if (!is_array($order)) {&lt;br /&gt;         $order = array($order);&lt;br /&gt;      }&lt;br /&gt;      foreach ($order as $val) {&lt;br /&gt;         $select-&gt;order($val);&lt;br /&gt;      }&lt;br /&gt; &lt;br /&gt;      // the LIMIT clause&lt;br /&gt;      $select-&gt;limit($count, $offset);&lt;br /&gt; &lt;br /&gt;      // return the results&lt;br /&gt;      $stmt = $this-&gt;_db-&gt;query($select);&lt;br /&gt;      $data = $stmt-&gt;fetchAll(Zend_Db::FETCH_ASSOC);&lt;br /&gt;                  &lt;br /&gt;      return $data;&lt;br /&gt;   }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Osoby, które przyglądały się klasie Zend_Db_Table_Abstract zauważą szybko, że moja metoda nie jest niczym innym jak lekko zmodyfikowaną metodą _fetch(...).&lt;br /&gt;Warto jednak spojrzeć na implementacje metody fetchAll(...) tej klasy. Otóż tablicę asocjacyjną opakowuje ona w obiekt Zend_Db_Table_Rowset. W sytuacjach kiedy zależy nam na wydajności oraz niskim zapotrzebowaniu na pamięć warto zrezygnować z ułatwienia jakie niesie za sobą klasa Zend_Db_Table_Rowset.&lt;br /&gt;&lt;br /&gt;Na koniec jeszcze jedna rada. Warto korzystać z instrukcji unset($data), szczególnie jeśli obiekt $data jest pokaźnych rozmiarów tablicą, której dalej nie zamierzamy używać. Tymbardziej, że często administratorzy serwerów nie dają dla skryptów php więcej niż 16MB pamięci. &lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/889576792288551864-1192137014437796047?l=mmolak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmolak.blogspot.com/feeds/1192137014437796047/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=889576792288551864&amp;postID=1192137014437796047' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/889576792288551864/posts/default/1192137014437796047'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/889576792288551864/posts/default/1192137014437796047'/><link rel='alternate' type='text/html' href='http://mmolak.blogspot.com/2007/04/zend-framework-obsuga-baz-danych.html' title='Zend Framework - obsługa baz danych'/><author><name>Marcin 'frodo2000' Molak</name><uri>http://www.blogger.com/profile/11445820412848135632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='14' height='32' src='http://lh5.google.com/image/frodo2000/RhJvf1W7piI/AAAAAAAAAAk/R-TrBNFKJ5M/s144/ja.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-889576792288551864.post-3142747166769652631</id><published>2007-04-04T19:27:00.000+02:00</published><updated>2007-04-12T13:45:01.974+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SAX'/><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='DOM'/><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><category scheme='http://www.blogger.com/atom/ns#' term='SimpleXML'/><title type='text'>Przetwarzanie XML w językach Java i PHP (cz.2)</title><content type='html'>&lt;div style="text-align: justify; overflow: auto"&gt;&lt;br /&gt;W przypadku PHP dostępność standardów obsługi XMLa ewoluowała wraz z kolejnymi wersjami. Dla wersji 3 dostępny był interfejs SAX, który nie zmienił się do chwili obecnej (problemy kompatybilności mogą być związane jedynie z obsługą przestrzeni nazw dla elementów, jeżeli zainstalowana jest biblioteka libxml2 w wersji starszej niż 2.6).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;W wersji 4 dodano obsługę DOM (rozszerzenie domxml) oraz XSLT (rozszerzenie xslt). Pierwsze z nich nie spełniało jednak założeń W3C, powodowało wiele wycieków pamięci, przez co nie było zbyt popularne. Drugie wymagało do działania biblioteki Sablotron lub Expat.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Prawdziwy przełom przyniosła wersja 5. Obsługa DOM została przepisana na nowo, zgodnie ze standardami W3C i umieszczona w rozszerzeniu DOM. Dodano obsługę XPath oraz walidację według plików DTD (odnośnik umieszczony w pliku XML), XSchema oraz RelaxNG (nazwa pliku definiowana w wywołaniu funkcji).&lt;br /&gt;XSLT zostało oparte o bibliotekę libxslt (najszybsze rozwiązanie na rynku) i umieszczone w rozszerzeniu XSL.&lt;br /&gt;Oba nabrały również prawdziwie obiektowego charakteru.&lt;br /&gt;Co więcej dodano interfejs SimpleXML umożliwiający łatwą modyfikacje plików XML bez znacznego obciążenia systemu charakterystycznego dla DOM.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;SAX&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Parser SAX tworzymy poprzez wywołanie funkcji xml_parser_create(); Kolejnym etapem jest utworzenie funkcji odpowiadających zdarzeniom XML i ich zarejestrowanie. Pod adresem &lt;a href="http://pl.php.net/manual/en/ref.xml.php#id7330424"&gt; http://pl.php.net/manual/en/ref.xml.php#id7330424&lt;/a&gt; dostępny jest przykład takiego parsera (łącznie ze sprawdzaniem zewnętrznych encji).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;DOM i SimpleXML&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;W przypadku PHP 5 użycie DOM jest analogiczne jak w innych językach programowania (JavaScript, Java...). Pracę z nim rozpoczynamy od utworzenia obiektu DOMDocument.&lt;br /&gt;SimpleXML jest natomiast bardzo ciekawym intefejsem. Na podstawie pliku XML tworzy on coś na kształt klasy PHP stdClass (dla innych języków obiektowych można porównać to do klasy będącej kolekcją obiektów). Dzięki czemu do danego elementu odwołujemy się w bardzo przyjemny sposób (Zend wykorzystał ten intefejs przy tworzeniu klasy Zend_Config_XML).&lt;br /&gt;Warto zauważyć, że poprzez funkcję simplexml_import_dom i dom_import_simplexml możemy łatwo konwertować dane z jednego standardu na drugi (jest to szczególnie przydatne w przypadku zapisywania dokumentu XML do pliku, której to SimpleXML funkcji nie posiada).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Przykład&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Na koniec chciałbym przedstawić przykład, który pobiera dane z tabeli Customers (baza Sample XML dla IBM DB2 9) i wyciąga z nich imię i nazwisko klienta. Pragnę zwrócić uwagę na dwa elementy. Po pierwsze różnice w objętości dla SimpleXML i DOM realizujących tą samą operację. Po drugie warto zauważyć, iż metody klas DOMDocument w PHP i Document dla Javy są takie same:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   error_reporting(E_ALL|E_STRICT);&lt;br /&gt;   &lt;br /&gt;   $user = "db2admin";&lt;br /&gt;   $password = "***";&lt;br /&gt;   $database = "SAMPLE";&lt;br /&gt;   $hostname = "localhost";&lt;br /&gt;   $port = 50000;&lt;br /&gt; &lt;br /&gt;   $connect_string = "DRIVER={IBM DB2 ODBC DRIVER};" .&lt;br /&gt;                     "DATABASE=$database;" .&lt;br /&gt;                     "HOSTNAME=$hostname;" .&lt;br /&gt;                     "PORT=$port;" .&lt;br /&gt;                     "PROTOCOL=TCPIP;" .&lt;br /&gt;                     "UID=$user;" .&lt;br /&gt;                     "PWD=$password;";&lt;br /&gt;   $connection = db2_connect($connect_string,'','');&lt;br /&gt;   if ($connection){&lt;br /&gt;      echo "Connection successful.&amp;lt;br /&amp;gt;";&lt;br /&gt;      $sql = "SELECT INFO FROM CUSTOMER WHERE CID = ?";&lt;br /&gt;      $statement = db2_prepare($connection, $sql);&lt;br /&gt;      db2_execute($statement,array(1001));&lt;br /&gt;  &lt;br /&gt;      while ($customer = db2_fetch_object($statement)){&lt;br /&gt;         $info = $customer-&gt;INFO;&lt;br /&gt;      &lt;br /&gt;         //SimpleXML&lt;br /&gt;         $simpleXML = new SimpleXMLElement($info);&lt;br /&gt;         echo $simpleXML-&gt;name."&amp;lt;br /&amp;gt;";&lt;br /&gt;&lt;br /&gt;         //DOM&lt;br /&gt;         $domDocument = new DOMDocument('1.0','UTF-8');&lt;br /&gt;         $domDocument-&gt;loadXML($info);&lt;br /&gt;         $names = $domDocument-&gt;getElementsByTagName('name');&lt;br /&gt;         foreach ($names as $name) {&lt;br /&gt;            echo $name-&gt;nodeValue.'&amp;lt;br /&amp;gt;';&lt;br /&gt;         }&lt;br /&gt;      }&lt;br /&gt;      db2_close($connection);&lt;br /&gt;   }else{&lt;br /&gt;      echo "Connection failed.";&lt;br /&gt;   }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Podsumowanie&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Pokazane w obu częściach przykłady stanowią jedynie czubek góry lodowej związanej z przetwarzaniem dokumentów XML w językach Java i PHP. Jednak mogę okazać się przydatnym wstępem do dalszego zgłębiania tematu.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Wszelakie komentarze i uwagi mile widziane&lt;/b&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/889576792288551864-3142747166769652631?l=mmolak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmolak.blogspot.com/feeds/3142747166769652631/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=889576792288551864&amp;postID=3142747166769652631' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/889576792288551864/posts/default/3142747166769652631'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/889576792288551864/posts/default/3142747166769652631'/><link rel='alternate' type='text/html' href='http://mmolak.blogspot.com/2007/04/przetwarzanie-xml-w-jzykach-java-i-php_04.html' title='Przetwarzanie XML w językach Java i PHP (cz.2)'/><author><name>Marcin 'frodo2000' Molak</name><uri>http://www.blogger.com/profile/11445820412848135632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='14' height='32' src='http://lh5.google.com/image/frodo2000/RhJvf1W7piI/AAAAAAAAAAk/R-TrBNFKJ5M/s144/ja.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-889576792288551864.post-2807369039599387116</id><published>2007-04-04T15:04:00.000+02:00</published><updated>2007-04-12T13:43:09.816+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SAX'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='DOM'/><category scheme='http://www.blogger.com/atom/ns#' term='StAX'/><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><title type='text'>Przetwarzanie XML w językach Java i PHP (cz.1)</title><content type='html'>&lt;div style="text-align: justify; overflow: auto;"&gt;&lt;br /&gt;Realizując praktyki z bazą IBM DB2 9 (w szczególności jej hybrydowym silnikiem) napotkałem na brak informacji na temat przetwarzania danych XML dostępnych w postaci strumieni.&lt;br /&gt;&lt;br /&gt;Podczas lektury książki J2EE. Vademecum Programisty doszedłem nawet do błędnego wniosku jakoby przed wersją 1.6 Javy nie była taka obsługa zaimplementowana w standardzie. Wszędzie były tylko informacje jak parsować pliki XML.&lt;br /&gt;&lt;br /&gt;Po przeszukaniu internetu natrafiłem na STreaming Api for XML (StAX) i jego dokumentacje w postaci JSR-173. Okazało się, że Java SE 1.6 zawiera nawet interfejs do niego, jednak brak jest implementacji. Na stronie &lt;a href="http://stax.codehaus.org/"&gt;http://stax.codehaus.org/&lt;/a&gt; szybko tą implementację znalazłem, a później natrafiłem jeszcze na implementację Sun'a (pod adresem &lt;a href="https://sjsxp.dev.java.net/"&gt;https://sjsxp.dev.java.net/&lt;/a&gt;) oraz Bea Weblogic (pod adresem &lt;a href="http://dev2dev.bea.com/xml/stax.html"&gt;http://dev2dev.bea.com/xml/stax.html&lt;/a&gt;). Ponieważ pierwsza z tych trzech stanowi implementację referencyjną będzie użyta w niniejszym tutorialu.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Niezależnie od wszystkiego postanowiłem jeszcze raz sprawdzić możliwości analizy strumieni tekstowych z XMLem dla standardów Simple Api for XML (SAX) i Document Object Model (DOM). Okazało się, że tkwiłem w błędnym przekonaniu.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;SAX&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;SAX jest uznawany za najszybszy i najmniej pamięciożerny parser XML. Opiera się o reprezentację zdarzeniową, w której otwarcie i zamknięcie każdego dokumentu, znacznika czy występowanie tekstu jest określane jako zdarzenie.&lt;br /&gt;&lt;br /&gt;Niewątpliwą wadą SAXa jest brak wiedzy o położeniu w pliku XML (stanu). Jest to również dość ciężki do implementacji we własnych projektach interfejs.&lt;br /&gt;&lt;br /&gt;Pracę z SAXem rozpoczynamy od stworzenia klasy reagującej na zdarzenia (u mnie MyHandler). Poniższy przykład opiera się na kodzie zawartym w książce J2EE. Vademecum Programisty dostępnej w sprzedaży wydawnictwa Helion:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package org.f2k.test;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;import java.io.OutputStreamWriter;&lt;br /&gt;import java.io.UnsupportedEncodingException;&lt;br /&gt;import java.io.Writer;&lt;br /&gt;import org.xml.sax.Attributes;&lt;br /&gt;import org.xml.sax.SAXException;&lt;br /&gt;import org.xml.sax.helpers.DefaultHandler;&lt;br /&gt;&lt;br /&gt;public class MyHandler extends DefaultHandler {&lt;br /&gt;   StringBuffer textBuffer;&lt;br /&gt;   static private Writer  out;&lt;br /&gt;   &lt;br /&gt;   public MyHandler() throws UnsupportedEncodingException{&lt;br /&gt;      out = new OutputStreamWriter(System.out, "UTF8");&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public void startDocument() throws SAXException{&lt;br /&gt;      nl();&lt;br /&gt;      nl();&lt;br /&gt;      emit("START OF DOCUMENT");&lt;br /&gt;      nl();&lt;br /&gt;      emit("&lt;?xml version='1.0' encoding='UTF-8'?&gt;");&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public void endDocument() throws SAXException{&lt;br /&gt;      nl(); &lt;br /&gt;      emit("END OF DOCUMENT");&lt;br /&gt;      try {&lt;br /&gt;         nl();&lt;br /&gt;         out.flush();&lt;br /&gt;      } catch (IOException e) {&lt;br /&gt;         throw new SAXException("IO Exception", e);&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   public void startElement(String namespaceURI,&lt;br /&gt;   String sName, // nazwa skrócona&lt;br /&gt;   String qName, // nazwa pełna&lt;br /&gt;   Attributes attrs) throws SAXException{&lt;br /&gt;        &lt;br /&gt;      echoText();&lt;br /&gt;      nl(); &lt;br /&gt;      emit("ELEMENT: ");&lt;br /&gt;      String eName = sName; // nazwa elementu&lt;br /&gt;      // bez uwzględnienia nazwy przestrzeni nazw&lt;br /&gt;      if ("".equals(eName)) &lt;br /&gt;         eName = qName; &lt;br /&gt;      emit("&lt;"+eName);&lt;br /&gt;      if (attrs != null) {&lt;br /&gt;         for (int i = 0; i &lt; attrs.getLength(); i++) {&lt;br /&gt;            String aName = attrs.getLocalName(i); // nazwa atrybutu&lt;br /&gt;            if ("".equals(aName)) aName = attrs.getQName(i);&lt;br /&gt;            nl();&lt;br /&gt;            emit("   ATR: ");&lt;br /&gt;            emit(aName);&lt;br /&gt;            emit("\t\"");&lt;br /&gt;            emit(attrs.getValue(i));&lt;br /&gt;            emit("\"");&lt;br /&gt;         }&lt;br /&gt;      }&lt;br /&gt;      if (attrs.getLength() &gt; 0) nl();&lt;br /&gt;      emit("&gt;");&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public void endElement(String namespaceURI,&lt;br /&gt;   String sName, // nazwa skrócona&lt;br /&gt;   String qName  // nazwa pełna&lt;br /&gt;   )throws SAXException {&lt;br /&gt;      echoText();&lt;br /&gt;      nl();&lt;br /&gt;      emit("END_OF_ELEM: ");&lt;br /&gt;      String eName = sName; // nazwa elementu&lt;br /&gt;      if ("".equals(eName)) &lt;br /&gt;         eName = qName;&lt;br /&gt;      emit("&lt;/"+eName+"&gt;");&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public void characters(char buf[], int offset, int len)&lt;br /&gt;   throws SAXException{&lt;br /&gt;      String s = new String(buf, offset, len);&lt;br /&gt;      if (textBuffer == null) {&lt;br /&gt;         textBuffer = new StringBuffer(s);&lt;br /&gt;      } else {&lt;br /&gt;         textBuffer.append(s);&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;    &lt;br /&gt;&lt;br /&gt;   // Metody pomocnicze&lt;br /&gt;   private void echoText() throws SAXException{&lt;br /&gt;      if (textBuffer == null) return;      &lt;br /&gt;      nl(); &lt;br /&gt;      emit("CHARS: |");&lt;br /&gt;      String s = ""+textBuffer;&lt;br /&gt;      emit(s);&lt;br /&gt;      emit("|");&lt;br /&gt;      textBuffer = null;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private void emit(String s) throws SAXException{&lt;br /&gt;      try {&lt;br /&gt;         out.write(s);&lt;br /&gt;         out.flush();&lt;br /&gt;      } catch (IOException e) {&lt;br /&gt;         throw new SAXException("IO Exception", e);&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private void nl() throws SAXException{&lt;br /&gt;      String lineEnd =  System.getProperty("line.separator");&lt;br /&gt;      try {&lt;br /&gt;         out.write(lineEnd);&lt;br /&gt;      } catch (IOException e) {&lt;br /&gt;         throw new SAXException("IO Exception", e);&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Skoro mamy już klasę obsługującą zdarzenia przygotujmy klasę testową, dzięki której będziemy mogli podać String zawierający XML:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package org.f2k.test;&lt;br /&gt;&lt;br /&gt;import java.io.ByteArrayInputStream;&lt;br /&gt;import java.io.InputStream;&lt;br /&gt;import javax.xml.parsers.SAXParser;&lt;br /&gt;import javax.xml.parsers.SAXParserFactory;&lt;br /&gt;import org.xml.sax.helpers.DefaultHandler;&lt;br /&gt;&lt;br /&gt;public class SAXTest {&lt;br /&gt;   SAXTest(String xml){&lt;br /&gt;      this(new ByteArrayInputStream(xml.getBytes()));&lt;br /&gt;   }&lt;br /&gt; &lt;br /&gt;   SAXTest(InputStream stream){&lt;br /&gt;      try {&lt;br /&gt;         DefaultHandler handler = new MyHandler();&lt;br /&gt;         SAXParserFactory factory = SAXParserFactory.newInstance();&lt;br /&gt;         SAXParser parser = factory.newSAXParser();&lt;br /&gt;         parser.parse(stream, handler);&lt;br /&gt;      } catch (Exception e) {&lt;br /&gt;         e.printStackTrace();&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Mamy właściwie wszystko co potrzeba dla SAX. Możemy jeszcze dla obiektu factory ustawić opcję sprawdzania dokumentu XML według DTD, itp. Ale to pozostawiam już programistom:)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;DOM&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;DOM jest parserem, który wykorzystuje się do złożonych modyfikacji XML, czy jego reprezentacji w postaci drzewa obiektu. Jego wadą jest fakt, że jest zasobożerny. Cały dokument jest bowiem przetwarzany w pamięci komputera.&lt;br /&gt;&lt;br /&gt;W przypadku DOM możemy od razu napisać naszą klasę testową:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package org.f2k.test;&lt;br /&gt;&lt;br /&gt;import java.io.ByteArrayInputStream;&lt;br /&gt;import java.io.InputStream;&lt;br /&gt;import javax.xml.parsers.DocumentBuilder;&lt;br /&gt;import javax.xml.parsers.DocumentBuilderFactory;&lt;br /&gt;import org.w3c.dom.Document;&lt;br /&gt;import org.w3c.dom.NodeList;&lt;br /&gt;&lt;br /&gt;public class DOMTest {&lt;br /&gt;   public DOMTest(String xml){&lt;br /&gt;      this(new ByteArrayInputStream(xml.getBytes()));&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public DOMTest(InputStream stream){&lt;br /&gt;      try {&lt;br /&gt;         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();&lt;br /&gt;         DocumentBuilder builder = factory.newDocumentBuilder();&lt;br /&gt;         Document document = builder.parse(stream);&lt;br /&gt;         NodeList names = document.getElementsByTagName("name");&lt;br /&gt;         for(int i=0; i &amp;lt; names.getLength(); i++){&lt;br /&gt;            System.out.println(names.item(i).getTextContent());&lt;br /&gt;         }&lt;br /&gt;      } catch (Exception e) {&lt;br /&gt;         e.printStackTrace();&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Nasz test wyszukuje w dokumencie XML węzły o nazwie name i wyświetla ich zawartość.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;StAX&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;StAX jest pareserem opracowanym przez firmę BEA. Choć jego działanie opiera się na zdarzeniowej formie XML, to udostępnia nam wiedzę o położeniu w dokumencie poprzez iterator. Pozwala to na szybszą niż w przypadku DOM deserializację prostych obiektów.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Najprostszym użyciem StAXa jest stworzenie funkcji, która będzie analizować zdarzenia. W poniższym przykładzie funkcja processEvent będzie realizować podobne zadanie do klasy MyHandler z testu SAX:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package org.f2k.test;&lt;br /&gt;&lt;br /&gt;import java.io.*;&lt;br /&gt;import javax.xml.stream.*;&lt;br /&gt;import javax.xml.stream.events.*;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public class StAXTest {&lt;br /&gt;   StringBuffer textBuffer;&lt;br /&gt;   static private Writer out;&lt;br /&gt;&lt;br /&gt;   StAXTest(String xml){&lt;br /&gt;      this(new ByteArrayInputStream(xml.getBytes()));&lt;br /&gt;   }&lt;br /&gt; &lt;br /&gt;   StAXTest(InputStream stream){&lt;br /&gt;     try {&lt;br /&gt;        out = new OutputStreamWriter(System.out, "UTF8");&lt;br /&gt;     } catch (UnsupportedEncodingException e1) {&lt;br /&gt;        e1.printStackTrace();&lt;br /&gt;     }&lt;br /&gt;     /*Implementation of StAX*/&lt;br /&gt;     System.setProperty("javax.xml.stream.XMLInputFactory",&lt;br /&gt;     "com.bea.xml.stream.MXParserFactory"); &lt;br /&gt;&lt;br /&gt;     try {&lt;br /&gt;        XMLInputFactory inputFactory &lt;br /&gt;            = XMLInputFactory.newInstance();&lt;br /&gt; XMLEventReader eventReader &lt;br /&gt;            = inputFactory.createXMLEventReader(stream);&lt;br /&gt;        while (eventReader.hasNext()){&lt;br /&gt;           XMLEvent event = (XMLEvent) eventReader.next();&lt;br /&gt;           processEvent(event);&lt;br /&gt;        }&lt;br /&gt;     } catch (Exception e) {&lt;br /&gt;       e.printStackTrace();&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   public void processEvent(XMLEvent event) throws IOException{&lt;br /&gt;      if (event.isStartElement()){&lt;br /&gt;         echoText();&lt;br /&gt;         nl(); &lt;br /&gt;         emit("ELEMENT: &lt;");&lt;br /&gt;         emit(((StartElement) event).getName().toString());&lt;br /&gt;         emit("&gt;");&lt;br /&gt;      }&lt;br /&gt;      if (event.isCharacters()){&lt;br /&gt;         String s = ((Characters) event).getData();&lt;br /&gt;         if (textBuffer==null){&lt;br /&gt;            textBuffer = new StringBuffer(s);&lt;br /&gt;         } else {&lt;br /&gt;            textBuffer.append(s);&lt;br /&gt;         }&lt;br /&gt;      }&lt;br /&gt;      if (event.isEndElement()){&lt;br /&gt;         echoText();&lt;br /&gt;         nl();&lt;br /&gt;         emit("END_OF_ELEM: ";&lt;br /&gt;         emit("&lt;/"+((EndElement) event).getName().toString()+"&gt;");&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt; &lt;br /&gt;   // Metody pomocnicze&lt;br /&gt;   private void echoText() throws IOException{&lt;br /&gt;      if (textBuffer == null) return;      &lt;br /&gt;      nl(); &lt;br /&gt;      emit("CHARS: |");&lt;br /&gt;      String s = ""+textBuffer;&lt;br /&gt;      emit(s);&lt;br /&gt;      emit("|");&lt;br /&gt;      textBuffer = null;&lt;br /&gt;   }&lt;br /&gt;   private void emit(String s) throws IOException{&lt;br /&gt;      out.write(s);&lt;br /&gt;      out.flush();&lt;br /&gt;   }&lt;br /&gt;   private void nl() throws IOException{&lt;br /&gt;      String lineEnd =  System.getProperty("line.separator");&lt;br /&gt;      out.write(lineEnd);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Skoro mamy już wszystkie testy pora sprawdzić działanie każdego z parsera. Do tego celu wykorzystałem tabelę Customer z bazy SAMPLE (w wersji XML) dostępnej z DB2 9. Poniżej kod zestawiający połączenie i pobierający rekord:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package org.f2k.test;&lt;br /&gt;&lt;br /&gt;import java.io.InputStream;&lt;br /&gt;import java.sql.Connection;&lt;br /&gt;import java.sql.DriverManager;&lt;br /&gt;import java.sql.PreparedStatement;&lt;br /&gt;import java.sql.ResultSet;&lt;br /&gt;import com.ibm.db2.jcc.DB2Xml;&lt;br /&gt;&lt;br /&gt;public class DB2Connector {&lt;br /&gt;   String password="***";&lt;br /&gt;   String user="db2admin";&lt;br /&gt;&lt;br /&gt;   String url = "jdbc:db2://localhost:50000/SAMPLE";&lt;br /&gt;   public DB2Connector(){&lt;br /&gt;      try {&lt;br /&gt;         Class.forName("com.ibm.db2.jcc.DB2Driver").newInstance();&lt;br /&gt;         Connection conn = DriverManager.getConnection(url, &lt;br /&gt;                                             user, password);&lt;br /&gt;         PreparedStatement stmt  = conn.prepareStatement(&lt;br /&gt;                "SELECT INFO FROM MCUSTOMER WHERE CID = ?");&lt;br /&gt;         //Należy wcześniej sprawdzić czy użytkownik o CID 1001 istnieje&lt;br /&gt;         stmt.setInt(1, 1001);&lt;br /&gt;         ResultSet result = stmt.executeQuery();&lt;br /&gt;         while (result.next()){&lt;br /&gt;            DB2Xml info = (DB2Xml) result.getObject("INFO");&lt;br /&gt;            String xmlText = info.getDB2XmlString();&lt;br /&gt;     System.out.print("DB2XmlString:\n"+xmlText);&lt;br /&gt;            //Dla kodowania innego niż UTF-8 tylko StAX przechodzi test&lt;br /&gt;            InputStream stream = info.getDB2XmlBinaryStream("UTF-8");&lt;br /&gt;            System.out.println("\n");&lt;br /&gt;            System.out.println("DB2Xml from StAX test:");&lt;br /&gt;            new StAXTest(stream);&lt;br /&gt;            System.out.println("\n");&lt;br /&gt;            System.out.println("DB2Xml from SAX test:");&lt;br /&gt;            stream.reset();&lt;br /&gt;            new SAXTest(stream);&lt;br /&gt;            System.out.println("\n");&lt;br /&gt;            System.out.println("DB2Xml from DOM test:");&lt;br /&gt;            stream.reset();&lt;br /&gt;            new DOMTest(stream);&lt;br /&gt;         }&lt;br /&gt;         result.close();&lt;br /&gt;         conn.close();&lt;br /&gt;      } catch (Exception e) {&lt;br /&gt;         e.printStackTrace();&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   public static void main(String[] args){&lt;br /&gt;      new DB2Connector();&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Wyniki&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Parsery StAX i SAX powinny zwrócić w wyniku poszatkowaną strukturę XML z opisami zdarzeń. Natomiast DOM powinien wyświetlić imię i nazwisko klienta, wyciągnięte z XMLa (u mnie Kathy Smith).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;W drugiej części opiszę systemy przetwarzania XML z PHP. Również na podstawie danych zaczerpniętych z DB2.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/889576792288551864-2807369039599387116?l=mmolak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmolak.blogspot.com/feeds/2807369039599387116/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=889576792288551864&amp;postID=2807369039599387116' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/889576792288551864/posts/default/2807369039599387116'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/889576792288551864/posts/default/2807369039599387116'/><link rel='alternate' type='text/html' href='http://mmolak.blogspot.com/2007/04/przetwarzanie-xml-w-jzykach-java-i-php.html' title='Przetwarzanie XML w językach Java i PHP (cz.1)'/><author><name>Marcin 'frodo2000' Molak</name><uri>http://www.blogger.com/profile/11445820412848135632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='14' height='32' src='http://lh5.google.com/image/frodo2000/RhJvf1W7piI/AAAAAAAAAAk/R-TrBNFKJ5M/s144/ja.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-889576792288551864.post-8752980831646187129</id><published>2007-04-04T11:49:00.000+02:00</published><updated>2007-04-12T13:42:14.740+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Zend Framework'/><category scheme='http://www.blogger.com/atom/ns#' term='Zend'/><title type='text'>Zend_Controller_Router_Route i tworzenie nowych tras (dla wersji 0.9 i nowszych)</title><content type='html'>&lt;div style="text-align: justify; overflow:auto;"&gt;&lt;br /&gt;Jak słusznie zauważył Wojciech w komentarzu do poprzedniego postu od wersji 0.9 wprowadzono kilka zmian. Między innymi w celu umieszczenia biblioteki w jednym katalogu postanowiono podzielić klasę Zend na kilka innych. Plik Zend.php zapewnie zniknie w wersji 1.0.&lt;br /&gt;&lt;br /&gt;Jako, że ja w swoim projekcie opierałem się o wersję 0.8 postanowiłem podać zmodyfikowaną wersję kodu, a właściwie jedynie fragmentu pliku index.php:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; //Od tej pory zamiast pliku Zend.php ładujemy klasę loadera&lt;br /&gt;&lt;br /&gt; require_once 'Zend/Loader.php';&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; try {&lt;br /&gt;&lt;br /&gt;    //&lt;b&gt;Ładowanie klas odbywa się poprzez metodę klasy&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;    //&lt;b&gt;Zend_Loader&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;    //&lt;b&gt;Dodatkowo wymagana jest klasa obsługi rejestu&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;    Zend_Loader::loadClass('Zend_Registry');&lt;br /&gt;&lt;br /&gt;    Zend_Loader::loadClass('Zend_View');&lt;br /&gt;&lt;br /&gt;    Zend_Loader::loadClass('Zend_Controller_Front');&lt;br /&gt;&lt;br /&gt;    Zend_Loader::loadClass('Zend_Controller_Router_Rewrite');&lt;br /&gt;&lt;br /&gt;    //Ustalamy adres bazowy&lt;br /&gt;    $baseUrl = substr($_SERVER['PHP_SELF'], 0,&lt;br /&gt;&lt;br /&gt;                     strpos($_SERVER['PHP_SELF'], '/index.php'));&lt;br /&gt;  &lt;br /&gt;    //Konfigurujemy klasę widoku&lt;br /&gt;    $view = new Zend_View();&lt;br /&gt;    $view-&gt;baseUrl = $baseUrl;&lt;br /&gt;    $view-&gt;setScriptPath('./application/views');&lt;br /&gt;    //Umieszczamy ją w rejestrze poprzez metodę nowej klasy&lt;br /&gt;    Zend_Registry::set('view',$view);&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Reszta kodu pozostaje bez zmian&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/889576792288551864-8752980831646187129?l=mmolak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmolak.blogspot.com/feeds/8752980831646187129/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=889576792288551864&amp;postID=8752980831646187129' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/889576792288551864/posts/default/8752980831646187129'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/889576792288551864/posts/default/8752980831646187129'/><link rel='alternate' type='text/html' href='http://mmolak.blogspot.com/2007/04/zendcontrollerrouterroute-i-tworzenie_04.html' title='Zend_Controller_Router_Route i tworzenie nowych tras (dla wersji 0.9 i nowszych)'/><author><name>Marcin 'frodo2000' Molak</name><uri>http://www.blogger.com/profile/11445820412848135632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='14' height='32' src='http://lh5.google.com/image/frodo2000/RhJvf1W7piI/AAAAAAAAAAk/R-TrBNFKJ5M/s144/ja.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-889576792288551864.post-509812213381113847</id><published>2007-04-03T17:42:00.000+02:00</published><updated>2007-04-04T11:48:37.468+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Zend Framework'/><category scheme='http://www.blogger.com/atom/ns#' term='Zend'/><title type='text'>Zend_Controller_Router_Route i tworzenie nowych tras</title><content type='html'>&lt;div style="text-align: justify;"&gt;&lt;br /&gt;Ostatnio na polskim forum Zend Framework spotkałem się z problemem obsługi przyjaznych adresów. Standardowo biblioteka ta obsługuje adresy w postaci:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;http://nazwa_strony/nazwa_kontrolera/nazwa_akcji/parametr/wartość&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Jednak strona miała zawierać treść wielojęzyczną. I choć Zend obsługuje możliwość odczytania informacji z przeglądarki to programista chciał sterować językiem poprzez umieszczenie kodu przed nazwą kontrolera, np.:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;http://nazwa_strony/pl/nazwa_kontrolera/...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Postanowiłem zatem zajrzeć do dokumentacji i napisać niezbędny kod. Zaczniemy od struktury katalogów, którą zaczerpnąłem z jednego tutoriala:&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;application&lt;/li&gt;&lt;ul&gt;&lt;li&gt;controllers&lt;/li&gt;&lt;ul&gt;&lt;li&gt;IndexController.php&lt;br /&gt;&lt;/li&gt;       &lt;/ul&gt;&lt;li&gt;models&lt;br /&gt;&lt;/li&gt;&lt;li&gt;views&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;library&lt;br /&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Zend&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Zend.php&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;public&lt;br /&gt;&lt;/li&gt;&lt;li&gt;.htaccess&lt;br /&gt;&lt;/li&gt;&lt;li&gt;index.php&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/span&gt;Plik .htaccess zawiera informacje sterujące dla modułu rewrite:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;RewriteEngine on&lt;br /&gt;RewriteRule .* index.php&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Plik index.php stanowi tak zwany bootstrap dla ZF. W nim dokonujemy należy zainicjalizować wszystkie niezbędne do działania elementy środowiska. A więc do dzieła:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   //Konfiguracja debugowania&lt;br /&gt;&lt;br /&gt;   define('_DEBUG',1);&lt;br /&gt; &lt;br /&gt;   &lt;br /&gt;&lt;br /&gt;   if (defined('_DEBUG'))&lt;br /&gt;&lt;br /&gt;      if (_DEBUG == 1)&lt;br /&gt; &lt;br /&gt;         error_reporting(E_ALL|E_STRICT);&lt;br /&gt;&lt;br /&gt;   &lt;br /&gt;&lt;br /&gt;   date_default_timezone_set('Europe/Warsaw');&lt;br /&gt;&lt;br /&gt;   &lt;br /&gt;&lt;br /&gt;   //Konfigurujemy ścieżki bibliotek&lt;br /&gt;&lt;br /&gt;   set_include_path('.' . PATH_SEPARATOR&lt;br /&gt;&lt;br /&gt;                    . './library' . PATH_SEPARATOR&lt;br /&gt;&lt;br /&gt;             . './application/models/' . PATH_SEPARATOR&lt;br /&gt;&lt;br /&gt;             . get_include_path() );&lt;br /&gt;&lt;br /&gt;   &lt;br /&gt;&lt;br /&gt;   //Ładujemy jądro ZF&lt;br /&gt;&lt;br /&gt;   include('Zend.php');&lt;br /&gt;&lt;br /&gt;   &lt;br /&gt;&lt;br /&gt;   try {&lt;br /&gt;&lt;br /&gt;      //Ładujemy niezbędne klasy&lt;br /&gt;&lt;br /&gt;      Zend::loadClass('Zend_View');&lt;br /&gt;&lt;br /&gt;      Zend::loadClass('Zend_Controller_Front');&lt;br /&gt;&lt;br /&gt;      Zend::loadClass('Zend_Controller_Router_Rewrite');&lt;br /&gt;&lt;br /&gt;      &lt;br /&gt; &lt;br /&gt;      //Ustawiamy adres bazowy&lt;br /&gt;&lt;br /&gt;      $baseUrl = substr($_SERVER['PHP_SELF'], 0, &lt;br /&gt;&lt;br /&gt;                        strpos($_SERVER['PHP_SELF'], '/index.php'));&lt;br /&gt;&lt;br /&gt;      &lt;br /&gt;&lt;br /&gt;      //Konfiguracja klasy widoku&lt;br /&gt;      $view = new Zend_View();&lt;br /&gt;&lt;br /&gt;      $view-&gt;baseUrl = $baseUrl;&lt;br /&gt;&lt;br /&gt;      $view-&gt;setScriptPath('./application/views');&lt;br /&gt;&lt;br /&gt;      Zend::register('view',$view);&lt;br /&gt;&lt;br /&gt;      &lt;br /&gt;&lt;br /&gt;      //Tutaj konfigurujemy naszą nową trasę&lt;br /&gt;&lt;br /&gt;      $route = new Zend_Controller_Router_Route(&lt;br /&gt;&lt;br /&gt;      ':lang/:controller/:action',&lt;br /&gt; &lt;br /&gt;      //&lt;b&gt;Zmienna określająca język znajduje się przed kontrolerem&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;      array('lang'=&gt;'pl', 'controller'=&gt;'index',&lt;br /&gt; &lt;br /&gt;      'action'=&gt;'index'), //Wartości domyślne&lt;br /&gt;&lt;br /&gt;      array('lang'=&gt;'[a-z_]+')); //Warunek dla lang&lt;br /&gt;&lt;br /&gt;      &lt;br /&gt; &lt;br /&gt;      //Utworzenie routera z naszą trasą&lt;br /&gt;&lt;br /&gt;      $router = new Zend_Controller_Router_Rewrite(); &lt;br /&gt;&lt;br /&gt;      $router-&gt;removeDefaultRoutes();&lt;br /&gt;&lt;br /&gt;      $router-&gt;addRoute('user', $route);&lt;br /&gt;&lt;br /&gt;      &lt;br /&gt;&lt;br /&gt;      //Inicjalizacja głównego kontrolera&lt;br /&gt;&lt;br /&gt;      $frontController = Zend_Controller_Front::getInstance();&lt;br /&gt;&lt;br /&gt;      $frontController-&gt;setRouter($router);&lt;br /&gt;&lt;br /&gt;      $frontController-&gt;setBaseUrl($baseUrl);&lt;br /&gt;&lt;br /&gt;      $frontController-&gt;setControllerDirectory(&lt;br /&gt;&lt;br /&gt;                        './application/controllers');&lt;br /&gt;&lt;br /&gt;      $frontController-&gt;throwExceptions(true);&lt;br /&gt;&lt;br /&gt;      $frontController-&gt;returnResponse(true);&lt;br /&gt;&lt;br /&gt;      &lt;br /&gt;&lt;br /&gt;      //Inicjalizacja obiektu odpowiedzi&lt;br /&gt;&lt;br /&gt;      $response = $frontController-&gt;dispatch();&lt;br /&gt;&lt;br /&gt;      $response-&gt;renderExceptions(true);&lt;br /&gt;&lt;br /&gt;      $response-&gt;setHeader('Pragma', 'No-cache');&lt;br /&gt;&lt;br /&gt;      $response-&gt;setHeader('Cache-Control', 'no-cache');&lt;br /&gt;&lt;br /&gt;      &lt;br /&gt;&lt;br /&gt;      //Wyświetlenie strony&lt;br /&gt;&lt;br /&gt;      echo $response;&lt;br /&gt;&lt;br /&gt;   } catch (Exception $exception) {&lt;br /&gt;&lt;br /&gt;      //Obsługa wyjątku&lt;br /&gt;&lt;br /&gt;      $message = '&lt;b&gt;Application setup exception: &lt;/b&gt;';&lt;br /&gt;&lt;br /&gt;      $message.= $exception-&gt;getMessage();&lt;br /&gt;&lt;br /&gt;      if (defined('_DEBUG')) if (_DEBUG){&lt;br /&gt;&lt;br /&gt;         $message .= '&lt;b&gt;Trace: &lt;/b&gt;'.$exception-&gt;getTraceAsString();&lt;br /&gt;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      die($message);&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Nie pozostało zatem nic innego jak odczytać informacje o języku. Dokonamy tego w pliku IndexController.php:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class IndexController extends Zend_Controller_Action&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;   function indexAction()&lt;br /&gt;&lt;br /&gt;   {&lt;br /&gt;&lt;br /&gt;      echo $this-&gt;_getParam('lang','pl');&lt;br /&gt;&lt;br /&gt;      echo " in IndexController::indexAction()";&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Po przekopiowaniu plików na serwer dostaniemy informacje o języku i wywołanej metodzie&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/889576792288551864-509812213381113847?l=mmolak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmolak.blogspot.com/feeds/509812213381113847/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=889576792288551864&amp;postID=509812213381113847' title='Komentarze (3)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/889576792288551864/posts/default/509812213381113847'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/889576792288551864/posts/default/509812213381113847'/><link rel='alternate' type='text/html' href='http://mmolak.blogspot.com/2007/04/zendcontrollerrouterroute-i-tworzenie.html' title='Zend_Controller_Router_Route i tworzenie nowych tras'/><author><name>Marcin 'frodo2000' Molak</name><uri>http://www.blogger.com/profile/11445820412848135632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='14' height='32' src='http://lh5.google.com/image/frodo2000/RhJvf1W7piI/AAAAAAAAAAk/R-TrBNFKJ5M/s144/ja.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-889576792288551864.post-4780575624343675151</id><published>2007-04-03T17:34:00.000+02:00</published><updated>2007-04-03T17:40:34.564+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ogólne'/><title type='text'>Powitanie</title><content type='html'>&lt;span style="font-family: arial;"&gt;Na wstępie nie wypada mi nie przywitać wszystkich osób, które pojawiły się na moim blogu. Powstał on właściwie pod wpływem Jacka Laskowskiego, który w przejrzysty sposób dzieli się swoimi doświadczeniami z zakresu J2EE.&lt;br /&gt;Co prawda nie mogę porównać swojej wiedzy do zakresu wiadomości Jacka. Jednak postanowiłem dzielić się swoimi doświadczeniami z programowaniem. Często zdarzało mi się bowiem dotykać technologii, które nie były popularne na rynku polskim i ciężko było znaleźć dokładny opis ich działania.&lt;br /&gt;Zapraszam zatem do czytania i komentowania moich nowych postów.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/889576792288551864-4780575624343675151?l=mmolak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mmolak.blogspot.com/feeds/4780575624343675151/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=889576792288551864&amp;postID=4780575624343675151' title='Komentarze (1)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/889576792288551864/posts/default/4780575624343675151'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/889576792288551864/posts/default/4780575624343675151'/><link rel='alternate' type='text/html' href='http://mmolak.blogspot.com/2007/04/powitanie.html' title='Powitanie'/><author><name>Marcin 'frodo2000' Molak</name><uri>http://www.blogger.com/profile/11445820412848135632</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='14' height='32' src='http://lh5.google.com/image/frodo2000/RhJvf1W7piI/AAAAAAAAAAk/R-TrBNFKJ5M/s144/ja.jpg'/></author><thr:total>1</thr:total></entry></feed>
