PHP Solutions 06 2007 PL

84

description

* Symfony Framework* Vanilla* Delphi i PHP* Creole* AJAX w CakePHP* Atom* Google Web Toolkit* PayPal – omówienie i zalety* SEO i SEM* Delphi for PHP* UPS* Wywiad z Markiem Sodolskim (Amway) i Tomaszem Skutnikiem (e-point)* PEAR i Marketing z Google* Społeczność PHP?

Transcript of PHP Solutions 06 2007 PL

Page 1: PHP Solutions 06 2007 PL
Page 2: PHP Solutions 06 2007 PL
Page 3: PHP Solutions 06 2007 PL
Page 4: PHP Solutions 06 2007 PL

4 06/2007 5www.phpsolmag.org

06 AKTUALNOŚCIIreneusz Wierzejski

08 OPIS CD

DLA POCZĄTKUJĄCYCH10 Symfony Framework Łukasz KlejnbergŁukasz pokaże Ci w przystępny sposób, jak zainstalować i skonfigu-rować Symfony, a na przykładzie prostej strony WWW zapoznasz się z możliwościami tego frameworka. Między innymi dowiesz się jak zrobić rejestrację nowego użytkownika oraz w jaki sposób można sprawdzić dane przesłane z formularza.

18 VanillaPaweł ChwastPaweł w artykule przedstawia alternatywę dla najpopularniejsze-go skryptu forum punBB. Autor pokrótce przestawia historię Vani-lii, wymagania oraz możliwości tej aplikacji. Ponadto dowiesz się jak zwiększyć możliwości forum za pomocą specjalnych rozszerzeń.

TECHNIKA22 PHP i WAPTomasz RoszkoTomasz pokaże Ci, jak stworzyć dynamiczną witrynę WWW dla WAP z wykorzystaniem PHP. Dowiesz się, jak wykonać menu i przesłać in-formacje na serwer. Dzięki tym informacjom można bez trudu two-rzyć podobne aplikacje, włączając w to system logowania, system newsów i wiele, wiele innych.

26 Delphi i PHPArtur ChudzikArtur pokaże Ci, jak prostym sposobem można stworzyć własne aplikacje służące do komunikacji pomiędzy językami Delphi i PHP, za pomocą metody POST.

SPIS TREŚCI

PHP Solutions jest wydawany przez Software-Wydawnictwo Sp. z o.o.

Dyrektor wydawniczy: Sylwia Pogroszewska

Redaktor naczelny: Patrycja Wądołowska [email protected]

Redaktorzy prowadzący: Anna Kozioł [email protected] Magdalena Sobiś [email protected]

Projekt okładki: Agnieszka Marchocka

Skład i łamanie: Robert Zadrożny [email protected]

Kierownik produkcji: Marta Kurpiewska [email protected]

Korekta: Agnieszka Bronowicka [email protected]óżnieni betatesterzy: G. Hibner, H. Woroszył, A. Trafalski

Dział reklamy: [email protected]: Marzena Dmowska [email protected]

Nakład: 6 000 egz.

Page 5: PHP Solutions 06 2007 PL

4 06/2007 5www.phpsolmag.org

ROZWIĄZANIA32 CreolePiotr GradzińskiPiotr przedstawi Ci, jak pisać skrypty łączące się z różnymi typami baz danych - od połączenia poprzez zapytania aż do obróbki wyni-ków. Do tego celu użyje pakietu Creole oraz pokaże Ci jak wykorzy-stać niektóre narzędzia biblioteki Jargon.

38 AJAX w CakePHPPiotr GapińskiPiotr pokaże Ci praktyczne zastosowanie technologii AJAX w środo-wisku framework'u CakePHP. Po analizie przedstawionego kodu bę-dziesz mógł wzbogacić własny serwis o dynamicznie prezentowane dane. Po zapoznaniu się z artykułem, dowiesz się, że dzięki zastoso-waniu framework’ów, takich jak CakePHP możesz zwiększyć funkcjo-nalność serwisów.

44 AtomPatryk SzlagowskiPatryk zaprezentuje Ci składnię kanału informacyjnego typu RSS. Ponadto pokarze Ci jak za pomocą php wygenerować taki działający kanał informacyjny. Wystarczy, że znasz podstawy obsługi bazy My-SQL i operacji na plikach.

NARZĘDZIA46 Google Web Toolkit Rafał MalinowskiRafał przedstawi Ci zalety GWT. Dowiesz się jakie możliwości wy-korzystania i rozbudowania narzędzi języka Java przy pomocy Ja-vaScriptu daje GWT. Ponadto będziesz wiedział kiedy wybrać Go-ogle Web Toolkit.

54 PayPal – omówienie i zaletyMariusz Wielkopolski, Mariusz TytykMariusz pokaże Ci, jak założyć sobie konto w PayPal. Dowiesz się jak zintegrować płatności ze swoją stroną internetową i jak testować moduł płatności nie używając prawdziwych pieniędzy.

KASA DLA WEBMASTERA62 SEO i SEMPiotr KenigPiotr porusza podstawowe aspekty związane z przeprowadzeniem kampanii marketingowej pod kątem działań SEO i SEM dla małych i średnich firm.

ARTYKUŁ WARSZTATOWY66 Delphi for PHPŁukasz SkowrońskiPierwszy z trzech artykułów warsztatowych opisujący pratyczne za-stosowanie programu Delphi for PHP. Lektura tych artykułów pomo-że wam w wykonaniu własnej aplikacji i zdobyciu rewelacyjnych na-gród w ogłoszonym konkursie.

TESTY KONSUMENCKIE70 UPS

WYWIAD74 Wywiad z Markiem Sodolskim (Amway)i Tomaszem Skutnikiem (e-point)Magdalena Sobiś, Anna KoziołWywiad z Markiem Sodolskim – dyrektorem naczelnym Amway Pol-ska oraz Tomaszem Skutnikiem – dyrektorem badań i rozwoju fir-my e-point.

RECENZJE77 PEAR i Marketing z GooglePaweł Kołodziej, Łukasz Skowroński

FELIETON78 Społeczność PHP?Łukasz Skowroński

Adres korespondencyjny:Software-Wydawnictwo Sp. z o.o., ul. Bokserska 1, 02-682 Warszawa, Polskatel. +48 22 427 36 86, fax +48 22 427 36 69www.phpsolmag.org [email protected]

Dołączoną do magazynu płytę CD przetestowano programem AntiVirenKit firmy G DATA Software Sp. z o.o.

Redakcja dokłada wszelkich starań, by publikowane w piśmie i na towarzyszących mu nośnikach informacje i programy były poprawne, jednakże nie bierze odpowiedzialności za efekty wykorzystania ich; nie gwarantuje także poprawnego działania programów shareware, freeware i public domain.

Uszkodzone podczas wysyłki płyty wymienia redakcja.

Wszystkie znaki firmowe zawarte w piśmie są własności odpowiednich firm zostały użyte wyłącznie w celach informacyjnych.

Redakcja używa systemu automatycznego składu

Do tworzenia wykresów i diagramów wykorzystano program firmy

Osoby zainteresowane współpracą prosimy o kontakt:[email protected]

Druk: ArtDruk

Wysokość nakładu obejmuje również dodruki. Redakcja nie udziela pomocy technicznej w instalowaniu i użytkowaniu programów zamieszczonych na płycie CD-ROM dostarczonej razem z pismem.

Sprzedaż aktualnych lub archiwalnych numerów pisma po innej cenie niż wydrukowana na okładce – bez zgody wydawcy – jest działaniem na jego szkodę i skutkuje odpowiedzialnością sądową.

Pismo ukazuje się w następujących wersjach językowych:

polskiej , francuskiej

Page 6: PHP Solutions 06 2007 PL

Aktualności

6

Aktualności

7

Alladyn i strona ZPAVMinęły już prawie trzy miesiące od czasu ogłoszenia, że strona internetowa Związ-ku Producentów Audio-Video (ZPAV) naru-sza licencję skryptu Alladyn. Jednak przed-stawiciele Związku jak dotąd nie wyjaśnili tej sprawy, a chodzi przecież o organizację, która na co dzień zajmuje się ochroną praw autorskich twórców.

Przypomnijmy więc pokrótce - kilka osób przeglądając źródła witryny ZPAV dostrze-gło, że korzysta ona ze skryptu o nazwie Alladyn, a licencja tej biblioteki wymaga zamieszczenia informacji o jej wykorzysta-niu, czego w kodzie strony ZPAV nie ma ani teraz, ani nigdy wcześniej nie było.

Witrynie ZPAV przyjrzeli się także sami twórcy Alladyna. Spostrzegli oni, iż sko-rzystano na niej ze zmodyfikowanej wersji tego skryptu, na co nie zezwala żadna licencja. Stało się więc oczywiste, że ZPAV, który korzystając z pomocy policji, ściga osoby i firmy łamiące prawo autorskie, sam to prawo łamie.

Po pewnym czasie, zupełnie bez związ-ku z tą sprawą, biblioteka Alladyn została upubliczniona na licencji Open Source a jej autorzy ogłosili, że chcieliby, aby była ona jak najczęściej stosowana. Nie wpłynęło to jednak w żaden sposób na fakt, że witry-na Związku wcześniej tę licencję naruszy-ła, a na stronie ZPAV najprawdopodobniej nadal znajduje się wersja biblioteki, która została tam zamieszczona z naruszeniem warunków licencji.

Związek Producentów Audio-Video koja-rzony jest przede wszystkim z antypiracki-mi akcjami policji. Warto jednak nadmienić, że organizacja statutowo zajmuje się rów-nież edukacją, a jednym z jej sztandaro-wych programów jest akcja „Bądź oryginal-ny”. Za jej pomocą ZPAV stara się zaszczepić przekonanie, iż naruszanie praw autorskich jest nieetyczne oraz, że należy szanować pracę twórców. Z tymi niewątpliwie szczyt-nymi ideami sam Związek najwyraźniej ma pewien problem – organizacja nie wykaza-ła się najmniejszym szacunkiem dla twór-ców biblioteki Alladyn.

Przekaz płynący z działań ZPAV jest, jak się wydaje, następujący: „Duże organiza-cje mające za sobą kapitał mogą naruszać prawa autorskie twórców małego skryptu”. Tenże przekaz jest zresztą zgodny z jedną z wypowiedzi pełnomocnika Związku, który nieuważnie stwierdził, że „Alladyn to tylko mały program”.

Koniec PHP4Ciągle bardzo popularny w ofertach firm hostingowych PHP 4.x już wkrótce będzie musiał ustąpić miejsca PHP 5, albowiem oficjalnie ogłoszono wstrzymanie prac nad rozwojem tej wersji języka. Wsparcie ma być kontynuowane do końca bieżą-cego roku, później nie będą już wydawa-ne żadne nowe wersje, za wyjątkiem pat-chów łatających wykryte błędy krytyczne. Porady dotyczące migracji z PHP 4 do PHP 5 znajdują się na stronie http://www.php.net/manual/en/migration5.php

Php Blue Dragon 3.0.0

Polski system CMS rozbudowuje się co-raz bardziej. Jest on dostępny na zasa-dach licencji GNU GPL. Właśnie kil-

ka dni temu pojawiła się wersja 3.0.0. Ta wer-sja została wzbogacona w nowe elementy sys-temu takie jak na przykład edytor WYSIWYG TinyCE który dostępny jest z panelu admini-stratora.

Dzięki niemu można wpisywać treści od ra-zu bez potrzeby ich podglądu na stronie. Do-datkowe zmiany zostały także wprowadzone w klasie do generowania formularzy zwiększa-jąc ich pole. Pojawiły się poprawki pozwalające na pracę systemu w PHP wersji 5 która obec-nie jest wersją stabilną.

System jest też dostępny w dwóch językach: polskim i angielskim, które można wybrać pod-czas instalacji, a następnie zastosować podczas wprowadzania treści.

Sam system w obecnej wersji zawiera po-nad 35 modułów: nowości, proste nowości, artykuły, zaawansowane artykuły, pobiera-nie, słownik, FAQ, strony informacyjne, fo-rum dyskusyjne z możliwością tworzenia grup i podgrup.

Posiada on także liczne bloki do prezento-wania wprowadzonych treści: menu systemo-we, najnowsze i najczęściej czytanie nowo-ści, najnowsze artykuły, pliku do pobrania, informacje, wyszukiwarkę Google oraz wie-le innych.

Dla użytkowników systemu został wypo-sażony w system rejestracji, logowania, zmia-ny profilu, zmiany hasła, przypominanie ha-

sła, listę użytkowników oraz prywatne wia-domości które użytkownicy mogą do siebie wysyłać.

Dodatkowo został wprowadzony podział na grupy który przydaje się na forum do de-finiowania dostępu i moderatorów danego działu.

CMS posiada także opcję przeznaczoną dla redaktorów, każdy użytkownik może zostać ad-ministratorem jednego działu który przydzieli mu administrator.System ten doczekał się już ponad 450 stron opartych o niego oraz licznej społeczności.

Można także zakupić wersję CMS w opcji Premium która zawiera bardziej rozbudowane menu administratora pozwalające na definio-wanie własnych stron z dowolną treścią, pod-stron dla nich, a także deklarowania modułów do wprowadzania treści.

Moduły działają dokładnie w taki sam spo-sób jak w przypadku darmowej wersji. Jed-nak wersja płatna daje o wiele większe możli-wości w zarządzaniu swoją stroną WWW.

Dodatkowo system posiada także edytor TinyMCE zintegrowany ze wszystkimi pola-mi do wprowadzania treści.

Strona domowa: http://phpbluedragon.pl/Strona systemu CMS: http://phpbluedragon.pl/php-blue-dragon-cms/

Rysunek 1. Strona domowa systemu Php Blue Dragon CMS

06/2007

Page 7: PHP Solutions 06 2007 PL

Aktualności

6

Aktualności

7

Kto edytuje WikipedięStudent California Institute of Techno-logy Sam Griffith zaprojektował narzę-dzie o nazwie WikiScanner, które umożli-wia sprawdzenie jakie firmy i organizacje edytowały artykuły zamieszczane w Wiki-pedii. WikiScanner identyfikuje autorów edycji na podstawie adresów IP, z któ-rych dokonana została zmiana w ency-klopedii. Dzięki temu, iż w bazie Wiki-Scannera umieszczono ponad 2 mln róż-nych organizacji i prawie 34.5 mln zapi-sanych edycji na stronach Wikipedii, któ-rych dokonano na przestrzeni ostatnich pięciu lat już wykryto, że zmiany doko-nane były z komputerów należących do CIA, IBM, Białego Domu oraz Kurii Waty-kańskiej.

Rewolucja w domenachNASK przygotował dla wydawców inter-netowych niespodziankę. Znany już m.in. w Europie Zachodniej i Stanach Zjedno-czonych Domain Name Tasting ma umoż-liwić wypróbowanie domeny przed pod-jęciem decyzji o jej zakupie. Po co ktoś miałby testować domenę? Aby za sym-boliczną złotówkę sprawdzić jej atrak-cyjność mierzoną ilością odwiedzin jaką może ona generować. Wiadomo już, że testowanie w ramach Domain Name Tasting będzie mogło trwać do 5 dni, a po tym czasie będzie trzeba się zdecydować czy jest się zainteresowanym domeną czy też nie.

Wsparcie dla HD w FlashFirma Adobe wraz z kolejną udostęp-nieniem użytkownikom i webmasterom wersji beta Flash Player 9 poinformowała, iż rozpoczyna rozwijanie formatu filmów o wysokiej rozdzielczości na potrzeby inter-netu. Moviestar będzie obsługiwać stan-dard wideo H.264 oraz audio High Efficien-cy AAC. Wsparcie dla H.264 już wcześniej zostało zaimplementowane m.in. w pro-gramach Adobe Premiere Pro oraz Adobe After Effects, a obecnie będzie możliwe odtwarzanie filmów w standardzie High Definition w Flash Player. W niedalekiej przyszłości obsługą H.264 będzie dyspo-nować także międzyoperacyjna platforma Adobe Integrated Runtime.

700 tysięcy domen .plKilka dni temu została zarejestrowana 700. tysięczna polska domena narodowa. Naj-popularniejsze polskie domeny to: .pl (454 tysięcy), .com.pl (143 tysięcy), .net.pl (19 tysięcy) i .waw.pl (14 tysięcy). Prawdopo-dobne jest, że jeżeli obecny trend wzro-stowy utrzyma się, to na koniec przyszłe-go roku będziemy mieli co najmniej milion polskich domen narodowych. Wśród krajów europejskich Polska jest w drugiej dziesiątce pod względem ilości zarejestro-wanych domen krajowych. Do liderów należą Niemcy z 11.3 miliona domen .de, Anglicy, którzy zakupili 6.2 miliona domen .uk oraz Holendrzy do których należy 2.4 mln domen .nl.

Strona internetowa jest czasopismem

Dnia 27 lipca Sąd Najwyższy wydał wyrok potwierdzający zasadność re-jestracji stron internetowych jako

prasy. Obowiązek rejestracji przewiduje art. 20 ustawy, a co więcej podtrzymał go również Try-bunał Konstytucyjny. Sam problem rejestracji witryn internetowych jako prasy pojawił się po raz pierwszy na początku roku 2007 roku, kie-dy Trybunał Konstytucyjny orzekł, że karanie osób które nie dopełniły obowiązku rejestracji prasy jest zasadne i zgodne z Konstytucją RP, ponieważ jak mówi Prawo Prasowe w artyku-le 20. ustęp 1.: „Wydawanie dziennika lub cza-sopisma wymaga rejestracji w sądzie wojewódz-kim właściwym miejscowo dla siedziby wydaw-cy, zwanym dalej organem rejestracyjnym. Do postępowania w tych sprawach stosuje się prze-pisy Kodeksu postępowania cywilnego o postę-powaniu nieprocesowym, ze zmianami wyni-kającymi z niniejszej ustawy.” To samo Prawo Prasowe w artykule 45. stwierdza: „Kto wydaje dziennik lub czasopismo bez rejestracji albo za-wieszone - podlega grzywnie albo karze ograni-czenia wolności.”

Taki zapis w żadnej mierze nie ogranicza wolności słowa, ponieważ jest to jedynie wy-móg administracyjny zarejestrowania środków przekazu, a nie głoszonych tam poglądów i wy-rażanych opinii. Nie ma więc żadnej wątpliwo-ści, że póki obecne prawo prasowe nie będzie zmienione, dzienniki i czasopisma trzeba re-jestrować. Czy jednak strona internetowa jest

dziennikiem lub czasopismem? Jak najbardziej tak. Prawo Prasowe w artykule 7. ustęp 2. mó-wi wyraźnie: „W rozumieniu ustawy:

1) prasa oznacza publikacje periodyczne, które nie tworzą zamkniętej, jednorodnej cało-ści, ukazujące się nie rzadziej niż raz do roku, opatrzone stałym tytułem albo nazwą, nume-rem bieżącym i datą, a w szczególności: dzien-niki i czasopisma, serwisy agencyjne, stałe prze-kazy teleksowe, biuletyny, programy radiowe i telewizyjne oraz kroniki filmowe; prasą są tak-że wszelkie istniejące i powstające w wyniku postępu technicznego środki masowego prze-kazywania, w tym także rozgłośnie oraz te-le - i radiowęzły zakładowe, upowszechniające publikacje periodyczne za pomocą druku, wi-zji, fonii lub innej techniki rozpowszechniania; prasa obejmuje również zespoły ludzi i poszcze-gólne osoby zajmujące się działalnością dzien-nikarską.”Tym samym strona internetowa, któ-ra jest aktualizowana częściej niż raz w roku jest albo dziennikiem albo czasopismem.

Z faktu zaklasyfikowania strony internetowej jako czasopisma wynika jeszcze jeden obowią-zek. Polskie prawo obliguje wydawców do przeka-zywania egzemplarzy wydanych dzieł wyznaczo-nym bibliotekom, a kto tego nie zrobi może zo-stać ukarany karą grzywny. Ustawa wyraźnie mó-wi o publikacjach „zapisanych na nośnikach elek-tronicznych” należy więc założyć, że także strony internetowe musimy obowiązkowo przekazać, m.in. do Biblioteki Narodowej.

Rysunek 3. Trybunał Konstytucyjny

www.phpsolmag.org

Page 8: PHP Solutions 06 2007 PL

8

Opis CD

EdytoryNa płycie umieszczone są edytory FOXEdit - edytor do użytku ko-mercyjnego, oraz kED 2.1.4.0. FOX Edit jest lekkim i bardzo wy-godnym edytorem tekstu przeznaczonym głownie dla progra-mistów PHP/XHTML/CSS. Od początku swojego istnienia ce-chą wyróżniającą go spośród innych edytorów jest pełna obsłu-ga Unikodu, włącznie z automatycznym rozpoznawaniem ty-pu kodowania wczytywanych plików tekstowych. Oprócz pod-powiadaczy nazw funkcji i argumentów znanych z dużych śro-dowisk programistycznych ciekawą funkcją edytora jest kon-tekstowe kolorowanie składni, które pomaga tworzyć walidują-ce się dokumenty XHTML. Program nie używa rejestru do prze-chowywania swoich ustawień, dzięki czemu zawsze możesz go mieć ze sobą na swoim PenDrive. Więcej informacji na temat dostępnych funkcji edytora można przeczytać na stronie http://www.fox.com.pl/foxedit/

kED 2.1.4.0 to tekstowy edytor XHTML. Koloruje składnię dokumentów, konwertuje strony kodowe (Windows-1250, ISO-8859-2, UTF-8, UTF-16), ułatwia wstawianie tabel, grafik, od-syłaczy; umożliwia współpracę z walidatorem Tidy oraz lokalnym serwerem WWW; zawiera spis znaczników wraz z ich atrybuta-mi, a ponadto pełną listę właściwości CSS2 i listę kilkudziesięciu funkcji PHP.

Szablony stron WWWNa płycie znajduje się sześć unikalnych szablonów stron WWW. Prezentowane szablony stron są gotowymi do użycia projektami stworzonymi wprost dla Ciebie. O zaletach korzy-stania z gotowych szablonów do stworzenia własnej witryny WWW można mówić długo. Przede wszystkim takie rozwiąza-nie jest o wiele prostrze.

Dzięki zamieszczonym szablonom WWW szybko i tanio stworzysz swoją stronę. Szablon to gotowa strona wypełniona łatwą do edycji grafiką. Wykorzystując prosty edytor HTML i program graficzny, możesz przystosować stronę do swoich wy-mogów. Szablony edytować można w najprostszych progra-mach obsługujących kod HTML.

W każdym archiwum znajduje się plik PSD (otwieramy go programem Photoshop). W tym pliku możemy zmieniać kolo-rystykę strony, dodać tekst lub go usunąć.

Każdy znajdzie coś dla siebie. Szablony reprezentują róż-ne treści i różne może być ich przeznaczenie. Mając szablon, wystarczy, że wpiszesz swój tekst w odpowiednie miejsca oraz ewentualnie dodasz właściwe grafiki, a po chwili masz już cał-kowicie gotową, profesjonalną witrynę internetową do umiesz-czenia w sieci.

Rysunek 1. FOX Edit v 1.00

06/2007

Page 9: PHP Solutions 06 2007 PL

Jeśli nie możesz odczytać zawartości płyty CD, a nie

jest ona uszkodzona mechanicznie, sprawdź ją na co

najmniej dwóch napędach CD. W razie problemów

z płytą, prosimy pisać pod adres: [email protected]

Redakcja nie udziela pomocy technicznej w instalowaniu

i użytkowaniu programów zamieszczonych na płytach

CD-ROM dostarczanych razem z pismem.

Page 10: PHP Solutions 06 2007 PL

Dla początkujących

10 06/2007

Symfony Framework

11www.phpsolmag.org

W pierwszej części artykułu prze-brnęliśmy przez instalację i kon-figurację Symfony. Zaczęliśmy

również proces tworzenia nowej aplikacji, do której dodaliśmy moduł użytkownika. Zaopatrzyliśmy go w możliwość rejestracji wraz z potwierdzeniem wysyłanym na e-ma-il. Wprowadziliśmy również logowanie. Jed-nak czym byłby serwis bez możliwości wylo-gowania, przypomnienia hasła, edycji profi-lu użytkownika i dodawania do niego treści? W tym artykule dowiemy się, jak to wszystko można zrobić.

Na samym początku dodamy bardzo pro-stą metodę logout odpowiedzialną za akcję wylogowania użytkownika, która będzie po-legała na wyczyszczeniu sesji, w dalszej części artykułu metoda ta zostanie rozbudowana o kolejne właściwości. Trochę bardziej skom-plikowaną metodą będzie reminder, dzię-ki której użytkownik, który zapomniał ha-sło będzie mógł wygenerować nowe i otrzy-mać je wraz z linkiem do potwierdzenia dro-gą e-mailową.

Wprowadzimy również metodę profile, dzięki której użytkownik, który zaloguje się

poprawnie będzie mógł edytować swój pro-fil. Poznamy również możliwość zabezpiecze-nia danej metody AddPost w module posty, tak aby miał do niej dostęp tylko i wyłącznie użytkownik zalogowany, oczywiście będzie mógł edytować tylko swoje posty. Ostatecz-nie wprowadzimy nową aplikację backend, której głównym celem będzie ułatwienie za-rządzania przyszłym serwisem. Zapraszamy do artykułu.

Moduł użytkownik – metoda logoutZajmiemy się najprostszą metodą modułu użytkownik, jaką jest logout, która będzie miała na celu wyczyszczenie sesji użytkownika utwo-rzonej podczas logowania. Otwieramy plik ac-

tions.class.php do edycji i na jego końcu dopi-sujemy następujące linijki:

public function executerLogout() {

$this->getUser()->setAuthenticated

(false);

$this->getUser()->clearCredentials();

}

Następnie w katalogu templates tworzymy plik logoutSuccess.php, w którym zamieszczamy in-formację dla użytkownika o poprawnym wy-logowaniu. Kilka linijek i nasza metoda dzia-ła. Zalogujmy się i sprawdźmy. Oczywiście, aby wywołać formularz logowania, wpisujemy w przeglądarce http://symfony/uzytkownik/login. Aby wylogować się wpisujemy http://symfony/uzytkownik/logout.

Zwróćmy uwagę na podobieństwo przy pro-cesie logowania. Użyliśmy takiej samej funkcji setAuthenticated(). Różnica jest tylko taka, że jako jej parametr podajemy true albo false. Z kolei funkcja clearCredentials() służy do usuwania praw użytkownika z sesji credentials.

Moduł użytkownik – metoda reminderDodamy kolejną metodę reminder, która po-może zapominalskim użytkownikom odzyskać

Symfony Framework

Framework symfony posiada bardzo dobrze rozwiązane nadawanie praw dla modułów i ich metod. Natomiast dzięki narzędziu admin generator można w szybki i prosty sposób stworzyć główną funkcjonalność aplikacji, zajmującej się zarządzaniem serwisu przez administratora.

Dowiesz się...• Jak nadawać odpowiednie prawa dla modu-

łów i ich metod;

• Jak dodać swój własny helper;

• Poznasz doskonałe narzędzie symfony admin

generator, dzięki któremu w prosty sposób

stworzysz edycję podstron serwisu;

• Stworzysz drugą aplikację backend dla admi-

nistratora.

Powinieneś wiedzieć...• Powinieneś znać podstawy programowania

obiektowego w PHP 5 oraz podstawy Propela.

Znajomość CSS może pomóc w analizie strony

wizualnej.

Poziom trudności

Część druga – Moduł użytkownik, posty, osymfony, kontakt oraz aplikacja Backend

Listing 1. Sprawdzanie e-maila

$email = new Criteria();

$email->setLimit(1);

$email->add(UzytkownikPeer::EMAIL, $this->getRequestParameter('email'));

$uzytkownik = UzytkownikPeer::doSelectOne($email);

if ($uzytkownik)

{

// jeśli istnieje użytkownik to dokonujemy zmian

}

Page 11: PHP Solutions 06 2007 PL

Dla początkujących

10 06/2007

Symfony Framework

11www.phpsolmag.org

Lisitng 2. Wysyłamy e-mail z nowym hasłem i linkiem do potwierdzenia

hasło i przypomnieć login pod warunkiem, że pamiętają jakiego adresu e-mail używali pod-czas rejestracji. Na końcu pliku actions.class.php dodajemy nową metodę o nazwie reminder. Dla przypomnienia:

public function executeReminder()

{

// zawartość metody

}

Uzupełniamy ją następującymi liniami:

if ($this->getRequest()->getMethod() ==

sfRequest::POST) {

// gdy formularz został

wysłany poprawnie

} else {

// wyświetlanie formularza

return sfView::SUCCESS;

}

W miejscu, gdzie wykonywane są instrukcje po poprawnym wysłaniu formularza, wpisu-jemy następujące linie kodu, które mają na ce-lu generowanie kodu do potwierdzenia zmian oraz nowego hasła:

$potwierdzenie = mt_rand(10000,99999);

$nowe_haslo = substr(md5(uniqid(rand(),

true)), 0, 7);

Kolejnym krokiem będzie sprawdzanie poda-nego e-maila w formularzu, dzięki czemu za-

bezpieczamy się podwójnie, ponieważ wcze-śniej zajmuje się tym plik reminder.yml. Przy okazji będziemy mieli dostęp do ID użytkow-nika, które jest wymagane do poprawnych operacji na danych w tabeli użytkownik. Ope-racja ta nie zajmuje zbyt wiele pamięci i czasu, więc możemy ją spokojnie wykonać. Ostatecz-nie sprawdzamy czy dany e-mail istnieje, jeśli tak, to dokonujemy zmian w haśle i potwier-dzeniu, przypisując do nich kolejno zmien-ne $potwierdzenie i $nowe _ haslo. Następ-nie wysyłamy e-mail z potwierdzeniem zmian i nowym hasłem. Na koniec wyświetlamy sza-blon nowe_hasloSuccess.php z katalogu templa-tes. Sprawdzanie e-maila przeprowadzamy przy pomocy następującego fragmentu kodu (Listing 1.)

$mail = new sfMail();

$mail->initialize();

$mail->setMailer('sendmail');

$mail->setCharset('iso-8859-2');

$mail->setSender('[email protected]','Redaktor');

$mail->setFrom('[email protected]','Redaktor');

$mail->addAddress($this->getRequestParameter('email'));

$mail->setSubject('Utworzono nowe hasło dla użytkownika '.

$uzytkownik->getNick().'!');

$mail->setBody('

Witamy,

Dokonałeś zmiany hasła. W celu potwierdzenia zmian,

prosimy kliknąć poniższy link:

http://symfony/uzytkownik/potwierdzenie/kod/'.

$potwierdzenie.'

Twoje nowe hasło to: '.$nowe_haslo.'.\nLogin: '.

$uzytkownik->getNick().'

Pozdrawiamy,

Redakcja projektu Symfony w akcji

');

<?php

class myReminderemailValidator extends sfValidator

{

public function initialize($context, $parameters = null)

{

parent::initialize($context);

$this->setParameter('email_error', 'Invalid input');

$this->getParameterHolder()->add($parameter);

return true;

}

public function execute(&$value, &$error)

{

$email_param = $this->getParameter('email');

$email = $this->getContext()->

getRequest()->

getParameter($email_param);

$email = $value;

$mail->send();

$this->setTemplate('nowe_haslo');

// W katalogu templates dodajemy plik reminderSuccess.php

// i reminderError.php, w którym umieszczamy formularz

// wysłania nowego hasła:

<?php use_helper('Validation') ?>

<?php echo form_tag('uzytkownik/reminder') ?>

<?php echo form_error('email') ?>

<div class=”input-default”>

<label for=”email”>Podaj swój e-mail przy rejestracji:</label>

<?php echo input_tag('email') ?>

</div>

<?php echo input_hidden_tag('referer') ?>

<?php echo submit_tag('przypomnij hasło ->') ?>

</form>

// szukanie takiego samego e-maila

$c = new Criteria();

$c->add(UzytkownikPeer::EMAIL, $email);

$email_user = UzytkownikPeer::doSelectOne($c);

// jeśli nie istnieje taki e-mail to zwracamy błąd

if ($email_user) {

return true;

} else {

$error = $this->getParameter('email_error');

return false;

}

}

}

?>

Listing 3. Klasa odpowiedzialna za szukanie e-maila podanego w formularzu do generowania nowego hasła

Page 12: PHP Solutions 06 2007 PL

Dla początkujących

12 06/2007

Symfony Framework

13www.phpsolmag.org

Jeśli użytkownik o podanym emailu ist-nieje, to dokonujemy zmian w haśle, kodzie potwierdzenia i statusie konta. Status kon-ta musimy ustawić na 0, dzięki czemu nie będzie możliwości logowania z nowym ha-słem do czasu potwierdzenia konta. Dopisu-jemy następujące linijki kodu w warunku if ($uzytkownik):

$c = UzytkownikPeer::

retrieveByPk($użytkownik->getId());

$c->setPassword($nowe_haslo);

$c->setPotwierdzenie($potwierdzenie);

$c->setStatus(0);

$c->save();

Po zmianie danych, wysyłamy e-mail z no-wym hasłem i linkiem do potwierdzenia (Listing 2.)

Następnie w katalogu validate tworzymy plik reminder.yml, w którym będziemy spraw-dzali zmienną email. Dzięki zastosowaniu kla-sy myReminderemailValidator (widocznej na Listingu 3.) będziemy mogli sprawdzić czy da-ny e-mail istnieje w bazie danych.

Oczywiście przy uzupełnianiu pliku remin-der.yml należy zwrócić szczególną uwagę, aby używać tylko i wyłącznie znaku spacji, nie moż-na używać tabulatora. Jeśli zdarzy się tak, że użyjemy tabulatora, to symfony zwróci nam błąd w trakcie próby sprawdzania e-maila. Na Listingu 3. przedstawiamy klasę myReminderemailValidator, z której korzysta validator o nazwie checkdbemailValidator w pliku re-minder.yml (widocznym na listingu 4.). Plik z naszą nową klasą (myReminderemailValida-tor.class.php) musi znajdować się w katalo-gu lib aplikacji frontend.

Możemy już przetestować naszą nową ak-cję. W przeglądarce wpisujemy adres http://symfony/uzytkownik/reminder, powinien poja-

Listing 4. Plik Reminder.yml

methods:

post: [email]

names:

email:

required: true

required_msg: musisz

wpisać adres email, którego

użyłeś podczas rejestracji

nowego konta

validators:

[checkdbemailValidator]

checkdbemailValidator:

class: myReminderemailValidator

param:

email: email

email_error: ten email

nie istnieje w bazie, musisz

wpisać adres email, który podałeś

przy rejestracji nowego konta

Listing 5. Metoda profile. Odpowiedzialna jest za aktualizację danych użytkownika

public function executeProfile()

{

if ($this->getRequest()->getMethod() == sfRequest::POST)

{

// zapisywanie danych do tabeli uzytkownik

$uzytkownik = UzytkownikPeer::retrieveByPk($this->getUser()->

getAttribute('user_id'));

$uzytkownik->setStronaWww($this->getRequestParameter('strona_www');

$uzytkownik->setPodpis($this->getRequestParameter('podpis'));

if ($this->getRequestParameter('haslo'))

{

$uzytkownik->setPassword($this->getRequestParmeter('haslo'));

}

// zapisujemy dane do tabeli uzytkownik

$uzytkownik->save();

// przekierowanie po aktualizacji na profil użytkownika

$this->redirect('uzytkownik/profile');

} else {

// przekazujemy zmienną uzytkownika do szablonu

$c = new Criteria();

$c->add(UzytkownikPeer::ID, $this->getUser()->getAttribute('user_id'));

$uzytkownik = UzytkownikPeer::doSelectOne($c);

$this->uzytkownik = $uzytkownik;

return sfView::SUCCESS;

}

}

Listing 6. handleErrorProfile

public function handleErrorProfile()

{

$c = new Criteria();

$c->add(UzytkownikPeer::ID, $this->getUser()->getAttribute('user_id'));

$uzytkownik = UzytkownikPeer::doSelectOne($c);

$this->uzytkownik = $uzytkownik;

return sfView::SUCCESS;

}

Listing 7. Dodawanie pola formularza

<?php echo form_error('haslo') ?>

<div class=”input-default”>

<label for=”haslo”>Podaj hasło, jeśli chcesz zmienić:</label>

<?php echo input_password_tag('haslo') ?>

</div>

<?php echo form_error('powtorz_haslo') ?>

<div class=”input-default”>

<label for=”powtorz_haslo”>Powtórz hasło:</label>

<?php echo input_password_tag('powtorz_haslo') ?>

Page 13: PHP Solutions 06 2007 PL

Dla początkujących

12 06/2007

Symfony Framework

13www.phpsolmag.org

wić się formularz z jednym polem, w które na-leży wpisać adres e-mail. Spróbujmy wpisać e-mail, którego nie ma w bazie danych i ten pra-widłowy, którego użyliśmy przy rejestracji no-wego konta.

Moduł użytkownik – metoda profileAby użytkownik mógł edytować swój profil, do-damy kolejną metodę o nazwie profile. Najpierw musimy dodać nowy atrybut podczas logowania, jakim będzie user_id zawierający ID użytkowni-ka. Wobec tego musimy edytować metodę login. Zaraz po linijce uzytkownik = UzytkownikPeer::doSelectOne($uzytkownik); dodajemy user_id

Listing 8. Podpis

<?php echo form_error('strona_www') ?>

<div class=”input-default”>

<label for=”strona_www”>Strona www:</label>

http://<?php echo input_tag('strona_www', $uzytkownik->getStronaWww()) ?>

</div>

<?php echo form_error('podpis') ?>

<div class=”input-default”>

<label for=”podpis”>Twój podpis:</label>

<?php echo input_tag('podpis',$uzytkownik->getPodpis()) ?>

</div>

Kończymy formularz następującymi trzema linijkami kodu:

<?php echo input_hidden_tag('referer') ?>

<?php echo submit_tag('zmień') ?>

</form>

Listing 9. Zapytanie z sortowaniem według daty utworzenia postu

public function executeIndex()

{

$posty – new Criteria();

$posty->addDescendingOrderByColumn(PostyPeer::CREATED_AT);

$posty = PostyPeer::doSelect($posty);

$this->posty = $posty;

return sfView::SUCCESS;

}

Listing 10. Walidatory dla zmiennych strona_www i podpis

strona_wwwValidator:

class: sfStringValidator

param:

min: 4

max: 255

min_error: adres internetowy musi składać się przynajmniej z 3 znaków

max_error: adres internetowy nie może przekroczyć 255 znaków

podpisValidator:

class: sfStringValidator

param:

min: 4

max: 255

min_error: podpis musi składać się przynajmniej z 4 znaków

max_error: podpis nie może przekroczyć 255 znakówRysunek 1. Brak dostępu. Komunikat informacyjny dla niezalogowanych użytkowników, którzy próbują się dostać do modułu profile

= $uzytkownik->getId();. Następnie w wa-runku if ($uzytkownik) { } po linijce$uzytkownik->addCredentail('subscriber');

dodajemy $uzytkownik->setAttribute('user_id', $user_id);. Dzięki tym zmianom, tuż po zalogowaniu, zostanie utworzony atry-but user_id, który będzie zawierał ID użyt-kownika. Musimy dodać jeszcze jedną linij-kę w metodzie logout, aby atrybut w mo-mencie wylogowania był niszczony. Po linij-ce $this->getUser()->clearCredentials(); dodajemy $this->getUser()->getAttribute-

Holder()->remove('user_id');. Jeśli chcesz sprawdzić, czy rzeczywiście user_id jest zapisy-wane i usuwane, zobacz w trybie developerskim

poprzez adres http://symfony/frontend_dev.php/uzytkownik/login i logout. Dla przypomnienia jest to w zakładce Vars&Config/Globals.

Teraz możemy przejść do naszej nowej meto-dy profile (Listing 5.). Dodajemy ją na samym końcu pliku actions.class.php.

Musimy jeszcze dodać jedną metodę, któ-ra będzie przekazywała zmienną użytkownik do szablonu profileError.php. Jeśli tego nie zro-bimy, to w momencie, gdy zostanie przełado-wana strona i jeśli będzie jakiś błąd, to nie bę-dziemy mieli już dostępu do zmiennej z sza-blonu profileSuccess.php gdyż będziemy w pro-fileError.php. Musimy dodać zaraz pod naszą nową metodą, metodę handleErrorProfile (Listing 6.) .

Jak pewnie zauważyliście, powtórzyliśmy fragment kodu z metody profile. Jest to naj-prostsze wyjście. Dzięki niemu, po urucho-mieniu szablonu z komunikatem o błędzie, bę-dziemy mieli dalej dostęp do zmiennej użyt-kownik.

Mamy już metody. Teraz stworzymy szablo-ny profileSuccess.php i profileError.php, które z kolei są kopią profileSuccess.php. Szablon pro-file będzie składał się na formularz z polami ha-sło, powtórz hasło, strona www, podpis:

<?php use_helper('Validation') ?>

Na samym początku dodajemy możliwość wa-lidacji danych.

<?php echo form_tag('uzytkownik/profile') ?>

Rozpoczynamy formularz z akcją na użyt-kownik/profile. Następnie będziemy dodawać pola formularza (Listing 7.).

W następnych polach będziemy korzysta-li ze zmiennej użytkownik, którą przekaza-liśmy z metody profile. Dostęp do danych jest bardzo prosty. Żeby odczytać podpis wy-starczy wpisać: $uzytkownik->getPodpis() (Listing 8.)

Następnym krokiem będzie stworzenie pli-ku profile.yml w katalogu validate. Będzie on sprawdzał zmienne haslo, powtorz_haslo, strona_www i podpis. Zaczynamy od definicji zmiennych:

methods:

post: [haslo, powtorz_haslo, strona_

www, podpis]

Page 14: PHP Solutions 06 2007 PL

Dla początkujących

14 06/2007

Symfony Framework

15www.phpsolmag.org

Dalej, od słowa kluczowego names, będzie-my definiować warunki poszczególnych zmiennych. Początkowo haslo i powtorz _

haslo oznaczone są jako nie wymaga-ne false, ale jest zdefiniowany walidator checkhasloValidator, który ma na celuprzypilnowanie w razie gdyby użytkow-nik chciał zmienić hasło poprawności tych dwóch pól:

names:

haslo:

required: false

required_msg: twoje hasło jest

wymagane

powtorz_haslo:

required: false

required_msg: ponów hasło

validators: [checkhasloValidator]

Dalej dodajemy definicje dla strona _ www i podpis. Zmienna strona _ www ma swój wali-dator strona _ wwwValidator, który korzysta z klasy sfStringValidator, a ma za zadanie przypilnowaniet minimalnej i maksymalnej długości wpisanych znaków do pola. Zmien-na podpis również posiada swój walidator podpisValidator, który działa identycznie, jak w poprzednim przypadku:

strona_www:

required: false

validators: [strona_wwwValidator]

podpis:

required: false

validators: [podpisValidator]

Tak jak wcześniej wspomnieliśmy zmien-na powtorz _ haslo ma swój walidator chekhasloValidator, który porównuje zmien-ne haslo i powtorz _ haslo używając do tego klasy sfCompareValidator:

checkhasloValidator:

class: sfCompareValidator

param:

check: haslo

compare_error: hasła nie

zgadzają się

Na sam koniec dopisujemy walidatory dla zmiennych strona _ www i podpis (Listing 10.).

Kolejnym etapem jest wywołanie, w głów-nym katalogu projektu, polecenia /symfony clear-cache, które wyczyści cały cache stro-ny. Możemy już przetestować edycję profi-lu poprzez adres http://symfony/uzytkownik/profile.

Musimy nadać odpowiednie prawa dla mo-dułu profile, aby dostęp miał jedynie użyt-kownik zalogowany subscriber, ponieważ w tej chwili może się do niego również dostać anonimowy użytkownik. Żeby to wykonać wchodzimy do katalogu config modułu użyt-

kownik i tworzymy plik security.yml o zawar-tości:

profile:

id_secure: on

credentials: [[ subscriber ]]

Sprawdźmy teraz, czy nasze zabezpieczenie działa. Zalogujmy się i wejdźmy na adres http://symfony/uzytkownik/profile. Powinien wy-świetlić się nasz profil do edycji. Teraz wyloguj-my się i wywołajmy ponownie ten sam adres. Te-raz wyświetli się komunikat jak na Rysunku 1.

Listing 11. Opcja edytuj z możliwością edycji tylko i wyłącznie swojego posta

<?php use_helper('Check') ?>

<?php foreach($posty as $post) : ?>

<div class=”tytul”>

<?php echo $post->getTytul() ?>

<span class=”data”>(<?php echo $post->getCreatedAt() ?>), dodał:

<?php echo checkNickName($post->getIdUzytkownik()) ?>

</span>

</div>

<div class=”tresc”>

<?php echo $post->getTresc() ?>

</div>

<?php if($sf_user->isAuthenticated()): ?>

<div class=”edytuj”>

<?php if($post->getIdUzytkownik() == $sf_user->getAttribute('user_id'))

{

echo link_to('edytuj', 'posty/editpost?id='.$post->getId());

}

</div>

<?php endif ?>

<hr>

<?php endforeach ?>

Listing 12. Zwrócenie nazwy użytkownika

function checkNickName($user_id)

{

$c = new Criteria();

$c->add(UzytkownikPeer::ID, $user_id);

$check = UzytkownikPeer::doSelectOne($c);

if($check) {

return $check->getNick();

} else {

return 0;

}

}

Listing 13. Proces dodawania nowego postu

public function executeAddpost()

{

if ($this->getRequest()->getMethod() == sfRequest::POST) {

$posty = new Posty();

$posty->setIdUzytkownik($this->getRequestParameter('user_id');

$posty->setTytul($this->getRequestParameter('tytul'));

$posty->setTresc($this->getRequestParameter('tresc'));

$posty->save();

$this->redirect('posty');

} else {

// wyświetlanie formularza dodawania nowego posta

return sfView::SUCCESS;

}

}

Page 15: PHP Solutions 06 2007 PL

Dla początkujących

14 06/2007

Symfony Framework

15www.phpsolmag.org

Moduł posty – metoda indexMetoda index w pliku actions.class.php od-powiedzialna będzie za wyświetlanie po-stów. Przekażemy w niej zmienną posty do szablonu.

W zapytaniu do bazy danych użyjemy sorto-wania według daty utworzenia postu, przy po-mocy addDescendingOrderByColumn() w języ-ku PROPE (Listing 9.).

Następnie tworzymy w katalogu templa-tes szablon index, czyli plik indexSuccess.php. W pliku tym będziemy prezentować posty. Każdy post będzie składał się z tytułu, daty, na-zwy użytkownika oraz treści. Dodatkowo po zalogowaniu wyświetli się opcja edytuj z moż-liwością edycji tylko i wyłącznie swojego posta (Listing 11.).

Na samym początku użyliśmy nowego helper'a o nazwie Check, czyli pliku Chec-kHelper.php, który umieszczamy w katalo-gu lib/helper. Jeśli w katalogu lib nie będzie katalogu helper to utwórzmy go. Nowy helper zawiera funkcję checkNickName(), która zo-stała użyta w szablonie index. Zadaniem tej funkcji jest zwrócenie nazwy użytkownika(Listing 12.).

W szablonie index odwołaliśmy się również do atrybutu user_id. Aby się do niego dostać z poziomu szablonu, należy użyć polecenia $sf_user->getAttribute('user_id').

Mamy gotowe wyświetlanie postów z moż-liwością edycji. Teraz musimy dodać metodę, która pozwoli użytkownikom zalogowanym dodawanie nowych postów.

Moduł posty – metoda AddpostAby użytkownik miał możliwość pisania no-wych postów, musimy dodać nową metodę Addpost w pliku actions.class.php. Metoda ta będzie pobierać z formularza zmienne user_id, tytul i tresc.

Następnie będzie przekierowywała na stro-nę z listą wszystkich postów przy pomocy polecenia $this->redirect('posty'). Pro-ces dodawania nowego postu jest podobny jak w przypadku zakładania nowego konta (Listing 13.).

Tworzymy plik addpostSuccess.php i jego ko-pię addpostError.php. Formularz będzie skła-dał się z dwóch pól tytul i tresc oraz ukrytego

Listing 14. Metoda Editpost i handleErrorEditpost

public function executeEditpost()

{

if ($this->getRequest()->getMethod() == sfRequest::POST) {

// zapis zmian

$posty = new Criteria();

$posty = PostyPeer::retrieveByPk($this->getUser()->getAttribute('id_posta'));

$posty->setTytul($this->getRequestParameter('tytul'));

$posty->setTresc($this->getRequestParameter('tresc'));

$posty->save();

$this->getUser()->getAttributeHolder()->remove('id_posta');

$this->redirect('posty');

}

else

{

// udostępnianie zmiennej post w szablonie

// wyświetlanie formularza edycji posta

$c = new Criteria();

$c->add(PostyPeer::ID, $this->getRequestParameter('id'));

$post = PostyPeer::doSelectOne($c);

$this->post = $post;

$this = $this->getUser();

$post->setAttribute('id_posta', $this->getRequestParameter('id'));

return sfView::SUCCESS;

}

}

public function handleErrorEditpost()

{

// udostępnianie zmiennej post w szablonie editpostError

$c = new Criteria();

$c->add(postyPeer::ID, $this->getUser()->getAttribute('id_posta'));

$post = PostyPeer::doSelectOne($c);

$this->post = $post;

return sfView::SUCCESS;

}

Listing 15. Metoda index

public function executeIndex()

{

// udostępnia zmienną osymfony w szalonie

$osymfony = new Criteria();

$osymfony->addDescendingOrderByColumn(OsymfonyPeer::ID);

$osymfony = OsymfonyPeer::doSelectOne($osymfony);

$this->osymfony = $osymfony;

$return sfView::SUCCESS;

}

Rysunek 2. Aplikacja backend. Widok na listę użytkowników

Page 16: PHP Solutions 06 2007 PL

Dla początkujących

16 06/2007

pola user_id, które będzie przechowywało ID użytkownika. Aby przekazać zmienną user_id, należy użyć polecenia $sf_user->getAttribute('user_id'). Formularz two-rzymy podobnie, jak w innych przypadkach. Dodajemy również plik addpost.yml do kata-logu validate, który powinien mieć za zada-nie wymuszenie wpisania treści w polu tytul i tresc, jednocześnie pamiętając, że pole treść musi mieć minimum 3 znaki. Nale-ży również zabezpieczyć naszą metodę przed użytkownikami niezalogowanymi, tworząc plik security.yml w katalogu config modułu po-sty o zawartości:

addpost:

is_secure: on

credentials: [[ subscriber ]]

Możemy już sprawdzić dodawanie postu wywołując adres http://symfony/posty/addpost. Następnym krokiem będzie dodanie meto-dy umożliwiającej edycję postów przez użyt-kownika.

Moduł posty – metoda EditpostEdycja postu będzie możliwa przy pomocy me-tody Editpost. W metodzie tej przy przekazy-waniu zmiennej post do szablonu użyliśmy no-wego atrybutu o nazwie id_posta, który jest usuwany po poprawnym zapisaniu zmian.

Ustawienie tego atrybutu było wymagane przy przekazywaniu zmiennej post, w przy-padku błędu, w trakcie wysyłania formularza. Ostatecznie dodaliśmy dwie metody Editpost i handleErrorEditpost oraz dwa pliki w kata-logu templates o nazwach editpostSuccess.php i editpostError.php, który jest kopią tego pierw-szego.

Dodaliśmy również zabezpieczenie dla me-tody Editpost, aby była tylko dostępna dla użytkowników typu subscriber. Dokonaliśmy tego w pliku security.yml, podobnie jak w przy-padku addpost.

Musimy jeszcze dodać plik editpost.yml do katalogu validate. Możemy skopiować za-wartość pliku addpost.yml. Na Listingu 14. przedstawiam metody Editpost i handle

ErrorEditpost.

Moduł osymfony – metoda indexAby wyświetlić podstronę symfony, należy do-dać metodę index do pliku actions.class.php. Następnie musimy stworzyć plik indexSuc-cess.php w katalogu templates. Metoda index zo-stała przedstawiona na Listingu 15. Plik inde-xSuccess.php zawiera:

<div class=”tresc”><?php echo

$osymfony->getTresc() ?></div>

Mamy już wyświetlanie treści z tabeli symfo-ny. Polecam uzupełnić treść podstrony sym-fony i kontakt przy pomocy aplikacji backend opisanej w dalszej części artykułu.

Moduł kontakt – metoda indexAby wyświetlić podstronę kontakt należy postą-pić identycznie, jak w przypadku podstrony sym-fony. Dodajemy metodę index, następnie two-rzymy szablon w katalogu templates. Jeżeli wyda-je Ci się to zbyt skomplikowane, to zamieszczam w Listingu 16. kod. Plik indexSuccess.php zawiera:

<div class=”tresc”><?php echo

$kontakt->getTresc() ?></div>

Treść kontaktu możemy łatwo uzupełnić przy pomocy aplikacji backend.

Aplikacja backendStworzymy teraz nową aplikację backend, która będzie nam pomagała przy edycji pod-stron serwisu jak i zarządzaniu postami oraz użytkownikami serwisu. Aplikację tworzymy z głównego katalogu projektu przy pomocy polecenia ./symfony init-app backend. Na-stępnie będziemy tworzyć dla tej aplikacji mo-duły użytkownik i posty. Jeśli chcemy zarzą-dzać podstronami spod tej aplikacji, to musi-my w tabeli symfony i kontakt dodać jedną ko-lumnę:

<column name=”id” type=”integer”

required=”true” primaryKey=”true”

autoIncrement=”true” />

Dzieje się tak, dlatego, że admin generator wymaga kolumny z kluczem podstawowym.

Jeśli już dodaliśmy kolumnę do tabel w pli-ku schema.xml, to musimy po kolei wywołać polecenia z głównego katalogu projektu:

./symfony propel-build-model

./symfony propel-build-sql

./symfony propel-insert-sql

Uwaga, po tej operacji wszystkie dane z tabel znikną. Nie będzie też naszego użytkownika. Tworzymy moduły aplikacji backend wpisu-jąc po kolei:

./symfony propel-init-admin backend

uzytkownik Uzytkownik

./symfony propel-init-admin backend

pozsty Posty

./symfony propel-init-admin backend

osymfony Osymfony

./symfony propel-init-admin backend

kontakt Kontakt

Dostęp do tych modułów jest podobny jak w aplikacji frontend poprzez adres: http://symfony/backend.php/nazwa_modułu. Propo-nuję, abyśdodał kilku użytkowników a następ-nie wszedł na adres http://symfony/backend.php/uzytkownik, powinna pojawić się lista użytkowników, którą będziesz mógł edyto-wać (zobacz Rysunek 2.).

Możesz teraz uzupełnić treść w podstronie o symfony oraz w kontakcie. Użyj oczywiście do tego celu aplikacji backend.

PodsumowanieW tym artykule dowiedzieliśmy się jak wy-generować nowe hasło dla użytkownika, któ-ry korzysta z opcji przypomnij hasło. W tym celu napisaliśmy metodę reminder w module użytkownika. Nauczyliśmy się jak ustawiać odpowiednie prawa dla modułów oraz jak dodać nowe atrybuty. Rozbudowaliśmy na-szą aplikację o możliwość edycji profilu, wylo-gowania, dodawania postów i ich edycji, a tak-że dodaliśmy nową aplikację backend. Dzię-ki niej możemy z łatwością zarządzać na stro-nie. Na razie aplikacja ta nie jest zabezpieczona przed wejściem użytkowników anonimowych. Zabezpieczymy ją w następnej części artykułu. Oczywiście cała nasza aplikacja jest na razie w częściach. Już w następnym artykule zajmiemy się jej składaniem i opisem w stylach CSS, po-znamy również ciekawe i godne polecenia miej-sca w internecie na temat frameworka symfony. Do zobaczenia!

Listing 16. Dodajemy metodę index, następnie tworzymy szablon w katalogu templates

public function executeIndex()

{

// udostępnia zmienną kontakt w szalonie

$kontakt = new Criteria();

$kontakt->addDescendingOrderByColumn(KontaktPeer::ID);

$kontakt = KontaktPeer::doSelectOne($kontakt);

$this->kontakt = $kontakt;

$return sfView::SUCCESS;

}

ŁUKASZ KLEJNBERGAutor jest studentem informatyki w Wyższej Szkole

Informatyki i Zarządzania w Rzeszowie. Pracuje ja-

ko projektant stron WWW. Uczestniczy w projekcie

uczelnianym tonieproblem.pl opartym na frame-

worku symfony.

Kontakt z autorem: [email protected]

Page 17: PHP Solutions 06 2007 PL
Page 18: PHP Solutions 06 2007 PL

06/2007

Rozwiązania

18

Vanilla

www.phpsolmag.org 19

Vanilla wywodzi się z projektu o8 stwo-rzonego przez Marka O'Sullivana, który pod naciskiem szerokiego gro-

na użytkowników zdecydował się upublicznić aplikację na licencji GPL. Po roku Vanilla sta-ła się bardzo popularną aplikacją, a duża spo-łeczność przyczyniła się do powstania wielu pluginów rozszerzających podstawowe możli-wości forum.

Podstawowe wymaganiaMinimalne wymagania, jakie musimy spełnić, aby zainstalować forum, to: serwer z obsłu-gą >= PHP 4.1 i >=MySQL 3.23. Pełny pakiet instalacyjny możemy pobrać ze strony domo-wej projektu, która dostępna jest pod adresem http://getvanilla.com/. Dzięki niewielkim wyma-ganiom możemy tę aplikację zainstalować na prawie każdym serwerze hostingowym, a pro-ces instalacji sprowadza się do wpisania podsta-wowych parametrów niezbędnych do połącze-nia z bazą danych i utworzeniem konta admi-nistratora.

Podstawowe możliwościZainstalowana aplikacja umożliwia rejestra-cję użytkownikom, którzy po akceptacji przez administratora mogą brać udział w dyskusji w utworzonych kategoriach. Interfejs udostęp-niony użytkownikowi jest bardzo prosty w ob-słudze, a wszystkich dostępnych opcji używa się intuicyjnie. Ze strony administratora zarzą-

dzanie forum podzielone jest na kilka podsta-wowych kategorii. Inaczej niż w phpBB mamy tutaj przejrzyste menu, które umożliwia doko-nywanie zmian w ustawieniach forum.

Ustawienia aplikacjiJest to główny ekran konfiguracyjny Vanilli. Tu-taj zmieniamy tekst w bannerze, ustawienia anty-spamowe, definiujemy ustawienia ciasteczek (co-okies), oraz zmieniamy podstawowe opcje forum, takie jak wiadomości prywatne, kategorie, itp.:

• aktualizacje i przypomnienia: tutaj ustala-my, jak często Vanilla ma nam przypomi-nać o aktualizacjach. Możemy sprawdzić w Lussumo, czy są dostępne nowsze wersje;

• rangi użytkowników: tutaj dodajemy, zmie-niamy i porządkujemy rangi użytkowni-ków i przysługujące im prawa dostępu;

• ustawienia rejestracji: definiujemy, w jaki sposób mają być rejestrowani nowi człon-kowie: jaką otrzymują rangę, czy wymaga-na jest akceptacja administratora itd.;

• kategorie: dodajemy, zmieniamy i porząd-kujemy kategorie;

• rozszerzenia: dodają do Vanilli różne funk-cje. W tym menu włączamy rozszerzenia i znajdujemy nowe ze strony Lussumo;

• szablony i Style: tutaj zmieniamy szablon (plik XHTML), na którym oparte jest fo-rum, lub domyślny styl (CSS i grafikę);

• języki: możemy zmienić pliki językowe, których używa Vanilla;

• prośby o członkostwo: Vanilla nie posia-da 'listy użytkowników' jak inne popular-ne fora. W opcji Szukaj znajdujemy i za-rządzamy nowymi użytkownikami. Jeże-li administrator musi zatwierdzać proś-

by, ten link uruchamia nam wyszukiwa-nie nowych (jeszcze niezatwierdzonych) użytkowników;

• inne opcje: zależnie od uprawnień dostę-pu i rozszerzeń, z których korzystamy, mogą się tutaj pojawić dodatkowe opcje.

Dzięki zakładce Ustawienia możemy sprawnie moderować prowadzone dyskusje.

GrafikaZaimplementowany System szablonów umoż-liwia łatwą zmianę wyglądu. Ze strony domo-wej możemy pobrać sporą liczbę templatek i stylów, którymi zarządzamy w panelu admi-nistracyjnym.

RozszerzeniaMożliwości forum możemy zwiększać za po-mocą specjalnych rozszerzeń. W przeciwień-stwie do forum phpBB ich in stalacja nie po-lega na ręcznej edycji wielu plików, lecz spro-wadza się do aktywacji dodatku w sekcji Usta-wienia. Taki system eliminuje konieczność spędzania kilkunastu minut w celu zainsta-lowania rozszerzenia oraz uniezależnia je-go instalację od aktualizacji Vanilli do now-szej wersji. Do dyspozycji mamy ponad 200 rozszerzeń, które na żądanie modyfikują po-szczególne elementy aplikacji. Liczba rozsze-rzeń wciąż rośnie.

Przykładowe rozszerzenia:Do najbardziej popularnych rozszerzeń funk-cjonalności możemy zaliczyć chat status. Po-kazuje on bieżącą aktywność użytkowników w popularnych komunikatorach interneto-wych (Gadu-Gadu, Skype). Dzięki wtycz-ce notify forumowicze mogą być na bieżą-co (e-mailem) informowani o odpowiedzi na post. Ciekawą funkcją jest, iż użytkownik nie dostanie więcej niż jeden e-mail, dopóki nie odwiedzi forum. Invite-Only System umożli-wia zmianę warunków rejestracji użytkowni-

Vanilla

Jeśli chcemy zainstalować forum, które będzie przyjazne dla użytkownika, przyjemne i łatwe w obsłudze, najlepszym wyborem będzie forum Vanilla. W odróżnieniu od popularnego phpBB świeżo zainstalowana aplikacja Vanilla jest pozbawiona zbędnych elementów i zawiera jedynie podstawowe funkcje potrzebne do prowadzenia dyskusji.

Dowiesz się...• Jaka jest dobra alternatywa dla najpopular-

niejszego obecnie skryptu forum phpBB.

Powinieneś wiedzieć...• Jak umieszczać źródła strony na serwerze

• Jak tworzyć bazę danych MySQL

Poziom trudności

Alternatywa dla phpBB

Page 19: PHP Solutions 06 2007 PL

06/2007

Rozwiązania

18

Vanilla

www.phpsolmag.org 19

ków. Po zainstalowaniu tego rozszerzenia będą mogły się zarejestrować tylko osoby zaproszo-ne.Dodatek LatestBlog umożliwia użytkowni-kowi wyświetlanie w swoim profilu pięć ostat-nich wpisów z bloga.

Instalacja przykładowego rozszerzeniaBardzo przydatną funkcją w czasie prowa-dzenia dyskusji na forum jest możliwość cy-towania wypowiedzi innych użytkowników. Aby Vanilla udostępniała taką możliwość, ko-nieczne jest zainstalowanie odpowiedniego dodatku. Aby to zrobić, wchodzimy na stro-nę http://lussumo.com/addons/ i ściągamy Qu-oteText. Następnie rozpakowujemy pobrane archiwum i wgrywamy je na serwer do kata-logu extensions. Pozostaje nam jeszcze tylko aktywowanie rozszerzenia w panelu admini-stracyjnym.

Po tym kroku opcja cytowania jest do-stępna dla użytkowników pod przyciskiem Quote. Aby zmienić nazwę linku na „cytuj”, niezbędna będzie edycja pliku rozszerzenia. Wystarczy otworzyć plik default.php (plik za-wiera zaledwie kilka linijek kodu) i odnaleźć interesującą nas sekcję: Listing1. i zmienia-my Quote na cytuj lub jakiś inny tekst, który będzie dla nas dogodny. Po zapisaniu nowej wersji pliku instalacja rozszerzenia jest w peł-ni zakończona i użytkownicy mogą z niej ko-rzystać. Możliwa jest również zmiana domyśl-nego stylu dla cytowania, który zapisany jest w pliku style.css folderze rozszerzenia. Jak wi-dzimy, gama rozszerzeń dostępnych na stronie Vanilla jest bardzo szeroka. Dzięki zastosowa-niu mechanizmu zarządzania dodatkami bez trudu możemy w znaczący sposób rozbudo-wać nasze forum i zmienić je tak, by nasi użyt-kownicy byli usatysfakcjonowani.

Rysunek 1. Aktywacja rozszerzenia w panelu administracyjnym

Rysunek 2. Widok mapki google w profilu użytkownika

Listing 1. Edycja pliku rozszerzenia

<a href="./" onclick="QuoteText

(document.getElementById

(\'CommentBox\'),\'' .

$Comment->AuthUsername. '\');

return false;">Quote</a>

Listing 2. Klasa rozszerzająca klasę Control

class ShowText extends Control {

function Displayer(&$Context)

$this->Name = 'Displayer';

$this->Control($Context);

}

function Render() {

echo '<div id=\'ShowText\'>'.file_get_

contents

('extensions/showtext/

something.txt').'</div>';

}

}

Pozycja użytkownika vna mapie świataZ biegiem czasu ciągle rośnie popularność Go-ogle Maps. Rozwiązanie to, dzięki udostępnie-niu API (http://pl.wikipedia.org/wiki/API_(infor-matyka)) znajduje wiele bardzo ciekawych za-stosowań. Dzięki temu nasze forum możemy wzbogacić o mapkę pokazującą lokalizację po-szczególnych użytkowników w realnym świe-cie. Aby w pełni korzystać z narzędzia udo-stępnionego przez Google niezbędne jest za-rejestrowanie naszej witryny w celu uzyskania klucza, który umożliwi nam dostęp do serwe-ra map. Możemy tego dokonać na stronie http://www.google.com/apis/maps/signup.html wpisu-jąc adres naszej domeny w formularzu. Ma-py dla określonego rejonu ziemi pobierane są z serwera Google po przekazaniu długości i sze-rokości geograficznej. Oznacza to, iż musimy w jakiś sposób powiązać numery IP komputerów naszych użytkowników ze współrzędnymi geo-

graficznymi, które posłużyć mogą do pobrania odpowiedniej mapy. Do popularnych witryn umożliwiających tego typu powiązanie nale-żą między innymi http://www.maxmind.com (wersja komercyjna) oraz http://www.hostip.info udostępniająca API za darmo. Dzięki ogromnej społeczności Vanilla mamy dostępne rozszerzenie do naszego forum, które wykona za nas całą pracę. Ze strony http://lussumo.com/addons/ pobieramy plik add-ons IpMap i po roz-pakowaniu kopiujemy na serwer do katalogu rozszerzeń. Edytujemy plik default.php i za-mieniamy w linii 14 wartość zmiennej $Configuration['GoogleMapAPI'] przechowującejklucz google maps api, na ten, który otrzyma-liśmy w czasie rejestracji witryny. Wartość zmiennej $Context->Dictionary["IPMap"] określa nazwę wyświetlaną nad mapką w profi-lu użytkownika. Dla polskiego forum możemy zmienić jej wartość na Lokalizacja Użytkownika lub dowolną inną pamiętając iż forum korzysta

Page 20: PHP Solutions 06 2007 PL

06/2007

Rozwiązania

20

Vanilla

www.phpsolmag.org 21

wyświetlać różne dodatkowe składniki. I znów w bazie add-ons projektu znajduje się wiele pro-pozycji do pobrania poczynając od linków do stron w postaci listy, a skończywszy na formu-larzu wyszukiwania na forum. My skupimy się na zastosowaniu rozszerzenia SidepanelImage-Link, które poddamy pewnej modyfikacji. Po jego instalacji w typowy sposób, mamy moż-liwość zaobserwowania jego działania. W le-wym bocznym panelu strony wyświetla się lo-sowo, z zadeklarowanej wcześniej listy, (w pli-ku imglinks.txt) plik graficzny, który jest jednocześnie odnośnikiem do strony. Modyfi-kacja jaką wprowadzimy będzie zmieniała spo-sób deklaracji linku, tak, aby odnośnik zawie-rał znacznik TITLE, który jest cennym elemen-tem przy pozycjonowaniu stron internetowych.

Na początek edytujemy plik definicji linków i uzupełnimy każdą linię o dodatkowy parametr np. image1.jpg,http://www.mojastrona.pl zmie-niamy na image1.jpg,http://www.mojastrona.pl,najlepsza strona na świecie. Teraz pozostaje nam już tylko edycja pliku rozszerzenia, w celu wpro-wadzenia odpowiednich modyfikacji. Odnajdu-jemy kod odpowiedzialny za utworzenie tablicy elementów na podstawie pliku zawierającego na-sze rekordy: list($images[$i], $links[$i])

= $row; i zmieniamy go tak;aby możliwe było odczytanie parametru title, który został dodany list($images[$i], $links[$i], $title[$i])

= $row; Bezpośrednio po linii losującej element do wyświetlenia ($pos = mt_rand(0, $i - 1 );)następuje przepisanie elementów wiersza tabli-cy do zmiennych –dopiszemy tam jedną linijkę kodu, która przepisze nam wartość naszego title do zmiennej: $imgtitle = $title[$pos]; Po-została nam już tylko zmiana deklaracji samego linku, która może być różna dla poszczególnych podstron serwisu. Wszędzie gdzie delkalowa-ny jest link (<a href=\"$imglink\">) uzupeł-niamy wpis do następującej postaci: <a href=\

"$imglink\" title=\"$imgtitle\" > Teraz, po zapisaniu zmian w plikach, możemy zobaczyć efekt, jaki osiągnęliśmy. Wystarczy najechać kur-sorem myszy na wyświetlany w lewym panelu ob-razek by zobaczyć, iż ma on ustawiony element ti-tle. Możemy przygotować dowolnie dużą liczbę obrazków i linków, które po wpisaniu do odpo-wiedniego pliku będą się losowo wyświetlać.

Piszemy własne rozszerzenieMoże się zdarzyć, iż nie będziemy mogli zna-leźć rozszerzenia spełniającego nasze oczeki-wania. Nie pozostaje nam wtedy nic innego jak napisać własne rozszerzenie. Nie jest to wyzwanie bardzo trudne, ale będzie od nas wymagało poszerzenia wiedzy na temat bu-dowy rozszerzeń Vanilla. Na stronie http://lussumo.com/docs/doku.php w sekcji Developing New Extensions znajdziemy niewielki prze-wodnik, który przeprowadzi nas przez proces tworzenia rozszerzenia. Na początek musimy określić co nasze rozszerzenie miało by wpro-wadzać nowego do naszego forum. Załóżmy, że będziemy chcieli wyświetlać cokolwiek nad główną zawartością forum tak jak to jest poka-zane na Rysunku 4.

Z dokumentacji dowiadujemy się, że Vanilla potrafi wyświetlić w dowolnym miejscu strony obiekt Control za pomocą metody render obiek-tu Page. Pozostaje nam więc utworzenie nowe-go klasy, która będzie rozszerzała klasę Control. Kod php tej klasy przedstawia Listing 1., który jest fragmentem pliku default.php naszego roz-szerzenia.

Obiekt Control posiada wiele metod, za po-mocą których możemy kontrolować treść wy-świetlaną na stronie. Możemy między innymi określić poziom uprawnień użytkownika, któ-remu dana treść zostanie wyświetlona. W ce-lu uproszczenia nasze rozszerzenie będzie wy-Rysunek 4. Wstępne założenia dla tworzonego rozszerzenia

Rysunek 3. Odnośnik obrazkowy z ustawionym atrybutem title

z kodowania znaków utf8 i takie kodowanie powinno być ustawione w edytorze plików któ-rego używamy, w przeciwnym wypadku pol-skie znaki nie będą się poprawnie wyświetlać. Po uaktywnieniu zainstalowanego rozszerze-nia możemy przejść do widoku profilu dowol-nego użytkownika i jeśli jego IP znajduje się w bazie na stronie http://www.hostip.info zoba-czymy mapkę Google z zaznaczonym marke-rem określającego lokalizację, tak jak to widać na Rysunku 2.

Dynamiczny sidebarJak dotąd nasze forum jest bardzo statyczne, a strona główna nie zawiera żadnej grafiki z wy-jątkiem layout'u strony. Domyślny układ forum zaplanowany jest tak by po jego lewej stronie

Page 21: PHP Solutions 06 2007 PL

06/2007

Rozwiązania

20

Vanilla

www.phpsolmag.org 21

świetlać treść pliku something.txt wszystkim użytkownikom, w miejscu, które wcześniej wybraliśmy. Mamy już klasę definiującą nasz obiekt. Pozostaje nam już tylko jego utworze-nie oraz wyświetlenie. Listing 2. przedstawia kod php wykonujący tę czynność.

Zmienna $to_display zawiera nasz obiekt do wyświetlenia, który wyświetlamy za pomo-cą metody render. Pozycję do wyświetlenia usta-lamy względem pozycji CONTROL_POSI-TION_BODY_ITEM zapisanej w pliku konfi-guracyjnym. Dzięki temu mamy lepszą kontro-

lę nad pozycjami poszczególnych elementów wy-świetlanych na stronie. Wyjaśnimy teraz krótko, w jaki sposób Vanilla dodaje nasz element do wy-świetlenia. Obiekt Page zawiera wszystko co ma być wyświetlone danemu użytkownikowi. Na treść wyświetlaną składa się szereg obiektów ty-pu Control, które są tworzone w trakcie inicjacji skryptu. Nasze rozszerzenie ( i wszystkie inne), dodaje kolejny obiekt typu Control do wyświe-tlenia. Metody obiektu Page pobierają ustawienia przekazywanego obiektu typu Control i decydu-ją co, gdzie i komu ma być wyświetlone. I tak na przykład metoda render obiektu Control zwraca kod do wyświetlenia. W naszym przypadku jest to zwykły tekst, który zostaje przekazany do Page i wyświetlony. Listing 3. zawiera kompletny kod php naszego rozszerzenia.

Do obiektu Head dołączamy jeszcze plik ze stylami, które pozwolą nam kontrolować wy-gląd tekstu, jaki będziemy wyświetlać. Wyświe-tlanie tekstu ograniczone jest jeszcze do kilku stron Vanilla –nie chcemy przecież, by prezen-towana treść była wyświetlana w panelu admi-nistracyjny. Przykładowe style pokazane są na Listingu 4.

Vanilla a phpBBDo podstawowych różnic pomiędzy tymi apli-kacjami należy przede wszystkim system rozsze-rzeń, które są największym problemem phpBB. Twórcy tego forum skupili się na dostarcze-niu w pełni działającej aplikacji i nie wzięli pod uwagę możliwości poszerzania funkcjonalno-ści swojego produktu. Mimo swojego dużego stażu forum to nie zmienia się pod tym wzglę-dem, przez co traci na popularności. Mimo że dostępna jest cała gama pluginów do tego fo-rum, ich instalacja jest czasochłonna i niezachę-cająca. Twórca Vanilli zaprezentował inny punkt widzenia. Dostarczył uproszczony skrypt, który może być w bardzo prosty sposób poszerzany za pomocą panelu, w którym jednym kliknięciem aktywujemy lub dezaktywujemy wtyczkę. Da-je to możliwość sprawdzania przydatności wie-lu rozszerzeń, gdyż w każdej chwili mogą być one odinstalowane. Dużą przewagę nad swoim konkurentem Vanilla ma również w kwestii sza-blonu. Cały układ zbudowano bez użycia tabel, dzięki czemu jest dużo bardziej uniwersalny. Fo-rum oparte na Vanillia jest niewielką aplikacją o ogromnych możliwościach. Jej instalacja jest prosta i daje nam w pełni działające forum po-zbawione elementów, których większość użyt-kowników nigdy nie wykorzysta. Dzięki temu uzyskujemy wydajne forum, które możliwościa-mi nie ustępuje swoim konkurentom, również najpopularniejszym jak phpBB.

Rysunek 5. Końcowy efekt, osiągnięty przez nasze rozszerzenie

Listing 3. Kod php wyświetlający obiekt typu Control

$to_display = new ShowText($Context);

$Page->AddRenderControl($to_display,$Configuration

['CONTROL_POSITION_BODY_ITEM']-2);

Listing 4. Kod php utworzonego rozszerzenia

class ShowText extends Control {

function Displayer(&$Context) {

$this->Name = 'Displayer';

$this->Control($Context);

}

function Render() {

echo '<div id=\'ShowText\'>'.file_get_contents

('extensions/showtext/something.txt').'</div>';

}

}

if (in_array($Context->SelfUrl, array

('index.php', 'categories.php', 'comments.php', 'post.php'))) {

$Head->AddStyleSheet('extensions/show_something/style.css');

$to_display = new ShowText($Context);

$Page->AddRenderControl

($to_display,$Configuration['CONTROL_POSITION_BODY_ITEM']-2);

}

Listing 5. Zawartość pliku style.css

#ShowText {

color: grey;

border: 1px solid black;

margin: 10px;

padding: 10px;

}

PAWEŁ CHWASTMa 26 lat, mieszka w Legnicy, ukończył Kolegium

Karkonoskie w Jeleniej Górze, gdzie uzyskał tytuł

inżyniera w specjalności inżynieria komputerowa.

Kontakt z autorem: [email protected]

Page 22: PHP Solutions 06 2007 PL

Technika

22 06/2007

PHP i WAP

23www.phpsolmag.org

Poziom trudności

Mimo, że technologia ta od jakiegoś czasu nie jest już obiektem wes-tchnieniem fanów postępu tech-

nicznego, to wciąż jest dostępna w większo-ści aparatów komórkowych. Jeżeli chcesz do-wiedzieć się jak stworzyć dynamiczną stro-nę WWW, która poprawnie wyświetli się w komórce, przeczytaj ten artykuł.

TestowanieKażdy z nas, tworząc projekt witryny ,od sa-mego początku sprawdza wyniki swojej pra-cy. Znamy także doskonale różne interpreta-cje kodu przez przeglądarki. Niestety sytu-acja powtarza się także w telefonach komór-kowych. Na szczęście nie musimy kupować każdej wersji telefonu, aby sprawdzić dzia-łanie naszej witryny. Większość firm udo-stępnia specjalne symulatory, które pomo-gą nam przewidzieć efekt działania stworzo-nej aplikacji.

Oto kilka produktów: Nokia Mobile inter-net Toolikt , Openwave SDK, Motorola Wireless IDE/SDK . Istnieją także strony WWW, któ-re wyświetlają witryny WAP, tak jak w telefo-nach komórkowych. Oto adres jednej z nich: www.igsm.pl.

Jak tylko zaopatrzymy się w jeden z symula-torów, możemy przystąpić do tworzenia pierw-szej aplikacji internetowej dostępnej dla nasze-go telefonu komórkowego.

WML – podstawa działania WAPW klasycznych przeglądarkach interneto-wych, podstawową technologią jest (X)HTML,tak dla witryn wyświetlanych w technologii WAP, podstawową technologią jest WML. Jest to język, podobnie jak HTML, oparty o strukturę znaczników, całkowicie zgodny z XML-em i tak naprawdę jest to po prostu specyficzny rodzaj dokumentu XML. Ozna-cza to, że tworząc dokument WML obowią-zują nas takie same zasady, jak przy tworze-niu dokumentów XML.

Istnieją jednak pewne dodatkowe aspekty, które należałoby uwzględnić. Przede wszyst-kim jest interpretacja zawartości dokumen-tu jako talii a poszczególnych podstron jako kart. Listing 1. pokazuje podstawową kon-strukcję dokumentu WML wraz z podzia-łem na karty.

W momencie załadowania witryny WAP w naszym telefonie, domyślnie zostaje wy-świetlana karta pierwsza. Zatem, aby stwo-rzyć naszą pierwszą witrynę WAP wystar-czy jeśli w karcie pierwszej wpiszemy powi-talny tekst.

Niezbędnym jest także, aby tekst został umieszczony w akapicie, czyli znacznikach

<p>. Kod wystarczający do stworzenia pierw-szej witryny WAP jest pokazany na Listin-gu 1.,a na Rysunku 1. znajduje się wynik je-go działania.

To oczywiście dopiero początek, albowiemżaden z klientów nie chce ponieść kosztów za nawiązanie połączenia z siecią dla zwykłe-go powitania.

Tworząc taką witrynę, powinniśmy przede wszystkim nastawić się na zawartość mery-toryczną i praktyczną. Nie należy przejmo-wać się ani układem, ani oprawą graficzną, dźwiękami i animacjami.

Przede wszystkim skupmy się na funkcjo-nalności i ograniczeniu pojemności, gdyż zbyt duża witryna to jest to, co najbardziej doskwiera użytkownikom stron tworzonych na potrzeby WAP.

Jak stworzyć menu?Oczywiście niezbędną rzeczą w każdej szanującejsię witrynie jest możliwość wyboru dowolnej dostępnej podstrony. W witrynach WAP mamy dwie możliwości rozwiązania problemu nawiga-cji. Pierwszą z nich jest możliwość wczytania za-wartości różnych podstron już za pierwszym po-łączeniem z serwerem i zapisanie ich do innych kart. Drugą możliwością jest łączenie się z ser-werem i wywoływanie innego pliku. Przy czym możliwe są kombinacje obu tych technik. Na Listingu 2. przedstawiony jest sposób tworze-nia odnośników, z pewnością znany doskonale z HTML-a.

PHP i WAP

WAP – Wireless Application Protocol, czyli znana wszystkim posiadaczom telefonów komórkowych technologia bezprzewodowego dostępu do internetu.

Dowiesz się...• Jak stworzyć dynamiczną witrynę WWW dla

WAP.

Powinieneś wiedzieć...• Powinieneś znać podstawy programowania

w PHP.

Tworzenie dynamicznych stron WWW dla WAP

Podstawowe zasady tworzenia dokumentu XMLW dokumencie XML może istnieć tylko jeden główny element. W przypadku witryn WAP jest nim znacznik <wml>. Każdy znacznik powinien zostać zamknięty, nawet w przypadku znacz-ników takich jak <br> w następujący sposób: <br /> lub <br></br>. Ważne jest, aby za-chowywać poprawną hierarchię znaczników tzn., nie wolno wykonać następującej opera-cji: <znacznik1><znacznik2></znacznik1></znacznik2>. Powinna ona wyglądać tak: <znacznik1><znacznik2></znacznik2></znacznik1>. Należy pamiętać, że XML odróżnia małe litery od wielkich, zatem znacznik <Card> to co innego niż znacznik <card>. Każdy atrybut dowolnego znacznika powinien zostać zapisany w cudzysłowach.

Page 23: PHP Solutions 06 2007 PL

Technika

22 06/2007

PHP i WAP

23www.phpsolmag.org

Istotą tego rozwiązania jest ustawienie wła-ściwego typu MIME dla wyświetlanego ry-sunku.

Komunikacja użytkownika z witrynąChcąc zapewnić możliwość komunikacji użyt-kownika z witryną, tak jak w przypadku zwy-kłych witryn wyświetlanych przez przeglądarki internetowe, możemy skorzystać z formularzy. Zasada ich tworzenia jest bardzo podobna do tej znanej z HTML-a.

Pamiętajmy jednak, że wpisywanie długich napisów w komórkach jest dość kłopotliwe, dlatego nie zmuszajmy do tego użytkownika, jeżeli nie jest to konieczne.

Przechodząc już ściśle do formularzy, oto ja-kie elementy możemy wykorzystać: pole teksto-we – tworzone za pomocą znacznika input w na-stępujący sposób <input type=”text” /> , po-le hasła – również tworzone za pomocą znaczni-ka input, przy jednoczesnej zmianie typu <input type=”password”>.

Pozostałe elementy, takie jak lista wyboru, przy-cisk opcji i pola wyboru, reprezentowane są przez znacznik <select> .

Samo tworzenie formularza jest dość pro-stym zadaniem. Aby wyświetlić dane zawar-te w formularzu używamy zmiennych WML, które tworzone są po wypełnieniu danych for-mularza. Zmienne w WML poprzedzone są znakiem dolara, a sama nazwa ujęta jest w na-wiasy i odpowiada nazwie atrybutu pola for-mularza.

Istnieje jeszcze pytanie, jak przesłać dane na serwer. Oczywiście są dwie metody: GET i POST. Samo przesyłanie różni się nieco od tej metody którą znamy, albowiem nie mamy do dyspozy-cji parametru action. Jeżeli wykorzystujemy metodę GET – co w większości sytuacji jest gor-szym rozwiązaniem, gdyż ogranicza ona moż-liwości przesyłu danych – wystarczy jeżeli wy-wołamy odpowiedni odnośnik i dopiszemy do

Listing 1. Podstawowa konstrukcja dokumentu WML

<?xml version=”1.0”?>

<!DOCTYPE wml PUBLIC ”-//WAPFORUM//DTD WML 1.2//EN” ”http://www.wapforum.org/DTD/

wml12.dtd”>

<!-- to nasza talia-->

<wml>

<card id=”card1” title=”PHPSOLUTION”>

<p>

Twoja pierwsza strona WAP.

</p>

</card>

<card id=”card2”>

<!--Zawartość drugiej karty-->

</card>

</wml>

Listing 2. Tworzenie odnośników w WML̀ u

<!-- Nastąpi wczytanie strony powitanie.wml-->

<a href="powitanie.wml">Powitanie</a>

<!-- Nastąpi wyświetlanie karty o id=card2 -->

<a href="#card2">Autor</a>

<!-- Nastąpi wczytanie strony powitanie.wml i wyświetlenie karty o id=card2 -->

<a href=”powitanie.wml#card2</a>

Listing 3. Przesyłanie danych metodą POST

<anchor>

<go href=”dane.php” method=”post”>

<postfield name=”imie” valuve=”$(imie)” />

</go>

</anchor>

Gdzie umieścić witrynę przeznaczoną dla WAP?W najnowszych wersjach serwera Apache nie ma najmniejszych problemów z poprawną inter-pretacją tego rodzaju witryn, dlatego polecamy ich umieszczanie właśnie tam. Przy innych ser-werach być może pojawią się problemy ze skojarzeniem odpowiedniego rozszerzenia z typem zawartości MIME. W takim przypadku należy ustawić dla rozszerzenia WML typ zawartości (MI-ME) na text/vnd.wap.wml.

Atrybuty pola tekstowego w WML`uIstnieje kilka podstawowych atrybutów pozwalających na uszczegółowienie oczekiwanej war-tości:

• emptyok – przyjmuje wartość true, jeżeli pole nie musi być wypełnione;• format – pozwala na określenie formatu wprowadzanego tekstu;• maxlenght – maksymalna dozwolona długość;• http://name – atrybut oznacza identyfikator;• size – określa szerokość pola na ekranie;• title – tytuł dla danego pola; nie jest wyświetlany przez wszystkie przeglądarki;• value – tekst, który jest wyświetlany.

Jak wstawić grafikę na stronę?Grafika dla witryn WAP przedstawiana jest w formie plików WBMP, czyli jednokolorowych map bitowych. Spowodowane jest to przez tech-nologiczne możliwości WAP lub przez szyb-kość przesyłu danych. Im mniej kolorów i mniej-szy rozmiar obrazka, tym szybsze połączenie. Chcąc stworzyć obraz w formacie WBMP, mo-żemy posłużyć się aplikacją Adobe Photoshop 7.0, gdzie mamy możliwość eksportu obrazu właśnie do formatu WBMP. Sam kod, realizu-

jący wyświetlanie, wygląda następująco: <img src=”obrazek.wbmp” alt=”” />.

W przypadku wyświetlania grafiki w for-macie WBMP, przy pomocy PHP, mogą wystą-pić pewne problemy, szczególnie jeżeli nie ma-my dostępu do plików konfiguracyjnych. W ta-kim przypadku pomocny okaże się następują-cy kod:

header(„Content-type: image/und.wap.wbmp”);

echo(file_get_contents('rysunek.wbmp');

Rysunek 1. Twoja pierwsza witryna WWW dla WAP

Page 24: PHP Solutions 06 2007 PL

Technika

24 06/2007 www.phpsolmag.org

adresu url dane, które chcemy przesłać. Może to wyglądać tak: <a href=”dane.php?imie=$(imie)”>wyslij</a>.

Właściwie nie wprowadzamy tu specjalnejrewolucji. Sprawa ma się nieco inaczej w przypad-ku metody POST, gdyż wymaga ona użycia dodat-

kowych elementów. Na początku musimy wy-korzystać znaczniki <postfield> i nadać im żądane wartości w następujący sposób: <post-

fieldname=”imie” value=”$ (imie)”/>. Następ-nie wykorzystując elementy <anchor> i tworzy-my skrypt taki jak na Listingu 3.

Wykorzystanie PHP i dynamiczna witryna WAPPo tym jak już zapoznaliście się z podstawami działania technologii WML, możemy przystąpić do dynamicznego kreowania zawartości witryny, oczywiście przy pomocy PHP. Aby nabrać wpra-wy, stwórzmy witrynę, której celem będzie wy-świetlenie informacji o statusie wprowadzonego numeru komunikatora gadu-gadu.

Wykonajmy zatem podstawową strukturę dokumentu WML, w którym zamieścimy treść wstępną i pole tekstowe, wpiszmy numer gadu-gadu, którego chcemy poznać aktualny status. Całość możemy zaobserwować na Listingu 4.i podzieliliśmy na trzy karty. W pierwszej przed-stawiamy tekst informacyjny, w następnej da-ne autora skryptu i kartę, w której wpisujemy numer gadu-gadu. W każdej z kart powtarza-my wyświetlanie menu tak, aby nawigacja by-ła możliwa na każdej podstronie. Do przesła-nia danych wykorzystujemy metodę post opi-saną wcześniej. Teraz zajmiemy się już tylko i wyłącznie odpowiednimi formułami PHP. Zacznijmy od tego, w jaki sposób ustawić po-prawny typ MIME. Wystarczy, jeżeli podacie wskazaną przez nas formę nagłówka:

header(”Content-type: text/vnd.wap.wml”);

Teraz możemy pobrać przekazywany numer gadu-gadu: $ggnumer=$ _ POST['ggnumber']; i zadeklarować odpowiednią wersję dokumen-tu XML: echo "<?xml version=\"1.0\"?>";. Aby pobrać aktualny status wybranego nume-ru komunikatora gadu-gadu stwórzmy nastę-pującą zmienną:

$string="http://status.gadu-gadu.pl/

users/status.asp?id=".$ggnumer."&styl

=2";

i skorzystajmy z funkcji fopen. Dzięki tym za-biegom otrzymamy informacje w postaci cy-fry, która pozwoli nam na określenie aktual-nego statusu użytkownika. Całość skryptu przedstawiona jest na Listingu 5.

Jak rozpoznać klientaKolejnym istotnym problemem jest stworze-nie funkcji, która pozwoli nam odczytać rodzaj klienta z jakim mamy do czynienia (może to być np. przeglądarka internetowa lub właśnie tele-fon komórkowy). Może to być przydatne gdy tworzona przez nas witryna ma być dostępna za-równo dla telefonów komórkowych jak i dla kla-sycznych użytkowników internetu. Pierwszym nasuwającym się sposobem jest wykorzystanie zmiennej $_SERVER['HTTP_USER_AGENT'].

Możemy porównywać wartość tej zmiennej ze znanymi przeglądarkami WWW i przeglą-darkami WAP, co pozwoli nam na otworzenie pożądanej witryny. Przy zastosowaniu tej tech-niki występuje jednak poważny minus, mia-nowicie, nieustannie powinniśmy aktualizo-

Listing 4. Dokument WML

<?xml version="1.0"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.2//EN" "http://www.wapforum.org/DTD/

wml12.dtd">

<wml>

<!-- to nasza talia-->

<card id="card1" title="Sprawdz GG">

<p>

Witamy na naszej stronie. Dzieki niej bedziesz mogl sprawdzic status podanego przez

siebie numeru GADU-GADU.

</p>

<p>

Menu<br />

<a href="#card3">Wprowadz numer gg</a>

<a href="#card2">Autor</a>

</p>

</card>

<card id="card2" title="PHPSOLUTION">

<p>

Autorem jest Tomasz Roszko

</p>

<p>

Menu<br />

<a href="#card3">Wprowadz numer gg</a>

<a href="#card2">Autor</a>

</p>

</card>

<card id="card3" title="Podaj numer">

<p>

Numer gg:

<input type="text" name="ggnumber" size="8" title="Numer gg" />

</p>

<p>

<anchor>

<go href="gg.php" method="post">

<postfield name="ggnumber" value="$(ggnumber)" />

</go>

Wyslij dane

</anchor>

</p>

<p>

Menu<br />

<a href="#card3">Wprowadz numer gg</a>

<a href="#card2">Autor</a>

</p>

</card>

</wml>

WmlScriptMożemy powiedzieć, że jest to uproszczona wersja JavaScript dla języka WML. Zachodzi jednak jedna znacząca różnica. WmlScript nie działa po stronie klienta, tylko tak jak PHP, już na serwe-rze. Zasadność używania WmlScript jest mocno dyskusyjna, gdyż do tych samych celów możemy wykorzystać PHP. Jednakże wszystkich zainteresowanych WmlScript odsyłam do witryny http://www.webreference.com/.

Page 25: PHP Solutions 06 2007 PL

Technika

24 06/2007 www.phpsolmag.org

wać listę dostępnych przeglądarek. Innym spo-sobem jest sprawdzanie listy obsługiwanych przez klienta typów MIME. Taką listę zawiera zmienna PHP $_SERVER['HTTP_ACCEPT'];.

Jeżeli odnajdziemy na liście typ MIME dla plików WML, oznacza to będzie że najprawdo-podobniej klient korzysta z przeglądarki obsłu-gującej WAP. Obie te metody mogą jednak być zawodne dlatego najlepszym rozwiązaniem jest całkowite rozgraniczenie klasycznej aplikacji WWW i tej tworzonej dla WAP.

WAP i bramka e-mailWykorzystując PHP bez większych problemów możemy stworzyć jakże pożyteczną aplikację WAP, której zadaniem będzie wysyłanie wiado-mości e-mail. Wystarczy, że przygotujemy no-wą kartę wraz odpowiednimi polami formula-rza, tak jak na Listingu 6. (zamieszczony w ma-teriałach dodatkowych na płycie).

Po wysłaniu danych formularza przekazane zo-staną one do strony email.php. Cały proces kon-strukcji formularza jak i sposobu przesyłania da-nych do innego pliku na serwerze jest identyczny z tym przedstawianym wcześniej. Następnie aby

wysłać wiadomość w pliku email.php niezbędne jest odebranie wysłanych metodą POST danych i skorzystanie z wbudowanej funkcji mail. Całość skryptu realizującego to zadanie przedstawione jest na Listingu 7. zamieszczonym na płycie.

Oczywiście aby stworzyć w pełni funkcjonal-ną aplikację niezbędnym jest także sprawdze-nie poprawności wprowadzonych danych, co jednak nie jest istotą tego artykułu.

PodsumowaniePokazaliśmy jak stworzyć witrynę WAP i wyko-rzystać w tym celu PHP. Podany przykład zilu-strował najważniejsze aspekty tworzenia strony WAP. Pokazaliśmy, jak wykonać menu i przesłać informacje na serwer. Dzięki tym informacjom można bez trudu tworzyć podobne aplikacje, włączając w to system logowania, system new-sów i wiele, wiele innych.

TOMASZ ROSZKOAutor jest studentem informatyki na Uniwersytecie

w Białymstoku.

Kontakt z autorem: [email protected]

Listing 5. Aktualny status gadu-gadu w witrynie WAP

<?php

header("Content-type: text/vnd.wap.wml");

$ggnumer=$_POST['ggnumber'];

echo "<?xml version=\"1.0\"?>";

?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.2//EN" "http://www.wapforum.org/DTD/wml12.dtd">

<wml>

<card id="card1" title="Sprawdzanie zakonczone">

<?php

$string="http://status.gadu-gadu.pl/users/status.asp?id=".$ggnumer."&styl=2";

$fp =fopen($string,"r");

$numer = fread($fp, 1000);

fclose($fp);

if ($numer==2 or $numer==3) {

echo "<p>Podany numer jest aktualnie dostepny</p>";

} else {

echo "<p>Podany numer nie jest aktualnie dostepny</p>";

}

?>

<p>

<a href="gg.wml#card3">Powrot</a>

</p>

</card>

</wml>

Atrybuty elementu <img>

• align – standardowe wyrównanie grafiki, do środka, lewej bądź prawej strony;• alt – przechowuje alternatywną treść, wyświetlaną w momencie gdy grafika nie może zostać

wyświetlona;• height, width – odpowiada za wysokość i szerokość obrazka, domyślne wykorzystywane są

oryginalne wymiary obrazka;• src – określa adres URL do pliku WBMP;• vspace – wolne pole wyrażone w pikselach znajdujące się nad i pod obrazek WBMP.

Page 26: PHP Solutions 06 2007 PL

Technika

26 06/2007

Delphi i PHP

27www.phpsolmag.org

Sposób komunikacji, opiera się na meto-dzie POST, która umożliwia wysyłanie danych przy pomocy nagłówków HTTP.

Dane przesyłane tą metodą mają postać:

pole1=wartość&pole2=wartość2.

Tak więc: nazwa pola jest oddzielona od jego wartości znakiem „=”, natomiast poszczególne porcje danych oddziela znak „&”. Przykładowy nagłówek z powyższymi informacjami wyglą-dałby więc tak, jak na Listingu 1.

Z Delphi do PHPZacznijmy projektować naszą aplikację, która prześle dane do skryptu metodą POST . Uru-chamiamy Delphi i z menu File wybieramy New Application.

Po instalacji pakietu INDY w Delphi, przy-będzie nam kilka nowych zakładek na pa-lecie komponentów. Odszukajmy zakład-kę Indy Clients i wybierzmy z niej kompo-nent IdHTTP. To on umożliwi nam wysyła-nie danych.

Umieścimy jeszcze następujące kompo-nenty: 3x Edit, 4x Label, 1x Button, oraz 1x Memo (wszystkie one znajdują się w zakład-ce Standard). Ich przykładowe rozmieszcze-nie, a także właściwości Caption jakie powin-

niśmy im nadać, zostały zaprezentowane na Rysunku 1.

Po umieszczeniu wszystkich elementów, kliknijmy tylko raz na komponent IdHTTPi przejdźmy do Object Inspector’a, a następ-nie – odszukajmy listę Request. Po jej rozwinię-ciu ukaże się nam kilka atrybutów, interesować nas będzie ten o nazwie ContentType. W to pole musimy wpisać ciąg:

application/x-www-form-urlencoded.

Więcej o kodowaniu danych możemy przeczy-tać w ramce „Kodowanie danych”.

Pisanie koduProjektowanie aplikacji mamy już za sobą, czas więc na napisanie kilku linijek kodu. Nasz pro-gram będzie miał za zadanie:

• pobrać adres strony;• pobrać dwie zmienne do wysłania;• wysłać dane;• odebrać kod wynikowy.

Jego lista zadań jest krótka. Dzięki zastoso-waniu komponentu IdHTTP, kod również bę-dzie krótki. Kliknijmy dwa razy na Button’ie i wpiszmy kod, który znajduje się na Listingu 2.

Przyjrzyjmy się linijce odpowiadającej za utworzenie strumienia StreamIn, a szczególnie fragmentowi:

(Format('text1=%s&text2=%s', [Edit2.Text,Ed

it3.Text])).

Jak pamiętamy, dane przesyłane metodą POST mają postać:

pole1=wartość&pole2=wartość2.

Dlatego musimy je przesłać w taki sposób. Nazwy pól: „text1” i „text2” są nazwami przy-kładowymi, które następnie zastosujemy w skrypcie odbierającym dane. Należy pamię-tać, że będą one różne dla każdej strony, która odbiera pakiety z danymi.

Powyższa linijka tworzy ciąg powstały z po-łączenia tekstu w cudzysłowie, z tekstem wpi-sanym w Edit2 i Edit3. Owy ciąg jest następ-nie wysyłany do skryptu za pomocą funkcji POST komponentu IdHTTP. Ostatnim kro-kiem będzie zapisanie i skompilowanie nasze-go projektu.

Gdy mamy już gotową aplikację, może-my stworzyć najprostszy plik PHP, który po-służy nam do jej testowania. Propozycja ko-du znajduje się na Listingu 3. W skrypcie, dla ułatwienia, zostały zastosowane zmien-ne o takich samych nazwach, jak w naszym programie.

Po zapisaniu pliku PHP i umieszczeniu go na serwerze, uruchamiamy naszą aplikację, po-dajemy odpowiednie parametry i naciskamy przycisk POST. Pole tekstowe „Memo” podpisa-ne jako „Kod wynikowy” zostanie automatycz-nie uzupełnione danymi zwróconymi przez skrypt. Przedstawia to Rysunek 2.

Delphi i PHP

Pomiędzy Delphi i PHP można stworzyć własne aplikacje do komunikacji pomiędzy tymi językami. Służy do tego metoda POST.

Dowiesz się...• W jaki sposób odebrać dane ze skryptu.

• W jaki sposób wysłać dane do skryptu.

Powinieneś wiedzieć...• Powinieneś znać podstawy języka i środowi-

ska Delphi.

• Powinieneś znać podstawy języka PHP i HTML.

• Powinieneś znać podstawowe pojęcia związa-

ne z protokołem http.

Poziom trudności

Komunikacja

Listing 1. Przykładowy nagłówek z danymi wysłanymi metodą POST

POST /index.php HTTP/1.1

Host: www.domena.com

User-Agent: Mozilla/5.0

Content-Length: 28

Content-Type: application/x-www-form-

urlencoded

pole1=wartość&pole2=wartość2

Page 27: PHP Solutions 06 2007 PL

Technika

26 06/2007

Delphi i PHP

27www.phpsolmag.org

Przykładowe zastosowaniePrzykładowym zastosowaniem powyższej metody komunikacji może być program, któ-ry będzie uploadował wybrane obrazy z na-szego dysku twardego na darmowy hosting zdjęć ImageShack (dostępny pod adresem www.imageshack.us). Zaczniemy od małego rekonesansu, tak więc otwieramy ową stro-nę. Aby uniknąć żmudnej analizy kodu w celu „wydobycia” szczegółów, skorzystajmyz wtyczki do Firefox’a pod nazwą Web Develo-per (link znajduje się w ramce „W Sieci”). Po-siada ona funkcję, która modyfikuje wyświe-tlaną stronę pokazując, na przykład, szcze-góły formularzy. Zostało to pokazane na Ry-sunku 3.

Co na nim widzimy? Po pierwsze – for-mularz odwołuje się do strony głównej Ima-geShack.us (fragment form action=””), po drugie- format kodowania danych to multipart/form-data (fragment enctype=””), i wreszcie po trzecie- pole, z którego pobierana jest ścież-ka do wysyłanego pliku (input name="fileuplo-ad”). Posiadając te informacje możemy rozpo-cząć projektowanie aplikacji.

Przykładowa aplikacjaZacznijmy od stworzenia nowego projek-tu. Potrzebne nam będą komponenty: 1x Edit, 1x Memo, 1x button, a także komponent IdHTTP.

Podobnie jak ostatnio – kliknijmy raz na komponent IdHTTP i przejdźmy do Object Inspector’a , a następnie – odszukajmy li-stę Request. Po jej rozwinięciu ukaże nam się kilka atrybutów; interesować nas będzie ten o nazwie ContentType. W to pole musimy wpi-sać ciąg:

multipart/form-data.

Teraz, kliknijmy dwa razy na komponent But-ton, i w edytorze kodu wpiszmy fragment z Listingu 4. Jak widać została tam zawarta zmienna MyData typu TIdMultiPartFormDa-taStream. Jest to specyficzny typ strumienia

Rysunek 1. Przykładowe rozmieszczenie komponentów. Z lewej strony – komponenty ze standardowymi właściwościami Caption, natomiast z prawej – komponenty posiadające zmodyfikowaną tę właściwość

Listing 2. Wysyłanie danych z aplikacji do skryptu metodą POST

procedure TForm1.Button1Click(Sender: TObject);

var

StreamIn,StreamOut: TStringStream;

begin

try

{Tworzymy strumień StreamIn zawierający łańcuch danych,

zostanie on potem wysłany do skryptu}

StreamIn := TStringStream.Create(Format('text1=%s&text2=%s', [Edit2.Text,Edit3.Text]

));

{Tworzymy pusty strumień StreamOut. Będzie on odpowiedzialny

za odbiór kodu wynikowego skryptu}

StreamOut := TStringStream.Create('');

{Procedura POST komponentu IdHTTP i jej kolejne parametry:

Adres URL, strumień z danymi, strumień odbierający}

IdHTTP1.Post(Edit1.Text,StreamIn,StreamOut);

{Wyświetlamy kod wynikowy ze strumienia w Memo}

Memo1.Lines.Text:=StreamOut.DataString;

finally

{Zwalniamy strumienie}

StreamIn.Free;

StreamOut.Free;

end;

end;

Listing 3. Odbieranie danych z aplikacji wysłanych metodą POST

<?php

$text1=$_POST['text1'];

$text2=$_POST['text2'];

echo "Zmienna \"text1\" to: $text1\n"; //wyświetlamy zmienną „text1”

echo "Zmienna \"text2\" to: $text2\n"; //wyświetlamy zmienną „text2”

?>

Rysunek 2. Gotowa aplikacja wysyłająca dane do skryptu

Rysunek 3. Wtyczka Web Developer wyświetlająca szczegóły formularza na stronie ImageShack.us

Page 28: PHP Solutions 06 2007 PL

Technika

28 06/2007

Delphi i PHP

29www.phpsolmag.org

OnClose naszej formy, wpiszemy ponownie kod z Listingu 5. który tym razem jest opisa-ny jako:

{Procedura OnClose}.

Główne zdarzenia zostały już napisane, czas teraz na kod, który umożliwi odbieranie da-nych. Klikamy na komponent IdHTTPServer1 i przechodzimy do Object Inspector. Odszu-kujemy Event podpisany jako OnCommand-Get i wpisujemy kod z Listingu 6.

Aplikacja jest już gotowa, możemy ją zapi-sać i skompilować. Podobnie jak wcześniej, stworzymy jeszcze plik PHP, z tym, że te-raz to on będzie wysyłał dane do serwera. W tym celu posłużymy się najprostszym for-mularzem, którego propozycja kodu znajdu-je się na Listingu 7. Pamiętajmy, że nasz pro-gram działa na porcie 8008 (aby uniknąć ko-lizji z innymi aplikacjami), więc będziemy odwoływać się do niego w następujący spo-sób http://AdresIP:NumerPortu, czyli http://localhost:8008.

Teraz musimy jeszcze uruchomić nasz pro-gram i wypełnić pola formularza, a następnie go zatwierdzić. Wynik działania aplikacji, która odebrała parametry i zwróciła wynik do prze-glądarki znajduje się na Rysunku 6.

Przykładowe zastosowaniePowyższy sposób komunikacji może być wyko-rzystany- np. do zdalnej administracji kompu-terem poprzez stronę WWW.

Wg definicji serwera aplikacji jest to „pro-gram działający na zdalnej maszynie obsługu-jący żądania kierowane do aplikacji, do której dostęp zapewnia. Użytkownik łączy się za po-średnictwem przeglądarki internetowej, kieru-je żądanie do wybranej aplikacji, a całość ope-racji odbywa się po stronie komputera nale-żącego do organizacji, która udostępnia daną aplikację.”(pl.wikipedia.org).Zastanówmy się naj-pierw nad ogólną koncepcją naszej aplika-cji – zarówno klienta jak i serwera. Klient – w tym przypadku strona WWW – powinien zawierać pola: „Login” oraz „Hasło”, aby nasze-go zdalnego systemu nie mogły przechwycić

Listing 4. Wysyłanie danych z aplikacji do strony ImageShack

procedure TForm1.Button1Click(Sender: TObject);

var

MyData: TIdMultiPartFormDataStream;

begin

{tworzymy specyficzny strumień z danymi}

MyData:=TIdMultiPartFormDataStream.Create;

try

{kolejny krok to dodanie do strumienia, metodą AddFile, kolejno:

nazwy pola (fileupload),ścieżki pliku, a także typu zawartości

pakietu z danymi(file)}

MyData.AddFile('fileupload',Edit1.Text,'file');

{kod wynikowy zostanie wyświetlony w Memo1}

Memo1.Lines.Text:=IdHTTP1.Post('http://imageshack.us/',MyData);

finally

{Zwalniamy strumień}

MyData.Free;

end;

end;

Listing 5. Aktywacja i deaktywacja serwera IdHTTPServer1

{Procedura OnCreate}

procedure TForm1.FormCreate(Sender: TObject);

begin

{Ustawiamy numer portu dla serwera}

IdHTTPServer1.DefaultPort := 8008;

{aktywujemy serwer}

IdHTTPServer1.Active:=True;

end;

{- - -}

{procedura OnClose}

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);

begin

{dezaktywujemy serwer}

IdHTTPServer1.Active:=False;

end;

{- - -}

Kodowanie danychJeżeli chcemy wysłać dane do serwera za-wierające elementy formularza, to muszą one wcześniej zostać zakodowane. Kodo-wanie application/x-www-form-urlencoded jest kodowaniem domyślnym, które prze-glądarka wysyła do skryptu; używamy go do wysyłania małych ilości informacji. Nie sprawdza się ono jednak podczas wysyła-nia dużych ilości danych binarnych lub roz-ległego tekstu. Do tego celu należy użyć ko-dowania multipart/form-data.

Niezależnie od tego, na jakie kodowa-nie się zdecydujemy, musimy pamiętać o je-go implementacji w naszym programie.

z danymi, którego implementacja konieczna jest do wysłania danych, zakodowanych w for-macie multipart/form-data. Aby z niego skorzy-stać, konieczne jest dodanie do sekcji Uses mo-dułu IdMultipartFormData. Jest on dołączony do pakietu INDY. Po kompilacji projektu na-leży w pole Edit wpisać ścieżkę obrazu, któ-ry chcemy uploadować, a następnie nacisnąć przycisk Button.

Zachęcam do przejrzenia kodów źródło-wych, które zostały dołączone do płyty. Do aplikacji dodałem również parser, który po-biera z kodu wynikowego linki do naszego obrazu, ale to temat na inny artykuł. Przy-kład działania aplikacji pokazany jest na Ry-sunku 4.

Z PHP do Delphi...Teraz nadszedł czas na napisanie programu, który będzie umożliwiał odbieranie zmien-nych wysyłanych przez skrypt.

Stworzymy nową aplikację i na formie umieścimy komponenty: 2x Label, 1x Edit

oraz 2x Memo (wszystkie one znajdują się w zakładce Standard). Ostatnio użyliśmy kom-ponentu, który był klientem protokołu HTTP. Pisząc tę aplikację, będziemy musieli stwo-rzyć serwer HTTP. Odszukajmy więc zakład-kę Indy Servers i wybierzmy z niej komponent IdHTTPServer. Ich przykładowe rozmieszcze-nie, a także właściwości Caption jakie powin-niśmy im nadać, zostały zaprezentowane na Rysunku 5.

Pisanie koduPrzyszedł czas na oprogramowanie naszej apli-kacji. Zacznijmy od aktywacji serwera- klikamy na formie i odszukujemy właściwość OnCre-ate na zakładce Events w oknie Object Inspector i wpisujemy tam fragment kodu z Listingu 5. podpisanego jako:

{Procedura OnCreate}.

Deaktywacja serwera odbywać się będzie pod-czas zamykania programu, więc w zdarzenie

Page 29: PHP Solutions 06 2007 PL

Technika

28 06/2007

Delphi i PHP

29www.phpsolmag.org

niepowołane osoby, a także kilka opcji wybo-ru, które będą reprezentowały możliwe do wy-konania funkcje przez zdalny system. Po wy-braniu opcji „Wyślij”, skrypt wyśle parametry do aplikacji – serwera.

Serwer natomiast, po odbiorze porcji da-nych, powinien mieć możliwość ich wali-dacji, w tym danych użytkownika (jego na-zwy oraz hasła), który chce skorzystać z jego usług, a także oczywiście mieć możliwość wy-konania żądanego polecenia. Po jego wykona-niu serwer powinien zwrócić wynik, następ-nie wszystkie operacje powinny być zapisywa-ne w logach.

Rysunek 5. Przykładowe rozmieszczenie komponentów. Z góry: komponenty ze standardowymi właściwościami Caption, natomiast u dołu: komponenty posiadające zmodyfikowaną tą właściwość

Rysunek 4. Gotowa aplikacja wysyłająca obrazy na hosting ImageShack.us i parsująca kod wynikowy

Rysunek 6. Gotowa aplikacja odbierająca dane od skryptu

Listing 6. Odbieranie danych przez aplikację

procedure TForm1.IdHTTPServer1CommandGet(AThread: TIdPeerThread;

ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);

var

StrResult: String;

begin

{w Memo zostaną umieszczone żądania (request server)}

Memo1.Lines.Add(ARequestInfo.Document);

{tworzymy kod wynikowy dla przeglądarki}

StrResult := '<h1>Testowa strona serwera.</h1>'

+'<b>Odebrane dane:</b>'

{ARequestInfo.Host zawiera informacje o hoście użytkownika...}

+ '<p>Host: ' + ARequestInfo.Host + '</p>'

{...natomiast ARequestInfo.UnparsedParams wyświetla parametry

przekazane do naszego serwera}

+ '<p>Parametry: ' + ARequestInfo.UnparsedParams + '</p>';

{wyświetlamy w przeglądarce stworzony łańcuch}

AResponseInfo.ContentText := StrResult;

{do Edit1 dodajemy parametry przekazane do serwera}

Edit1.Text:=ARequestInfo.UnparsedParams;

end;

Listing 7. Formularz wysyłający zmienne metodą POST do aplikacji

<html>

<!--implementacja formularza: odwołuje się on do „http://localhost:8008” i przesyła

dane metodą „POST”-->

<form action="http://localhost:8008" method="post">

<label for="login">Login: </label>

<br />

<input name="login" type="text">

<br />

<label for="password">Password: </label>

<br />

<input name="password" type="password">

<br />

<input value="GO!" type="submit">

</form>

</html>

Listing 8. Przykładowa aplikacja klienta

<html>

<form action="http://localhost:8008" method="post">

<label for="login"><b>Login</b></label>

<br />

<input name="login" type="text" value="" style="width: 300px" />

<br />

<label for="pass"><b>Hasło</b></label>

<br />

<input name="pass" type="text" value="" style="width: 300px" />

<br />

<label><b>Polecenie</b></label>

<br />

<input type="radio" name="opcje" value="shutdown" checked/>Wyłącz zdalny komputer

<br />

<input type="radio" name="opcje" value="message"/>Wyślij wiadomość:

<br />

<textarea name="wiadomość" style="width: 300px; height: 150px"></textarea>

<br />

<input type="submit" name="submit" value="Wyślij">

</form>

</html>

Rysunek 7. Zarządzanie komputerem z poziomu przeglądarki

Page 30: PHP Solutions 06 2007 PL

Technika

30 06/2007

Projekt klientaPierwszym krokiem będzie stworzenie stro-ny WWW, której funkcją będzie wysyłanie pa-kietów z danymi do naszej aplikacji. Opierać się ona będzie na prostym formularzu, które-go kod został zaprezentowany na Listingu 8. Podobnie jak poprzednio, będziemy korzystać z portu numer 8008. Jeżeli zamierzamy korzy-stać z aplikacji, z innego komputera niż local-host, niekiedy wymagane będzie odblokowanie tego portu na firewall’u.

Przyjrzyjmy się Listingowi 8. Jak widać, zo-stały w nim zawarte planowane pola: Login oraz Hasło, a także pola typu „Radio”, które repre-zentują możliwe do wykonania zadania. Dla przykładu umieściłem dwa: możliwość wyłą-czenia zdalnego komputera, a także opcję wy-świetlenia na nim wiadomości. Skoro ten etap mamy już za sobą możemy przejść do projekto-wania serwera.

Projekt serweraProjekt serwera w dużej mierze opierać bę-dzie się na aplikacji zaprezentowanej na po-czątku obecnego rozdziału. Śmiało możemy otworzyć tamten projekt i zacząć go mody-fikować.

Zacznijmy od usunięcia Label-u podpi-sanego jako „Odebrane parametry”, a także komponentu Edit1. Nie będą one nam już potrzebne.

Następnie, tak jak poprzednio, klikamy na komponent IdHTTPServer1 i przechodzimy do Object Inspector’a. Odszukujemy Event pod-pisany jako OnCommandGet i wpisujemy kod z Listingu 9. Pozostałe procedury projektu po-zostawiamy bez zmian.

Procedura OnCommandGet, którą przed chwilą wpisaliśmy, zawiera przykładowe po-lecenie zamykające system- w tym wypad-ku posłużyliśmy się funkcją ShellExecute, tak

więc do sekcji Uses musimy dodać moduł ShellAPI.

Sam kod nie jest trudny do zrozumienia, zo-stał on oczywiście opatrzony komentarzami, dlatego zachęcam do jego przejrzenia. Przyj-rzyjmy się fragmentowi odpowiedzialnemu za walidację danych.

Zmienna ARequestInfo.Params[index] zawie-ra kolejne parametry, do których możemy od-woływać się po ich indeksie. Nasz skrypt, który pisaliśmy wcześniej, wysyła kolejno porcje da-nych: login, będący parametrem zerowym, ha-sło, będące parametrem pierwszym, i tak da-lej. Ważna jest kolejność, jaką zachowujemy. Wysyłając najpierw hasło, a dopiero potem lo-gin do serwera- automatycznie zmieniamy ich indeksy, co powoduje, że dane nie przechodzą walidacji.

Możemy oczywiście skorzystać na przykład z instrukcji for...to i sprawdzać po kolei wszystkie odebrane skrypty, jednakże, przy tak małej ilo-ści danych nie jest to konieczne.

Wynik działaniaProces tworzenia aplikacji, zarówno serwe-ra jak i klienta, mamy już za sobą. Teraz nad-szedł czas na przyjrzenie się rezultatom ich działania.

Tak więc: uruchamiamy nasze aplikacje- ser-wer i stronę z formularzem. Wypełniamy poda-ne pola (niekoniecznie poprawnie, aby zoba-czyć, czy wszystko działa tak jak należy) i wysy-łamy dane. Przykład działania aplikacji pokaza-ny jest na Rysunku 7.

PodsumowanieMój niewielki artykuł opisuje tylko wierz-chołek góry lodowej, jaką jest pakiet INDY. Dla jego potrzeb wykorzystałem zaledwie dwa komponenty z ponad ich stuelemento-wej kolekcji. Pamiętaj, że „teoria śni, prakty-ka uczy”. W momencie, gdy sam stworzysz i przeanalizujesz aplikacje, zmodyfikujesz ich kody i prześledzisz działanie, będziesz mógł w pełni zrozumieć zagadnienia, które nimi kierują.

Listing 9. Odbieranie danych przez aplikację i wykonywanie żądanych poleceń

procedure TForm1.IdHTTPServer1CommandGet(AThread: TIdPeerThread;

ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);

var

StrResult: String;

login,pass,autoryzacja: boolean;

begin

{w Memo zostaną umieszczone żądania (request server)}

Memo1.Lines.Add(ARequestInfo.Document);

{do logów dodajemy parametry przekazane do serwera}

Memo1.Lines.Add('Odebrane parametry:');

Memo1.Lines.Add(ARequestInfo.Params.Text);

{walidacja danych:}

{czy login (parametr 0) jest poprawny?}

if ARequestInfo.Params[0]='login=admin'

then login:=True else login:=False;

{czy hasło (parametr 1) jest poprawne?}

if ARequestInfo.Params[1]='pass=password'

then pass:=True else pass:=False;

{identyfikacja}

if (login and pass) then autoryzacja:=True

else autoryzacja:=False;

{wypisujemy kod wynikowy}

StrResult := '<b>Odebrane dane:</b>'

+ '<p>Autoryzacja loginu: ' + BoolToStr(login,True) + '</p>'

+ '<p>Autoryzacja hasła: ' + BoolToStr(pass,True) + '</p>'

+ '<p>Wykonanie polecenia: ' + BoolToStr(autoryzacja,True) + '</p>';

AResponseInfo.ContentText := StrResult;

{zwracamy informację do przeglądarki}

AResponseInfo.WriteContent;

{sprawdzenie polecenia}

if ((ARequestInfo.Params[2]='opcje=message') and autoryzacja)

then

ShowMessage(StringReplace(ARequestInfo.Params[3],'wiadomość=','',[]))

else

if ((ARequestInfo.Params[2]='opcje=shutdown') and autoryzacja)

then

{wywołanie cmd.exe z parametrem shutdown- zamykamy system}

ShellExecute(Handle,'open','cmd.exe','/c shutdown /s','C:',SW_HIDE)

else

end;

ARTUR CHUDZIKAutor w wolnych chwilach zajmuje się progra-

mowaniem, a także administracją portalem We-

bHat.pl, którego jest założycielem. Obecnie uczy się

w drugiej klasie 1LO w Łańcucie.

Kontakt z autorem: [email protected]

W Sieci

• http://www.codegear.com/downloads/free/delphi

• http://www.indyproject.org/• https://addons.mozilla.org/pl/firefox/

addon/60• http://www.4programmers.net

Page 31: PHP Solutions 06 2007 PL
Page 32: PHP Solutions 06 2007 PL

Rozwiązania

32 06/2007

Creole

33www.phpsolmag.org

Każdy producent baz danych zapewnia interfejs, za pomocą którego skrypt może komunikować się z serwerem.

Chcąc, aby nasza aplikacja współpracowała z różnymi systemami zarządzania bazami da-nych – RDBMS (ang. Relational DataBase Ma-nagement System), takimi jak MySQL, Postgre-SQL czy SQLite, należy zaimplementować każdy z nich na jej potrzeby. Jednak powstały w ten sposób kod, sprawia wiele problemów. Aby rozszerzyć funkcjonalność aplikacji o ko-lejne systemy, trzeba pisać kolejne implemen-tacje ich interfejsów. Tutaj z pomocą przycho-dzą abstrakcje bazodanowe. Warstwa abstrak-cji udostępnia ujednolicony interfejs programi-styczny dla różnych systemów bazodanowych. Dzięki takiej warstwie, można ukryć szczegóły implementacji standardu SQL w różnych ser-werach i stworzyć interfejs, za pomocą które-go możemy obsługiwać każdy z nich. W sie-ci przykładów takich abstrakcji możemy spo-tkać wiele – AdoDB, PEAR::DB, PDO, Creole i wiele innych.

Pakiet Creole powstał jako podprojekt pakie-tu Propel, służącego do odwzorowywania klas PHP w ramach relacyjnej bazy danych, będą-cego rozwiązaniem typu ORM (ang. Object-Re-lational Mapping). W tej formie pakiet został wykorzystany w wielu framework’ach np. we Framework’u Symfony. Podczas tworzenia pa-

kietu wzorowano się na podobnych rozwią-zaniach z języka Java – mowa tutaj o ste-rownikach JDBC (ang. Java Database Con-nectivity) oraz już istniejących rozwiąza-niach z języka PHP – AdoDB, PEAR::DB i PEAR::MDB. Creole obsługuje popular-ne bazy danych, takie jak: MSSQL, MySQL, Oracle, PostgreSQL i SQLite.

W ramach projektu Creole został stworzo-ny pakiet o nazwie Jargon, który jest zbiorem wielu użytecznych klas. Nie jest to inna abs-trakcja bazodanowa, gdyż do komunikacji z ba-zą Jargon używa klas Creole'a. Jest to API, za pomocą którego możemy wykonywać zapyta-nia do bazy danych (odczytywanie i zapisywa-

nie) w jeszcze prostszy sposób. Niektóre po-jęcia, takie jak DataSet, zostały zapożyczone z Working-Dogs Village z języka Java. Pakiet Jar-gon nie wchodzi standardowo w skład pakietu Creole – należy go zainstalować osobno. W dal-szej części artykułu zostanie przedstawiona in-stalacja obu pakietów oraz przykład zastosowa-nia pakietu Creole.

Jak zainstalować i skonfigurować pakiet CreoleInstalacja pakietu Creole jest niezwykle pro-sta. Możemy przeprowadzić ją na dwa sposo-by – pierwszy – z użyciem instalatora PEAR lub drugi – ściągając odpowiednie biblioteki ze strony projektu. Do poprawnej pracy pakie-tów wymagane jest: PHP w wersji 5 oraz jeden (lub więcej) z obsługiwanych systemów zarzą-dzania bazą danych (MySQL, PostgreSQL, MS SQL Server, SQLite, Oracle, ODBC). W każ-dym z tych dwóch przypadków będziemy in-stalować pakiet Creole oraz towarzyszący mu pakiet Jargon.

Creole

Pisząc skrypty, prędzej czy później, będziemy musieli połączyć się z bazą danych. Jednak co zrobić, gdy nasz skrypt będzie musiał połączyć się zarówno z bazą MySQL jak i PostgreSQL? Odpowiedzią na to pytanie jest właśnie pakiet Creole.

Dowiesz się...• Czym jest Creole.

• Jak korzystać z Creole'a.

Powinieneś wiedzieć...• Powinieneś znać podstawy programowania

obiektowego w PHP5.

• Powinieneś znać pojęcia związane z bazami

danych.

Poziom trudności

Tabela 1. Flagi funkcji getConnection()

Flaga Opis

Creole::PERSISTENT Tworzy trwałe połączenie z serwerem.

Creole::COMPAT_ASSOC_LOWER Nazwy pól przekształcane są na małe litery.

Creole::COMPAT_RTRIM_STRING Usuwa białe znaki znajdujące się na końcu obiektów typu string, np. przy użyciu ResultSet->getString().

Creole::COMPAT_ALL Ustawia wszystkie flagi związane ze zgodnością.

Tabela 2. Metody klasy Query

Nazwa metody Opis

getAssoc() Zwraca tablicę, której indeksem są wartości pierwszej kolumny zbioru wynikowego. Wartościami tablicy są wartości pozostałych kolumn (indeksowane numerycznie od 0).

getCol() Zwraca pierwszą kolumnę wyniku w formie tablicy.

getOne() Zwraca pierwszą kolumnę pierwszego wiersza wynikowego. Reszta wierszy zo-staje pominięta.

getRow() Zwraca pierwszy wiersz wynikowy. Reszta wierszy zostaje pominięta.

getRows() Zwraca wiersze wynikowe w formie tablicy.

Abstrakcja bazodanowa

Page 33: PHP Solutions 06 2007 PL

Rozwiązania

32 06/2007

Creole

33www.phpsolmag.org

Pierwszy sposób – instalator PEARJeżeli dysponujemy instalatorem PEAR, w na-szym systemie możemy zainstalować oba pa-kiety wykonując w konsoli następujące pole-cenia:

pear channel-discover pear.phpdb.org

pear install phpdb/creole

pear install phpdb/jargon

Jeżeli instalator nie zwróci żadnych błędów, oznacza to, że pakiety zostały poprawnie za-instalowane.

Drugi sposób – ręczna instalacja pakietówW przypadku, gdy nie dysponujemy instala-torem PEAR, możemy ręcznie przeprowa-dzić instalację pakietów. W tym celu musi-

my najpierw udać się na stronę http://creole.phpdb.org/trac/wiki/Users/Download i ściągnąć pakiet z sekcji Current Release oznaczony creole-version o rozszerzeniu .tar.gz lub .zip w zależności od upodobania (wersja dostępna w trakcie pisania artykułu to 1.1.0).

Nie musimy ściągać osobnego archiwum z pakietem Jargon, gdyż został on już do-łączony do wcześniej ściągniętego archiwum. Następnie należy rozpakować ściągnięte ar-chiwum i przekopiować foldery classes/creole i classes/jargon do katalogu wskazywane-go przez zmienną include_path (jej wartośćmożna sprawdzić wywołując funkcję php-info() ) lub stworzyć powiązania tych fol-derów do katalogu wskazywanego przez tą zmienną. W przypadku jakichkolwiek nie-jasności możesz zapoznać się z plikami INSTALL i README, które są dołączone do archiwum.

Creole w zastosowaniachPo krótkim wprowadzeniu i instalacji, możemy przejść do tego co najważniejsze, czyli do tego jak używać Creole'a w naszych skryptach. Ze względu na to, że pakiet został całkowicie na-pisany w PHP5 jest w pełni obiektowy. Ważne jest, aby na samym początku włączyć do skryp-tu plik Creole.php.

Nawiązywanie połączeniaDo nawiązania połączenia z bazą używamy sta-tycznej metody Creole::getConnection(). W pierwszym argumencie przekazujemy adres w postaci DSN (ang. Data Source Name). Może-my go przekazać jako tablicę lub jako ciąg zna-ków. W drugim argumencie przekazujemy flagi z jakimi ma zostać utworzone nasze połączenie. Na szczególną uwagę zasługuje tutaj flaga Creole::PERSISTENT, która umożliwia nawiązanie trwa-łego połączenia z serwerem. Odpowiada to uży-

Listing 1. Nawiązywanie połączenia

<?php

require_once('creole/Creole.php');

$dsn = array('phptype' => 'mysql',

'hostspec' => 'localhost',

'username' => 'user',

'password' => 'pass',

'database' => 'test');

$dsn2 = "mysql://user:pass@localhost/test";

$flags = Creole::COMPAT_ALL;

$connection = Creole::getConnection($dsn, $flags);

?>

Listing 2. Odczytywanie danych z bazy

<?php

$resultSet = $connection->executeQuery('SELECT imię, nazwisko, telefon FROM adresy', ResultSet::FETCHMODE_NUM);

echo $resultSet->getRecordCount().'<br/>';

foreach($resultSet as $rowNumber => $row){// przeglądanie wyników przy użyciu SPL Iterator

echo 'Imię: '.$row[0].'<br/>';

echo 'Nazwisko: '.$row[1].'<br/>';

echo 'Telefon: '.$row[2].'<br/><br/>';

}

while($resultSet->next()){// przeglądanie wyników przy użyciu metody next() i funkcji get*()

echo 'Imię: '.$resultSet->getInt(1).'<br/>';

echo 'Nazwisko: '.$resultSet->getInt(2).'<br/>';

echo 'Telefon: '.$resultSet->getInt(1).'<br/><br/>';

}

?>

Listing 3. Działanie obiektów klasy Statement

<?php

$statement = $connection->createStatement();

$statement->setLimit(10);

$statement->setOffset(3);

$resultSet = $statement->executeQuery('SELECT imie, nazwisko, telefon FROM adresy');

$statement2 = $connection->createStatement();

$rowsAdded = $statement2->executeUpdate(„INSERT INTO adresy VALUES ('Jan', 'Nowak', '12 123 45 67'), ('Marek', 'Nowak', '98 765 43

21')”);

$rowsUpdated = $statement2->executeUpdate(„UPDATE adresy SET nazwisko='Marecki' WHERE id=4”);

$rowsDeleted = $statement2->executeUpdate(„DELETE FROM adresy WHERE id>3”);

?>

Page 34: PHP Solutions 06 2007 PL

Rozwiązania

34 06/2007

Creole

35www.phpsolmag.org

ciu funkcji mysql_pconnect(), przy połączeniu z bazą MySQL. Wszystkie flagi zostały wyszcze-gólnione w Tabeli 1. Przykład nawiązywania połą-czenia został przedstawiony na Listingu 1.

Operacje na danychCreole posiada metody, za pomocą których mo-żemy wybierać, dodawać i aktualizować dane

w bazie. Dzięki metodzie executeQuery(), może-my wysyłać zapytania do serwera. Oprócz nich, możemy również zdefiniować sposób indek-sowania wyników, używając flag ResultSet::FETCHMODE_ASSOC i ResultSet::FETCHMODE_NUM. Domyślnie wyniki są indeksowane nazwa-mi pól (pierwsza flaga). W odpowiedzi otrzy-mamy obiekt ResultSet, który będzie zawie-

rał wyniki naszego zapytania. Do przeglądania wyników możemy użyć pętli foreach, gdyż został zaimplementowany SPL Iterator. Może-my posłużyć się również bardziej tradycyjny-mi funkcjami: first(), next(), previous(), last(), relative() (niestety w Oracle wstecz-ne przewijanie nie jest obsługiwane).

Na Listingu 2. został przedstawiony przy-kład wybierania z tabeli test kolumn id i name oraz dwa sposoby wyświetlenia wyni-ków. Została tutaj zastosowana metoda exe-cuteQuery() klasy Connection. Istnieją jesz-cze dwie takie metody dla klas Statement oraz PrepareStatement, które opiszę za chwilę. Wcześniej przyjrzyjmy się drugiemu przypadkowi wyświetlenia wyników. Wyko-rzystano w nim metodę next() oraz meto-dy get*(), gdzie * oznacza typ na jaki ma zo-stać przekonwertowana wartość pola z wier-sza wynikowego. Oprócz int i string może-my używać także Blob, Boolean, Clob, Date, Float, Time, Timestamp. Metoda get() zwra-ca niesformatowaną wartość pola (najczę-ściej typu string). Funkcje get*() i get() jako argument, pobierają nazwę pola lub jeśli została ustawiona flaga ResultSet::FETCHMODE_NUM jego numer (w tym przy-padku numeracja pól zaczyna się od 1). Na-tomiast korzystając z metody getRow(), mo-żemy pobrać wiersz wyniku z aktualnej po-zycji w zbiorze wyników, w formie tablicy asocjacyjnej. W drugim wierszu Listingu 2. została użyta kolejna metoda z rodziny get – getRecordCount(), dzięki której możemy się dowiedzieć, ile wierszy wyników zwróci-ło nasze zapytanie.

Jak wspominałem wcześniej, oprócz metody executeQuery() klasy Connection istnieją jesz-cze dwie takie metody w klasach Statement i PrepareStatement. Klasy te obsługują ele-menty nieobsługiwane przez klasę Connection – parametry Limit/Offset oraz wstępnie przygotowane zapytania SQL (ang. Prepared-Statement).

Aby móc ograniczyć liczbę wierszy wy-nikowych, za pomocą parametrów Limit/

Offset, tworzymy obiekt typu Statement, za pomocą metody createStatement(), obiek-tu Connection. W tak przygotowanym obiek-cie możemy ustawić wartości Limit i Offset. Klasa ta posiada inną interesującą metodę – executeUpdate(), za pomocą której mo-żemy dodawać, usuwać i aktualizować dane z tabeli (metoda ta dostępna jest we wszyst-kich trzech klasach). Wynikiem jej działania jest liczba zmienionych wierszy. Jest to wygod-niejsze i efektywniejsze, niż w przypadku me-tody executeQuery(), gdyż tam otrzymujemy obiekt typu ResultSet. Na Listingu 3. został przedstawiony przykład użycia obiektów kla-sy Statement.

Za pomocą trzeciej klasy możemy tworzyć obiekty z wstępnie przygotowanym zapy-taniem SQL. Klasa PreparedStatement po-

Listing 4. Używanie wstępnie przygotowanych zapytań

<?php

$statement = $connection->prepareStatement('SELECT imię, nazwisko,

telefon FROM adresy WHERE id = ? OR nazwisko = ?');

$statement->setInt(1, 3);

$statement->setString(2, 'Marecki');

$resultSet = $statement->executeQuery();

?>

Listing 5. Używanie wstępnie przygotowanych zapytań – przekazywanie tablicy z parametrami

<?php

$statement = $connection->prepareStatement('SELECT imie, nazwisko,

telefon FROM adresy WHERE id = ? OR nazwisko = ?');

$resultSet = $statement->executeQuery(array(3, 'Marecki'));

?>

Listing 6. Obsługa wyjątków SQL Exception

<?php

try

{

$resultSet = $connection->executeQuery('SELECT imie, nazwisko FROM adresy');

foreach($resultSet as $rowNumber => $row)

{

echo 'Imie: '.$row['imie'].'<br/>';

echo 'Nazwisko: '.$row['nazwisko'].'<br/>';

}

}

catch(SQLException $e)

{

echo 'Nastąpił błąd podczas wykonywania: '.$e

}

?>

Listing 7. Przykład użycia transakcji i obsługi błędów

<?php

try{

$connection->setAutoCommit(false);

$connection->executeUpdate(„UPDATE adresy SET id=3 WHERE nazwisko='Nowak'”);

$connection->executeUpdate('DELETE FROM adresy WHERE id>2');

$connection->commit();

}

catch(Exception $e)

{

$connection->rollback();

echo 'Przerwano transakcję !!! Wystąpił błąd: '.$e->getMessage();

}

?>

Page 35: PHP Solutions 06 2007 PL

Rozwiązania

34 06/2007

Creole

35www.phpsolmag.org

winna być traktowana jako rozszerzenie kla-sy Statement. Klasy te nie są połączone ze względu na pewne ograniczenia języka PHP5. Na Listingu 4. został przedstawiony przykład pobierania danych z tabeli test, przy uży-ciu wstępnie przygotowanych zapytań. Do stworzenia takiego zapytania należy wywołaćmetodę prepareStatement() na obiekcie typu Connection. Jako argument przekazu-jemy nasze zapytanie, jednak w miejscach,gdzie będziemy dynamicznie podawali wartości wstawiamy znak '?'. W rezultaciemetoda zwróci nam obiekt typu PreparedStatement, na rzecz którego możemy wywo-łać metody set() i set*(), gdzie * to typ, na jaki zostanie dokonana konwersja, za po-mocą których możemy ustawić dynamiczne części zapytania. Mechanizm ten działa do-kładnie tak, jak wcześniej omawiane meto-dy get() i get*(), jednak w tym przypad-ku podajemy numer wartości występują-cej w zapytaniu (tak jak w przypadku get() i get*() numeracja rozpoczyna się od 1) oraz wartość jaka w to miejsce zostanie wstawio-na. Przy użyciu metody set() zostaną uży-te natywne typy PHP do konwersji. Zamiast metod set() i set*() możemy do funkcji PreparedStatement::executeQuery() i PreparedStatement:: executeUpdate() prze-kazać tablicę, która będzie zawierała wszyst-kie potrzebne parametry – tak jak przedsta-wiono to na Listingu 5.

Operacje na tabelachPosługując się pakietem Creole możemy do-konywać różnych operacji na tabelach. Po-lecenia takie jak: CREATE, DROP czy ALTER możemy wykonywać przy pomocy metod executeQuery() lub executeUpdate(), jeżeli tylko nasz użytkownik posiada do tego upraw-nienia.

Obsługa błędów SQL Exception oraz transakcjePakiet Creole został całkowicie napisany w PHP5, dlatego do obsługi błędów użyto wy-jątków. Klasa odpowiedzialna za obsługę błę-dów w pakiecie Creole to SQL Exception, któ-ra rozszerza standardową klasę Exception. Za pomocą metody getNativeError() jeste-śmy w stanie określić rodzaj błędu ze stro-ny RDBMS-a. Na Listingu 6. został zapre-zentowany przykład obsługi błędów. W przy-padku rzucenia wyjątku jest on obsługiwany w bloku catch, w tym przypadku zostaje wy-pisana treść wyjątku (dzięki temu, że kla-sa SQLException posiada zaimplementowaną metodę __toString()).

W przypadku, gdy zostanie rzucony wy-jątek, dalsza część skryptu znajdująca się w bloku try nie jest wykonywana. Tutaj wi-dać, w jaki sposób można wykorzystać trans-akcje oraz obsługę wyjątków. Przykład takie-go kodu został zaprezentowany na Listingu

7. Używając metody setAutoCommit() z ar-gumentem false rozpoczynamy transakcję (domyślnie zapytania są automatycznie za-twierdzane zaraz po wykonaniu). Dalej wyko-nujemy pewne działania na bazie danych. Je-żeli wydarzy się jakaś awaria lub błąd, wtedy

w bloku catch transakcja jest anulowana za pomocą metody rollback(). Jeżeli nie wy-stąpią żadne błędy, transakcja zostaje za-twierdzona poprzez metodę commit(). Ta-kie działanie chroni przed konsekwencjami różnych błędów.

Listing 8. Pobieranie metadanych na temat tabel bazy

<?php

$databaseInfo = $connection->getDatabaseInfo();

foreach($databaseInfo->getTables() as $table)

{

echo 'Tabela: '.$table->getName().'<br/>';

foreach($table->getColumns() as $column)

{

echo $column->getName().': '.$column->getNativeType().'<br/>';

}

}

?>

Listing 9. Wykorzystanie obiektu Query do odczytywania danych z bazy

<?php

require_once 'creole/Creole.php';

require_once 'jargon/Query.php';

$dsn = 'mysql://user:pass@localhost/database';

$connection = Creole::getConnection($dsn, Creole::COMPAT_ALL);

$query = new Query($connection, 'SELECT id, imie, nazwisko, telefon FROM adresy');

$resultArray = $query->getAssoc();

foreach($resultArray as $id => $values)

{

echo $id.' : ';

foreach($values as $valueNumber => $value)

{

echo $value.' ';

}

echo '<br/>';

}

?>

Listing 10. Podział zapytania na strony przy użyciu obiektu klasy PagedQuery

<?php

require_once 'creole/Creole.php';

require_once 'jargon/Query.php';

$dsn = 'mysql://user:pass@localhost/database';

$connection = Creole::getConnection($dsn, Creole::COMPAT_ALL);

$page = 3;

$rowsPerPage = 20;

$pagedQuery = new PagedQuery($connection, 'SELECT tytul, tresc FROM newsy', $page,

$rowsPerPage);

$resultArray = $pagedQuery->getRows();

foreach($resultArray as $rowNumber => $row)

{

echo $row['tytul'].'<br/>'.$row['tresc'].'<br/><br/>';

}

?>

Page 36: PHP Solutions 06 2007 PL

Rozwiązania

36 06/2007

Introspekcja w bazę danych – metadataZa pomocą pakietu Creole możemy uzyskać informacje o aktualnie używanej bazie danych.Możemy odczytać informacje na temat tabeli, indeksów, kluczy, kluczy obcych i inne przy-datne informacje. Mechanizm ten jest podobny do używanego w pakiecie Hibernate. Przykład odczytywania metadanych został zaprezento-wany na Listingu 8. Odczytujemy tutaj pod-stawowe informacje na temat tabel zawartych w bazie, której aktualnie używamy (nazwę ta-beli, nazwę pola oraz jego typ). Dzięki meto-dzie getDatabaseInfo() wykonanej na obiek-cie klasy Connection, otrzymujemy obiekt kla-sy DatabaseInfo, z którego możemy wydobyć wszystkie interesujące nas informacje. Aby uzyskać informacje na temat metod, za pomo-cą których możemy pobierać różne metadane z bazy, należy przejrzeć rozdział creole.metada-ta dokumentacji projektu.

Narzędzia JargonPakiet Jargon to zbiór przydatnych narzędzi, które zapewniają prostszą obsługę zapisywa-nia i odczytywania danych z bazy. Komuni-kacja z serwerem baz danych spoczywa na pa-kiecie Creole, dzięki czemu nie ma potrze-by implementacji obsługi bazodanowej. Te-raz postaram się przedstawić niektóre z tych narzędzi.

Pierwszym z przydatnych narzędzi będzieklasa Query do obsługi zapytań typu SELECT. Tworząc obiekt typu Query, przekazujemy mu obiekt typu Connection oraz zapyta-nie jakie ma zostać wykonane. Po utworze-niu nasz obiekt zawiera zbiór wierszy wy-nikowych naszego zapytania. Do manipula-cji tym zbiorem otrzymujemy kilka użytecz-nych metod, których działanie zostało opisa-

ne w Tabeli 2. Natomiast na Listingu 9. zo-stał zaprezentowany przykład użycia takie-go obiektu.

Drugim z ciekawszych narzędzi pakietu Jargon, jest klasa PagedQuery. Wyobraźmy so-bie bazę newsów. Aby wyświetlić odpowied-nią stronę, z odpowiednią na niej liczbie new-sów, musieliśmy się gimnastykować używając parametrów LIMIT i OFFSET. Teraz możemy skorzystać z obiektu typu PagedQuery. Na Li-stingu 10. został przedstawiony przykład ta-kiego rozwiązania. Stronę oraz liczbę wier-szy pobieranych na stronę możemy określić w konstruktorze obiektu lub po jego utwo-rzeniu przy pomocy metod setPage() oraz setRowsPerPage(). Dla parametru Page do-myślna wartość wynosi 1, natomiast dla pa-rametru RowsPerPage domyślna wartość wy-nosi 25. Do odczytywania wartości z poszcze-gólnych stron używamy metod opisanych w klasie Query.

Creole a inne abstrakcjePierwszymi abstrakcjami bazodanowymi – prekursorami – byli Metabase, PEAR::DB i AdoDB. Obecnie w sieci dostępnych jest znacznie więcej rozwiązań tego typu, jak chociażby PDO, MDB, MDB2, DBX. Trudno okre-ślić, która z nich jest najlepsza. Zależy to od wiedzy, upodobań, charakteru projektu do którego ma zostać wdrożona oraz od zasobów jakie będzie miała do dyspozycji.

Spróbuję teraz pokrótce porównać omawiany pakiet Creole z innymi popularnymi abstrak-cjami – AdoDB, PDO i PEAR::DB. Zastrzegamjednak, że będzie to krótkie i pobieżne porów-nanie.

Dużym plusem w kierunku pakietu Cre-ole jest fakt, iż bazuje on na sprawdzonych rozwiązaniach z języka JAVA (JDBC) oraz

rozwiązaniach z PHP – AdoDB i PEAR::DB. Spośród czterech porównywanych abstrak-cji obsługuje relatywnie najmniejszą liczbę baz danych. Obsługuje jednak najpopular-niejsze systemy. Natomiast w AdoDB może-my znaleźć wiele podobieństw do standar-du ADO Mircrosoft-u. Oprócz PDO wszystkie abstrakcje zostały napisane w PHP (4 lub 5), którego centralny podsystem został napisany w C. PDO jest właściwie interfejsem komuni-kacyjnym i aby uzyskać funkcjonalność ofe-rowaną przez inne abstrakcje, należy zain-stalować dodatkowe biblioteki (np. Open Power Driver). Dodatkowo AdoDB jest dostęp-ne również dla Python-a. W Creole'u nieste-ty nie ma możliwości cache'owania danych. AdoDB obsługuje tę możliwość natywnie, na-tomiast do PDO i PEAR::DB należy zainstalo-wać dodatkowe biblioteki. W przypadku in-nych funkcjonalności, takich jak transakcje, procedury składowane czy wstępnie przy-gotowane zapytania SQL (ang. Prepared Sta-tements) wszystkie cztery abstrakcje zapew-niają ich obsługę. Wyjątek może stanowić pakiet PEAR::DB, który nie obsługuje proce-dur składowanych.

PodsumowanieW artykule przedstawiliśmy w jaki sposób używać abstrakcji bazodanowych – w tym przypadku Creole'a. Oprócz podstawowej funkcjonalności, poruszyliśmy także kwe-stię transakcji, obsługi błędów oraz przed-stawiliśmy niektóre narzędzia biblioteki Jar-gon. Jest to zarys metod, jakie oferuje nam pakiet Creole. Ich konkretna implementacja zależy wyłącznie od Ciebie. Więcej pomocy możesz znaleźć na stronach znajdujących się w ramce „W sieci”.

W Sieci

• http://creole.phpdb.org/ – strona domowa projektu Creole

• http://creole.phpdb.org/docs/api/ – dokumentacja API projektu Creole

• http://pear.php.net/ – strona domowa instalatora rozszerzeń PHP

• http://pear.php.net/manual/en/package.database.db.intro-dsn.php – strona opi-suje sposób tworzenia poprawnego obiektu DSN

• http://dev.mysql.com/tech-resources/articles/4.1/prepared-statements.html – opis wstępnie przygotowywanych zapytań w serwerze MySQL

• http://pl.php.net/manual/en/language.exceptions.php – obsługa wy-jątków w PHP

PIOTR GRADZIŃSKIAutor jest studentem III roku informatyki stosowa-

nej na Uniwersytecie Jagiellońskim.

Kontakt z autorem: [email protected]

TransakcjeTransakcje to mechanizm, za pomocą którego możemy wykonywać różne działania na ba-zie danych. W mechanizmie transakcyjnym nie zostaną wykonane żadne operacje na fizycz-nych plikach, dopóki transakcja nie zostanie zatwierdzona. W przeciwnym wypadku, wszyst-kie wykonane operacje od rozpoczęcia transakcji zostaną cofnięte, bez żadnego uszczerb-ku dla danych. Najlepiej ilustrującym transakcje przykładem są przelewy bankowe. Wyobraź-my sobie hipotetyczną sytuację, kiedy wykonywany jest przelew z konta pana Kowalskiego na konto pana Nowaka. Po pomniejszeniu stanu konta pana Kowalskiego następuje awaria serwera i stan konta pana Nowaka nie zostaje powiększony. Pieniądze rozpłynęły się w sie-ci. Przy użyciu transakcji, w przypadku awarii, gdy nie zostanie ona potwierdzona, nie zosta-ną wykonane żadne operacje na kontach pana Kowalskiego i Nowaka. Mechanizm transakcji musi spełniać pewne warunki, które opisywane są przez zasady ACID (ang. Atomicity, Consi-stency, Isolation, Durability – Atomowość, Spójność, Izolacja, Trwałość).

Prepared StatementsWstępnie przygotowane zapytania SQL to mechanizm, za pomocą którego możemy w dy-namiczny sposób przygotowywać zapytanie. Zmienne części zapytania, jak np. wartości, które mają zostać odnalezione w danej tabeli, zostają zastąpione specjalnymi znacznikami. Zapytanie musi zostać tylko raz przesłane do serwera bazodanowego, gdzie jest przygoto-wywane do wykonania. Przy kolejnych wywołaniach zapytania przesyłamy tylko przezna-czone dla niego wartości. Taki mechanizm oszczędza wiele czasu przy przesyłaniu zapyta-nia oraz przy jego realizacji, dzięki wbudowanym mechanizmom serwera.

Page 37: PHP Solutions 06 2007 PL
Page 38: PHP Solutions 06 2007 PL

Rozwiązania

38 06/2007

AJAX

39www.phpsolmag.org

Przeładowywana jest cała zawartość – gra-fika, szablony stylów, informacje pobiera-ne ze źródeł danych – mimo, że strona po-

zostaje prawie niezmieniona! Technologia AJAX (ang. Asynchronous JavaScript And XML) powsta-ła, by zerwać z dotychczasowym modelem funk-cjonowania aplikacji webowych. Jest świetnym na-rzędziem do tworzenia interaktywnych witryn internetowych, które umożliwia maksymalnie upodobnić aplikacje webowe do ich odpowied-ników ze stacji roboczych. Wprowadza asynchro-niczną komunikację między przeglądarką użyt-kownika i serwerem WWW, która pozwala na ak-tualizację tylko wymaganych fragmentów stron, zamiast przeładowywania całej zawartości.

W artykule przedstawimy praktyczne wpro-wadzenie do technologii AJAX, na przykładzie framework'u CakePHP. Zbudujemy przykłado-wy serwis WWW ilustrujący korzyści (i ograni-czenia) AJAX.

Czym jest AJAX?AJAX nie jest językiem programowania stron WWW. To nowy sposób wykorzystania zna-nych wcześniej technologii:

• JavaScript – język programowania działa-jący w środowisku przeglądarki interne-towej, po stronie użytkownika. Jest spo-

iwem łączącym DOM z XHR (opis poni-żej). Innymi słowy, pozwala na aktualiza-cję fragmentów stron WWW o dane ode-brane dynamicznie za pomocą XHR;

• XMLHttpRequest (XHR) – obiekt umoż-liwiający wymianę danych między serwe-rem WWW i przeglądarką. Pomimo XML w nazwie, XHR nie wymusza używania tego formatu przy przesyłaniu informacji. Ponieważ, po otrzymaniu danych, ich dal-sza obróbka odbywa się za pomocą Java-

Script, to o wiele wygodniej jest operować na danych, które w prosty sposób można przetwarzać w tym języku;

• Cascading StyleSheets (CSS) – kaskadowe arkusze stylów to język służący do opisu sposobu wizualizacji stron WWW. Za je-go pomocą można przypisać atrybuty, takie jak np.: kolor, wielkość czcionki, margine-sy do poszczególnych elementów XHTML lub XML;

• Document Object Model (DOM) – obiektowy model umożliwiający nawigację w struktu-rze dokumentu XML oraz modyfikację za-wartości jego określonych fragmentów;

• JSON (ang. JavaScript Object Notation) umożliwia prostą zamianę obiektów Java-Script do postaci tekstu (tzw. proces seria-lizacji), który może być przesyłany za po-mocą XHR. Proces odwrotny przebiega równie sprawnie.

AJAX w CakePHP

Tradycyjne serwisy WWW przeważnie posiadają interfejs użytkownika zbudowany z wykorzystaniem formularzy HTML. Powoduje to, iż nie są interaktywne – wprowadzane dane są wysyłane do serwera, co z kolei powoduje odświeżanie całej strony.

Dowiesz się...• Poznasz praktyczne zastosowanie technologii

AJAX w środowisku Framework'u CakePHP. Po

analizie przedstawionego kodu będziesz mógł

wzgobacić własny serwis o dynamicznie pre-

zentowane dane.

Powinieneś wiedzieć...• Wymagana jest znajomość Framework'u Cake-

PHP, umożliwiająca samodzielne skonfiguro-

wanie środowiska Apache, MySQL i PHP. Przy-

datna będzie także znajomość podstaw języ-

ka JavaScript.

Poziom trudności

Zwiększenie funkcjonalności serwisu

Rysunek 1. Zasilanie aplikacji danymi – tryb scaffold

Page 39: PHP Solutions 06 2007 PL

Rozwiązania

38 06/2007

AJAX

39www.phpsolmag.org

Na szczęście nie ma potrzeby, by samodziel-nie tworzyć kod, umożliwiający połączenie powyższych technologii. Nie ma również po-trzeby samodzielnego operowania na pozio-mie obiektu XHR, czy troszczenia się o współ-pracę z różnymi typami przeglądarek inter-netowych. W internecie znajduje się wiele go-towych bibliotek rozszerzających JavaScript i ułatwiających integrację z PHP. W dalszej części artykułu skupimy się na bibliotekach Prototype oraz script.aculo.us, których obsłu-ga jest częścią funkcjonalności framework'u CakePHP.

Korzyści ze stosowania technologii AJAX

• AJAX umożliwia wykorzystanie doświad-czeń użytkowników pracujących z aplika-cjami desktopowymi. Podobne zachowanie aplikacji, zbudowanej z wykorzystaniem AJAX, może sprawić, iż będą one używa-ne efektywniej;

• AJAX pozwala na ograniczenie ilości da-nych przesyłanych między przeglądar-ką internetową użytkownika i serwerem WWW, przy zachowaniu dotychczaso-wych funkcjonalności. Zamiast przesy-łania zawartości całych stron, aktualizo-wane są tylko te fragmenty, które uległy zmianie;

• AJAX umożliwia tworzenie interaktyw-nych metod prezentacji danych, które nie były możliwe przy zastosowaniu dotych-czasowych technologii (np. drag'n'drop, dy-namicznie rozwijające się listy czy auto-matyczne uzupełnianie tekstów wprowa-dzanych do formularzy).

Ograniczenia

• AJAX wymaga od użytkowników, by po-sługiwali się nowoczesnymi przeglądar-kami obsługującymi technologie: DOM, JavaScript, CSS. Wymaga to również posia-dania równie nowoczesnych komputerów o odpowiedniej mocy obliczeniowej;

• AJAX to dodatkowe kilobajty kodu, któ-ry musi być dołączony do strony WWW. W przypadku bibliotek Prototype oraz script.aculo.us należy się liczyć z dodat-kowymi 200KB kodu przesyłanych do przeglądarki użytkownika. Ilość nowo wprowadzanych danych można w znacz-nym stopniu zmniejszyć, wcześniej kom-presując przesyłane pliki (zobacz „kom-presowanie komponentów”);

• AJAX zmienia funkcjonalność serwisów WWW, ale nie przeglądarki internetowej. Funkcje związane z przeglądaniem histo-rii stron, w tym i przycisk wstecz, przywo-łujący oglądane wcześniej dane, będą za-chowywały się odmiennie, co może wpro-wadzać użytkowników w błąd (w AJAX

nie ma konieczności przechodzenia mię-dzy stronami, więc pojęcie poprzednia stro-na traci swoje znaczenie).

CakePHPJak już wiemy, obsługa AJAX w CakePHP, wymaga obecności biblioteki Prototype oraz script.aculo.us. Niestety nie są one częścią framework'u – musimy je samodzielnie po-brać z internetu oraz zmodyfikować konfigura-cję CakePHP, by ich obecność została uwzględ-niona przy tworzeniu dynamicznych stron WWW.

Zacznijmy od przygotowania prostego ser-wisu, umożliwiającego zapisywanie do bazy danych informacji wprowadzanych do formu-larza. Najpierw przygotujemy wersję działają-cą bez AJAX, którą następnie rozbudujemy

o elementy zwiększające jej interaktywność (i atrakcyjność). Model danych, który wyko-rzystamy będzie prosty: pojedyncza tabela po-wiązana z modelem Task (pol. zadanie). Szcze-góły związane z implementacją tej części apli-kacji znajdują się na Listingach 1. oraz 2.

Przygotowane struktury nie zawierają jesz-cze danych. Uzupełnimy je, wykorzystując tryb scaffold, w którym CakePHP automaty-cznie stworzy interfejs, umożliwiający dostęp do danych za pomocą strony WWW. Tryb ten jest aktywowany, gdy w kontrolerzejest zdefi-niowana zmienna $scaffold. Nie ma potrzeby definiowania funkcji obsługi modelu danych – framework zrobi to za nas automatycznie. Utworzymy teraz kontroler TasksControl-ler odpowiadający modelowi danych Task (Listing 3.).

Rysunek 2. Wynik działania przykładowej aplikacja działającej bez AJAX

Rysunek 3. Przykładowa aplikacja wykorzystująca technologię AJAX

Page 40: PHP Solutions 06 2007 PL

Rozwiązania

40 06/2007

AJAX

41www.phpsolmag.org

Nasza przykładowa aplikacja jest już goto-wa. Wystarczy uruchomić przeglądarkę in-ternetową i wpisać adres IP serwera Cake-PHP, razem z nazwą kontrolera np. http://127.0.0.1/tasks. Teraz możemy w prosty sposób wprowadzić dane, które później bę-dziemy wyszukiwać za pomocą formularza HTML (Rysunek 1.).

Pobieranie danych tak zdefiniowanych struk-tur powierzymy kontrolerowi TodoControl-ler (Listing 3.) oraz domyślnemu widoko-wi (plik app/views/todo/index.thtml), w którym umieścimy kod generujący formu-larz WWW (Listing 4.).

Po zasileniu testowymi danymi, nasza aplikacja zachowuje się w sposób standar-dowy – wprowadzenie informacji do for-mularza i naciśnięcie przycisku Wyślij, po-woduje przeładowanie całej strony i wyświe-tlenie tytułów zadań pasujących do zadane-go kryterium (Rysunek 2.). Wybierane są za-dania nie ukończone (Task.done = 0) o na-zwie identycznej z podanym ciągiem zna-ków (Task.title = $title), posortowa-ne według kolejności utworzenia (Task.id DESC).

Wprowadzamy technologię AJAXZastanówmy się teraz jak, w naszym uprosz-czonym przykładzie, wykorzystać technologię AJAX. Wiemy już, że AJAX umożliwia dyna-miczną (przebiegającą w tle) wymianę infor-macji między serwerem WWW i przeglądar-ką internetową. Możemy więc spróbować prze-szukiwać bazę danych, w miarę jak użytkownik wprowadza dane do formularza. Za każdym ra-zem, gdy zmieni się kryterium wyszukiwania, przeglądarka automatycznie wyśle zapytanie do naszej aplikacji, która sprawdzi, czy odpo-wiednie rekordy znajdują się w bazie danych. Przekazana z serwera odpowiedź zostanie wy-świetlona, dając wizualną podpowiedź o rezul-tatach poszukiwań.

Realizacja powyższego schematu funkcjono-wania aplikacji wymaga od nas kilku dodatko-wych zabiegów:

• musimy cyklicznie badać, czy w formula-rzu pojawiły się nowe dane;

• musimy utworzyć metodę kontrolera, któ-ra będzie sprawdzała obecność wyszuki-wanych informacji w bazie danych;

• musimy znaleźć sposób, by informacje zwra-cane przez serwer pojawiały się w prze-glądarce bez konieczności przeładowania całej strony WWW.

Na szczęście nie jesteśmy pierwszymi, któ-rzy zadają sobie pytanie Jak to zrobić? Wspo-mniana wcześniej biblioteka Prototype zawie-ra wszystkie niezbędne funkcje, które maksy-malnie ułatwią nam to zadanie. Uwolni ona nas od konieczności samodzielnego badania

Listing 1. Struktura danych wykorzystywana w przykładowej aplikacji

CREATE TABLE `tasks` (

`id` int(10) NOT NULL auto_increment,

`title` varchar(60),

`done` int(1) NOT NULL default '0',

PRIMARY KEY (`id`)

) ENGINE=MyISAM;

Listing 2. Model danych Task

// plik app/models/task.php

class Task extends AppModel

{

// jeżeli używamy PHP4 musimy zdefiniować zmienną zawierającą nazwę klasy

var $name = 'Task';

// domyślnie nazwa klasy odpowiada nazwie tabeli w liczbie pojedynczej

// jeżeli jest inaczej i np. zamierzamy wykorzystać

// inną tabelę z bazy danych musimy zdefiniować jej nazwę

var $useTable = 'tasks';

}

Listing 3. Kontroler odpowiadający za zasilanie struktur danych informacjami z formularza WWW (tryb scaffold)

// plik app/controllers/tasks_controller.php

class TasksController extends AppController

{

// jeżeli używamy PHP4 musimy zdefiniować zmienną zawierającą nazwę klasy

var $name = 'Tasks';

var $uses = array('Task');

var $helpers = array('Html');

var $scaffold;

}

// plik app/controllers/todo_controller.php

class TodoController extends AppController

{

// jeżeli używamy PHP4 musimy zdefiniować zmienną zawierającą nazwę klasy

var $name = 'Todo';

var $uses = array('Task');

var $helpers = array('Html','Time');

// nie wyświetlaj żadnych informacji

function index() {

}

function search()

{

if (! empty($this–>data))

{

$data = $this–>data;

$title = strip_tags($data['Task']['title']);

$tasks = $this–>Task–>findAll(

array('Task.done' => 0, 'Task.title' => $title), null, 'Task.id DESC');

$this–>set('todo', $tasks);

}

else

{

$this–>redirect('/todo/index');

}

}

}

Page 41: PHP Solutions 06 2007 PL

Rozwiązania

40 06/2007

AJAX

41www.phpsolmag.org

stanu formularza, obsługi obiektu XHR i ak-tualizacji strony WWW o zwrócone informa-cje. Po naszej stronie pozostanie tylko przygo-towanie metody kontrolera, odpowiedzialne-go za wyszukiwanie danych (będzie wywo-ływany przy każdej aktualizacji formularza) oraz powiązanie ze sobą odpowiednich kom-ponentów CakePHP i Prototype.

Zacznijmy od początku. Włączenie obsługi Prototype i script.aculo.us w CakePHP wymaga pobrania bibliotek i umieszczenia ich w kata-logu app/webroot/js. W kolejnym kroku mu-simy zmodyfikować domyślny szablon serwi-su: wymusić kodowanie UTF–8 (niezbędne do poprawnej pracy AJAX) oraz załadować biblio-teki Prototype oraz script.aculo.us (Listing 5.). Następnie dołączamy do kontrolera dodat-kowe moduły, przez umieszczenie deklaracji:

var $helpers = array('Html',

'Javascript', 'Ajax');

W pierwszym momencie można się przera-zić wielkością kodu, który będzie dołączony do generowanych stron WWW. Obydwie bi-blioteki to ponad 200KB dodatkowych da-nych, które z pewnością nie przyspieszą star-tu naszej aplikacji. Wielkość przesyłanych pli-ków można jednak zmniejszyć o ponad poło-wę, kompresując je przed przesłaniem do prze-glądarki użytkownika (zobacz Kompresowanie komponentów).

Następnym wyzwaniem jest wykrycie zmianw formularzu – chcemy przecież reagować na każdy znak wprowadzony przez użytkowni-ka. Biblioteka Prototype zawiera gotowe ele-menty, które nas wyręczą w tej czynności. Chodzi o metodę element:observe(), która pozwala na automatyczne wywołanie funk-cji JavaScript w przypadku, gdy obserwowa-ny element (określany za pomocą identyfika-tora DOM ID) uległ zmianie. Nie musimy jed-nak umieszczać kodu JavaScript w naszej apli-kacji – CakePHP zawiera funkcję, która za-troszczy się o inicjalizację niezbędnych struk-tur (plik plik app/views/todo/index.thtml na Listingu 6.).

Jak widzimy, parametry do metody AjaxHel-per::observeField() są przekazywane w asocja-cyjnej tablicy $options. Ponieważ większość metod obsługujących AJAX w CakePHP ko-rzysta z tego sposobu, omówimy poszczegól-ne parametry i ich znaczenie dla funkcjonowa-nia aplikacji:

• $options['url'] – adres URL akcji Ca-kePHP, która ma zostać wywołana (w na-szym przypadku – po modyfikacji formu-larza);

• $options['frequency'] – liczba sekund między kolejnymi testami wykrywający-mi zmiany;

• $options['update'] – identyfikator DOM elementu, który ma zostać zaktualizowa-

Listing 4. Widoki definiujące formularz WWW

// plik app/views/todo/index.thtml

<?php

echo $html–>formTag('/todo/search');

?>

<div>

Wyszukiwanie zadań:

<div>

<?php

echo $html–>input('Task/title', array('id' => 'search'));

?>

<?php

echo $html–>submit('Wyślij');

?>

</div>

<div>

</div>

</form>

// plik app/views/todo/search.thtml

<h2>Znalezione zadania:</h2>

<?php if (count($todo) > 0): ?>

<ul>

<?php foreach ($todo as $task): ?>

<li>

<?php

echo $task['Task']['title'];

?>

</li>

<?php endforeach ?>

</ul>

<?php else: ?>

<p>Nic nie znaleziono!?</p>

<?php endif ?>

<?php

echo $html–>link('> powrót do formularza wyszukiwania', '/todo/index');

?>

Listing 5. Modyfikacja domyślnego szablonu strony CakePHP w celu automatycznego wczytywania bibliotek Prototype i script.aculo.us

<?php echo $html–>charsetTag('UTF–8'); ?>

<?php echo $javascript–>link('prototype'); ?>

<?php

echo $javascript–>link('scriptaculous.js?load=effects');

?>

Kompresowanie komponentówCzas potrzebny na przesłanie kodu HTML do użytkownika, może być znacznie zredukowany za pomocą różnego rodzaju buforowania (cache, proxy). Innym czynnikiem, który wpływa na szyb-kość przesyłania danych jest ich wielkość. Możemy przyspieszyć przesyłanie stron WWW, pod-dając je wcześniejszej kompresji. Protokół HTTP/1.1 umożliwia stacjom klienckim sygnalizowanie obsługi skompresowanych danych za pomocą nagłówka: Accept–Encoding: gzip, deflate. Jeżeli serwer WWW wykryje takie informacje, może wysłać dane skompresowane, za pomocą jednej z metod obsługiwanej po stronie klienta.

Kompresja gzip umożliwia zmniejszenie ilości danych średnio o 60–70%, w zależności od ich rodzaju (typu). Największe redukcje osiągniemy kompresując pliki HTML, szablony CSS oraz kod JavaScript (dane tekstowe). Kompresja plików graficznych, plików PDF czy archiwów jest zbędna, gdyż dane w nich zapisane już wcześniej zostały poddane kompresji.

W chwili obecnej, ponad 90% przeglądarek internetowych, używanych do przeglądania stron WWW obsługuje kompresję danych. Od strony serwera niezbędna jest konfiguracja odpo-wiedniego modułu – w przypadku Apache 1.3 jest to mod_gzip, w Apache 2.x – mod_deflate.

Page 42: PHP Solutions 06 2007 PL

Rozwiązania

42 06/2007

AJAX

43www.phpsolmag.org

ny informacjami otrzymanymi w wyniku działania akcji zawartej w $options['url'];

• $options['with'] – identyfikator DOM elementu, który ma zostać dołączony do żądania wysyłanego przez AJAX;

• $options['type'] – sposób komunika-cji przeglądarki z serwerem aplikacji. Do-myślnie przybiera wartość 'asynchronous' (pol. asynchronicznie, w tle), jednak można wymusić połączenie synchroniczne przez umieszczenie wartości 'synchronous';

• $options['loading'] – kod JavaScript, który będzie wywołany podczas pobiera-nia danych z serwera;

• $options['loaded'] – kod JavaScript, który będzie wywołany po zakończeniu pobierania danych z serwera;

• $options['complete'] – kod JavaScript, który będzie wywołany, gdy obiekt XHR zakończył transfer danych;

• $options['condition'] – kod JavaScript zawierający warunki, które muszą być spełnione, zanim obiekt XHR zostanie za-inicjalizowany;

• $options['confirm'] – tekst, który bę-dzie wyświetlony w okienku potwierdze-nia rozpoczęcia transferu danych przez obiekt XHR (tzn. przed rozpoczęciem transferu danych);

• $options['before'] – kod JavaScript, który będzie wywołany, zanim żądanie dostępu do danych będzie wysłane do ser-wera WWW;

• $options['after'] – kod JavaScript, któ-ry będzie wywołany po żądanie dostę-pu do danych serwera WWW (zdarzenie 'after' występuje przed 'loading').

Wracając do naszej aplikacji i Listingu 6. Za po-mocą przedstawionego kodu będziemy moni-torowali formularz (search) co jedną sekundę ($options['frequency'] => 1). W przypad-ku wykrycia zmian zostanie wywołana akcja CakePHP, powodująca przeszukiwanie bazy da-nych ($options['url'] => '/todo/search'), któ-rej wyniki zostaną wyświetlone w przeglądarce ($options['update'] => 'results'). Kolejne zmiany w stosunku do serwisu działającego bez AJAX, dotyczą uniemożliwienia przeładowania strony, w wyniku wysłaniaformularza. Standar-dowo, klikając na przycisk Wyślij, powodujemy wczytanie i wyświetlenie strony określonej pa-rametrem <form action="URL">. W AJAX za-bezpieczamy się przed tym, umieszczając para-metr <form onsubmit="return false">. Nie-wielkie modyfikacje dotknęły także metodę To-do Controller::search(), która teraz umożli-wia wybieranie wszystkich danych pasujących do ciągu znaków wprowadzonych do formula-rza. Jest to możliwe dzięki zastosowaniu opera-tora SQL "LIKE" (Listing 7.).

Modyfikacja formularza spowoduje wysła-nie zapytania do serwera WWW, który w od-powiedzi prześle listę danych pasujących do

Listing 6. Kod CakePHP umożliwiający reagowanie na zmiany w formularzu WWW

// plik app/views/todo/index.thtml

<!–– informacja o wczytywaniu danych jest domyślnie ukryta (display: none)–>

<div id="loading" style="display: none; padding: 4px; color: black;

background–color: #FAD163; width:400px">

<center>Trwa ładowanie danych...</center>

</div>

<form onsubmit="return false">

<p>

<h2>Wyszukiwanie:</h2>

<input type="text" id="search" name="search" />

</p>

</form>

<?php

// obserwacja zmian tekstu w formularzu wyszukiwania

$options = array(

'update' => 'results',

'url' => '/todo/search',

'frequency' => 1,

'loading' => "Element.hide('results')",

'complete' => "Element.show('results')"

);

echo $ajax–>observeField('search', $options);

?>

<!–– miejsce na wyniki poszukiwań domyślnie jest ukryte (display: none) ––>

<div id="results" style="display: none; margin–top: 10px;

background–color: #EEEEEE; padding:

4px; border: 1px solid #DDDDDD; width: 400px"></div>

<div style="margin–top: 10px;">

<?php

// link umożliwiający czyszczenie wyników wyszukiwania

// bez przeładowania strony WWW

$options = array(

'update' => 'results',

'loading' => "Element.hide('results')",

'complete' => "Element.show('results')"

);

echo $ajax–>link('Wyczyść listę wyszukiwania!', '/todo/clear', $options);

?>

</div>

// plik app/views/todo/clear.thtml

// zawiera informację wyświetlaną przy czyszczeniu wyników wyszukiwania

<center>Brak danych</center>

// plik app/views/todo/search.thtml

<?php if (count($todo) > 0): ?>

<ul>

<?php foreach ($todo as $task): ?>

<li><?php echo $task['Task']['title']; ?></li>

<?php endforeach ?>

</ul>

<?php else: ?>

Nic nie znaleziono!?

<?php endif ?>

Page 43: PHP Solutions 06 2007 PL

Rozwiązania

42 06/2007

AJAX

43www.phpsolmag.org

Przygotowana przez nas aplikacja, to tyl-ko przykład tego, jak prosto można wykorzy-stać AJAX w CakePHP. Korzystając z faktu, iż oprócz Prototype, mamy do dyspozycji biblio-tekę script.aculo.us (Listing 4.) możemy w prosty sposób dodać różne efekty graficzne, które będą towarzyszyć wyszukiwaniu danych. Wystarczy zmodyfikować tablicę $options z Listingu 6. i dodać kod JavaScript, który wy-kona się podczas wymiany danych z serwerem i po jej zakończeniu (Listing 8.).

Co oznaczają wprowadzone zmiany?Podczas czekania na dane z serwera ($options['loading']) zostanie ukryty fragment strony, zawierający dotychczasowe wyniki wyszukiwania (Element.hide('res

ults')) i wyświetlony tekst informujący, że połączenie jest aktywne i trwa wymiana da-nych (Element.show('loading')). Dzię-ki temu, nawet gdy transmisja będzie trwa-ła dugo, to użytkownik cały czas będzie wie-dział, co się aktualnie dzieje z aplikacją – nie zostanie pozostawiony z tzw. pustą stroną. Gdy połączenie z serwerem dobiegnie koń-ca ($options['complete']), to informacja o transferze zostanie ukryta (Element.hide('loading')), a nowe wyniki wyszukiwania pojawią się w przeglądarce (Effect.Appear('results')). Pojawią się w dosłownym zna-czeniu – za sprawą efektu graficznego appear (pol. objawiać się, ukazać się) powodującego, iż nowe dane wyłonią ze strony WWW. Oczywi-ście nie musimy się ograniczać tylko do dwóch efektów. Biblioteka script.aculo.us obsłu-guje ich kilkanaście, co w połączeniu z faktem, że większość z nich jest parametryzowana, da-je duże możliwości dostosowania pożądanych efektów do własnych potrzeb (Listing 9.).

PodsumowanieBudowanie interaktywnych serwisów WWW wymaga od projektantów posługiwania się co-raz to nowszymi technologiami. AJAX umoż-liwia osiągnięcie pożądanych efektów, wyko-rzystując istniejące standardy, takie jak Java-Script, CSS czy DOM. Dzięki niemu strony mogą być bardziej przyjazne dla użytkowni-ków i efektywniej prezentować dane. Warto jednak przeanalizować, czy osiągnięte korzy-ści będą istotniejsze niż wydłużenie czasu ła-dowania aplikacji za sprawą dodatkowych bi-bliotek JavaScript. Mam nadzieję, iż przedsta-wiony artykuł pokazał, że dzięki zastosowaniu framework'ów, takich jak CakePHP, zwiększe-nie funkcjonalności serwisów nie musi się od-bywać kosztem wzrostu czasochłonności ich przygotowania.

Listing 7. Uzupełnienie kontrolera o metodę TaksController::search() umożliwiającą przeszukiwanie danych

// plik app/controllers/tasks_controller.php

class TodoController extends AppController {

var $helpers = array('Html','Javascript','Ajax');

function search() {

$tasks = array();

$this->layout = 'ajax';

if (! empty($this->params['form']['search'])) {

$title = strip_tags($this->params['form']['search']);

// zwracamy maksymalnie 10 wierszy

$tasks = $this->Task->findAll(

array('Task.done' => 0, 'Task.title' => "LIKE ${title}%"), null, 'Task.id DESC', 10);

}

$this->set('todo', $tasks);

}

}

Listing 8. Rozbudowa AJAX o efekty graficzne towarzyszące wyszukiwaniu danych w przykładowej aplikacji

$options = array(

'update' => 'results', 'url' => '/todo/search', 'frequency' => 1, 'loading' =>

"Element.hide('results');Element.show('loading')", 'complete' => "Element.hide(

'loading');Effect.Appear('results')"

);

echo $ajax–>observeField('search', $options);

Listing 9. Przykładowe efekty script.aculo.us, które możemy wykorzystać, by podnieść atrakcyjności naszej przykładowej aplikacji

/* przeźroczystość */

Effect.Opacity('results', { duration: 2.0, transition: Effect.Transitions.linear,

from: 1.0, to: 0.5 });

/* wyróżnienie kolorem */

Effect.Highlight('results', { startcolor:'#ff99ff', endcolor:'#999999'});

/* blednięcie, wygaszanie */

Effect.Fade('results', { transition: Effect.Transitions.wobble })

W Sieci

• Forum użytkowników CakePHP: http://groups.google.com/group/cake–php• Dokumentacja CakePHP: http://cakephp.org• Dokumentacja biblioteki Prototype: http://www.prototypejs.org/learn• Dokumentacja biblioteki script.aculo.us oraz przykłady jej wykorzystania:

http://wiki.script.aculo.us/scriptaculous/• Informacje o Document Object Model (DOM): http://www.w3.org/DOM/• Informacje o obiektach XMLHttpRequest: http://www.w3.org/TR/XMLHttpRequest/• Informacje o JavaScript: http://developer.mozilla.org/pl/docs/

PIOTR GAPIŃSKIAutor w wolnych chwilach zajmuje się programo-

waniem w różnych językach (głównie Rebol, Ruby,

PHP i AmigaE).

Kontakt z autorem: piotr–[email protected]

kryterium wyszukiwania, wprowadzonego przez użytkownika. Pozostaje już tylko wy-świetlić otrzymane informacje bez przełado-wywania całej strony WWW. Jak wcześniej wspomnieliśmy, brudną robotę wykona za nas metoda AjaxHelper::observeField() – Li-sting 6. Musimy jednak zwrócić uwagę na ma-ły szczegół. Modyfikacja formularza wywo-ła akcję CakePHP, która może zwrócić kod HTML wraz z domyślnym szablonem serwisu (plik cake/libs/view/templates/layouts/

default.thtml), zawierającym całą strukturę dokumentu HTML. Jeżeli nie zmienimy sza-blonu, to otrzymamy błędny wynik, w którym

będą zagnieżdżone dwie strony WWW! Cake-PHP posiada szablon, który powinien być uży-wany przy zapytaniach uruchamianych przez AJAX. Znajduje się on w katalogu cake/libs/view/templates/layouts/ajax.thtml, a akty-wuje się go poprzez umieszczenie we właści-wej metodzie kontrolera wywołania: $this–>layout='ajax' (Listing 7.).

Nasza aplikacja jest już gotowa. Wystarczy uruchomić przeglądarkę internetową i wpisać adres IP serwera CakePHP razem z nazwą kon-trolera np. http://127.0.0.1/todo. Teraz mo-żemy sami się przekonać, jakie zalety posiada technologia AJAX (Rysunek 3.).

Page 44: PHP Solutions 06 2007 PL

Rozwiązania

44 06/2007

ATOM

45www.phpsolmag.org

Jeszcze niedawno zachwycaliśmy się kana-łem typu RSS. Duża liczba osób, nie chcąc ładować strony, sprawdzała nowości przez

kanał (o ile webmaster się o to postarał). Teraz przychodzi czas na małą zmianę.

Przyszłością kanałów informacyjnych na ra-zie wydaje się być ATOM. Jest to kanał funk-cjonalnością bardzo zbliżony do RSS, jednak już po pierwszej styczności z jego konstruk-cją każdy dojdzie do wniosku, iż RSS niedłu-go odejdzie do lamusa. Autorzy kanału posta-rali się o to, aby konstrukcja była jak najbar-dziej czytelna i dostępna dla wszystkich użyt-kowników. Wprowadzono wiele innowacji, ta-kich jak np. nowe tagi. W tym artykule poka-żę Państwu, jak w prosty sposób napisać parser w php, który będzie korzystał z danych pobiera-nych z bazy MySQL.

Przygotowujemy miejsce pracy.Na początek przygotujmy sobie miejsce pra-cy. Nasz parser musi pobierać dane, dlate-go tworzymy tabelę z newsami. Jest to bar-dzo proste zadanie. Wystarczy jedno zapy-tanie do bazy:

CREATE TABLE `newsy`

(id int not null auto_increment,

title char(200),

news text, primary key(id))

Zapytanie to możemy wykonać z poziomu strony, jak i poprzez panel phpMyAdmin. W celu wysłania zapytania z poziomu stro-ny, musimy skorzystać z funkcji obsługują-cych łączenie i operacje na bazie. Tego chy-

ba tutaj opisywać nie muszę. Mamy już ta-belę. Teraz czas zająć się dodawaniem rekor-dów. Posłużymy się następnym zapytaniem do naszej bazy danych. Wypełnijmy na razie tabe-lę sześcioma rekordami dla testu:

INSERT INTO `newsy` SET `id` = NULL,

`title` = 'News testowy nr 1',

`news` = 'Nasz news nr 1 do parsera.

Zobaczymy jak działa!Wysyłamy to zapytanie sześć razy, za każdym razem zmieniając liczbę porządkową w ty-

ATOM

Czasami pojawia się konieczność wygenerowania jakichkolwiek plików automatycznie. Czasami sami nawet tego chcemy, aby ułatwić sobie pracę i móc cieszyć się zautomatyzowanym procesem. Nie jest inaczej, jeżeli uwagę skupimy na efektownym i szybkim generowaniu kanału informacyjnego ATOM.

Dowiesz się...• Jak za pomocą php wygenerować działający

kanał informacyjny.

• Poznasz bardzo ogólnikowo składnię kanału

informacyjnego.

Powinieneś wiedzieć...• Powinieneś znać podstawy obsługi bazy My-

SQL i operacji na plikach.

Poziom trudności

Piszemy swój pierwszy parser

Linsting 1. Kod config.php

<?php

$nameparser = "/parser.php";

//Ta linijka jest bardzo ważna. Umieszczamy tutaj nazwę pliku z parserem +

rozszerzenie + ewentualny katalog nadrzędny!

if($_SERVER['REQUEST_URI'] == $nameparser){

//adres przeznaczony dla atrybutu link. Tego nie zmieniać!

$adres = 'http://'.$_SERVER['HTTP_HOST'].''.$_SERVER['REQUEST_URI'];

//tutaj ustawiamy ilość sekund, po których upłynięciu kanał zostanie skasowany

//z cache i pobrany nowy. 604800 czyli tydzień.

$sec = '604800';

// deklarujemy datę ostatniej modyfikacji. Tego nie zmieniać!

$date = date("Y-m-d\TH:i:sP");

$title = 'Mój pierwszy kanał!'; //definiujemy tytuł kanału

$autor = 'Jan Kowalski'; //autor kanału

$mail = '[email protected]'; //mail autora kanału

//adres www strony, dla której jest przeznaczony kanał

$site = 'http://www.example.com';

$substr = '20'; //długość skróconego newsa

$news = '5'; //ilość newsów wyświetlanych na kanale

$host = 'localhost'; // host bazy danych

$user = 'user'; // user bazy danych

$pass = 'password'; // password usera bazy danych

$base = 'base'; // nazwa bazy

} else {

echo("Brak dostępu!");

}

?>

Page 45: PHP Solutions 06 2007 PL

Rozwiązania

44 06/2007

ATOM

45www.phpsolmag.org

tule i newsie, zgodnie z numeracją (pomoże nam to później ocenić czy parser działa pra-widłowo).

Jak widzimy, wartość dodawana do pola news liczy sobie 48 znaków. Sama liczba nie jest o ty-le ważna, co sprawdzenie, czy skracanie będzie działało prawidłowo. Tutaj mamy do czynienia z małymi rozmiarami tekstu i brakiem znaków specjalnych, ale o tym za chwilę.

Bierzemy się do pracy– piszemy swojego parsera.Jeżeli mamy już przygotowaną tabelę, na któ-rej będziemy pracować, możemy przystąpić do tworzenia właściwego parsera. Będzie się

on składał z dwóch plików. Jeden, w którym umieścimy zmienne konfiguracyjne (config) i drugi, właściwy plik parsera. Budowa ca-łości będzie bardzo prosta. Uwagę tutaj ra-czej chciałem zwrócić na wykorzystanie php w połączeniu z kanałem informacyjnym, ja-ki jest ATOM. Najpierw tworzymy plik o na-zwie config.php. Dla bezpieczeństwa doda-my linijki kodu odpowiadające za sprawdze-nie ciągu znaków przekazywanych w adre-sie (config.php będziemy mogli includować, otwieranie poprzez podanie adresu nie jest brane pod uwagę ze względów bezpieczeń-stwa). Kod pliku config.php znajdziemy na Listingu 1.

Utworzyliśmy plik config.php. Jak widzimy, jeżeli wywołamy plik config.php poprzez adres w przeglądarce, wyświetli nam błąd. Jeżeli za-includujemy plik do skryptu php o nazwie „par-ser.php”, będziemy mieli pewność, że zmienne zostały przekazane skryptowi.

Przyszedł czas na plik parsera. Jak wcze-śniej napisałem, będziemy korzystać z wycią-gów z bazy danych. Najpierw jednak musimy się zdecydować na parę istotnych elementów. Otóż trzeba wiedzieć, jak długi ma być skróco-ny news oraz ile newsów ma się subskrybować. Pomyślałem, że na potrzeby naszego skryptu 20 znaków i 5 newsów wystarczy. Tak więc two-rzymy plik parser.php (jeżeli chcemy inaczej na-zwać ten plik musimy to uwzględnić również w config.php!), a w nim umieszczamy kod z Listin-gu 2. Zanim jednak wykonamy skrypt i utwo-rzymy plik z kanałem informacyjnym, przyj-rzyjmy się skryptowi. Trzeba wiedzieć bowiem co się w nim znajduje.

Na początku łączymy się z bazą i wysyła-my zapytanie o pięć najnowszych rekordów. Oczywiście sprawdzamy czy zapytanie szczę-śliwie dostało się do bazy i czy coś wróciło. Na-stępnie przypisujemy zmiennej $atom począt-kową wartość kanału z określonymi atrybuta-mi po czym wykorzystujemy pętlę while do nadpisania wątkami zmiennej $atom2. Jak wi-dzimy, w pętli wykonaliśmy operację skraca-nia newsa do 20 znaków, tak jak zadeklarowa-liśmy to w config.php. Sama pętla while powin-na wykonać się pięć razy (to też zadeklarowali-śmy). Po wykonaniu while w zmiennej $atom2 mamy przypisane pięć newsów. Zmienną tą musimy następnie dodać do „całości”, która będzie tworzyła nam kanał. Na koniec nie po-zostaje nic innego, jak stworzyć plik z warto-ścią zmiennej $atomcaly, wykorzystując funk-cję fopen(). Dla dopełnienia i pewności, spraw-dzamy czy utworzenie pliku powiodło się. Je-żeli tak - drukujemy napis potwierdzający to i podający link do kanału. Analogicznie jeżeli nie - wyświetlamy błąd.

PodsumowanieOsobiście korzystam z tego typu parsera, jed-nakże z kilkoma dodatkami, takimi jak filtro-wanie newsów, odpowiednia ich edycja itd. Moim zdaniem ATOM jest dużym krokiem na przód i mam nadzieję, że nie zostanie porzuco-ny przez autorów, tak jak znaczna liczba pro-jektów internetowych. Oczywiście można po-łączyć RSS z ATOM-em dla wygody użytkow-ników. Wszystko zależy od pomysłu i inwencji webmastera.

Listing 2. Kod pliku właściwego parser.php

<?php

include("config.php");

mysql_connect($host, $user, $pass);

mysql_select_db($base);

//nasze zapytanie do tabeli z newsami

$sql = "select `id`, `title`, `news` from `newsy` order by `id` desc limit ".$news."";

$mysql = mysql_query($sql);

if($mysql == TRUE){

$atom1 = '<?xml version="1.0" encoding="iso8859-2"?>

<feed xmlns="http://www.w3.org/2005/Atom">

<title>Kanał informacyjny ATOM</title>

<link rel="self" href="'.$adres.'"/>

<updated>'.$data.'</updated>

<author>

<name>'.$autor.'</name>

<email>'.$mail.'</email>

<uri>'.$site.'</uri>

</author>

<id>'.$site.'</id>';

while($news = mysql_fetch_array($mysql)){

$substrnews = substr($news['news'], 0, $substr);

$atom2 .= '<entry>

<title>'.$news['title'].'</title>

<link rel="self" href="'.$adres.'"/>

<id>'.$rekord['id'].'</id>

<updated>'.$date.'</updated>

<summary>'.$substrnews.'</summary>

</entry>';

}

$atom3 = '</feed>';

$atom = $atom1."".$atom2."".$atom3;

$fopen = fopen('atom.xml', w);

fwrite($fopen, $atom);

fclose($fopen);

if($fopen == TRUE){

echo("Kanał został stworzony!<br/>Adres do niego to: <a href='atom.xml'>atom.xml

</a>!<br/>");

}else{

echo("Nie udało się stworzyć kanału!<br/>");

}

}else{

echo('Zapytanie nie dotarło do bazy!<br/>');

}

mysql_close();

?>

PATRYK SZLAGOWSKIAutor jest programistą z zamiłowania. Uczy się

w szkole średniej w Lęborku. Zajmuje się freelan-

cerstwem oraz prowadzeniem własnej strony

www.haes-suqad.net.

Kontakt z autora: [email protected]

Page 46: PHP Solutions 06 2007 PL

Narzędzia

46 06/2007

GWT

47www.phpsolmag.org

Dlaczego w dzisiejszym świecie Web 2.0 GWT się liczy? Odpowiedź jest prosta, daje możliwości wykorzysta-

nia rozbudowanych i dojrzałych narzędzi ję-zyka Java, przy pracy z JavaScript–em. Dzię-ki GWT , możemy teraz refaktorować swój Ja-vaScript, debugować go, używać mechanizmu podpowiadania nazw i składni. Już samo to, da-je duże możliwości w pracy z JavaScriptem, ale GWT idzie dalej!

Wyobraźmy sobie, że możemy wykorzystać w JavaScript–cie wszystkie zalety silnie obiek-towego języka wysokiego poziomu, a przy tym dalej tworzyć kod zrozumiały dla przeglą-darek internetowych. To jest np. możliwość używania interfejs’ów, typowania zmiennych (a co za tym idzie i przeładowania konstruk-torów czy metod) i wielu, wielu innych. Posia-da cechy, które zawiera język Java, a które nie są dostępne w JavaScript. Jak to możliwe? To niesamowicie proste, GWT pozwala Ci tłuma-czyć aplikacje napisane w Javie na JavaScript, przy zachowaniu pełnej kontroli nad wyniko-wym kodem. W artykule tym dowiesz się, co tak naprawdę to oznacza i dlaczego jest to tak rewolucyjne. Cała treść podzielona została na cztery części:

• wprowadzenie do GWT – gdzie poznasz podstawowe informacje, jak rozpocząć pracę z GWT;

• pierwsza aplikacja – gdzie pokażemy jak to działa, ale na razie tylko po stronie klienckiej;

• GWT i RPC / AMFPHP – gdzie przedsta-wimy bardziej zaawansowany przykład, w którym komunikujemy się z serwerem;

• dodatkowe informacje – gdzie wejdziemy mocniej w szczegóły, które, mamy nadzie-ję, przekonają do GWT tych jeszcze nie-przekonanych.

Wprowadzenie do GWTTeraz, gdy już wiemy, że Google Web Toolkit to narzędzie do tłumaczenia kodu Java na Java-Script, warto wspomnieć, że to także doskona-ły framework, którego zaletą jest prostota w wy-korzystaniu AJAX. Tak naprawdę GWT składa się z trzech części, zamkniętych w pojedyn-czych plikach JAR (Java ARchiwe):

• gwt–user.jar – to paczka przechowująca gotowe do wykorzystania w środowisku JS komponenty i narzędzia;

• gwt–servlet.jar – paczka implemen-tująca mechanizmy pozwalające na ko-

Google Web Toolkit

Google Web Toolkit (GWT), to nowe dziecko Google, wydane na świat niespełna dwa lata temu. Swoją karierę GWT rozpoczął na sympozjum JavaOne w 2006 roku i od tego czasu jego popularność lawinowo wzrasta. Niedawno ogłoszono, że GWT ściągnęło już ponad milion użytkowników. Można zaryzykować stwierdzenie, że świat Javy oszalał na punkcie GWT.

Dowiesz się...• Jakie są zalety GWT.

Powinieneś wiedzieć...• Przydatna będzie podstawowa znajomość JAVA.

Poziom trudności

Listing 1. Uruchamiamy projectCreator

C:\gwt>projectCreator –overwrite –eclipse SmallBear –ant smallbear –out c:\workspace\

smallbear

w wyniku czego powinniśmy zobaczyć:

Created directory c:\workspace\smallbear\src

Created directory c:\workspace\smallbear\test

Created file c:\workspace\smallbear\smallbear.ant.xml

Overwriting existing file c:\workspace\smallbear\.project

Overwriting existing file c:\workspace\smallbear\.classpath

a następnie aplicationCreator poleceniem:

C:\gwt>applicationCreator –overwrite –eclipse SmallBear –out c:\workspace\smallbear

pl.rmalinowski.client.SmallBear

w wyniku czego powinniśmy zobaczyć:

Created directory c:\workspace\smallbear\src\pl\rmalinowski

Created directory c:\workspace\smallbear\src\pl\rmalinowski\client

Created directory c:\workspace\smallbear\src\pl\rmalinowski\public

Created file c:\workspace\smallbear\src\pl\rmalinowski\SmallBear.gwt.xml

Created file c:\workspace\smallbear\src\pl\rmalinowski\public\SmallBear.html

Created file c:\workspace\smallbear\src\pl\rmalinowski\client\SmallBear.java

Created file c:\workspace\smallbear\SmallBear.launch

Created file c:\workspace\smallbear\SmallBear–shell.cmd

Created file c:\workspace\smallbear\SmallBear–compile.cmd

Czyli AJAX na szynach

Page 47: PHP Solutions 06 2007 PL

Narzędzia

46 06/2007

GWT

47www.phpsolmag.org

munikację serwera napisanego w Javie z aplikacją napisaną w JS. (My nie używa-my);

• gwt–dev–windows.jar lub gwt–dev–linux.jar – serce GWT, mechanizmy tłumaczą-ca Javę na JS.

Aby rozpocząć pracę z GWT musimy:

• mieć zainstalowaną wirtualną maszynę Ja-va (min wersja 1.4), jeśli jej nie masz, ścią-gnij i zainstaluj Sun Java Standard Edition SDK (http://java.sun.com/javase/downloads/index.jsp);

• ściągnąć Google Web Toolkit package (http://code.google.com/webtoolkit/download.html);

• posiadać podstawy w rozumieniu języka Java 1.4.

Do pracy przydatny będzie też edytor tekstu, posiadający możliwości analizowania składni Java, my używać będziemy Eclipse, ponieważ ma on bezpośrednie wsparcie dla i w GWT. GWT nie trzeba instalować, wystarczy ścią-gnąć i rozpakować np. do katalogu c:\gwt. Wraz z GWT dostajemy narzędzia do tworze-nia szkieletu projektu i aplikacji zgodnej z za-leceniami developerów z Google. Prawidłowa aplikacja GWT składa się z:

• pliku HTML, w którym osadzana zosta-nie nasza aplikacja JS, musi tu też zostać zainicjowany podstawowy moduł GWT;

• plik nazwa_mojego_modułu.gwt.xml, w któ-rym opisane są dodatkowe parametry dla translatora GWT;

• klasy, implementującej interfejs EntryPo-int, jest to miejsce w którym rozpoczyna pracę nasz program.

Przyjrzymy się teraz, jak działają wspomnia-ne narzędzia:

• projectCreator – tworzy szkielet nowego projekt, jego składnia to:

ProjectCreator [–ant projectName] [–

eclipse projectName] [–out dir] [–

overwrite] [–ignore] gdzie:• ant generuje Ant buildfile do kom-

pilacji źródeł (.ant.xml będzie doda-ny);

• eclipse generuje projekt eclipsowy• out folder do zapisania plików wyniko-

wych (domyślnie bierzący);• overwrite nadpisuje istniejące pliki;• ignore ignoruje istniejące pliki, (nie

nadpisuje);• applicationCreator – tworzy szkielet

startowej aplikacji, jego składnia to: ApplicationCreator

[–eclipse projectName] [–out

dir] [–overwrite] [–ignore]

className gdzie:

• eclipse tworzy konfiguracje urucha-miającą projekt eclipsowy w trybie de-bug;

• out folder do zapisania plików wyniko-wych (domyślnie bieżący);

• overwrite nadpisuje istniejące pliki;• ignore ignoruje istniejące pliki, (nie nad-

pisuje);• className pełna nazwa tworzonej

startowej klasy aplikacji.

Pierwsza aplikacjaPrzechodzimy do stworzenia pierwszej aplika-cji w GWT. Jeśli pojawiły się już jakieś nieja-sności, to ten krok prawdopodobnie większość

z nich rozwieje. Na początku stwórzmy nowy projekt w Eclipse. W tym celu klikamy: Menu –> File –> New –> Project.

Z wyświetlonych kreatorów wybieramy Java Project , nazywamy go SmallBear i klika-my na przycisk Finish, zapamiętując położenie naszego nowo powstającego projektu, (ramka Contents pole Direcotry) w naszym przypadku to c:\workspace. Teraz przechodzimy do nad-pisania tak powstałego zalążka nowego projek-tu, przez szkielet generowany przy użyciu na-rzędzi GWT.

Uruchamiamy projectCreator poleceniem: (Listing 1.). Po wykonaniu przedstawionych komend i odświeżeniu projektu w Eclipse,

Rysunek 1. Widok szkieletu aplikacji GWT w Eclipse

Rysunek 2. Widok działającej aplikacji w trybie HostedMode

Page 48: PHP Solutions 06 2007 PL

Narzędzia

48 06/2007

GWT

www.phpsolmag.org

szkielet aplikacji GWT powinien wyglądać tak, jak na Rysunku 1.

Warto w tym miejscu zauważyć, że two-rząc aplikację, klasę startową umieściliśmy w pakiecie client. Jest to zalecane przez develo-perów Google i jeśli tego nie zrobimy, skrypt generujący schemat aplikacji powinien po-kazać nam mniej więcej taki komunikat: (Listing 2.).

Warto o tym pamiętać, by w przypadku ta-kiego przeoczenia nie marnować czasu na za-stanawianie się, gdzie popełniliśmy błąd.

Ponieważ skorzystaliśmy z generatora szkieletu aplikacji, tak przygotowany pro-jekt możemy od razu uruchomić. Do wybo-

ru mamy dwa tryby: HostedMode i WebMo-de. Tryb HostedMode jest trybem w pełni za-rządzanym przez GWT, oznacza to, że może-my tu debugować uruchamiany kod i śledzić kolejne jego kroki, analizując dokładnie to, co dzieje się z powołanymi do życia zmiennymi czy obiektami.

Tryb WebMode to już domyślny tryb, w jakim będzie pracować nasza aplikacja, czy-li wskazana przez nas przeglądarka interneto-wa. Developerzy GWT dają nam gwarancję, że aplikacja uruchamiana w trybie Hosted, będzie działała identycznie jak w trybie Web. Warto tu zauważyć, że oznacza to też, że niezależnie od tego, czy uruchomimy nasz

skrypt w Internet Explorerze czy też w Fire-foksie, będzie on działał tak samo. Aby uru-chomić aplikację w trybie Hosted wywołu-jemy wygenerowany w katalogu domowym projektu skrypt SmallBear–shell, efekt oczekiwany widoczny jest na Rysunku 2. Aby uruchomić aplikację w trybie Web urucha-miamy skrypt SmallBear–compile, który to jednak nie otworzy nam domyślnej przeglą-darki, a jedynie przetłumaczy aplikację Java na JavaScript.

Wynik tego tłumaczenia widoczny jest w katalogu www (jest to domyślny katalog generowania JS – można to zmienić). War-to zauważyć, że tak wygenerowana aplikacja, jest zwykłą stroną html, którą możemy otwo-rzyć bezpośrednio na dysku twardym, inny-mi słowy, nie potrzebujemy do tego serwera WWW. Efekt uruchomienia pliku SmalBe-ar.html w przeglądarce Firefox widoczny jest na Rysunku 3.

Prześledźmy teraz kod programu (Listing 3.), aby sprawdzić co się tak naprawdę stało. Stworzyliśmy klasę SmallBear, która imple-mentuje interfejs EntryPoint. EntryPoint to miejsce, w którym rozpoczyna pracę aplika-cja. Pisząc dokładniej, przy ładowaniu stro-ny internetowej, w pierwszej kolejności ła-dowane jest i inicjowane środowisko GWT (plik gwt.js).

W kroku następnym ładowana jest nasza aplikacja, a po zakończeniu uruchamiana jest metoda onModuleLoad. Tu rozpoczy-na się praca programu. Jak widać, nie ma tu trudności, w kroku 1. tworzony jest no-wy przycisk z etykietką Click me, w kroku 2. tworzona jest pusta etykieta. Następnie oprogramowujemy zdarzenie onClick przy-cisku button krok 3., tworząc do tego calu tak zwaną klasę anonimową, czyli klasę bez nazwy, implementującą metodę onClick (4). Metoda ta zostanie wywołana za każdym ra-zem, gdy przycisk button zostanie kliknięty. Sprawdzamy tu, czy etykieta label jest wciąż pusta (5), jeśli tak, to ustawiamy nowy tekst do wyświetlania (6), jeśli nie (7) to czyścimy nazwę etykiety (8). Na koniec jeszcze wsta-wiamy przycisk (9) i etykietę (10) na stronę tak, by użytkownik mógł je zobaczyć.

Na koniec warto jeszcze spojrzeć na to, jak wygląda plik htmlowy (Listing 4.]. Ciekaw-sze miejsca to (1), gdzie dodajemy wygene-rowany przez GWT kod JavaScript aplikacji. (2) to opcjonalne włączenie emulatora histo-rii, dzięki tej linii kodu w przyszłości będzie można używać przycisku przeglądarki cofnij mimo, że nie doszło ani razu do przeładowa-nia strony internetowej.

W punkcie (3) tworzona jest tabelka z dwoma identyfikatorami slot1i slot2, ła-two skojarzyć to z punktami (9,10) Listingu 3., by zauważyć, że jest to miejsce, gdzie zo-staną wstrzyknięte przycisk i etykieta apli-kacji. Dzięki takiemu zapisowi możemy two-

Rysunek 3. Widok działającej aplikacji w przeglądarce Firefox (WebMode)

Rysunek 4. Przeglądanie serwisów – AMFPHP.

Page 49: PHP Solutions 06 2007 PL

Narzędzia

48 06/2007

GWT

www.phpsolmag.org

rzyć oddzielnie własną strukturę HTML, wy-pełniając tylko odpowiednie elementy, w peł-ni zarządzanymi przez GWT obiektami. Aby upewnić się, że wszystko jest zrozumiałe, pro-ponujemy dokonać własnych zmian w kodzie, sprawdzając, jak zareaguje (albo czy w ogó-le zareaguje) na to aplikacja GWT. Po więcej ciekawych przykładów wykorzystania GWT odsyłamy na stronę domową projektu: http://code.google.com/webtoolkit/documentation/examples/. Warto obejrzeć dema, zanim przej-dziemy do następnego tematu.

GWT i HTTPRequestJak na razie pokazaliśmy jedynie, że tłuma-czenie Javy do JavaScrpt–u działa, ale nie było w tym nic z asynchronicznej komunikacji z ser-werem (AJAX). Powoli przejdziemy do wywo-ływania zdalnych metod na serwerze PHP. Za-czniemy od odrobiny teorii.

Dla naszych potrzeb, komunikacją z serwe-rem w GWT, zajmuje się klasa HTTPRequest. Posiada ona cztery statyczne metody imple-mentujące asynchroniczną wymianę informa-cji. W poniższym przykładzie wykorzystamy tylko jedną z nich:

asyncGet(String url,

ResponseTextHandler handler)

gdzie:

url to – to URL (musi być adresem

bezwsględnym)

handler –to obiekt, który zostanie

poinformowany w momencie

odpowiedzi serwera.

Aby w najprostszy z możliwych sposo-bów zaprezentować działanie powyższe-go, zmieńmy bazową aplikację tak, by na zdarzenie kliknięcia pobierała informa-cję o naszym numerze IP z witryny http://whatismyip.org/.

W tym celu zmieniamy implementację me-tody onClick w klasie SmallBear (patrz Li-sting 5.), tak by w kroku 1. zapytać serwer o nasz numer IP, w kroku 2. zareagować na odpowiedź serwera, wyświetlając odpowiedź w kroku 3. – JavaScriptowy alert. To nam wy-starczy, by upewnić się, że komunikacja asyn-chroniczna działa.

GWT i AMFPHPPotrafimy już wysyłać i odbierać proste da-ne z serwera. Bardziej skomplikowane struk-tury danych trzeba niestety serializować. My do tego celu będziemy używać forma-tu JSON (JavaScript Object Notation), któ-ry doczekał się implementacji parserów w większości znanych języków programo-wania, a napewno w PHP i GWT. Pozosta-je nam tylko odebrać komunikat po stronie PHP, zdeserializować go, przetworzyć zapy-tanie i wysłać odpowiedź do GWT.

Sprawa prosta, ale dla bardziej zaawanso-wanych aplikacji, gdy serwer implementować będzie wiele zdalnie wywoływanych metod, należałoby przewidzieć możliwość dobrego zarządzania takimi metodami.

Z pomocą przychodzi dojrzała już apli-kacja AMFPHP. AMFPHP w wersji 1.9 na dzień pisania tego artykułu był dostępny jedynie na blogu twórcy projektu (http://www.5etdemi.com/blog/) (dla niecierpliwych

link bezpośredni: http://www.5etdemi.com/uploads/amfphp-1.9.beta.20070513.zip).

Po ściągnięciu wystarczy rozpakować ar-chiwum do katalogu hdocs serwera apache i przejść do katalogu bazowego aplikacji, czyli {$HTDOC_DIR}/amfphp/services. To tutaj będziemy umieszczali nasze usługi dla GWT.

Zasada działania AMFPHP jest bardzo pro-sta, jeśli wywołamy na serwerze www zapy-tanie postaci: http://localhost//amfphpjson/json.php/MyService.myRemoteMethod/arg1/arg2 to zostanie ono obsłużone w następu-jący sposób:

• AMFPHP powoła do życia instancje klasy MyService (której definicja musi znajdo-wać się w pliku MyService.php w katalogu /services);

• sprawdzi, czy myRemoteMethod jest me-todą ze zdefiniowanym zdalnym dostę-pem;

• uruchomi metodę myRemoteMethod z ar-gumentami arg1, arg2 odpowiednio dese-rializując parametry, jeśli trzeba;

• na koniec serializuje i zwraca wynik.

Listing 2. Komunikat skryptu generującego schemat aplikacji

Please use 'client' as the final

package, as in 'com.

example.foo.client.MyApp'.

It isn't technically necessary,

but this tool enforces the best

practice.

R E K L A M A

Page 50: PHP Solutions 06 2007 PL

Narzędzia

50 06/2007

GWT

51www.phpsolmag.org

smallbear\src\pl\rmalinowski\) dodać do-datkowy wpis:

<inherits name=

'com.google.gwt.json.JSON'/>

Poinformuje on kompilator GWT, że do wyge-nerowanego JavaScript–u należy dodać wska-zaną bibliotekę. Użycie biblioteki wygląda na-stępująco:

• serializacja:JSONNumber jsonNumber = new

JSONNumber(12.0);// zwraca zakodowaną wartość

//numeryczną

JSONNumber.toString();

• deserializacja :try {

JSONObject jsonObject =

(JSONObject) JSONParser.parse(

jsonStringWith

SerializedObject);

} catch (JSONException e) {

Window.alert('JSON parse error!');

}

Możemy teraz przejść do etapu komunikacji z serwerem AMFPHP. W tym celu URL z Li-stingu 5., kroku 1., zamieniamy zgodnie z sza-blonem przedstawionym powyżej. Wywoła-nie zdalnej metody powinno wyglądać jak na Listingu 7. Tak przygotowaną aplikację może-my już uruchamiać.

Dodatkowe informacjePrzedstawiony przykład komunikacji GWT z PHP jest bardzo prosty i dla bardziej za-awansowanych aplikacji wymaga rozbudo-wania.

Zanim zdecydujemy się, czy używać GWT we własnych projektach, warto jesz-cze zapoznaćsię z kilkoma dodatkowymi funkcjonalnościami, jakie zapewnia ten fra-mework.

DebugowanieUruchamiając aplikację GWT w tzw. hosted mode, mamy możliwość debugowania jej, co oznacza, że możemy śledzić krok po kro-ku jak wykonuje się aplikacja, jeszcze przed przetłumaczeniem jej na JavaScript.

Używając eclipse wystarczy z menu wy-brać Run –> Debug a następnie z listy Java Aplication wybrać nazwę projektu i klik-nąć w przycisk Debug. Jeśli wcześniej zo-stały ustawione breakpoint–y, to powinni-śmy zobaczyć widok podobny do ekranu z Rysunku 5.

Testy jednostkoweGWT wspiera również testy jednostkowe. Wraz z narzędziami ProjectCreator i Aplica-tionCreator dostajemy JunitCreator. Jest to

Rysunek 5. Debugowanie aplikacji GWT w Eclipse IDE

Rysunek 6. Wynik testów jednostkowych w Eclipse IDE

Przykład klasy implementującej prosty serwis dla AMFPHP widać na Listingu 5. W Punk-tach:1., 2. i 3. definiujemy odpowiednio na-zwę udostępnianej metody, jej opis i zdalny typ dostępu.

Punkt 4. to już implementacja metody, której nazwę zdefiniowaliśmy w Punkcie 1. Dla tak zdefiniowanego serwisu, może-my uruchomić dostarczoną przez AMFPHP przeglądarkę do testowania usług. Wystarczy otworzyć plik browser/index.html i powin-niśmy zobaczyć jak AMFPHP widzi nasz ser-wis (Rysunek 4.).

Tu możemy też, po raz pierwszy, sprawdzić czy działa on poprawnie. Przetestujmy meto-

dę getSum, wpisując w odpowiednie pola wy-brane wartości i uruchamiając metodę po-przez naciśnięcie przycisku call. Wynik spo-dziewany, widoczny jest na Rysunku 4. Pozo-staje teraz wywołać daną metodę poprzez apli-kację GWT.

Po stronie AMFPHP serializacja i deseriali-zacja robiona jest automatycznie, po stronie GWT musimy obsłużyć ją sami.

Do tego przykładu wykorzystamy wbu-dowaną w GWT bibliotekę (com.google.gwt.json.JSON).

Aby móc ją wykorzystać, musimy do pliku SmallBear.gwt.xml (w tym przypadku plik-ten znajduje się w katalogu c:\workspace\

Page 51: PHP Solutions 06 2007 PL

Narzędzia

50 06/2007

GWT

51www.phpsolmag.org

narzędzie do automatycznego generowania testów i osadzenia ich we wskazanym projek-cie. Składnia JunitCreator-a to:

• JUnitCreator – junit pathToJUnitJar – module moduleName [–eclipse projectName] [–out dir] [–overwrite]

[–ignore] className gdzie:• junit określa ścieżkę do junit.jar (wy-

magane);• module nazwa testowanego modułu

GWT (wymagane);• eclipse tworzy konfiguracje integru-

jący junit z eclipse;• out folder do zapisania plików wyni-

kowych (domyślnie bierzący);• overwrite nadpisuje istniejące pliki;• ignore ignoruje istniejące pliki, (nie

nadpisuje);• className pełna nazwa tworzonej kla-

sy testowej.

Aby móc przeprowadzać testy jednostkowe projektu SmallBear uruchamiamy junitCre-ator :

C:\gwt>junitCreator –junit c:\junit\

junit.jar –module pl.rmalinowski.

SmallBear –eclipse SmallBear –out c:

\workspace\smallbear pl.rmalinowski.

client.SmallBearTest

Używając junitCreator–a należy wskazać ścież-kę dostępu do biblioteki junit.jar, w tym przy-padku jest to c:\junit\junit.jar. Jeśli nie posia-dasz biblioteki junit.jar, możesz ją ściągnąć ze strony projektu (http://junit.org) lub użyć bi-blioteki wbudowanej w eclipse:

({$ECLIPSE_DIR}\plugins\

org.junit_3.8.1\junit.jar)

wynik to: Listing 8. Po odświeżeniu projek-tu w oknie eclipse, powinniśmy zobaczyć no-wy katalog test, a w nim wygenerowany test. Klikając prawym przyciskiem na pl.rmalinow-ski.client.SmallBearTest, a następnie wybie-rając Debug as –> Java application rozpoczy-namy test aplikacji. (Test uruchomić może-my również, wybierając z menu Run –> De-bug –> Junit –> SmallBearTest). Do wyboru mamy dwa rodzaje testów, testy w trybie ho-sted i web. Tak jak to zostało już na początku wspomniane, pierwszy tryb wykonuje aplika-cję bez tłumaczenia jej na JS, a drugi tryb naj-pierw konwertuje Javę do JS i dopiero wtedy ją uruchamia. W tym przypadku testy zosta-ną wykonane już na domyślnym kodzie JS. Rysunek 6. przedstawia ekran, prezentujący wynik sumaryczny uruchomionych testów.

JavaScript Native InterfaceGWT nie byłby tak popularny, gdyby zamy-kał drzwi tym, którzy chcieliby mimo wszyst-

Listing 3. Plik SmallBear.java

package pl.rmalinowski.client;

// klasy, które będziemy wykorzystywać w tym przykładzie

import com.google.gwt.core.client.EntryPoint;

import com.google.gwt.user.client.ui.Button;

import com.google.gwt.user.client.ui.ClickListener;

import com.google.gwt.user.client.ui.Label;

import com.google.gwt.user.client.ui.RootPanel;

import com.google.gwt.user.client.ui.Widget;

// i jeszcze to co będzie wykorzystywane w następnych przykładach

import com.google.gwt.user.client.HTTPRequest;

import com.google.gwt.user.client.Window;

import com.google.gwt.user.client.ResponseTextHandler;

import com.google.gwt.json.client.JSONException;

import com.google.gwt.json.client.JSONNumber;

import com.google.gwt.json.client.JSONParser;

public class SmallBear implements EntryPoint {

public void onModuleLoad() {

final Button button = new Button("Click me"); //(1)

final Label label = new Label(); //(2)

button.addClickListener(new ClickListener() { //(3)

public void onClick(Widget sender) { //(4)

if (label.getText().equals("")) //(5)

label.setText("Hello World!"); //(6)

else //(7)

label.setText(""); //(8)

}

});

RootPanel.get("slot1").add(button); //(9)

RootPanel.get("slot2").add(label); //(10)

}

}

Listing 4. Plik SmallBear.html

<html>

<head>

<title>Wrapper HTML for SmallBear</title>

<style>

body,td,a,div,.p{font–family:arial,sans–serif}

div,td{color:#000000}

a:link,.w,.w a:link{color:#0000cc}

a:visited{color:#551a8b}

a:active{color:#ff0000}

</style>

<script language='javascript' src='pl.rmalinowski.

SmallBear.nocache.js'></script> <!–– (1) ––>

</head>

<body>

<iframe src="javascript:''" id="__gwt_historyFrame

" style="width:0;height:0;border:0"></iframe> <!–– (2) ––>

<h1>SmallBear</h1>

<p>

This is an example of a host page for the SmallBear application.

(...).

</p>

<table align=center>

<tr>

<td id="slot1"></td><td id="slot2"></td> <!–– (3) ––>

</tr>

</table>

</body>

</html>

Page 52: PHP Solutions 06 2007 PL

Narzędzia

52 06/2007

ko uruchamiać natywny kod JavaScript. Kie-dy zachodzi taka potrzeba? Przede wszystkim w przypadku, gdy mamy już napisane spo-ro w JS i w nieinwazyjny sposób chcielibyśmy połączyć taki kod z GWT.

Inną potrzebą wykorzystania JSNI, jest przekazywanie parametrów z PHP do GWT. Możemy wtedy generować stronę, w której osadzany jest moduł GWT z wygenerowanym przez PHP kodem JS np.: Array wypełniony-mi danymi, a poprzez JSNI odwoływać się do tej tablicy.

PodsumowaniePrzedstawiliśmy zaledwie zarys możliwości, jakie daje Google Web Toolkit. Nic nie wspo-mnieliśmy o prostocie dodawania dodat-kowych komponentów do naszej aplikacji, a pojawia się ich coraz więcej.

Nie zostało też wspomniane o zarządza-niu historią przeglądarki, dzięki czemu, na-wet jeśli cała interakcja z użytkownikiem przebiega na jednej nieprzeładowanej stro-nie, to cały czas mamy do dyspozycji przy-cisk cofnij, który może dla nas zapamięty-wać poprzednie stany aplikacji. Nie wspo-mnieliśmy też o jednym z najważniejszych, że GWT to opensource.

Odsyłamy do stron projektu (http://code.google.com/webtoolkit/), gdzie wszystkie te i wiele innych informacji można doczytać.

Na koniec postaramy się jeszcze odpowie-dzieć na jedno pytanie. Kiedy warto wybrać GWT?

Przede wszystkim, gdy planujemy stworzyć rozbudowaną aplikację kliencką. Przy napraw-dę małych skryptach, tam gdzie istotna jest wielkość ściąganego przez przeglądarkę kodu, GWT nie jest dobrym wyborem.

Zawsze, gdy tylko zaczynamy myśleć, jak uła-twić użytkownikowi administrowanie naszym sklepem, czy CMS'em.

Tam gdzie rodzą się pomysły na dynamiczne pojawianie się list rozwijanych, automatyczne uzupełnianie nazw artykułów, czy choćby wa-lidacja kodów pocztowych, tam też jest miej-sce dla GWT.

Najlepsze jednak jest to, że kod GWT napi-sany raz, działa na wielu przeglądarkach, a je-śli nie działa, jest duże prawdopodobieństwo, że za chwilę będzie wszystko w porządku. Dla-tego jeśli tylko mamy wybór, uczyć się JS, czy uczyć się Javy pod kątem GWT, proponujemy wybrać GWT.

RAFAŁ MALINOWSKI(http://rmalinowski.pl) – zawodowo pracuje jako

Java EE 5 projektant i programista, bierze udział

w kilku projektach opensource rozwijanych w tech-

nologii PHP i Flash.

Listing 5. Przykład asynchronicznej komunikacji

button.addClickListener(new ClickListener() {

public void onClick(Widget sender) {

HTTPRequest.asyncGet("http://whatismyip.org", new ResponseTextHandler() { //(1)

public void onCompletion(String responseText) { //(2)

Window.alert("My ip is: " + responseText); //(3)

}

});

}

});

Listing 6. Przykład klasy implementującej serwis wAMFPHP

<?php

class MyService{

function MyService(){

$this–>methodTable = array(

"getSum" => array( //(1)

"description" => "Returns sum of two int", //(2)

"access" => "remote"//(3)

)

);

}

public function getSum($a, $b) { //(4)

return $a + $b;

}

}

?>

Listing 7. Przykład klasy komunikującej się z serwisem AMFPHP

button.addClickListener(new ClickListener() {

public void onClick(Widget sender) {

JSONNumber arg1 = new JSONNumber(12.0);

JSONNumber arg2 = new JSONNumber(100.0);

String url = "http://localhost//amfphp/json.php/MyService.getSum/"+arg1.toString()+

"/"+arg2.toString();

HTTPRequest.asyncGet(url, new ResponseTextHandler() { //(1)

public void onCompletion(String responseText) { //(2)

try

{

JSONNumber jsonNumber = (JSONNumber) JSONParser.parse(responseText);

Window.alert("Sum = " + jsonNumber.getValue());

}

catch (JSONException e)

{

Window.alert("JSON parse error!");

}

}

});

}

});

Listing 8. Wynik użycia biblioteki wbudowanej w eclipse

Created directory c:\workspace\smallbear\test\pl\rmalinowski\client

Created file c:\workspace\smallbear\test\pl\rmalinowski\client\SmallBearTest.java

Created file c:\workspace\smallbear\SmallBearTest–hosted.launch

Created file c:\workspace\smallbear\SmallBearTest–web.launch

Created file c:\workspace\smallbear\SmallBearTest–hosted.cmd

Created file c:\workspace\smallbear\SmallBearTest–web.cmd

Page 53: PHP Solutions 06 2007 PL
Page 54: PHP Solutions 06 2007 PL

Narzędzia

54 06/2007

PayPal

55www.phpsolmag.org

Warunkiem założenia konta w Pay-Pal jest posiadanie adresu e-ma-il. System oferuje trzy typy kont.

Wszystkie trzy bezpłatnie umożliwiają: otwie-ranie konta, wysyłanie pieniędzy, dodawanie środków.

Konto osobistePrzeznaczenie: osoby fizyczne głównie kupują-ce przez Internet.Przyjmowanie płatności krajowych: przelew, czek, saldo PayPal – bezpłatna, ograniczona możliwość; karta kredytowa i debetowa – ograniczona, płatna możliwość (opłata 5,4% plus 1,35 PLN).Transakcje w wielu walutach: ograniczona, płatna możliwość (opłata: od 2,4% do 3,9% + 1,35 PLN za transakcję plus 2,5% za przewa-lutowanie).Wypłata środków: bezpłatnie za 500 PLN i więcej, 5 PLN za mniej niż 500 PLN.Narzędzia handlowców: ograniczona możliwość.

Konto specjalnePrzeznaczenie: osoby fizyczne sprzedające i ku-pujące przez Internet.Przyjmowanie płatności krajowych: przelew, czek, saldo PayPal – bez ograniczeń, od 1,9% do 3,4% + 1,35 PLN; karta kredytowa i debetowa – bez ograniczeń, od 1,9% do 3,4% + 1,35 PLN.Transakcje w wielu walutach: bez ograniczeń, od 2,4% do 3,9% + 1,35 PLN za transakcję plus 2,5% za przewalutowanie).

Wypłata środków: bezpłatnie za 500 PLN i więcej, 5 PLN za mniej niż 500 PLN.Narzędzia handlowców: bez ograniczeń.

Konto firmowePrzeznaczenie: firmy działające online.Przyjmowanie płatności krajowych: przelew, czek, saldo PayPal – bez ograniczeń, od 1,9% do 3,4% + 1,35 PLN; karta kredytowa i de-betowa – bez ograniczeń, od 1,9% do 3,4% + 1,35 PLN.Transakcje w wielu walutach: bez ograniczeń, od 2,4% do 3,9% + 1,35 PLN za transakcję plus 2,5% za przewalutowanie).Wypłata środków: bezpłatnie za 500 PLN i więcej, 5 PLN za mniej niż 500 PLN.Narzędzia handlowców: bez ograniczeń.Dodatkowo: dostęp dla wielu użytkowników.

Zakładanie kontaPayPal umożliwia otwieranie kont użytkowni-kom indywidualnym w wieku powyżej 18 lat i firmom zdolnym do zawarcia wiążącej praw-nie umowy, po przejściu procedury rejestracji, w ramach której muszą: zarejestrować adres e-mail (będzie stanowił login) oraz zaakcep-tować zasady zachowania poufności i warun-ki umowy. Możemy również podać dane do-tyczące źródeł, za pomocą których ma być fi-nansowane nasze konto PayPal (np. dane ra-chunku bankowego, karty debetowej lub kre-dytowej).

Procedura zakładania konta polega za-tem na wyborze typu konta, podaniu da-nych osobowych/firmy (nazwa firmy, adres, nr telefonu, adres e-mail) oraz przeczyta-niu i zaakceptowaniu umowy. Po zakończe-niu rejestracji i zalogowaniu się otrzymuje-my dostęp do naszego konta. Na uwagę zasłu-guje Status użytkownika – jako użytkownik zweryfikowany otrzymamy dostęp rozsze-rzony i będziemy mogli wysyłać kwoty o nie-ograniczonej wysokości, a system PayPal bę-

PayPal

PayPal jest wszechstronnym i bezpiecznym, a co równie ważne, popularnym rozwiązaniem w zakresie płatności przez Internet. Umożliwia płatności kartą kredytową, przelewy bankowe i oczywiście płatności z konta PayPal.

Dowiesz się...• Jak wykorzystać PayPal do obsługi płatności

na Twojej stronie internetowej.

Powinieneś wiedzieć...• Powinieneś znać podstawy php oraz html.

Poziom trudności

Łatwy sposób na internetowe płatności

Najważniejsze zalety PayPal

• obsługa płatności z ponad 100 krajów/regionów;• akceptacja płatności kartami kredytowymi VISA i MasterCard;• bezpieczeństwo – szyfrowanie przy użyciu klucza o długości 128 bitów;• akceptacja płatności w wielu walutach;• zwroty wpłat;• brak kosztów dla wysyłającego;• opcja uwzględniania kosztów wysyłki dla sprzedającego;• prosta integracja ze stroną/sklepem internetowym;• środowisko testowe.

Sposoby/scenariusze integracji

• integracja własnego koszyka z systemem PayPal;• wykorzystanie Koszyka oferowanego przez PayPal;• użycie przycisku Kup teraz w wypadku sprzedaży pojedynczych przedmiotów;• użycie przycisku Subskrypcje i Płatności cykliczne – powtarzające się płatności;• użycie przycisku Darowizny – zbieranie darowizn przez Internet.

Page 55: PHP Solutions 06 2007 PL

Narzędzia

54 06/2007

PayPal

55www.phpsolmag.org

dzie nas przedstawiał jako bardziej wiarygod-nych. Aby uzyskać status Zweryfikowany, na-leży dodać do naszego konta kartę kredytową i przeprowadzić procedurę jej potwierdzenia, co w praktyce oznacza zakup przy użyciu tej karty kredytowej w wysokości 6,50 PLN od PayPal (kwota w całości zwracana po pierw-szej transakcji).

Prosty sklep internetowy – przykład integracjiZazwyczaj cała transakcja za pomocą PayPal przebiega według następującego schematu przedstawionego na Rysunku 2. Klient składa zamówienie w naszym sklepie internetowym, następnie zostaje przekierowany do strony PayPal, gdzie dokonuje płatności. Jeśli wszyst-ko przebiegnie pomyślnie, zostaje przekiero-wany z powrotem do sklepu, a tam zakup jest ostatecznie finalizowany. Równocześnie wła-ściciel sklepu zostaje powiadomiony o nowej transakcji za pomocą poczty e-mail, a wpłaco-na przez klienta kwota wpływa na konto Pay-Pal sprzedawcy.

Przedstawimy tutaj prostą implementację te-go scenariusza. Jest to tylko przykład – w praw-dziwym sklepie internetowym produkty bę-dą pobierane z bazy danych. W naszym przy-kładzie jednak wpiszemy artykuły na sztywno i skupimy się wyłącznie na pokazaniu, jak doko-nać płatności za złożone zamówienie za pomo-cą systemu PayPal.

Konstrukcję sklepu zaczniemy od zdefinio-wania kilku potrzebnych stałych w pliku con-fig.php, który jest przedstawiony na Listingu 1. Będziemy korzystać z sesji, a jej identyfi-kator będzie przechowywany na komputerze klienta za pomocą ciasteczka. Nasze ciastecz-ka będą ważne przez 2 dni, za co odpowiada stała EXPIRE_TIME. W ten sam sposób definiu-jemy jeszcze adres URL naszego sklepu, adres e-mail skojarzony z naszym kontem w PayPal oraz adres skryptu poprzez który PayPal bę-dzie odbierał dane z naszego sklepu. Zdefi-

niowanie wszystkich tych informacji w jed-nym miejscu bardzo upraszcza tworzenie sa-mego sklepu, jak też co nie mniej ważne póź-niejsze jego testowanie. Produkty w koszyku klienta zapamiętamy w danych sesji – tablicy $_SESSION. Koszyk wyświetlimy na stronie ja-ko box – przykładowa implementacja w pliku koszyk.php zamieszczonym na płycie CD.

Pierwsza strona naszego sklepu będzie wy-świetlać przykładowe produkty. Klient bę-

dzie mógł wybrać któreś z nich, włożyć do koszyka i następnie zamówić. Stronę tą im-plementuje skrypt produkty.php przedsta-wiony na Listingu 2. Na początku skryptu inicjujemy sesję, aby móc z niej odczytać in-formacje o produktach w koszyku. Następnie definiujemy tablicę z przy kładowymi pro-duktami, które będą wyświetlone na stronie. Dla każdego produktu wyświetlamy jego na-zwę, cenę oraz opis.

Rysunek 1. Zakładanie konta PayPal

Listing 1. Plik config.php

<?php

// czas ważności ciasteczek sesji -

// 2 dni

define('EXPIRE_TIME',60*60*24*2);

// URL naszego sklepu

define('SITE_URL','http://

adres.naszego.sklepu.pl/');

// adres e-mail skojarzony z naszym

// kontem w PayPal

define('PayPal_MAIL','test@adres.

naszego.sklepu.pl');

// URL skryptu w witrynie PayPal

// odbierającego dane

define('PayPal_URL','https://

www.PayPal.com/cgi-bin/webscr');

?>

Rysunek 2. Schemat transakcji w sklepie internetowym za pośrednictwem PayPal

����������������� ������

��������������������

����������������������

������������������

�������������

������������������

�����������

����������

���������������������

��������������������

������

������������

���������

Page 56: PHP Solutions 06 2007 PL

Narzędzia

56 06/2007

Listing 2. Plik produkty.php

<?php

include('config.php');

// Zainicjowanie sesji:

session_set_cookie_params(EXPIRE_TIME);

session_cache_limiter('nocache');

session_start();

// Definiujemy produkty dostępne w sklepie:

// nazwa produktu

$products[0]['name']='Produkt1';

// cena produktu

$products[0]['price']=10.0;

// opis

$products[0]['desc']='Opis produktu nr 1';

$products[1]['name']='Produkt2';

$products[1]['price']=11.0;

$products[1]['desc']='Opis produktu nr 2';

$products[2]['name']='Produkt3';

$products[2]['price']=12.0;

$products[2]['desc']='Opis produktu nr 3';

$currency='PLN';

?>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"

"http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type"

content="text/html; charset=iso-8859-2">

<meta http-equiv="Content-Language" content="pl">

<meta http-equiv="pragma" content="no-cache">

<title>Przykładowy sklep internetowy</title>

<link rel="stylesheet" type="text/css"

href="phpsol.css">

</head>

<body>

<div align="center">

<table style="width: 660px" cellpadding="0" cellspacing="0">

<tr>

<td width="177">

<?php

// wyświetlenie koszyka

include('koszyk.php');

?>

</td>

<td width="483">

<div align="center">

<table style="width: 483px" cellpadding="0"

cellspacing="0">

<?php

// Wyświetlamy każdą pozycję w tablicy produktów:

foreach($products as $product) {

// formatujemy cenę: 2 miejsca dziesiętne i przecinek

// jako separator

$price=number_format($product['price'], 2, ',', '');

?>

<tr>

<td width="323">

<p class="produkt"><?=$product['name']?></p>

</td>

<td width="160">

<p class="cena"><?=$price?> <?=$currency?></p>

</td>

</tr>

<tr>

<td width="323">

<p class="opis"><?=$product['desc']?></p>

</td>

<td width="160">

<p class="kup">

<a href="addtobasket.php?product_name=

<?=$product['name']?>&amp;price=

<?=$product['price']?>&amp;currency=$currency">

<img border="0" src="index/phpsol_03.jpg"

width="98" height="26">

</a>

</p>

</td>

</tr>

<?php

}

?>

</table>

</div>

</td>

</tr>

</table>

</div>

</body>

</html>

<?php

include('config.php');

session_set_cookie_params(EXPIRE_TIME);

session_cache_limiter('nocache');

session_start();

// Sprawdzamy, czy wszystkie wymagane

// dane zostały podane:

if(isset($_GET['product_name']) && isset($_GET['price']) &&

isset($_GET['currency'])) {

$tmp['name']=$_GET['product_name'];

// Tworzymy tymczasową tablicę

$tmp['price']=$_GET['price'];

$_SESSION['customer_basket'][]=$tmp;

// i dodajemy ją do koszyka

$_SESSION['sum'] += $_GET['price'];

// aktualizujemy sumę cen produktów w koszyku

$_SESSION['currency']=$_GET['currency'];

// oraz walutę zakupów

}

// na koniec przekierowujemy do głównej

// strony sklepu:

header("Refresh: 0; url=produkty.php");

?>

Listing 3. Plik addtobasket.php

Page 57: PHP Solutions 06 2007 PL
Page 58: PHP Solutions 06 2007 PL

Narzędzia

58 06/2007

Przy każdym produkcie jest też guzik umożliwiający dodanie wybranego artyku-łu do koszyka. Skrypt wykonujący to zadanie zawarliśmy w pliku addtobasket.php przed-stawionym na Listingu 3. Tutaj na początku również inicjujemy sesję, by mieć dostęp do informacji o koszyku. Skrypt otrzymuje in-formację o wybranym produkcie za pomocą tablicy $_GET. W prawdziwym sklepie dane pobierane byłyby z bazy danych, a do skryp-tu przekazalibyśmy jedynie ID wybrane-go produktu. Jeśli wszystkie wymagane da-ne są zdefiniowane, to tworzymy tymczaso-wą tablicę zawierającą nazwę oraz cenę pro-duktu. Następnie dodajemy ją do tablicy $_SESSION[‘customer_basket’]. Dodatko-wo aktualizujemy sumę cen wszystkich pro-duktów w koszyku, dodając do niej cenę do-kładanego właśnie produktu oraz zapamiętu-jemy walutę w jakiej dokonywane są zakupy. Zakładamy przy tym, że wszystkie ceny pro-duktów wyrażone są w tej samej walucie, więc nie musimy ich przeliczać. Na koniec klient zostaje przekierowany z powrotem do

głównej strony, na której zobaczy dodany pro-dukt w koszyku.

Kiedy klient włożył już coś do koszyka, może złożyć zamówienie. W tym celu kli-ka na link prowadzący do skryptu order.php przedstawionego na Listingu 4. Skrypt wy-świetla formularz przedstawiający podsu-mowanie tego, co klient ma w koszyku, oraz umożliwia złożenie zamówienia. Dane z for-mularza są przesyłane do ostatniego skryptu PayPal.php, który przedstawiliśmy na Listin-gu 5. Skrypt jest spreparowany w ten sposób, że zawiera kolejny formularz, który ostatecz-nie jest odsyłany do witryny PayPal. Zawie-ra pola o nazwach zrozumiałych dla PayPal. W tym przykładzie zawarliśmy tylko nie-zbędne minimum zmiennych, które są wy-magane, aby poprawnie obsłużyć prostą transakcję. Użyte przez nas pola to:

• upload oraz cmd wymagane przez PayPal;• return zawierające adres, pod który zosta-

nie przekierowany klient po udanym pro-cesie płatności;

• cancel _ return podobnie jak poprzed-nie, ale wykorzystywane wtedy, gdy klient rozmyśli się i kliknie na stronie PayPal link „Back to Merchant”;

• shopping _ url ustawiamy na główną stronę naszego sklepu;

• business – tutaj podajemy adres e-mail skojarzony z naszym kontem w PayPal, na które chcemy dostawać wpłaty;

• item _ name _ 1 – za co jest płatność;• amount _ 1 – suma, którą należy nam prze-

lać;• currency _ code – kod waluty.

Formularz zostaje automatycznie wysłany do PayPal za pomocą JavaScriptu, więc na-wet nie wyświetli się w przeglądarce – użyt-kownik od razu jest przekierowany do witry-ny PayPal.

Konstrukcja oparta jest na dwóch formu-larzach: order.php oraz PayPal.php. Pierw-szy z nich jest podsumowaniem transakcji dla klienta i nie musi zawierać wszystkich wymaganych przez PayPal pól. Możemy go

Listing 4. Plik order.php

<?php

include('config.php');

session_set_cookie_params(EXPIRE_TIME);

session_cache_limiter('nocache');

session_start();

?>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"

"http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html;

charset=iso-8859-2">

<meta http-equiv="Content-Language" content="pl">

<meta http-equiv="pragma" content="no-cache">

<title>Przykładowy sklep internetowy</title>

<link rel="stylesheet" type="text/css" href="phpsol.css">

</head>

<body>

<div align="center">

<form action="PayPal.php" method="post">

<table style="width: 460px" cellpadding="0"

cellspacing="0">

<tr>

<td width="483">

<div align="center">

<h1>Składanie zamówienia</h1><br><br>

<table style="width: 483px" cellpadding="0"

cellspacing="0">

<?php

if(!isset($_SESSION['customer_basket'])) {

?>

<tr><td><p>Brak produktów w koszyku!</p></td></tr>

<?php

} else {

?>

<tr><td><b>Nazwa produktu</b></

td><td><b>Cena</b></td></tr>

<?php

foreach($_SESSION['customer_basket'] as $item) {

$price = number_format($item['price'], 2, ',', '');

?>

<tr>

<td><?=$item['name']?></td>

<td><?=$price?> <?=$_SESSION['currency']?></td>

</tr>

<?php

}

?>

<tr style="height: 15px;"><td colspan="2">&nbsp;</td></tr>

<tr>

<td><b>Suma</b></td>

<td><b><?=$_SESSION['sum']?> <?=$_SESSION['currency']?></

b></td>

</tr>

<tr style="height: 40px;"><td colspan="2">&nbsp;</td></tr>

<tr><td colspan="2" style="text-align: center;">

<input type="submit" name="go" value="Zamów"> płac±c przez

<img style="vertical-align: middle;" src="index/

PayPal.jpg"></td>

</tr>

<?php

}

?>

</table>

</div>

</td>

</tr>

</table>

</form>

</div>

</body>

</html>

Page 59: PHP Solutions 06 2007 PL

PayPal

59www.phpsolmag.org

dowolnie zmieniać i przerabiać. Drugi for-mularz, który stanowi interfejs do systemu PayPal, projektujemy raz. Po przetestowaniu oraz upewnieniu się, że wszystko działa jak należy nie musimy już nic w nim zmieniać. Takie oddzielenie warstwy prezentacyjnej od funkcjonalnej jest zazwyczaj bardzo wygod-ne, chociaż możliwe jest oczywiście upako-wanie wszystkiego na jednym formularzu – widocznego podsumowania dla klienta oraz ukrytych pól z informacją dla PayPal.

Po dokonaniu płatności użytkownik wraca na naszą stronę zdefiniowaną w polu return. Możemy na niej wyświetlić potwierdze-nie dokonania zakupu i wykonać niezbęd-ne czynności związane z finalizacją trans-akcji. Nie jest to jednak zalecane, ponieważ klient może dokonać płatności, ale nie klik-nąć w ostatni link przekierowujący go z po-wrotem do naszego sklepu. Jest to jednak je-dyny sposób, aby w pełni zautomatyzować proces płatności i zakupu. Dla bezpieczeń-stwa lepiej jest gdzieś zapamiętać (np. w ba-zie danych) informacje o transakcji jeszcze przed przekierowaniem klienta do witryny PayPal (np. w skrypcie PayPal.php) i potem w razie wątpliwości porównać te informacje z tymi, które otrzymamy od systemu PayPal e-mailem. Analogicznie na stronie zdefinio-wanej w polu cancel_return możemy wy-świetlić odpowiednią informację o anulowa-niu transakcji.

Dodatkowe możliwościW przyjętym przez nas najprostszym roz-wiązaniu wystawiamy łączny rachunek na wszystkie produkty z koszyka. Nic nie stoi jednak na przeszkodzie, aby każdy przed-miot wycenić oddzielnie. W tym celu nale-ży podać nazwy przedmiotów w kolejnych polach item_name_x oraz ich ceny w polach amount_x, gdzie za x wstawiamy kolejne licz-by. W ten sposób możemy przenieść cały ko-szyk do witryny PayPal.

Ceny możemy definiować w dowolnej walu-cie obsługiwanej przez PayPal. Służy do tego po-le currency_code, które w naszym przykładzie ustawiliśmy na złotówki. Jeśli nie dołączymy te-go pola, domyślnie transakcje są dokonywane w dolarach amerykańskich.

Jeśli znamy dane osobowe naszego klien-ta, możemy przesłać je również do PayPal. Jeśli nasz klient nie ma jeszcze konta w Pay-Pal, będzie musiał je sobie założyć. Przesy-łając jego dane, zaoszczędzamy mu ich po-nownego wpisywania. W tym celu na for-mularzu wysyłanym do PayPal definiujemy dodatkowe pola:

• first _ name – imię klienta;• last _ name – nazwisko klienta;• address1 – ulica;• address2 – dodatkowe pole z ulicą (opcjo-

nalnie);

Rysunek 3. Zakładanie konta testowego PayPal

Rysunek 4. Polska strona PayPal

Page 60: PHP Solutions 06 2007 PL

Narzędzia

60 06/2007

PayPal Developer Center. W sekcji „Test Acco-unts” możemy sobie założyć testowe konto. Ma ono funkcjonalność dokładnie taką samą jak prawdziwe konto w PayPal, ale operuje na fikcyjnych pieniądzach – możemy go uży-wać do testowania bez ograniczeń. Wszyst-kie e-maile, które normalnie PayPal wysyła na naszą skrzynkę (np. potwierdzenia wyko-nania transakcji), trafiają do sekcji „Test Ema-il”, gdzie mamy do nich wgląd. Klikając na link „Help” znajdujący się na samej górze wi-tryny po prawej stronie, mamy dostęp do bo-gatej dokumentacji samego API PayPal. Tutaj znajdziemy szczegółowy opis integracji stron internetowych z witryną PayPal, a w szcze-gólności dokładny opis wszystkich pól for-mularza, które możemy wykorzystać. Nie-stety, jak dotąd całość dokumentacji oraz wi-tryna developerska dostępne są jedynie w ję-zyku angielskim.

W jaki sposób możemy przeprowadzić te-sty? Wszystko sprowadza się do tego, żeby podmienić adres na który wysyłamy formu-larz do PayPal. Pokażmy to na naszym przy-kładzie. Odszukajmy w tym celu w pliku con-fig.php linijkę:

define('PayPal_URL','

https://www.PayPal.com/cgi-bin/webscr');

i podmieńmy ją na:

define('PayPal_URL','

https://www.sandbox.PayPal.com

/cgi-bin/webscr');

Od tej pory mimo że wszystko wygląda do-kładnie tak samo jak wcześniej, transakcje bę-dą wykonywane jedynie wirtualnie, a do tes-tów używamy konta testowego, które założy-liśmy sobie w zakładce „Test Accounts” w ser-wisie developerskim. Należy jednak pamię-tać, aby najpierw zalogować się do strony deve-loperskiej (np. w drugim oknie przeglądarki) – dopiero wtedy możemy korzystać z testo-wego adresu. Gdy upewnimy się, że wszystko działa jak należy, z powrotem ustawiamy wła-ściwy adres, na który będziemy wysyłać for-mularz do PayPal.

Listing 5. Plik PayPal.php

<?php

include('config.php');

session_set_cookie_params(EXPIRE_TIME);

session_cache_limiter('nocache');

session_start();

$total=number_format($_SESSION['sum'], 2, '.', '');

?>

<html>

<body>

<form name= "order" action="<?=PayPal_URL?>" method="post">

<input type="hidden" name="upload" value="1"><br>

<input type="hidden" name="cmd" value="_cart"><br>

<input type="hidden" name="return" value="<?=SITE_URL?>info_success.php"><br>

<input type="hidden" name="cancel_return" value="<?=SITE_URL?>info_cancel.php"><br>

<input type="hidden" name="shopping_url" value="<?=SITE_URL?>produkty.php"><br>

<input type="hidden" name="business" value="<?=PayPal_MAIL?>">

<input type="hidden" name="item_name_1" value="Zakupy w Testowym Sklepie">

<input type="hidden" name="amount_1" value="<?=$total?>"><br>

<input type="hidden" name="currency_code" value="<?=$_SESSION['currency']?>">

</form>

<script type="text/javascript" language="JavaScript">

document.order.submit();

</script>

</body>

</html>

W Sieci

• PayPal w Polsce http://www.PayPal.pl/• PayPal Developer Center https://developer.PayPal.com/

MARIUSZ WIELKOPOLSKIMARIUSZ TYTYKMariusz Wielkopolski, Mariusz Tytyk zajmują się two-

rzeniem stron www, na stałe związani z firmą redF5.

Kontakt z autorem: [email protected]

• city – miasto;• zip – kod pocztowy;• country – kod kraju klienta;• email – e-mail klienta.

To tylko najczęściej używane zmienne, pełny ich spis znajdziemy w dokumentacji dostępnej w PayPal Developer Center.

Kup teraz oraz DarowiznyJeśli chcielibyśmy na naszej stronie wysta-wić na sprzedaż pojedyncze produkty i nie martwić się o tworzenie koszyka, możemy dać użytkownikom możliwość zakupu jedne-go produktu naraz. Za pomocą PayPal jest to bajecznie proste. Aby tego dokonać logujemy się do swojego konta PayPal. Następnie prze-chodzimy do zakładki Narzędzia handlow-ców. Klikamy w link Przyciski Kup teraz znaj-dujący się w prawym menu. Teraz wypełnia-my formularz opisujący sprzedawany przez nas przedmiot. Podajemy jego nazwę, cenę oraz wybieramy walutę i język. Do wybo-ru mamy kilka wyglądów przycisku, może-my też skorzystać z własnego obrazka. Na ko-niec wybieramy, czy dane o sprzedawanym przedmiocie mają być przechowywane w po-staci zaszyfrowanej czy nie. Jeśli wybierzemy opcję zaszyfrowaną, to nie będzie można ich podejrzeć podglądając źródło strony, na któ-rej osadzimy za chwile nasz guzik. Teraz jed-nak wybierzmy opcję niezaszyfrowaną. Kli-kamy w przycisk Utwórz przycisk teraz. Do-stajemy gotowy kod, który wystarczy wkleić w wybranym miejscu na stronie.

Jeśli zrezygnowaliśmy z szyfrowania da-nych, to możemy łatwo zauważyć, że wyge-nerowany kod jest bardzo podobny do te-go, który obsługiwał nasz koszyk. W ten spo-sób, jeśli chcemy oferować więcej produktów z opcją Kup teraz, możemy bardzo łatwo sa-mi generować kod dla przycisków. Wystar-czy podstawić w nim nazwę aktualnego pro-duktu do pola item_name oraz cenę do pola amount.

Często możemy się spotkać ze strona-mi, na których autorzy proszą o wsparcie za pomocą dobrowolnej darowizny. Rów-nież za pomocą PayPal możemy w łatwy spo-sób zbierać darowizny. Wystarczy w narzę-dziach dla handlowców wybrać opcję Da-rowizny. Dalej postępujemy analogicznie, jak dla przycisku Kup teraz. Jedyna różnica polega na tym, że możemy podać konkret-ną kwotę, o którą prosimy albo nie podawać kwoty. Jeśli jej nie podamy, to każdy użyt-kownik będzie mógł nas wspomóc sumą ja-ką będzie uważał za słuszną.

TestowaniePayPal oferuje całkiem rozbudowane na-rzędzia wspomagające pracę przy budo-wie modułów z niego korzystających. Aby skorzystać z oferowanych możliwości, mu-simy założyć sobie konto developerskie. W tym celu wchodzimy na adres: https://developer.PayPal.com/ i klikamy w link „Sign Up Now”. Następnie wypełniamy formu-larz przedstawiony na Rysunku 3. Po zało-żeniu konta możemy się już zalogować do

Page 61: PHP Solutions 06 2007 PL
Page 62: PHP Solutions 06 2007 PL

Kasa dla webmastera

62 06/2007

SEO i SEM

63www.phpsolmag.org

Marketing internetowy jest formą kam-panii promocyjnej towarów i usług w sieci internetowej, docierającą za-

równo do obecnych, jak i przyszłych klientów. Wydatki na reklamę internetową rosną w szalo-nym tempie i największe są w Stanach Zjedno-czonych. W pierwszym kwartale tego roku wy-niosły 4,9 mld dolarów, co stanowi 26-procento-wy wzrost w sosunku do tego samego okresu w 2006 roku. W Polsce sytuacja wygląda jak na Ry-sunku 1., czyli widoczny jest znaczny wzrost wy-datków na reklamę internetową.

Dotychczas znaczącą rolę e-reklamy dostrze-gały większe firmy, które mogły pozwolić so-bie na przeprowadzenie odpowiednich badań. Obecnie na polskim rynku coraz więcej firm, zarówno małych, jak i średnich, zauważa rosną-cą rolę reklamy internetowej. Nasuwa się pyta-nie: dlaczego Internet jest idealnym

miejscem na naszą reklamę? W Polsce już 38% osób korzysta reguralnie z Internetu, a ko-lejne 30% deklaruje, że chciałoby posiadać sta-łe łącze. Jeżeli wzrost gospodarczy utrzyma się na obecnym poziomie, niedługo będziemy mo-gli pochwalić się – tak jak Anglicy – obecnością w interaktywnym świecie ponad 60% obywateli.

Taka sytuacja stwarza firmom olbrzymie możliowści promocji różnorodnych produk-tów. Kolejnym bardzo ważnym aspektem ro-li Internetu jest znacząca przewaga w badaniu zachowań klienta. Dzięki różnego rodzaju ogól-nodostępnym (bezpłatnym) statystykom może-my zbadać reakcje klienta na odpowiednie tre-ści. Statystyki pozwalają nam, jak w żadnych in-nych mediach, ocenić praktycznie w stu procen-tach popularność serwisu, ustalić czas, jaki osoba poświęciła na zapoznanie się ze stroną interneto-wą, dowiedzieć się, które podstrony odwiedziła

i ile czasu na nich spędziła. Ponadto przy kam-paniach e-mailowych firmy udostępniają nam już nawet dokładną statystykę przeczytanych wiadomości, rodzaje linków, które były wybra-ne przez odbiorców. Wszyscy na pewno zdają sobie sprawę z tego, jak duże pole manewru ma później firma posiadająca tego typu informacje o swoim kliencie. Można wyróżnić co najmniej kilka istotnych cech reklamy w Internecie:

• rosnąca liczba użytkowników,• teoretycznie nasza reklama może docierać

do klienta 24h na dobę;• nieograniczony zasięg;• możliwości analizy danych;• darmowe analizy statystyczne;• dowolne formy reklamy – od tekstowej po

film i dźwięk;• stosunkowo atrakcyjne ceny.

SEO (Search engine optimization)Search engine optimization, czyli optymaliza-cja kodu strony internetowej pod względem po-lepszenia jej pozycji w wyszukiwarkach. Każdy właściciel strony internetowej pragnie, by po wpisaniu określonych słów kluczowych w naj-popularniejszych wyszukiwarkach jego stro-na widniała w pierwszych wynikach. Działa-nia SEO pozwalają osiągnąć zaskakujące efek-ty i zdecydowanie mogą przynieść firmie du-że zyski. Wyobraźmy sobie, iż jesteśmy właści-cielami internetowego sklepu komputerowe-go. Każdy użytkownik np. wyszukiwarki Go-ogle, wpisując

„sklep komputerowy” jako pierwszą pozycję zauważy link i opis naszego sklepu. Jest to bar-dzo istotne, ponieważ przeciętny użytkownik nie przegląda wiecej niż pierwszych pięć, góra dziesięć linków. Łatwo teraz można wyciągnąć wnioski, że dobra pozycja wielokrotnie zwięk-sza nasze zyski.

Przeprowadzenie kampanii SEO jest to do-syć kosztowny i długoterminowy proces. Ce-ny ustalane są m.in w zależności od liczby słów

kluczowych oraz „trudności wypozycjonowa-nia na dane słowo kluczowe”. Istnieje jednak kil-ka sposobów, które umożliwią nam poprawie-nie swojej pozycji przy stosunkowo niedużym nakładzie czasu i kosztów. Na wstępie musimy zapoznać się z obowiązującą terminologią:

• Bot/Robot – mechanizm mający na ce-lu przeszukanie i zindeksowanie strony w celu określenia jej pozycji w wynikach wy-szukiwania;

• link – odnośnik do strony internetowej;• PR/PageRank – matematyczny algorytm

stworzony przez Google w celu określenia wartości strony internetowej;

• BL/Backlink/Link popularity/linki przy-chodzące – jak sama nazwa mówi, jest to liczba linków prowadząca do

• wybranej strony internetowej;• linki wychodzące – liczba linków prowa-

dząca do innej domeny niż twoja strona;• SERP (Search engine results position) –

wyniki wyszukiwania;• DC/DataCenter – nazwa określająca bazę

danych wyszukiwarki. Często zdarza się, że wyniki z DC różnią się od siebie;

• filtr – jest to mechanizm mający na celu ukaranie danej strony internetowej spad-kiem o kilkanaście pozycji w wyniku wy-korzystywania nieetycznych technik po-zycjonowania;

• ban – wyrzucenie strony internetowej z bazy danych danej wyszukiwarki z po-wodu np. spamowania;

• spam – technika mająca na celu „sztucz-ne” podwyższenie pozycji danej strony in-ternetowej;

• sitemap/mapa strony – specjalnie sprepa-rowana podstrona umożliwiająca lepszą i szybszą indeksację strony internetowej;

• content – tekst na stronie internetowej;• zaplecze – rożnego rodzaju strony, z któ-

rych pozycjonerzy linkują w celu polep-szenia ich pozycji;

SEO i SEM

W artykule zostały poruszone podstawowe aspekty związane z przeprowadzeniem kampanii marketingowej pod kątem działań SEO i SEM dla małych i średnich firm.

Poziom trudności

Kampania dla małych i średnich firm

Page 63: PHP Solutions 06 2007 PL

Kasa dla webmastera

62 06/2007

SEO i SEM

63www.phpsolmag.org

• AT/Anchor Text – tekst, pod którym wy-stępuje link <a href =”link”>Anchor</a>;

• keywords – wyrazy, po których będziemy wyszukiwani w wyszukiwarkach.

Podstawową rzeczą, którą powinniśmy przy-gotować, jest odpowiedni i unikatowy con-tent. Musi on zawierać stosunkowo dużą licz-bę słów kluczowych, przy czym w żaden spo-sób nie powienien odchodzić od tematyki strony. Nastepnie należy wybrać odpowied-nie słowa kluczowe, które są bardzo istotne. Pomoże nam w tym np. zbadanie słów kluczo-wych u lepiej wypozycjonowanej konkurencji. Jest to jednak dopiero wierzchołek góry lodo-wej, ponieważ nawet takie same słowa nie da-dzą nam choćby porównywalnej pozycji. Na-rzędzia, które nam w tym pomogą, są m.in.

• http://inventory.overture.com/d/searchinventory/suggestion/,

• https://adwords.google.pl/select/Keyword-ToolExternal,

na podstawie ceny i proponowanej pozycji możemy wyciągnąć wnioski, które słowa są najlepsze, http://freekeywords.wordtracker.com/.Po odpowiednim wyborze słów kluczowych nie możemy zapomnieć o dodaniu ich do tzw. meta tagów, czyli:

<meta name="keywords"content="slowa

kluczowe”/>.

Następnie powinniśmy przygotować opis stro-ny, który będzie widoczny w wyszukiwarkach. Jest to tzw. description i powinien zawierać jak najwięcej popularnych słów kluczowych, przy czym nie może on skłądać się wyłącznie z tych fraz. Tekst w tym polu będzie widoczny w wy-szukiwarkach, dlatego istotne jest, żeby je-go treść była stosunkowo unikatowa, czytel-na i zawierała najistotniejsze informacje, czy-li przeważnie słowa kluczowe. Prawidłowo po-winno to wyglądać tak:

<meta name="description" content="opis”/>.

Taki opis możemy wykorzystać również w polu:

<title>tytuł</title>

bądź stworzyć oddzielny. Kolejnym zadaniem, które powinniśmy wykonać, jest sprawdzenie poprawności kodu ze standardami W3C. Do-kładny opis i narzędzie możemy znaleźć na: http://validator.w3.org/. Jest to bardzo ważny krok, ponieważ przy indeksacji wpływa na po-prawne zbadanie i zapis contentu.

Przy pierwszym dodaniu strony interneto-wej do wyszukiwarek można się spotkać z dłu-gim czasem jej zindeksowania bądź boty w ogó-le mogą jej nie indeksować. Jedną z metod na za-radzenie temu jest stworzenie sitemap i doda-

nie go do kodu strony, a następnie – jak to ma na przykład miejsce w przypadku Google – do-danie do Google's Webmaster Tools. Bardzo przydatne jest również dolinkowanie do strony z innych serwisów. Sitemap również wpływa na lepszą ocenę przez boty, ponieważ w pewnym stopniu ułatawia im indeksację contentu.

Kolejnymi dwoma krokami powinno być do-stosowanie pliku robots.txt oraz mod_rewrite. Plik robots jest jednym z pierwszych plików, któ-re są sprawdzane przez robota podczas indeksacji.W nim ustala się, które części serwisu mają być

dodane, a których bot ma nie sprawdzać i nie za-pisywać. Przykładowe ustawienie widoczne jest na Rysunku 3.

Po stworzeniu pliku robots.txt i zapisaniu w nim odpowiednich informacji przenosimy go do katalogu głównego na serwerze, na którym jest nasza strona internetowa. Mod_rewrite jest to jeden z modułów serwera Apache służący do nadpisywania adresów URL (tworzenia przyja-znych adresów). W celu edycji przechodzimy do katalogu głównego serwera i wyszukujemy plik htaccess. Na początku zapisujemy „Rewri-

Rysunek 1. Dane o rozwoju rynku reklamy internetowej w Polsce i Europie Zachodniej (www.bankier.pl)

Rysunek 2. Narzędzie Google do zarządzania słowami kluczowymi

Page 64: PHP Solutions 06 2007 PL

Kasa dla webmastera

64 06/2007

SEO i SEM

65www.phpsolmag.org

teEngine on”, po czym poniżej ustawiamy od-powiednie reguły. W kolejnej linijce ustalamy dyrektywę:

RewriteRule marketing\.html$ seo.html

i robimy [Enter] w celu pozostawienia jednej wolnej linii (trzeba pamiętać o pozostawieniu jednej wolnej linii). Analizując nasz przykład, możemy powiedzieć, że podczas uruchamia-nia adresu URL mod będzie wyszukiwać adre-su marketing.html, który zostanie wymieniony na seo.html. Dokładny opis tworzenia reguł do-stępny jest pod adresem: http://httpd.apache.org/docs/1.3/mod/mod_rewrite.html.

Kolejną metodą polepszenia swojej pozycji w wynikach wyszukiwania jest systematyczne do-linkowanie do strony. Możemy to zrobić, doda-jąc naszą stronę do różnego rodzaju katalogów internetowych (najlepiej z jak najwiekszym PR), WordPressów, blogów itp. Przy stosowa-niu tej metody musimy pamiętać o kilku waż-nych sprawach. Po pierwsze, przy wyborze ka-talogu powinniśmy zwrócić uwagę na jego PR (im większy, tym lepiej), przy pisaniu tekstu, np. do WordPressu, powinniśmy utrzymywać całość treści w tematyce strony oraz przy two-rzonych linkach odpowiednio dobierać tekst do anchor textów. Linkami o wysokiej „jakości” są linki ze stron o podobnej

tematyce co strona, którą staramy się wypo-zycjonować. Z tą techniką wiążę się kilka nie-bezpieczeństw. Przy nieodpowiedzialnym lin-kowaniu, czyli np. dopisywaniu do kilkuset ka-talogów mniej więcej w tym samym czasie, mo-żemy zostać sfiltrowani przez Google i tymcza-sowo całkowicie zablokowani. Musimy również pamiętać, że dolinkowanie z 10 stron z PR 5 jest lepsze niż z 50 z PR 1. Najważniejszym minu-sem w kampanii SEO jest długi okres oczeki-wania na efekty. Często może być to nawet kil-ka miesięcy. Również w sytuacji, gdy nie mamy dość czasu oraz wiedzy, kampania SEO może być kosztowna, szególnie na popularne frazy.

SEM (Search engine marketing)Search engine marketing są to działania marke-tingowe związane z wyszukiwarką oraz możli-wościami reklamowymi, które są przez nią ofe-rowane. Głównymi różnicami pomiędzy SEO i SEM jest czas, po jakim widoczne są efekty, oraz koszty. Wyszukiwarka w tym przypad-ku jest również miejscem komunikacji z klien-

tem, aczkolwiek w odmienny sposób. Kampa-nia SEM obejmuje wykupienie różnego rodza-ju linków sponsorowanych oraz reklam teksto-wych, które przy wyszukiwaniu na określone słowa kluczowe występują na pierwszych miej-scach w wynikach wyszukiwania.

Możliwości SEMDziałania SEM dają nam o wiele więcej moż-liwości dotarcia do klienta niż SEO. Wyszuki-warki udostępniają nam narzędzia, dzięki któ-

rym możemy na przykład skierować naszą re-klamę wyłącznie w określone województwo, czyli w sytuacji, gdy firma oferuje swoje pro-dukty na terenie województwa warmińsko-ma-zurskiego i korzysta z linków sponsorowanych, jej oferta będzie widoczna dla użytkowników z terenu Warmii i Mazur. Ponadto linki sponso-rowane są doskonałą metodą na promocję pro-duktu bądź na działania związane z promocją sezonową. Reklamodawca decyduje o kosztach i ma możliwość sterowania dziennym budże-

Rysunek 5. Wyniki wyszukiwania firm pod frazą „budownictwo”, posiadające nazwę w ofercie w www.pf.pl

Rysunek 4. Przykład linków sponsorowanych w przypadku wyszukiwarki Google

Rysunek 3. Przykładowe ustawienie pliku .htaccess

Page 65: PHP Solutions 06 2007 PL

Kasa dla webmastera

64 06/2007

SEO i SEM

65www.phpsolmag.org

tem. Czasem osiągnięcie wysokich pozycji przy pozycjonowaniu dla bardzo obleganych słów kluczowych jest właściwie niemożliwe bądź koszty mogą przerosnąć zyski. Alternatywą jest zastosowanie sponsorowanych linków.

Yellow PagesJedną z płatnych opcji promocji w Internecie są reklamy Yellow Pages. Przykładową witryną te-go typu jest http://www.yellowpages.pl/, czy http://www.pf.pl. Jest to baza firm, w której za od-powiednią opłatą możemy umieścić swoją re-klamę, ofertę i wizytówkę oraz wykupić linki sponsorowane czy baner reklamowy. Mogłoby się wydawać, że tego typu rozwiązania są już stosunkowo przestarzałe, ale wciąż dla wielu osób stanowią główne miejsce wyszukiwania konkretnych produktów i usług. Jest co naj-mniej kilka aspektów, które przemawiają za

skorzystaniem z Yellow Pages przy prowa-dzeniu kampanii SEM. Tego typu katalogi firm udostępniają dużo łatwiejszą metodę po-szukiwania określonych produktów lub usług na terenie lokalnym. Oferty są posegregowane i przejrzyste. Ponadto serwisy YP prowadzą wła-sną polityke promocji co dodatkowo zwiększa popularność i prawdopodobieństwo odnalezie-nia naszej oferty.

Linki SponsorowaneKolejną popularną metodą wykorzystywaną przy kampaniach SEM są linki i teksty spon-sorowane w najpopularniejszych wyszukiwar-kach. Najlepszym przykładem są usługi Ad-words świadczone przez Gooogle. Jest to praw-dopodobnie najpopularniejszaa i najczęściej wy-korzystywana metoda. Największym jej plusem jest to, że reklamodawca może kontrolować wszelkie koszty, a opłaty naliczane są w syste-mie CPC, czyli od kliknięcia na

link sponsorowany. Ponadto firma Google oferuje niezwykle rozbudowane narzędzie marketingowe. Możemy wybrać bardzo dużą liczbę słów kluczowych, przeprowadzić od-powiednie statystyki pokazujące nam cenny, a tym samym popularność różnego rodzaju key-wordsów (https://adwords.google.pl/select/Keyword-ToolExternal). Bardzo dobrym narzędziem, szczególnie dla średnich firm oferujących swo-je produkty w regionie, są ustawienia określa-jące teren występowania linku sponsorowane-go, czyli linków sponsorowanych dla użytkow-ników z określonego regionu. Link sponsoro-wany składa się z:

• nagłówka, który może liczyć do 25 zna-ków;

• tekstu reklamy – dwie linijki po 35 zna-ków (może występować tylko jeden wy-krzyknik);

• adresu strony internetowej – 35 znaków (podczas tworzenia reklamy do 1024).

Algorytm wyznaczający ceny w systemie Ad-words jest bardzo skomplikwany. Czynnikami wpływającymi na ceny są m.in.:

• popularność słów kluczowych;• częstotliwość odwiedzin reklamy pod da-

nymi słowami kluczowymi;• to, czy w tekście reklamy pojawiają się sło-

wa kluczowe.

Przy zdecydowaniu się na wybór linków spon-sorowanych powinniśmy dużo uwagi poświę-cić wyborowi słów kluczowych i tekstu rekla-my. Są to bardzo ważne czynniki wpływają-ce na trafność promocji. Przy komponowaniu i zbiorze potrzebnych informacji powinniśmy zbadać, w jaki sposób robi to konkurencja. Po-zwoli nam to wybrać optymalne rozwiązania i zaoszczędzić dużo czasu i najprawdopodob-niej pieniędzy. Powinniśmy również zapoznać się z różnego rodzaju narzędziami, które udo-stępniane są, jeśli zdecydujemy się na tego ty-pu usługi. Są to rozmaite analizatory, które po-mogą dostosować wybór słów kluczowych do naszych potrzeb i zwiększyć nasze szanse na sukces. Najwiekszym minusem linków sponso-rowanych jest to, że ich odwiedzalność jest du-żo mniejsza niż wypozycjonowanych linków „statycznych”. Użytkownicy większość swo-jej uwagi poświecają na wyniki wyszukiwarek, a nie na pojawiającą się reklamę.

W artykule poruszony jest przykład linków sponsorowanych w przypadku Google, ponie-waż jest to obecnie najbardziej popularna wy-szukiwarka w Polsce. Takie usługi świadczo-ne są również przez inne wyszukiwarki na ca-łym świecie.

PodsumowanieW artykule poruszyliśmy podstawowe metody działań SEO i SEM. Jest oczywiście wiele więcej możliwości wypromowania swojej firmy, produk-tów czy usług, jak chociażby kampania e-mailowa czy banerowa. Trudno jest określić jednoznacz-nie, która metoda jest bardziej opłacalna. Gdy ktoś chce szybko wypromować nowy produkt, na pew-no wybierze zastosowania SEM, natomiast osią-gnięcie dobrej pozycji, a tym samym stworzenie otoczki profesjonalizmu wokół firmy (szczególnie firm internetowych) wymaga działań SEO.

Rysunek 6. Przykładowy link sponsorowany w wyszukiwarce Google

PIOTR KENIGPiotr Kenig zawodowo zajmującesie projektowaniem i tworzeniem stron internetowych. W wolnych chwi-lach stale rozwija swoją wiedzę z zakresu programo-wania i marketingu internetowego.Kontakt z autorem: [email protected]

W Sieci:

• http://forum.optymalizacja.com/• http://www.google.com/support/webmasters/• http://katalog.onet.pl/pomoc/index.html• http://www.highrankings.com/forum/• http://searchenginewatch.com/• http://www.netsprint.pl/serwis/faq/

Page 66: PHP Solutions 06 2007 PL

Artykuł warsztatowy

66 06/2007

Delphi for PHP

67www.phpsolmag.org

Odkąd na rynku oprogramowania po-jawiło się pierwsze narzędzie RAD dla PHP, o nazwie Delphi for PHP,

w umysłach wielu osób pojawiły się pytania. Zaczęto dyskutować nad przydatnością tego typu narzędzi.

Jednak wiele osób wypowiadających się w dys-kusji, nie miało styczności z tym oprogramowa-niem i wypowiadało własne opinie w oparciu o ogólnie znane wszystkim stereotypy. Związa-ne były one bardziej z edytorami WYSWIG dla HTML w serii artykułów poświeconych opro-gramowaniu Delphi for PHP stworzonego i roz-prowadzanego przez firmę CodeGear.

Poznajmy VCLPrzed rozpoczęciem pracy z tym oprogramo-waniem musimy zadać sobie proste pytanie. Jak to w ogóle działa? Otóż trzonem całego oprogramowania jest biblioteka VCL. Biblio-teka ta jest tak naprawdę freamworkiem, za-wierającym wiele gotowych komponentów, z których możemy zbudować aplikację. W bi-bliotece VCL mamy wbudowane inne mniej-sze biblioteki wspomagające tworzenie opro-gramowania np. NuSoap , qooxdoo , Smarty czy xajax. Jak widzimy przekrój jest całkiem spory, ponieważ mamy wbudowany system szablonów, jak i biblioteki wspomagające ob-sługę ajax, czy też java script. Budowa VCL przyjmuje strukturę drzewiastą, co oznacza, że każdy element jest gałęzią lub liściem po-przedniego. Dzięki temu łatwiej jest zorien-tować się w możliwościach biblioteki. Syste-matyka ta ułatwia również naukę osobom, które nie miały z tym wcześniej styczności, a dla osób, które wcześniej miały okazję po-znać VCL w Delphi lub C++ Builderze, bę-dzie niezwykle przejrzysta. Należy zaznaczyć, że całe VCL jest projektem open sourcowym i na dodatek każdy z nas może wziąć udział w procesie jego tworzenia. Delphi for PHP mo-żemy poznawać z trzech różnych stron. Pierw-sza i podstawowa, to jako zwykły użytkownik,

który korzysta z programu i z dostępnych kom-ponentów. Drugą stroną jest rozwijanie możli-wości Delphi for PHP poprzez tworzenie no-wych komponentów do tej aplikacji. Trzecią i zarazem najbardziej zaawansowaną możli-wością jest rozwijanie biblioteki VCL. Każ-da chętna osoba może wziąć udział w popra-wianiu błędów, jak i tworzeniu nowych roz-wiązań. Podział na te trzy grupy użytkowni-ków można zaobserwować również na stro-nie projektu, gdzie każda z grup ma oddziel-ne strony Wiki.

W pracy z Delphi for PHP również możemy wyróżnić trzy różne podejścia. Możemy wyko-rzystywać je jako zwykły edytor PHP i tworzyć kod w sposób identyczny jak poprzednio. Mo-żemy również wykorzystać mix możliwości PHP oraz VCL. Ostatnim sposobem jest two-rzenie aplikacji przy wykorzystaniu wszystkich możliwości środowiska Delphi for PHP.

Ponieważ Delphi for PHP jest stosunkowo nowym projektem, nie ma do niego jeszcze wielu wyspecjalizowanych komponentów, jak to jest w Delphi Builderze, jednak z czasem z pewnością się one pojawią. Należy odnotować fakt, iż w przypadku Delphi oraz C++ istnie-ją firmy, które rozpowszechniają już wyspecja-lizowane komponenty i zarabiają na tym. Ta-ki rynek, w przypadku Delphi for PHP jeszcze nie istnieje, ale możemy być pewni, że to tylko kwestia czasu. Przed rozpoczęciem pracy z tym oprogramowaniem, warto uaktualnić naszą bibliotekę VCL. Aktualizacja taka przebiega w bardzo prosty sposób. Wystarczy tylko po-brać bibliotekę ze strony projektu, a następ-nie zastąpić nią stare pliki w folderze Delphi for PHP. Po tej czynności możemy przystąpić już do pracy.

ZaczynamyPierwsze uruchomienie aplikacji, może zszo-kować osoby nieprzyzwyczajone do środowisk typu IDE. Jednak po przeczytaniu poniższego opisu, każdy powinien poczuć się jak w domu.

Wygląd interfejsu użytkownika widoczny jest na [Rysunku 1].

Po lewej stronie formy mamy dostępny Code-Explorer, w którym możemy podejrzeć z czego składa się nasza forma. Zaraz pod nim, widzimy ObjectInsepctor’a, w którym widzimy wszystkie możliwe opcje konfiguracji, dotyczące zaznaczo-nego elementu lub formy oraz możliwe do ob-służenia akcje związane z obiektem. Natomiast po prawej stronie formy widzimy DataExplo-rer’a, w którym reprezentowane są informacje o obsługiwanych w tym momencie bazach danych. W naszym przypadku są to MySQL oraz InterBa-se. Pod DataExplorer–em umiejscowiona jest To-olPallete, w której mamy listę dostępnych do wy-korzystania komponentów, które możemy umie-ścić na formie. Po krótkim zapoznaniu się ze środo-wiskiem, powinniśmy pamiętać o ustawieniu ko-dowania programu, aby uniknąć później nieprzy-jemnych niespodzianek w postaci bliżej nieokre-ślonych krzaków zamiast polskich liter. Czynimy to poprzez opcje w menu Tools–>Options–>Edi-tor Options, gdzie musimy zaznaczyć Use UTF–8 to create new units and forms. Drugą rzeczą, o której warto pamiętać, jest zmiana kodowania w ObjectInspector–>Encoding z domyślnie ustawio-nej Western European (ISO)|iso–8859–1 na Unico-de (UTF–8)|utf–8. Po wykonaniu tych czynności możemy przejść dalej.

Naszym celem będzie stworzenie prostej stro-ny, którą w następnych artykułach z serii, będzie-my rozwijać o nowe możliwości. Ponieważ nie ma-my jeszcze doświadczenia w wykorzystaniu tego środowiska, zaczniemy od bardzo prostego projek-tu. Będzie to strona zawierająca księgę gości. Przy tworzeniu tej strony dodatkowo wykorzystamy możliwości Smarty, więc znajomość tego systemu szablonów okaże się niezwykle pomocna. Jednak zanim zaczniemy korzystać z oprogramowania, warto jest je przystosować do własnych potrzeb.

Tworzymy statyczną stronęPrzed rozpoczęciem pracy z Delphi for PHP, stwo-rzymy nasz szablon, z którego będziemy korzystać

Delphi for PHP

Prezentujemy pierwszy z trzech artykułów warsztatowych opisujący praktyczne zastosowanie programu Delphi For PHP. Lektura tych artykułów pomoże wam w wykonaniu własnej aplikacji i zdobyciu rewelacyjnych nagród w ogłoszonym konkursie.

Page 67: PHP Solutions 06 2007 PL

Artykuł warsztatowy

66 06/2007

Delphi for PHP

67www.phpsolmag.org

podczas tworzenia strony. Każdy szablon Smarty, aby móc współpracować z naszym oprogramowa-niem, musi zawierać w sobie określone zmienne. Najprostszy działający szablon, który nie jest opa-trzony żadną grafiką, ale będzie działać, ma postać widoczną na listingu 1.

Podane na nim zmienne Smarty są niezbęd-ne do działania. W analogiczny sposób będzie-my dołączać do szablonu niezbędne kompo-nenty Delphi for PHP, ale o tym później. Po ustaleniu podstaw związanych ze Smarty, mo-żemy przejść do połączenia obu systemów i pierwszego wyświetlenia strony.

Każdy projekt rozpoczynamy zawsze w ten sam sposób, tzn. poprzez kliknięcie w menu File–>New–>Application. W efekcie otrzymujemy projekt z pierwszą formą, na której umieszczać będziemy komponenty wykorzystane w naszej aplikacji. Dobrym nawykiem, przed rozpoczęciempracy z nowym projektem, jest zapisanie go po-przez File–>Save Project As. Zapis w tym przy-padku będzie dotyczyć dwóch plików. Pierw-szym plikiem będzie plik o rozszerzeniu php, który nazwiemy index.php i zapiszemy w specjal-nie utworzonym przez nas katalogu o nazwie we-bpage. Drugim plikiem będzie plik projektu, któ-ry nazwiemy webpage.phprj . Następnie musi-my zmienić jeszcze nazwę formy w ObjectInspec-tor–>name na wartość index. Po wykonaniu tych czynności możemy przejść do tworzenia naszej aplikacji. Założymy, że pierwsza strona ma za-wierać jedynie treść statyczną, bez generowanej poprzez PHP treści dynamicznej. Będziemy mu-sieli skorzystać w tym celu, z wcześniej przygoto-wanego szablonu, który dołączony jest na płycie. Aby, zachować pewien porządek utworzymy od-powiednią strukturę katalogów. W folderze we-bpage, utworzymy folder template, który będzie przechowywać nasze szablony oraz ich arkusze stylów i grafiki.

Mamy już wszystkie potrzebne części dla naszej strony. Czas więc złożyć stronę główną w całość.

Klikamy w formę, a następnie w ObjectInspec-tor–>TemplateEngine, wybieramy z dostępnych opcji interesujący nas szablon. W tym wypadku jest to jedyny domyślnie dostępny szablon, czy-li Smarty. Jednak w przyszłości pojawią się kolej-ne. Następnie musimy wskazać szablon, który zo-stanie połączony z naszą stroną. Aby to zrobić wy-bieramy ObjectInspector–>TemplateFilename, gdzie wskazujemy nasz szablon index.tpl, znajdujący się w folderze template. Ostatnim krokiem, który dzieli nas od zobaczenia wyniku naszej pracy jest po prostu wciśnięcie opcji w menu Run–>Run lub po prostu [F9], w efekcie czego zobaczymy na-szą piękna stronę widoczną na rysunku 2, na któ-rej wykonanie nie poświeciliśmy nawet pięciu mi-nut. Każdy, kto miał wcześniej styczność ze Smar-ty wie, że pierwsze uruchomienie Smarty może nie jednemu sprawić problem, jednak w przypad-ku Delphi for PHP obsługa staje się bardzo prosta i intuicyjna.

Tworzymy stronę dynamicznąPo nacieszeniu oka naszą pierwszą stroną, nad-szedł czas na kolejny krok. Przydałoby się, aby strona wykorzystywała możliwości PHP. Stwo-rzymy więc podstronę zawierającą bardzo prostą księgę gości. Tworzymy nową formę poprzez File–>New–>Form i zapisujemy ją jako guestbook.php, a następnie zmieniamy w ObjectInspector–>name na wartość guestbook. W tym przypadku zaczniemy od zdecydowania, jakie komponenty będą nam potrzebne, a następnie umieścimy je na formie. Po tych czynnościach utworzymy nasz sza-blon oraz wyświetlimy stronę z księgą gości i doko-namy pierwszego wpisu.

Każda typowa strona księgi gości zawiera for-mularz, poprzez który dodajemy wpisy oraz wyświetla wcześniejsze posty, odczytując je

z bazy danych. Na początek umieścimy na na-szej formie trzy komponenty Edit. Uczynimy to przeciągając komponent Edit z Tool Pallete bezpośrednio na formę lub poprzez podwój-ne kliknięcie. Umieszczenie ich na formie nie ma żadnego znaczenia, ponieważ będziemy i tak korzystać ze specjalnie przygotowanego szablonu. Rozmiar każdego z komponentów możemy dowolnie modyfikować poprzez roz-ciągania przy pomocy myszki lub kliknięcie w komponent znajdujący się na formie i wpro-wadzanie wartości w ObjectInsepctor–>Width lub Height. Każdy z wprowadzonych przez nas komponentów Edit ma przydzieloną dynamicz-nie nazwę, widoczną w ObjectInspector–>name. W naszym przypadku będzie to Edit1, Edit2, Edit3. Korzystanie z takiego nazewnictwa mo-że być niewygodne. Dlatego zmienimy je edy-tując pole ObjectInspector–>name na następują-ce title, author, content. Nazwy te są zdecydowa-nie łatwiejsze do zapamiętania oraz wykorzy-stania. Do zatwierdzenia formularza potrzebny będzie nam również jakiś przycisk. Umieści-my jeden komponent Button. W jego przypad-ku nie będziemy zmieniać parametru name a zmienimy parametr Caption dostępny w Ob-jectInspector–>Caption, w którym zmieniając

Rysunek 1. Interfejs użytkownika Delphi for PHP

Rysunek 2. Nasza pierwsza strona

Rysunek 3. Komponenty wchodzące w skład księgi gości

Rysunek 4. Prosta księga gości

Page 68: PHP Solutions 06 2007 PL

Artykuł warsztatowy

68 06/2007

Delphi for PHP

69www.phpsolmag.org

Listing 1. Najprostsza konstrukcja szablonu Smarty współpracująca z Delphi for PHP

<html>

<head>

<meta http-equiv="content-type" content="text/html; charset=utf-8" />

<title></title>

<meta name="keywords" content="" />

<meta name="description" content="" />

{HeaderCode}

</head>

<body>

{$StartForm}

{$EndForm}

</body>

</html>

Listing 2. Umieszczanie komponentów z Delphi for PHP w szablonie Smarty

<form action="" method="post">

Tytuł<br/>

{$title}<br/>

Autor:<br/>

{$author}<br/>

Wpis:<br/>

{$content}<br/>

{$Button1}<br/>

</form>

Listing 3. Zapytanie tworzące tabele z wpisami gości naszej strony

create table `guestbook`(

`id` int unsigned not null auto_increment primary key,

`title` char(255) not null,

`author` char(255) not null,

`content` text not null,

`date` datetime not null

);

sób możemy umieszczać wszystkie inne kompo-nenty dostępne w Tool Palette.

Mamy już formularz, ale nie wiemy co sta-nie się po naciśnięciu przycisku wyślij. W tym momencie, wykorzystamy kolejne usprawnie-nie Delphi for PHP. Oprogramujemy zdarzenie OnClick dla przycisku. Możemy to zrobić rów-nież na dwa sposoby. Pierwszym jest wybranie w ObjectInspektorze zakładki Events a tam nasze-go zdarzenia. Drugim i znacznie szybszym spo-sobem osiągnięcia tego samego celu jest po pro-stu podwójne kliknięcie na przycisk umieszczo-ny na formie. Po wykonaniu, jednej z wyżej omó-wionych akcji, zostaniemy przeniesieni do dru-giego widoku naszej formy. Tym razem operuje-my naszą formą od strony kodu. Możemy prze-mieszczać się pomiędzy obydwoma widokami, poprzez zakładki widoczne u dołu strony o na-zwach Code oraz Design lub przy pomocy klawi-sza [F12]. W widoku kodu możemy rozpocząć edycję zdarzenia. W tym przypadku została wy-generowana metoda o nazwie Button1Click, we wnętrzu której definiujemy naszą akcję. Pożąda-ną akcją, po naciśnięciu przycisku, będzie u nas zapis do bazy danych wartości przekazanych po-przez formularz. Tabelę, w której będziemy gro-madzić wpisy gości, należy utworzyć przy po-mocy zapytania widocznego na [Listingu 3].

Gdy dysponujemy już taką tabelą, możemy przejść do zapisu otrzymanych ze strony da-nych. Delphi for PHP do komunikacji z bazą danych korzysta z ADO, dzięki czemu zacho-wując odrobinę samodyscypliny przy tworze-niu zapytań do bazy danych, możemy sprawić, że nasza aplikacja będzie działać zarówno pod MySQL jak i np. Oracle jedynie po zmianie ste-rownika. Realizacja zapisu do bazy danych jest widoczna na [listingu 4]. Po zapisie do bazy da-nych należy również wyczyścić wartość pól tek-stowych, co robimy przy pomocy metody set-Text(), dla której przekazujemy puste stringi. – (czy na pewno stringi)?

Jak łatwo zauważyć, stworzony kod jest zwy-kłym kodem PHP, a co za tym idzie, nie musi-my uczyć się jakiegoś nowego języka, aby móc korzystać z tego oprogramowania. W reakcji na wciśnięcie przycisku, co równoznaczne jest za-akceptowaniu formularza, przygotowujemy za-pytanie SQL. Zabezpieczamy zmienne przeka-zane w tablicy $_POST, a następnie zapisujemy je do bazy danych. Za komunikację z bazą da-nych odpowiada egzemplarz ADO o nazwie $dbdelphi4php1 i to właśnie za jego pośrednic-twem musimy wykonywać wszystkie interak-cje. Kod jest bardzo prosty, a napisanie go rów-nież nie zabrało nam dużo czasu.

Mamy już zapis do bazy danych. Nadszedł czas na wyświetlenie wpisów zgromadzonych w bazie na naszej stronie. Aby wyświetlić jakieś dane pobrane z tablicy, będziemy musieli sko-rzystać ze specjalnego zdarzenia OnTemplate, utworzonego w celu współpracy z szablonami. Zdarzenie to jest dostępne jedynie dla formy. Znajdziemy je w ObjectInspectorze w zakładce

wartość zmieniamy napis widoczny na przyci-sku. Zmienimy w ten sposób domyślny napis Button1 na Wyślij. Mamy już umieszczone na formie komponenty związane z formularzem. Pozostał nam jeszcze do umieszczenia najważ-niejszy komponent, związany z połączeniem do bazy danych. W naszym przypadku będziemy zainteresowani komponentami związanymi z ba-zą danych MySQL. Odpowiedni komponent mo-żemy umieścić na formie na dwa sposoby. Pierw-szym z nich jest przeciągnięcie komponentu z Tool Palette o nazwie Database, którego parametry po-łączenia konfigurujemy następnie za pomocą Ob-jectInspector’a, wprowadzając zgodne z konkret-nym przypadkiem wartości DatabaseName, Host, UserName, UserPassword oraz zmieniając wartość Connected na true. Po wykonaniu tych czynności będziemy mieć dostępne połączenie z bazą da-nych. Możemy ten sam cel osiągnąć w inny dużo bardziej przyjazny sposób. Do tego celu będziemy musieli wykorzystać DataExplorer, w którym zde-finiujemy połączenie z bazą danych MySQL. Czy-nimy to poprzez kliknięcie na ikonę delfina przy napisie MySQL prawym przyciskiem myszy i wy-branie z podręcznego menu opcji Register Databa-se. My, jako nazwę połączenia podamy delphi4php. W efekcie tego działania otrzymujemy okienko, w

którym wypełniamy niezbędne dane. Po zaakcep-towaniu formularza na liście DataExplorer’a poja-wi się nasze połączenie. Teraz, aby wykorzystać je do ustanowienia połączenia z bazą danych wystar-czy, że przeciągniemy nasz element z listy na for-mę, w efekcie czego otrzymamy już skonfigurowa-ny komponent Database. Omówione wyżej dzia-łanie zaoszczędzi nam pracy przy każdorazowym konfigurowaniu połączenia, na każdej nowej for-mie. Umieszczając ten komponent na formie ze-braliśmy już wszystkie niezbędne elementy do działania naszej księgi gości. Efekt dotychczasowej pracy widoczny jest na Rysunku 3.

Zajmiemy się teraz przygotowaniem szablo-nu Smarty, na którym, w wygodny dla nas spo-sób, umieścimy formularz. Tworzymy nowy sza-blon o nazwie guestbook.tpl. Każdy z komponen-tów umieszczamy w szablonie, poprzez umiesz-czenie w nim zmiennej o nazwie komponen-tu. Dla naszych komponentów o nazwie title, au-thor, content będziemy musieli zastosować zmien-ne {$title}{$author} oraz {$content}, co wi-doczne jest na Listingu 2. Czynność ta jest bardzo prosta i nie powinna sprawić problemu nawet po-czątkującemu programiście. W miejscu umiesz-czonych zmiennych Smarty pojawią się kompo-nenty ułożone na naszej formie. W ten sam spo-

Page 69: PHP Solutions 06 2007 PL

Artykuł warsztatowy

68 06/2007

Delphi for PHP

69www.phpsolmag.org

Events. Po wyborze tego zdarzenia zostanie wy-generowana metoda GuestbookTemplate, w któ-rej zawrzemy cały kod odpowiedzialny za wy-świetlenie wpisów. Kod odpowiedzialny za ze-branie informacji i wysłanie ich do naszego sza-blonu widoczny jest na [listingu 5].

Za utworzenie uchwytu do szablonu odpo-wiada fragment kodu $template=$params['template']; natomiast za utworzenie nowej zmien-nej w szablonie odpowiada kod $template–>_smarty–>assign('guests',$guests);. Możemy w ten sposób przekazać do szablonu dowolną licz-bę własnych zmiennych, które następnie musimy wyświetlić. Jako, że do szablonu przekazaliśmy ca-łą tablicę wyników, będziemy musieli obsłużyć ją przy pomocy pętli wbudowanej w Smarty o na-zwie section. Fragment szablonu odpowiedzialny za wyświetlenie zawartości tej tablicy jest widocz-ny na [Listingu 6].

Konstruując tę pętlę zebraliśmy wszystkie elementy potrzebne do działania naszej księgi gości. Pozostało jedynie połączenie wszystkiego w całość. Szablon zapisaliśmy pod nazwą guest-book.tpl w folderze template. Łączymy go z pli-kiem guestbook.php, tak samo jak poprzednio, a następnie uruchamiamy oraz dodajemy przy-kładowy wpis o dowolnej treści. Efekt naszej pracy widoczny jest na [rysunku 4].

W ten sposób ukończyliśmy nasz pierwszy pro-jekt. Jednak powinniśmy jeszcze wiedzieć, któ-re pliki skopiować, aby umieścić go na serwerze. Dobrą wiadomością jest to, że nie musimy się o to martwić, ponieważ Delphi for PHP ma wbudowa-ny w sobie dodatek, który za nas zbierze niezbęd-ne elementy i umieści je w wybranym przez nas katalogu, który następnie musimy przenieść na nasz serwer. Aby skorzystać z tej funkcjonalności musimy wybrać w menu Tools–>Deployment Wi-

zard. Pojawi się wtedy kreator, w którym właściwie naszym jedynym zadaniem jest określenie ścieżki zapisu oraz klikanie next. Jednak po wykonaniu tej akcji musimy jeszcze pamiętać o przeniesieniu szablonów oraz grafik, bo tego Delphi for PHP już za nas nie zrobi. Drobną niespodzianką jest rów-nież nie przenoszenie w tym procesie folderu Smarty z biblioteki VCL, ale tak naprawdę trudno jest określić, czy jest to działanie zamierzone, czy też niewielkie nie dopatrzenie. Nie mniej jednak pamiętajmy, aby zrobić to samemu. Po wykona-niu tych czynności, musimy jedynie przenieść na-szą stronę na serwer i możemy już wtedy wysyłać link do znajomych.

PodsumowanieKorzystając z Delphi for PHP stworzyliśmy w bar-dzo prosty sposób prostą stronę, której główną atrakcją jest księga gości. Stworzenie takiej stro-ny w tradycyjny sposób wymagałoby dużo więk-szego nakładu pracy, a co za tym idzie i czasu. Sprawny użytkownik, wykorzystując to opro-gramowanie, byłby w stanie stworzyć taką stro-nę w czasie pięciu minut. Tradycyjnymi meto-dami nie byłoby to możliwe. Delphi for PHP po-zwala na tak szybka pracę, ponieważ nie zmusza nas do implementowania dobrze znanych i czę-sto powielanych rozwiązań. Najlepszym przy-kładem tego typu jest dostęp do bazy danych. W tradycyjnych metodach programowania, mu-sielibyśmy oprogramować połączenie. Natomiast w Delphi for PHP całe nasze działanie polega je-dynie na wprowadzeniu danych dostępowych oraz na przeciągnięciu komponentu na formę. Możemy jasno określić, że tak naprawdę wszyst-kie działania zostały ograniczone do niezbędne-go minimum, jakie musi wykonać użytkownik. To samo podejście możemy zaobserwować rów-nież podczas wykorzystywania szablonu Smar-ty. Zazwyczaj przed pierwszym uruchomie-niem Smarty, musieliśmy tworzyć klasę dziedzi-czącą po głównej klasie Smarty, aby ustawić da-ne konfiguracyjne, jednak w przypadku Delphi for PHP nie musimy się o to martwić. W arty-kule tym mamy do czynienia z bardzo prostym przykładem, dzięki czemu łatwiej będzie nam rozpocząć swoja przygodę z tym oprogramowa-niem. Wykorzystaliśmy tutaj jedynie podstawo-we elementy, a należy pamiętać, że do wykorzy-stania i przetestowania zostało jeszcze całe mnó-stwo komponentów korzystających np. z ajaxa, co powinno tym bardziej zachęcić do pozna-nia tej aplikacji. Chcąc skorzystać z ajax–a wca-le nie musimy go znać. Jedyne co naprawdę mu-simy u mieć, to po prostu klikać oraz czytać do-kumentację, która coraz intensywniej rozwija się na stronie biblioteki VCL.

Listing 4. Zapis do bazy danych w reakcji na kliknięcie przycisku

function Button1Click($sender, $params)

{

$query='INSERT INTO `guestbook` (`title`,`author`,`content`,`date`)

VALUES (?,?,?,NOW())';

$title=addslashes(htmlspecialchars($_POST['title']));

$author=addslashes(htmlspecialchars($_POST['author']));

$content=addslashes(htmlspecialchars($_POST['content']));

$array=array($title,$author,$content);

$this->dbdelphi4php1->Prepare($query);

$this->dbdelphi4php1->execute($query,$array);

$this->title->setText('');

$this->author->setText('');

$this->content->setText('');

}

Listing 5. Zebranie informacji o wpisach gości i wysłanie ich do szablonu Smarty

function Unit6Template($sender, $params)

{

$query="SELECT *

FROM `guestbook`

ORDER BY `date` DESC";

$result=$this->dbdelphi4php1->execute($query);

foreach($result as $guest)

{

$guests[]=$guest;

}

$template=$params['template'];

$template->_smarty->assign('guests',$guests);

}

Listing 6. Wyświetlenie wszystkich wpisów znajdujących się w naszej księdze gości

{section name=i loop=$guests}

<div class="post">

<p class="date">{$guests[i].date|truncate:10:''}</p>

<h1 class="title">{$guests[i].title}</h1>

<div class="entry">

{$guests[i].content}<br/>

<span style="font-size:0.8em;padding:5px;">{$guests[i].author}</span>

</div>

</div>

{/section}

ŁUKASZ SKOWROŃSKIAutor jest studentem informatyki na Uniwersytecie

w Białymstoku, pracuje również jako programista

PHP w firmie E-Studio.

Kontakt z autorem: [email protected]

Page 70: PHP Solutions 06 2007 PL

Testy konsumenckie

70 06/2007

UPS

71www.phpsolmag.org

Testy konsumenckie

W naszych testach konsumenckich przedstawiamy dwóch producentów zasilaczy awaryjnych UPS – ETA i Emerson Network Power oraz prezentujemy opinie firm, które skorzystały z ich oferty.

UPS

Netia S.A. jest największym niezależ-nym operatorem telefonii przewo-dowej w Polsce. Świadczy stacjonar-

ne usługi telekomunikacyjne w całym kraju. Oferta Netii, obok usługi głosowej obejmuje dostęp do Internetu po liniach analogowych i cyfrowych, hosting, usługi 0800, 0700, 0300 oraz zaawansowane usługi Netia Frame Relay, Integralnet, łącza dzierżawione i usłu-gi dla operatorów Netia Carrier. Netia współ-pracuje z czwartym operatorem telefonii ko-mórkowej PLAY przy budowie sieci UMTS. Obecnie z usług dostępu do Internetu Netii korzysta blisko 140 tysięcy klientów, a celem firmy jest pozyskanie miliona internautów do roku 2009.

Podczas realizacji projektu szerokopa-smowego radiowego dostępu do Internetu dla klientów biznesowych, pojawił się wy-móg zapewnienia zasilania awaryjnego o na-pięciu 230V dla terminali instalowanych u klientów.

W pierwszym etapie wyspecyfikowane zo-stały podstawowe wymagania dla zasilacza UPS, takie jak: zakres mocy pozornej, topo-logia zasilacza, czas autonomii, autostart po powrocie zasilania oraz możliwość zdalnego nadzoru. Dodatkowymi wymogami były ska-

lowalność zespołu baterii, umożliwiająca wy-dłużenie czasu autonomii w przypadku ocze-kiwanej, zwiększonej dostępności usługi oraz konstrukcja pozwalająca na instalację zasila-cza jako wolnostojący lub w szafie 19”, w za-leżności od wymagań klienta. Ze względu na dużą skalę projektu potrzebna była wyso-ka niezawodność urządzenia. Przy wyborze sprzętu, braliśmy pod uwagę zarówno jakość zasilacza, jak i dostępność serwisu. Mając złe doświadczenia wiedzieliśmy, że tanie i pro-ste rozwiązania po pewnym okresie ulegają awariom. Przez to, nie tylko generują koszty napraw, ale wstrzymują realizacje usługi dla klienta, czego rezultatem jest utrata przycho-dów oraz dobrego wizerunku operatora.

Po przeprowadzeniu analizy dostępnych na rynku zasilaczy oraz ich cen, wybrana zo-stała rodzina jednofazowych zasilaczy UPS GXT2U700-3000 o mocach od 700VA i 3000VA firmy Liebert, wchodzącej w skład Grupy Emerson Network Power.

Zasilacze GXT2U zbudowane są w opar-ciu o technologię VFI, na bazie podwójnej konwersji i przeznaczone są do ochrony kry-tycznych odbiorów przed wszystkimi rodza-jami zakłóceń, jakie mogą pojawić się od stro-ny sieci energetyki zawodowej. Uniwersal-na konstrukcja UPS pozwala na jego mon-taż w szafie 19”, w której, w podstawowej konfiguracji zajmuje tylko 2U lub pionowo, jako wolnostojący na specjalnej podstawie. Do zasilacza mogą być dołączane dodatko-we, zewnętrzne moduły baterii akumulato-rów. Od jednego do czterech, każdy o wyso-kości 2U, przedłużający czas podtrzymania zasilania odbiorów, co pozwala spełnić zróż-nicowane oczekiwania naszych klientów. Za-silacz charakteryzuje nowoczesny design, na płycie czołowej świecące się diody w przej-rzysty sposób obrazują aktualny stan pracy zasilacza.

Gniazdo zasilania sieciowego, cztery gniaz-da wyjściowe typu IEC320, gniazda baterii

dodatkowych oraz port komunikacyjny DB-9 zabudowane są na tylnym panelu. Istotnym elementem wyróżniającym tą rodzinę zasila-czy, jest wbudowany wejściowy układ PFC, który zapewnia wysoki cosφ = 0,97 i ogra-nicza poziom zniekształceń wprowadzanych do sieci. Ma to wpływ na coraz częściej po-strzeganą tzw. ekologię sieci zasilającej. Bar-dzo szeroki zakres napięć wejściowych oraz częstotliwości pozwala na znaczne wydłu-żenie czasu eksploatacji baterii, której ży-wotność w dużej mierze zależy od ilości cy-kli wyładowania i ładowania. Zaletą jest też łatwa wymiana baterii „na gorąco”, co nie wymaga odłączania w tym czasie odbiorów klienta. Zasilacze GXT2U wyposażone są w gniazdo, do zainstalowania karty sieciowej SNMP/WEB, zapewniające zdalną kontrolę i diagnostykę zasilacza oraz przesyłanie tra-pów alarmów do centrum nadzoru opera-tora. Umożliwia to podjęcie adekwatnych działań do rodzaju awarii, co jest szczegól-nie istotne przy dużej ilości instalacji i znacz-nej rozległości sieci. Z zastrzeżeń, jakie moż-na mieć do zasilacza to poziom hałasu, któ-ry może dochodzić do 55dBA z tyłu, w odle-głości 1m od urządzenia i może być uciążli-wy w przypadku długiego przebywania w je-go sąsiedztwie.

Wybór zasilaczy UPS GXT2U700 był ko-lejnym krokiem współpracy Grupy Netia z Emerson Network Power. Pierwsza umowa ramowa na dostawę i montaż systemów za-silania napięciem stałym podpisana została w 1997r. Cena adekwatna do jakości zasila-cza, była dodatkowym elementem na etapie wyboru. Dobry produkt, krótki czas dosta-wy, dostępność serwisu naprawczego, kom-petentne wsparcie techniczne oraz dobre do-świadczenia z dotychczasowej współpracy, pozwalają na przyznanie wysokiej oceny w odniesieniu do całego projektu.

Tomasz Idczak

Kierownik technologii zasilania i klimatyzacji Netia S.A.

Ocena: «««««Oc ena : «««««

Page 71: PHP Solutions 06 2007 PL

Testy konsumenckie

70 06/2007

UPS

71www.phpsolmag.org

Firma RRC Poland Sp. z o.o. istnieje na rynku polskim od 1992 roku. Zaczy-nała jako dystrybutor rozwiązań firmy

3Com. Jako RRC Enterprise Networking jest obecnie dystrybutorem technologii informa-tycznych, głównie z zakresu rozwiązań siecio-wych oraz serwerowych. W ofercie firmy są pro-dukty takich firm jak Cisco Systems, 3Com, Al-lied Telesis, Zyxel czy Funkwerk. Oferta serwe-rowa oraz storage oparta jest na sprzęcie IBM. W zeszłym roku zapoczątkowany został roz-wój dwóch nowych nisz technologicznych: dzia-

łu bezpieczeństwa sieciowego (oprogramowa-nie oraz sprzęt – MKS VIR, Symantec, F–Se-cure, SonicWall) oraz działu rozwiązań tele-komunikacyjnych (połączenie VOIP oraz PBX – Avaya, Funkwerk). Dynamicznie rozwijają-cym się działem są produkty tzw. personal ID – skanery, systemy RFID, drukarki termicz-ne – Symbol, Zebra, Motorola, O'Neal. Nasza firma pomaga swym partnerom, za pośrednic-twem spersonalizowanych stron WWW, wspar-cia inżynierów systemowych oraz poprzez orga-nizację różnego rodzaju szkoleń – także w róż-nych miastach Polski. W związku z tym, poja-wiła się potrzeba posiadania niezawodnych sys-temów informacyjnych – zarówno od strony sprzętu komputerowego (serwery, macierze dys-ków), jak i zasilania awaryjnego pozwalającego na ciągły i bezpieczny dostęp do danych, a tak-że zabezpieczenie przed ich utratą w razie bra-ku zasilania. W ramach rozwijania naszej ofer-ty poznaliśmy między innymi produkty Emer-son Network Power, jako element zabezpiecze-nia sieci komputerowych od strony ich zasilania. Ich oferta, z punktu widzenia zaplecza badaw-czo–rozwojowego oraz oferty produktowej, wy-dała nam się atrakcyjna zarówno pod względem zastosowanych rozwiązań, jak i poziomu cen, w porównaniu z konkurencją o podobnym pozio-mie technologicznym. Emerson Network Power to ogólnoświatowy dostawca rozwiązań związa-nych z zasilaniem – od małych zastosowań biu-rowych czy domowych do wielkich centrów da-nych. W kręgu naszych zainteresowań znalazły się zasilacze awaryjne do serwerów zainstalowa-

nych w naszej firmie, solidne i bezawaryjne, z możliwością zarządzania poprzez sieć kompu-terową, z co najmniej dwuletnią gwarancją i pol-skim serwisem. Zasilacze Emerson Network Po-wer z grupy PSI oraz GXT2 w zakresie mocy od 1440 do 3000 VA, spełniają z nadwyżką nasze wymagania, ponieważ oprócz wyżej wymienio-nych funkcji, oferują możliwość dokładania ba-terii dodatkowych wydłużających czas podtrzy-mania zasilania oraz możliwość montażu w sza-fie 19" – wszystko to w standardowej cenie urzą-dzenia. Zdecydowanie spełniły one zadanie pod-trzymywania serwerów dla aplikacji, poczty in-ternetowej oraz strony WWW dla naszych part-nerów. UPS-y z rodziny PSI znalazły zastosowa-nie do serwerów montowanych w szafach 19" – zastosowana technologia line–interactive jest wystarczająca do zasilania wszelkiego rodzaju komputerów – także serwerów. Mają też moż-liwość zarządzania nimi za pośrednictwem por-tu USB lub RS232, dołączone jest również opro-gramowanie do zdalnego zamknięcia serwerów w razie braku zasilania. UPS-y z rodziny GXT2 z powodu zastosowania w nich technologii on–li-ne (zerowy czas przełączania na baterie) służą do zasilania zewnętrznych macierzy dyskowych oraz urządzeń wrażliwych nawet na najmniejsze zaniki napięcia. Używane są w wersji wolnosto-jącej, istnieje możliwość, w razie potrzeby, doku-pienia do nich zestawu do zainstalowania w sza-fie 19". Zasilacze pracują cicho, co nie jest bez znaczenia dla pracujących w pobliżu ludzi.

Tomasz PawelskiProduct Manager 3Com, Allied Telesis, APC, LiebertRRC Poland Sp. z o.o.

Ocena: «««««Oc ena : «««««

klimatyzacji precyzyjnej marki Hiross oraz UPS-y marki Liebert. Obecnie wszystkie pro-dukty oferowane są pod jedną marką – Emer-son. Typowe zastosowania klimatyzacji precy-zyjnej to centrale telekomunikacyjne. Emer-son Network Power jest dostawcą klimatyzacji precyzyjnej dla Telekomunikacji Polskiej SA, Polkomtela, Polskiej Telefonii Cyfrowej, Netii i Energisu. Wyposaża również większość serwe-rowni oraz centrów danych w Polsce.

Niemal wszystkie zarejestrowane w Polsce banki: PKO SA, PKO BP, Kredyt Bank, Bank Millenium, Raiffeisen Bank Polska, a także ministerstwa oraz różne instytucje samorzą-dowe, mają urządzenia Emerson Network Po-wer. Emerson dostarcza także urządzenia dla przemysłu, np. dla kopalni, cementowni, elek-trowni, zakładów energetycznych oraz w prze-myśle drukarskim, czego przykładem jest Pań-stwowa Wytwórnia Papierów Wartościowych. Spółka jest wiodącym dostawcą klimatyzacji precyzyjnej na obszarze Polski, zaopatruje ok. 40% rynku.

UPS-y obsługują zakres mocy od 0 do 800 kVA. Marka Liebert znana jest z UPS-ów o dużej mocy, czyli głównie specjalistom z branży elektrycznej, którzy zajmują się roz-wiązaniami o większej skali. Nowością są za-

silacze awaryjne od 0 do 30 kVA. Pozostałe oferowane rozwiązania to, m.in. siłownie dla operatorów telekomunikacyjnych, straży gra-nicznej czy policji. Emerson kupił te produk-ty poprzez akwizycję: przejmując część fir-my Ericsson i firmy Nortel. Obecnie, wspól-nie z partnerem technologicznym, polską fir-mą Telzas, obsługuje Polkomtela. Kolejne pro-dukty to duże rozwiązania związane z trans-misją i zabezpieczenia przeciwzwarciowe. Różnego typu szafy i obudowy – są to rozwią-zania do montażu różnych urządzeń. Kluczo-wym elementem pozostaje jednak zasilanie. Niektóre urządzenia produkowane są na za-sadzie OEM dla innych producentów, np. za-silacze do różnego typu sprzętu, kable USB i światłowodowe – oferowane w szerokiej ska-li na rynku, często pod markami dystrybuto-rów. „Prawdopodobnie znacie Emerson bar-dziej, niż wam się wydaje” – mówi Dyrek-tor Generalny Emerson w Polsce – Małgorza-ta Kasperska.

Opinie naszych klientów są dla nas powo-dem do dumy. Rekomendacje od tak znakomi-tych firm jak Netia S.A. czy RRC Poland Sp. z o.o., liderów w swoich branżach, nie tylko wy-różniają nas na rynku ale i obligują do ciągłe-go doskonalenia naszych produktów i usług.

Emerson Network Power, część koncer-nu Emerson Electric, to spółka zareje-strowana w Polsce od 2000 r., choć ofe-

rowane przez nią produkty znane są na pol-skim rynku już od lat 70, w tym urządzenia

UstosunkowanieCezary Gutowski Kierownik Sprzedaży UPS-ów małej i średniej mocy w Emerson Network Power

Page 72: PHP Solutions 06 2007 PL

Testy konsumenckie

72 06/2007

UPS

73www.phpsolmag.org

UPS-y Emerson Network Power marki Lie-bert, to sprzęt z najwyższej półki, biorąc pod uwagę kryteria takie jak: jakość i niezawod-ność. Nie spoczywamy jednak na laurach. Do-wodem są kolejne udogodnienia dla naszych obecnych i przyszłych klientów. Najnowszą propozycją jest oferta „3 lata przez 3 miesią-ce” polegająca na wydłużeniu do 3 lat okresów gwarancyjnych na wybrane UPS-y GXT2 i PSI zakupione do końca października 2007. Nie przez przypadek, właśnie te modele wybra-li, jako element systemu bezpieczeństwa biz-nesu, rekomendujący nas klienci – Netia S.A. i RRC Poland.

To, w jaki sposób reagujemy na potrzeby na-szych partnerów, opracowujemy indywidualne rozwiązania, doradzamy i dbamy o bezpieczeń-stwo aplikacji o krytycznym znaczeniu, spra-wia, że pozostają z nami na lata. Przykładem zaufania, które procentuje, jest ponad 10-letnia współpraca firmy Emerson Network Power z li-derem rynku telekomunikacyjnego w Polsce, firmą Netia S.A.

Trudno też o lepszą rekomendację niż to, że jeden z największych w Europie Środkowej i Wschodniej dostawców produktów siecio-wych i telekomunikacyjnych, mający w swej ofercie między innymi UPS-y – firma RRC – na swój własny użytek wybrała właśnie UPS-y spod znaku Liebert, marki należącej do Emer-son Network Power.

Warto podkreślić, że UPS-y które oferuje-my obecnie w Polsce, i dedykujemy szczegól-nie małym i średnim przedsiębiorstwom, ce-chuje ta sama jakość i niezawodność, z której znane są nasze rozwiązania typu Power, sto-sowane w największych centrach danych na świecie. Można porównać je do polisy, któ-ra gwarantuje ciągłość funkcjonowania urzą-dzeń o krytycznym znaczeniu dla każdego biznesu.

Emerson Network Power to firma, która od wielu lat, na całym świecie, dostarcza rozwią-zania zasilania awaryjnego i klimatyzacji dużej skali, o krytycznym znaczeniu dla klientów z każdego sektora gospodarki. Obecnie inten-

syfikujemy działania, mające na celu dotarcie z naszą ofertą do klientów z sektora MŚP na obszarze całej Europy. Rozbudowanie kanału partnerskiego pełni dla nas kluczową rolę w realizacji tego zadania.

W roku 2007 planujemy w Polsce, na Litwie, Łotwie i Estonii podpisać umowy z wiodącymi dystrybutorami IT oraz rozpoczniemy rekru-tację partnerów do przygotowanego programu resellerskiego. Podstawowe wartości jakie ofe-rujemy, to relatywnie wysoka dla tego segmen-tu marża i produkty zaliczane, ze względu na parametry takie jak jakość i niezawodność, do tych „z najwyższej półki”.

Cezary Gutowski od stycznia 2007 r. objął stanowisko Kierownika Sprzedaży zasilaczy awaryjnych UPS małej mocy marki Liebert (do 30 kVA) w polskim oddziale Emerson Ne-twork Power. Jest odpowiedzialny za rozwój sprzedaży zasilaczy UPS Liebert w kanałach dystrybucyjnych branży informatycznej oraz elektrycznej.

AJM Electronics powstało w 1992 ro-ku. Od początku działalności zajmo-waliśmy się dystrybucją wszelkiego

rodzaju złącz, kabli i akcesoriów teleinforma-tycznych. Na rynku polskim staliśmy się zna-ni dzięki szerokiej ofercie komponentów siecio-wych, którą stale rozwijamy. Jednocześnie po-dejmujemy kroki, mające na celu zbudowanie i umocnienie naszej pozycji na innych polach.

AJM od kilku lat jest przedstawicielem zna-nej, niemieckiej firmy TELEGÄRTNER, pro-ducenta najwyższej jakości podzespołów do sieci, opartych na skrętce miedzianej i świa-tłowodach, złączy telekomunikacyjnych wy-sokiej częstotliwości oraz kabli telekomuni-kacyjnych i sieciowych. Dla Partnerów TELE-GÄRTNERA regularnie prowadzimy szkole-nia, po zakończeniu których, uzyskują oni au-toryzację, pozwalającą na udzielanie 25-letniej gwarancji na sieci wykonane w systemie TELE-GÄRTNER.

naszego obecnego partnera oraz szeroka ofer-ta produktowa. Zasilacze UPS ETA charakte-ryzują się bardzo dobrym współczynnikiem ce-na / jakość. Producent oferuje je w kilku pod-stawowych odmianach, o mocach od 720VA do 250kVA. Wszystkie modele charakteryzu-ją się zwartą, solidną konstrukcją oraz estetycz-nym wyglądem. Oferta jest na tyle atrakcyjna, że pozwala zaspokoić praktycznie każdą potrze-bę naszych klientów.

Nie bez znaczenia jest fakt, że ETA to uzna-ny gracz na rynku, który budzi zaufanie. Zna-cząco ułatwia nam to zwiększenie sprzedaży. Dodatkowo, oparte na długoletnim doświad-czeniu, rozwiązania ETA umożliwiają dosto-sowanie się do szerokich potrzeb instalatorów i wykonawców. W razie konieczności możemy liczyć na pomoc i wsparcie techniczne ze stro-ny naszego partnera. Bardzo duże znaczenie we wzajemnej współpracy odgrywa sprawnie dzia-łający serwis oraz elastyczność i terminowość dostaw. Z uwagi na to, że AJM prowadzi dys-trybucję szaf instalacyjnych w standardzie 19”, zależało nam na wzbogaceniu oferty o zasilacze UPS do tych szaf. Dzięki ETA bardzo szybko i sprawnie udało się rozwiązać ten problem.

Z całym przekonaniem możemy stwierdzić, iż nawiązanie kontaktu, a potem współpracy z poznańskim producentem, było słusznym po-sunięciem. Zasilacze awaryjne nie są naszym sztandarowym produktem, ale stanowią ważne uzupełnienie oferty. Musimy przyznać, że ETA doskonale wywiązuje się z roli dostawcy i part-nera. Niedawno podjęliśmy decyzję o wspól-nych działaniach marketingowych. Pozwoli nam to zwiększyć obroty, a przy okazji dodat-kowo promować markę.

Bardzo istotną część oferty AJM, stanowią produkty firmy ATEN - czołowego producen-ta przełączników KVM na świecie. Od 1997 r. jesteśmy jej autoryzowanym dystrybutorem. Obok podstawowej linii produktów, oferujemy także, stworzoną przez ATEN, linię zaawanso-wanych systemów KVM, dostępnych pod mar-ką ALTUSEN.

AJM Electronics to także szafy instalacyjne, których oferta jest z roku na rok bogatsza. Ofe-rujemy przede wszystkim rozwiązania GFlex w wielu odmianach. Jesteśmy wyłącznym przed-stawicielem tej marki w Polsce. Dostępne są u nas szafy wiszące, stojące, dzielone o różnych głębokościach i wersjach wykonania, szafy z bo-gatym wyposażeniem.

Klienci AJM mogą się także zaopatrywać w elementy aktywne sieci, takie jak: switche, ro-utery, modemy, karty sieciowe, elementy sie-ci wi-fi, etc. W naszej ofercie znajdują się m.in. urządzenia: SURECOM, D-Link, IP-Time, Edi-max oraz GFlex.

AJM Electronics jest także dystrybutorem pre-paratów czyszczących i konserwujących firmy AMBERSIL, stanowiącej część amerykańskiego koncernu chemicznego CRC, sprzedającego swo-je produkty w ponad 120 krajach świata.

AJM Electronics zajmuje się zaopatrzeniem hurtowym firm teleinformatycznych, instala-torskich, banków, zakładów przemysłowych, biur, sklepów komputerowych, szkół, wyższych uczelni.

W celu zapewnienia kontrahentom możli-wości kompleksowego zaopatrywania się w na-szej firmie, podjęliśmy decyzję o wprowadze-niu do oferty zasilaczy UPS. Kontakty targo-we ułatwiły nam nawiązanie współpracy han-dlowej z poznańską firmą ETA. O tym, a nie innym wyborze zadecydowało doświadczenie

Robert GałkaMarketing ManagerAJM Electronics Sp. z o.o.

Oc ena : «««««

Page 73: PHP Solutions 06 2007 PL

Testy konsumenckie

72 06/2007

UPS

73www.phpsolmag.org

Firma Hardsoft–Telekom powstała w sierpniu 1992. Od początku działalno-ści zajmowała się sprzedażą systemów

i podzespołów komputerowych. Obecnie za-trudnia ok. 25 pracowników, a jej działalność opiera się głównie o sprzedaż hurtową i obsłu-gę informatyczną przedsiębiorstw. Specjali-zujemy się w następujących zagadnieniach:

Kompleksowa dostawa systemów kom-puterowych, opartych na platformie Micro-soft, Novell, Linux obejmująca dostarcza-nie: sprzętu komputerowego (IBM, HP, Fujit-su–Siemens, Apple, Maxdata, AVAN – mar-ka własna); urządzeń sieciowych (3COM, CI-SCO, Linksys); urządzeń peryferyjnych (HP, OKI, Kyocera, Lexmark, Minolta i in.); syste-mów zasilania awaryjnego (APC, ETA, Ever

i in.); monitorów, projektorów, akcesoriów komputerowych, podzespołów; oprogramo-wania sieciowego wraz z instalacją okablowa-nia strukturalnego; oprogramowania do ob-sługi firm oraz wykonanie pełnej infrastruk-tury sieciowej Serwis sprzętu komputerowe-go i sieci, obejmujący: naprawy sprzętu kom-puterowego; konserwację sprzętu; analizę i monitorowanie pracy sieci; wydłużone go-dziny pracy serwisu interwencyjnego; sprzęt zastępczy niezbędny do utrzymania pracy przedsiębiorstwa.

Powyższe produkty nie wyczerpują na-szej oferty. Na życzenie klienta dostarczamy sprzęt i oprogramowanie zależnie od jego po-trzeb. Dlaczego wybraliśmy produkt firmy ETA? Firma ETA jest znana na naszym rynku od wielu lat, jako producent systemów zasila-nia UPS. Oprócz rozpoznawalności marki, o naszej współpracy zdecydowały dobra jakość produktów i sprawny serwis. Rozwiązania fir-my ETA sprawdzają się u naszych klientów, którzy chwalą produkty jako konkurencyjne cenowo i solidne. Niemałe znaczenie ma też obsługa serwisowa.

Firma ETA zatrudnia dobrych specjali-stów, przez co zapewnia serwis gwarancyj-ny i pogwarancyjny na wysokim poziomie. Do przyjemnych należy również kontakt z działem handlowym firmy ETA. Pracowni-cy, dzięki posiadanej wiedzy handlowej i zna-jomości produktów łatwo nawiązywali z na-mi współpracę. Wspólne działania z ETĄ wy-

tworzyły między naszymi firmami atmosfe-rę partnerstwa, dzięki czemu współpracuje się nam lepiej.

Firma ETA zdobywała swoją pozycję od lat. Działając na tym samym rynku i obserwu-jąc się od lat, nawiązaliśmy współpracę z fir-mą ETA już na początku lat 90. Chcieliśmy wprowadzić systemy UPS do naszej oferty. Obecnie firma ETA znana jest w całej Polsce i ma silną pozycję w naszym regionie.

Produkty i usługi firmy ETA w pełni speł-niają nasze oczekiwania, a współpraca ukła-da się dobrze. Do największych plusów moż-na zaliczyć: sprawny serwis, niska awaryjność, szeroka oferta, satysfakcjonująca polityka ce-nowa względem dystrybutorów, wiedza i do-świadczenie w zakresie zaawansowanych sys-temów zasilania o dużej mocy. Jedynym mi-nusem, który można wskazać, jest dość długi czas oczekiwania na dostawę w przypadku za-mówień większych partii towaru.

Wydaje mi się, że cena jest adekwatna do ja-kości usług, choć trudno nie zauważyć, że dla klienta staje się ona często decydującym czyn-nikiem w procesie zakupu. Szczególnie widać to na rynku małych UPS–ów. Tu, działając w mocno konkurencyjnym środowisku, coraz częściej zmuszeni jesteśmy to stosowania naj-tańszych rozwiązań. Niestety jakość, czy ob-sługa serwisowa w takich przypadkach scho-dzi na drugi plan.

Mariusz Gołębiowski

Hardsoft–Telekom

Oc ena : ««««

wisem urządzeń służących ochronie sprzę-tu elektronicznego przed zakłóceniami i za-nikami napięcia w sieci zasilającej. W naszej ofercie znajdują się zasilacze awaryjne (UPS) o mocy od 320 VA do 250 kVA, jak również listwy zasilające oraz agregaty prądotwórcze. Nasze produkty można nabyć w całym kraju, poprzez sklepy partnerskie oraz dystrybuto-rów. Zawsze staramy się pomóc naszym klien-tom w doborze UPS–a.

Zapewniamy również montaż i serwis wszystkich naszych urządzeń. Dużą wagę przykładamy do jakości oferowanych produk-tów. Dzięki temu możemy pochwalić się naj-dłuższą na rynku, pięcioletnią gwarancją na zasilacze awaryjne z serii „multisystem”.

Nasze udokumentowane, wieloletnie do-świadczenie w projektowaniu i produkcji za-silaczy awaryjnych, pozwala nam zapewnić najwyższy poziom obsługi klienta. Potwier-dzeniem naszych kwalifikacji, a także sku-teczności w zarządzaniu, jest wdrożony sys-tem jakości ISO–9001 certyfikowany w 2003 przez TÜV.

Atutem naszej firmy jest posiadanie wła-snego działu konstrukcyjnego, dzięki które-mu możemy na bieżąco pomagać klientom w przypadku nietypowych rozwiązań. Właśnie w odpowiedzi na powtarzające się pytania z

Spółdzielnia Pracy Elektroniki i Infor-matyki ETA powstała w 1988 roku. Od początku naszej działalności zaj-

mujemy się projektowaniem, produkcją i ser-

zakresu ogrzewania, powstały zasilacze z se-rii CO, współpracujące z kotłami grzewczymi, kominkami z płaszczem wodnym itp.

Chcąc utrzymać status wiarygodnego do-stawcy Systemów Zasilania Awaryjnego oraz dostarczania klientowi wyrobów zgodnych z jego wymaganiami, za najważniejsze uzna-jemy ciągłe podnoszenie kwalifikacji na-szego zespołu. Priorytetem jest zadowole-nie każdego Klienta. Właśnie wprowadzi-liśmy do sprzedaży nowy produkt, zasilacz ETA UPS Protelek 650, przeznaczony na ry-nek masowy. Jest to mały zasilacz do domo-wego lub biurowego użytku, za bardzo przy-stępną cenę.

Potwierdzeniem naszych starań w zakre-sie jakości, są opinie dystrybutorów, z który-mi współpracujemy od kilkunastu lat. Jest to dla nas największą nagrodą, a zarazem moty-wacją do dalszej pracy.

Ciągle poszerzamy naszą ofertę. Praca nig-dy nie kończy się na sprzedaży, służymy rów-nież pomocą w czasie eksploatacji urządzeń. Nasz serwis cechuje szybkość reakcji i wy-kwalifikowana kadra. Wszystkie te elementy wpływają na jego bardzo pozytywną ocenę.

UstosunkowanieKarol PietrowskiDyrektor ds. sprzedaży i marketinguSPEiI ETA

Page 74: PHP Solutions 06 2007 PL

Wywiad

74 06/2007

Wywiad

75www.phpsolmag.org

PHP Solutions: Kiedy kończy się praca pracownika – informatyka, a zaczyna wi-zja organizatora – przedsiębiorcy? Skąd przekonanie, że z sieci komputerów można „wycisnąć” o wiele więcej niż robią to „teraz” inni ludzie?Marek Sodolski (Amway): Osoby, które dzisiaj rozpoczynają działalność gospo-darczą lub podejmują pracę w firmach są znacznie lepiej przygotowane i wykształ-cone, niż ci, których początek kariery za-wodowej przypadał na lata dziewięćdzie-siąte. Teraz każdy pracownik jest poten-cjalnie kreatorem nowych pomysłów i no-wej wartości dodanej. W tym duchu stara-my się pracować w firmie Amway – każdy pomysł, który w znaczący sposób mógł-by wpłynąć na działanie firmy jest mile wi-dziany. Uważam, że najciekawsze pomy-sły rodzą się w dyskusji, podczas spotkań z ludźmi o różnym stopniu doświadczenia. Stawiamy tak naprawdę na „teamwork”, na pracę wielu osób, które mogą wnieść coś świeżego do projektu. Osobiście jest mi niezmiernie miło, że mogłem koordyno-wać pracą nad projektem e-commerce, ale to nie znaczy, że to tylko moja autorska wi-zja go kształtowała.

PS: Skąd pomysł na udział w takim pro-jekcie, jakim jest platforma e-commerce?MS: E-commerce to naturalna kontynuacja budowy otoczenia biznesowego dla róż-nego typu działalności. Jest jednym z lo-gicznych etapów rozwoju systemów za-rządzania i wspomagania działań przedsię-biorstwa. W naszym przypadku e-commer-ce nie pojawił się nagle, „deus ex machina”, ale był kolejną fazą rozwoju różnego ty-pu zaawansowanych systemów zarządza-nia dużą ilością danych, połączonych z sys-temami IT. Pracujemy w oparciu o system IBM AS/400, który pozwala na kalkulacje wyników biznesowych firmy i naszych dys-trybutorów w czasie rzeczywistym, zbiera-jąc te dane z całego świata. Od lat rozwi-jamy różnego rodzaju narzędzia związane z obsługą klienta, m.in. dostarczaniem to-

warów, bo logistyka jest czymś, bez cze-go e-commerce w ogóle nie istnieje. Doda-jąc do tego świetnie zorganizowane syste-my back office’owe na AS/400 osiągnęliśmy znakomity czas obsługi zamówień, który wynosi od 24 do 48 godzin, gdzie dostęp-ność towarów jest szacowana na poziomie 95%. Dla osób z branży logistycznej ten wynik wiele mówi. Doskonale działająca infrastruktura logistyczna plus zorganizo-wany system sprzedaży stały się idealnym i naturalnym podłożem do wprowadzenia kompleksowego rozwiązania e-commer-ce. Uważaliśmy, że e-biznes świetnie uzu-pełni tradycyjny model sprzedaży bezpo-średniej.

PS: Jaki był z góry założony cel?MS: Celem projektu było wprowadzenie zunifikowanego narzędzia zarządzania sprzedażą, a jednocześnie, dla setek ty-sięcy sprzedawców bezpośrednich – na-rzędzia zarządzania własnym biznesem. Chcieliśmy wdrożyć nowoczesną, przyja-zną użytkownikowi, bezpieczną, i atrak-cyjną wizualnie aplikację e-biznes, która byłby rozwinięciem systemu działającego wcześniej w Europie Wschodniej – systemu VEBSO. Nowa wersja aplikacji musiała speł-niać standardy informatyczne stosowane w naszej firmie globalnie, dlatego poszuki-waliśmy partnera, która doskonale zna roz-wiązania IBM, zarówno jeśli chodzi o ser-wery aplikacji, bazy danych, jak i hardware. Zależało nam również na jak najszybszym wdrożeniu systemu, czas jest bowiem nie-ubłagany w rozwiązaniach informatycz-nych. Systemy starzeją się bardzo szybko i jeśli proces wdrożenia trwa zbyt długo, to okazuje się potem, że system jest nieade-kwatny do oczekiwań rynku.

PS: Jak wyglądała realizacja projektu?MS: Zespół, który bezpośrednio pracował nad projektem był nieliczny, jednak zaple-cze merytoryczne bardzo duże. Każde roz-wiązanie weryfikowane było przez stwo-rzony przez Amway zespół ekspertów w da-

Wywiad z Markiem Sodolskim i Tomaszem Skutnikiem

Amway – lider sprzedaży bezpośredniej i e-point SA – czołowy polski developer systemów IT budowanych w oparciu o Javę – zjednoczyły siły, by stworzyć nowoczesny e-commerce – nową platformę Amway Online.

Marek Sodolski – dyrektor naczelny firmy Amway Polska

Tomasz Skutnik – dyrektor działu badań i rozwoju firmy e-point SA.

Page 75: PHP Solutions 06 2007 PL

Wywiad

74 06/2007

Wywiad

75www.phpsolmag.org

nej dziedzinie. Na każdym etapie prac do weryfikacji włączani byli również użytkow-nicy, którzy oceniali m.in. prototyp. W trak-cie realizacji projektu zespoły w każdym z krajów były zaangażowane na różnych eta-pach – analizy, tworzenia specyfikacji, te-stowania oraz podczas samej implementa-cji systemu. Każde wdrożenie było wspar-te pracą grupy projektowej, która kontak-towała się z użytkownikami, przeprowa-dzała dla nich i dla pracowników szkolenia. Ten system pracy ”bezpośredniej” spraw-dził się, ponieważ nie wszytko można za-łatwić mailem, telefonem czy wideokonfe-rencją. To było wyzwanie. Zarówno e-po-int, jak i my nie prowadziliśmy wcześniej takiego projektu i wzajemnie się uczyli-śmy. To był proces doskonalenia swoich umiejętności, czasem nauki od podstaw, który w ciągu dwóch lat doprowadził do tego, że rozszerzając projekt na kolejne kraje mieliśmy jasno podzielone role. Ca-ły projekt trwał dwa lata. Tam, gdzie działał już poprzedni system - VEBSO wprowadza-liśmy nowy system w ciągu sześciu miesię-cy. W tym czasie udało nam się tego doko-nać w ośmiu krajach.

PS: Wiemy, że odnieśli Państwo ogromny sukces dzięki współpracy Amway'a oraz firmy e-point S.A. Stąd pytanie - jak doszło do zjednoczenia sił na potrzeby tego projektu? Skąd wybór akurat firmy e-point?Tomasz Skutnik (e-point): Firma e-point została wybrana z jednego prostego po-wodu: była najlepsza technicznie. Przed-stawiliśmy najlepszą ofertę w zakresie ar-chitektury technicznej i procesu dostar-czenia wysokiej jakości rozwiązania. My-ślę, że byliśmy najbardziej konkurencyj-

ni. I dotrzymaliśmy słowa - wszystko to, co zaprezentowaliśmy na etapie przygoto-wania projektu, zostało zrealizowane. Fir-ma Amway dostała taki produkt i zmieściła się w takim budżecie i w takim czasie, jaki uzgodniliśmy na samym początku. MS: Otrzymaliśmy od firmy e-point znacz-nie więcej niż się spodziewaliśmy. E-po-int wniosła dużo wartości dodanych i wie-le ciekawych pomysłów, które wzbogaci-ły dotychczas funkcjonujące rozwiązania e-commerce. Niewątpliwie pomogło nam doświadczenie. W pracach nad projektami e-commerce znajomość tej branży jest nie-zbędna. Firma e-point znalazła się na bar-dzo krótkiej liście firm, które naszym zda-niem mogłyby podjąć się tego zadania. By-liśmy przekonani, że znajomość techno-logii, organizacja pracy, a także otwarte i kreatywne podejście będą podstawowymi umiejętnościami. Takie założenie sprawiło, że zaprosiliśmy e-point do złożenia oferty. Nie jest tajemnicą, że na rynku e-biznesu w Polsce jest kilka firm oferujących podob-ną jakość rozwiązań. Istniały jednak pew-ne warunki brzegowe, które zadecydowa-ły, że zaprosiliśmy tylko i wyłącznie e-point z Polski oraz kilka firm zagranicznych. Jed-nym z warunków była znajomość techno-logii i dobre relacje z IBM w Polsce oraz w innych krajach europejskich, bo nasza fir-ma od lat stosuje ich rozwiązania, zarówno back office jak i e-commerce.

PS: Jak układała się Państwa współpraca? Czy była zgodna, bez żadnych sprzeci-wów? Czy dochodziło do pewnych różnic w poglądach i ostrej wymiany zdań?TS: Zawsze na początku klient czegoś oczekuje, a my staramy się to zrozumieć i pomóc. Pewne sugestie uwzględniamy,

innym razem proponujemy alternatywne rozwiązania. Kluczowy obszar, w którym jest najwięcej do przedyskutowania to in-tegracja z systemami back office’owymi. Konieczne było przejście całego procesu ustalania protokołów przesyłania danych, aby zamówienia sprawnie przepływały. Wydaje mi się, że udało nam się osiągnąć naprawdę bardzo wartościowy konsensus co do tego, jak system ma działać. I zawsze współpraca przy tego rodzaju projektach nie obywa się bez tarć. Wystarczy jednak dobra wola z obu stron plus chęć dokoń-czenia projektu i wszelkie tego typu pro-blemy „w różnicach poglądów” przestają mieć znaczenie. Najważniejsze było to, że wszyscy pracowaliśmy w imię osiągnięcia wspólnego celu.MS: Nam pomaga doświadczenie w sprze-daży bezpośredniej. To jest biznes oparty na pracy z ludźmi, który zakłada, że do każde-go partnera, który pragnie z nami współpra-cować, a jest ich w Polsce dziesiątki tysięcy, podchodzimy z szacunkiem. Mamy świado-mość, że każdy może wnieść coś wartościo-wego, niezależnie od wielkości firmy. Jeste-śmy specjalistami od sprzedaży bezpośred-niej, ale to firma e-point jest specjalistą od systemów informatycznych.

PS: Ile wersji oprogramowania dzieliło podstawowy system od zaakceptowane-go przez klienta?TS: Wszystko zależy od tego, jak na to pa-trzeć. Zanim system pojawił się w produk-cji, było kilka wersji testowych. Od momentu wejścia w fazę produkcyjną również powsta-ło kilka wersji. W tej chwili, licząc od wdroże-nia produkcyjnego, było kilkanaście wersji, przy czym są to tzw. wersje bug fix’owe, czyli naprawiające błędy, ewentualnie usprawnia-jące efektywność. Sam rdzeń nie przecho-dził żadnej gruntownej zmiany od momen-tu wdrożenia.MS: Został zbudowany system, który jest pewnym trzonem, systemem zasadniczym – częścią wspólną dla wszystkich dziesię-ciu krajów, które działają w jednym obsza-rze biznesowym oraz Rosji, która jest trak-towana jako odrębny rynek. Trzon systemu jest ten sam, ale każdy z krajów wykorzystu-je różne specyficzne funkcjonalności, głów-nie dotyczące realizacji zamówień i płatno-ści. Jest jedna wersja systemu zasadnicze-go i kilkanaście wersji lokalnych. Aby speł-nić wszystkie potrzeby użytkowników sys-tem został przygotowany w języku lokalnym oraz w wersji angielskiej.

PS: Jak wyglądała sprawa testów? Ile trwały i jakie metodologie testowania zastosowano?TS: Mamy dwie podstawowe metody za-pewniania wysokiej jakości naszych roz-Rysunek 1. Zdjęcie z 21. Światowego Kongresu IPMA w Krakowie

Page 76: PHP Solutions 06 2007 PL

Wywiad

76 06/2007

wiązań. Po pierwsze, jest platforma One Web, którą stworzyliśmy na własny uży-tek w celu wdrażania właściwie wszyst-kich rozwiązań e-commerce realizowanych dla naszych klientów. Jest to rdzeń, na ba-zie którego budujemy kolejne rozwiązania – w sposób szybki i niewielkim kosztem. Druga to zintegrowane testowanie właści-wie od samego początku procesu produk-cyjnego, od momentu wdrożenia projek-tu, kiedy testowanie polega na przeglądzie specyfikacji, a także w trakcie sprawdzania czy specyfikacje te są spójne. W momen-cie implementacji systemu zawsze mamy zarezerwowany czas i zespół ludzi, aby od początku pisać testy jednostkowe i od razu korzystać z odpowiednich narzędzi prze-znaczonych do testowania.

Obecnie używamy narzędzia IBM Ratio-nal Functional Tester, które symuluje użyt-kownika korzystającego z przeglądarki, kli-kającego w system. Krótko mówiąc testo-wanie zaczynamy od momentu napisa-nia przez nas pierwszej linijki kodu. Pro-dukt musi przejść wiele testów, w tym te-stów nowych funkcjonalności, zanim zo-stanie zaakceptowany przez klienta i wej-dzie do użytku. MS: System e-point jest zintegrowany z naszymi systemami. Po testach, system jest przekazywany do nas i są sprawdza-ne elementy wspólne, tzn. czy funkcjonal-ność front -endowa działa z naszymi syste-mami back-endowymi. W naszej firmie jest wyspecjalizowany zespół Quality Assuran-ce - testerów, którzy sprawdzają wszyst-kie rozwiązania back-endowe i front-en-dowe standardowo, niezależnie od kraju czy systemu.

Oprócz tego systemy były testowane lo-kalnie. Jest wersja zasadnicza, trzon syste-mu – wspólny dla wszystkich krajów, na-tomiast funkcjonalność była sprawdzana indywidualnie – lokalnie, po dwóch stro-nach front i back-endu. Proces testowa-nia był dość skomplikowany, szczególnie, że istniały zależności czasowe pomiędzy krajami. Zespół testujący dostawał aplika-cję w miejscu, gdzie miała być ona wdro-żona. Niezwykle istotne było, aby osoby wdrażające na front i back-endzie mogły od razu odpowiadać na pytania lokalnych użytkowników, pomagając im w tym pro-cesie. Ten zabieg znacznie usprawnił całą fazę testowania, pomógł lepiej zrozumieć, jak system działa, jakie ma zalety, czasem jakie ograniczenia dla osób pracujących w poszczególnych biurach.

PS: Wiadomo, iż każda realizacja wy-maga zastosowania odpowiedniego zabezpieczenia. Jakie Państwozastosowali?TS: Sama architektura hostingowa jest za-bezpieczona wielowarstwowo – poprzez fi-re wall naszego dostawcy internetu oraz fi-re wall’e front-endowe. Ponadto, wszystkie serwery pracują na warstwach http, aplika-cyjnych i bazy danych, podzielonych na sie-ci VLAN i są one zabezpieczone dodatko-wo fire wall’em. Aplikacja sama w sobie ma mnóstwo mechanizmów z zabezpieczenia-mi przed nadużyciami aplikacyjnymi – został stworzony proces przeglądu kodu. Mamy odpowiednio podzielone strefy bezpieczeń-stwa, dlatego osoby chcące dokonać włama-nia już na samym początku napotkają barie-ry nie do pokonania.

MS: Zabezpieczenia to element krytyczny. Wybór partnera posiadającego doświad-czenie i znajomość technologii gwarantuje nam wysoki poziom zabezpieczeń, zarówno w przypadku aplikacji, jak i całej architektu-ry systemu. Kwestia bezpieczeństwa jest dla nas bardzo istotna – musimy mieć gwaran-cję maksymalnej ochrony przed włamania-mi, kradzieżą danych klientów, manipulacja-mi czy nadużyciami.

PS: Platforma e- commerce ma wiele zalet. Proszę podać kilka?MS: System został opracowany w taki spo-sób, aby spełnić rolę wielofunkcyjnego „na-rzędzia” – do zarządzania sprzedażą, ko-munikowania się, edukacji i zarządzania biznesem niezależnego przedsiębiorcy Am-way. Umożliwia niezależnym przedsiębior-com zarówno monitorowanie realizowa-nych obrotów, sprzedaży i stanu realizacjizamówień, jak i korzystanie z bibliotekiwiedzy przydatnej do prowadzenia włas-nego biznesu, pozyskiwania informacji o produktach, działaniach marketingowychfirmy czy aktualnych promocjach.

Z systemu mogą również korzystać klien-ci finalni i indywidualnie przeglądać ofertę produktów oraz dokonywać zamówień na konto opiekującego się nimi niezależnego przedsiębiorcy Amway. Użytkownicy plat-formy mają do dyspozycji skrzynki mailo-we, za ich pomocą mogą komunikować się zarówno z firmą, swoimi klientami, jak i mię-dzy sobą. Amway Online jest jak wirtualne biuro – służy do zarządzania biznesem i re-lacjami na wszystkich trzech poziomach: fir-ma – sprzedawca bezpośredni – klient. Jest więc to rozwiązanie zarówno B2B, jak i B2C.

PS: Jakie mają Państwo plany na przyszłość? Czy przewidują Państwo dalszy rozwój platformy?MS: Najbliższe plany to wdrożenie systemu e-commerce na rynkach Europy Zachodniej, w oparciu o rozwiązanie zastosowane w Europie Wschodniej. Platforma okazała się spektakularnym sukcesem, stąd też zainte-resowanie jej wdrożeniem na zachodzie Eu-ropy. Poza tym będziemy wprowadzać no-we funkcjonalności, na przykład bardziej zaawansowane zarządzanie relacjami z klientami – pojawią się elementy CRM-u.

Już wkrótce zaoferujemy naszym nie-zależnym przedsiębiorcom prowadzenie księgowości on-line, a także e-learning, czyli system prowadzenia szkoleń i mo-nitorowania ich wyników poprzez platfor-mę. Chcemy również wykorzystywać plat-formę do prowadzenia badań opinii i mo-nitorowania zadowolenia klientów – oczy-wiście również on-line.

PS. Dziękuję za rozmowę.

Rysunek 2. Zdjęcie z 21. Światowego Kongresu IPMA w Krakowie, Marek Sodolski, dyrektor naczelny Amway Polska (w środku), Marcin Żuchowicz, Prezes Zarządu e-point SA (pierwszy z prawej)

Page 77: PHP Solutions 06 2007 PL

77

Recenzja

www.phpsolmag.org

Język PHP swoją popularność zawdzięcza m.in. szerokiemu dostę-powi do rozszerzeń i bibliotek. Najważniejszym ich źródłem jest PEAR – internetowe repozytorium rozszerzeń. Przy jego pomocy możemy wykonać niemal każdą operację w PHP. Książka „PEAR. Programowanie w PHP” pokazuje, jak wykonywać codzienne za-dania z użyciem klas z pakietów PEAR. Można przeczytać, jak ob-sługiwać bazy danych za pomocą pakietu MDB2 oraz jak wyświe-tlać tabele, kalendarz, arkusz kalkulacyjny, data grid, czy jak wyge-nerować dokument PDF. Pozwala na zapoznanie się z pracą z do-kumentami XML – tworzenie, analizowanie oraz przekształcanie. Można zobaczyć, jak przekształcać obiekty PHP na format XML i odwrotnie. Pomocne może też być zapoznanie się, jak pracować z datami. Jest tu pokazane, jak tworzyć własne usługi WWW oraz jak używać innych udostępnionych interfejsów.

Książka ta jest skierowana zarówno do osób które z pakietemPEAR nie miały do czynienia, jak i do tych, którzy znają i używa-ją tych bibliotek. Napisana jest przystępnym językiem. Pokazuje krok po kroku na przykładach jak wydajnie i skutecznie używać jej na co dzień. Wszelkie wprowadzenia poparte są prostymi przy-kładani. Wszystkie przykłady oparte są na PHP5, pokazano rów-nież różnice z PHP4. Osoby, które jeszcze nie miały do czynienia z pakietami PEAR, w łatwy sposób zapoznają się z nimi i z me-todologią ich używania. Natomiast osoby znające i korzystające z dobrodziejstw tych pakietów, poszerzą swoją wiedzę i w razie po-trzeby szybko odnajdą pożądany przykład.

Zrecenzował: Paweł Kołodziej

Wydawnictwo: HelionAutorzy: Stephan Schmidt, Stoyan Stefanov, Carsten Lucke, Aaron WormusCena: 44,00 złISBN: 978-83-246-0897-3Ocena: 4

Umieszczenie strony WWW na pierwszej stronie wyników w wy-szukiwarce Google, dla znaczącej części użytkowników interne-tu, wydaje się czymś niesamowicie skomplikowanym. Wielu re-zygnuje z samodzielnej próby wypozycjonowania strony, zlecając tą czynność wyspecjalizowanym firmom. Jednak jak pokazuje Pa-weł Kobis w swojej książce, umieszczenie serwisu w top 10, w wy-nikach wyszukiwania, nie jest wcale takie trudne. W „Marketing z Google” zapoznamy się z różnymi punktami widzenia na techni-ki i sposoby pozycjonowania. W trakcie lektury dowiemy się nie-zbędnych rzeczy związanych z optymalizacją strony WWW. Dzię-ki temu będziemy wiedzieć, jak właściwie formatować treść w me-tatagach, takich jak title lub description, aby strona została do-brze odebrana przez wyszukiwarkę, jak i przez osoby poszukujące konkretnej treści. Autor bardzo dokładnie opisuje, jak osiągnąć cel i wyprowadzić naszą stronę na sam szczyt wyników wyszukiwania.

Plusem książki jest zwrócenie uwagi na wpływ standardów W3C, na pozycjonowanie strony. Poza tym, warto zauważyć fakt poru-szenia tematyki spamu, ponieważ, jak się przekonamy w trakcie lektury, granica pomiędzy spamem a rozwiązaniami legalnymi jest bardzo płynna. Do książki dołączona jest również płyta CD z opro-gramowaniem wspomagającym pozycjonowanie stron WWW. Dzięki oprogramowaniu takiemu jak: Web CEO lub SEO Studio, w szybki sposób będziemy w stanie zorientować się, jakich słów kluczowych użyć oraz jak poprawić naszą stronę, aby była lepiej odbierana przez wyszukiwarki. Podsumowując, książka jest pozy-cją godną polecenia dla każdego, kto potrzebuje wiedzy związanej z SEO do własnoręcznego pozycjonowania lub do wynegocjowania jak najlepszej oferty z firmą, która zrobi to za nas.

Zrecenzował: Łukasz Skowroński

PEAR. Programowanie w PHP

Wydawnictwo: Wydawnictwo Naukowe PWNAutor: Paweł KobisCena: 44,90 złISBN: 978-83-01-15133-1Ocena: 5

Marketing z Google. Jak osiągnąć wysoką pozycję. Techniki pozycjonowania a spam

Page 78: PHP Solutions 06 2007 PL

Felieton

78 06/2007

Ostatnimi czasy miałem okazję być uczestnikiem różnych konferencji i zjazdów grup programistów wielu języków programowania. Powstało wtedy w mojej głowie pewne

pytanie: Dlaczego nie były to zjazdy programistów PHP? Naturalne jest, że grupy ludzi starają się spotkać, aby rozmawiać o swoich pa-sjach i zainteresowaniach, więc dlaczego to nie działa w przypad-ku programistów PHP? Przecież każdy z nas ma mnóstwo przyjem-ności z tworzenia zarówno stron WWW, jak i innego oprogramowa-nia wykorzystującego lub wręcz bazującego na PHP. Osobiście, jeżeli tylko spotykam znajomą mi osobę, zajmującą się programowaniem na potrzeby internetu, zawszę zamienię kilka zdań na temat pozna-nych nowinek. Spotkana osoba bardzo chętnie podejmuje rozmo-wę, również dzieląc się swoimi doświadczeniami i spostrzeżenia-mi. Dlaczego więc nie istnieją zloty programistów PHP? Można tu-taj podać kilka powodów takiego stanu rzeczy. Pierwszy i chyba naj-bardziej oczywisty to pieniądze. Organizacja takiego spotkania wią-że się z kosztami. Zastanówmy się więc, kto mógłby zarobić na ta-kim zjeździe? Zarobić mogłyby wszystkie firmy hostingowe, ponie-waż stwarza to świetną okazję do zaprezentowania swoich usług. Rynek usług hostingowych jest już mocno przesycony i reklama np. poprzez sponsorowanie imprezy, pokazałaby przyszłym odbiorcom, u kogo warto postawić nasz serwis. Obecnie firmy hostingowe sta-rają się reklamować swoje usługi, nieraz nie trafiając do właściwe-go odbiorcy. Przy zorganizowaniu konferencji, promowane usłu-gi trafiłyby tylko do zainteresowanych osób, przez co reklama sta-łaby się opłacalna. Zarobić na takim zjeździe mogłyby również fir-my zajmujące się rozpowszechnianiem oprogramowania wspoma-gającego pracę w PHP, czyli np. firmy tworzące różnego rodzaju edy-tory. Istnieje kilka polskich firm zajmujących się tworzeniem takie-go właśnie oprogramowania, jak również wiele zagranicznych, ma-jących swoje przedstawicielstwa w Polsce. Zarobić na takim zlocie, choć może nie w dosłownym znaczeniu, mogłyby również firmy po-szukujące pracowników na stanowisko programistów i webmaste-rów. Obecne zapotrzebowanie na programistów jest ogromne i taki właśnie zjazd pomógłbym firmom w przedstawieniu się jako dobrzy pracodawcy i zachęceniu do pracy właśnie u nich. Na końcu zarobi-liby również sami uczestnicy, choć w ich przypadku byłoby to raczej pogłębienie wiedzy, zorientowanie się w nowościach na rynku oraz wymienienie opinii. Może to się przełożyć w dalszej perspektywie na lepsze zarobki. Zwróciliśmy już uwagę na komercyjną stronę takich spotkań, ale przecież nie muszą one być organizowane przez wiel-kie firmy. Często spotkania takie organizowane są np. na uniwersy-tetach. Wtedy celem jest jedynie zwiększenie stanu wiedzy, a nie po-szukiwanie zysku. Zjazdy takie pozwalają na poznanie nowych tech-nologii i skonfrontowanie opinii na ich temat z innymi uczestnika-mi. Nie mamy wtedy do czynienia z ogromną grupą ludzi, liczoną w

setkach, ale np. z kilkudziesięciu osobową grupą fanatyków, którzy przyjechali z różnych części Polski tylko po to, aby dowiedzieć się czegoś ciekawego i nowego oraz spotkać się z innymi ludźmi o po-dobnych zainteresowaniach. Każdy z nas czuje się z pewnością ta-kim fanatykiem, jednak nie każdy jest chętny do przejechania kil-kuset kilometrów tylko dla dwóch godzin rozmowy. Jestem zdania, że dla tej atmosfery spotkań jednak warto jest pokonać przeciwno-ści takie jak długa droga, czy niesprzyjająca pogoda. Myślę, że jeże-li ktoś raz pojawi się na konferencji to z pewnością będzie pojawiać się i na kolejnych. Przecież każdy z nas lubi poczuć się czasem mą-drzejszym lub też wyznaczyć sobie kolejne cele do osiągnięcia po-przez poznanie własnych słabych stron czy luk w wiedzy. Niestety w Polsce nie istnieją żadne, cyklicznie powtarzające się zjazdy społecz-ności PHP, jak to jest np. w przypadku programistów Javy, które od-bywają się co dwa tygodnie w Warszawie. Moim zdaniem, ilość pro-gramistów PHP jest znacznie większa niż Javy, ale nie można tego zaobserwować, ponieważ trudno mówić o społeczności, która nigdy się nie spotyka. Zaryzykowałbym stwierdzenie, że niemal każdy zaj-mujący się programowaniem na poważnie, miał styczność z PHP w mniejszym bądź większym stopniu. Wg mnie wystarczy to do stwier-dzenia, że dobrze zorganizowana i rozreklamowana konferencja po-święcona temu językowi, zrzeszyłaby ogromne ilości ludzi. Za gra-nicami naszego państwa mają miejsce takie zjazdy, co łatwo można zauważyć na stronie będącej biblią dla każdego programisty PHP. W USA takich zjazdów jest mnóstwo, a w innych krajach (zazwyczaj za-chodnich) również ich nie brakuje. Taki stan rzeczy może wyjaśnić, dlaczego w Polsce, która przecież nie jest małym krajem, jedynie dwadzieścia trzy osoby posiadają certyfikat Zend, a ma on przecież swój prestiż. Wpływ na taką sytuację ma zapewne też opinia wyro-biona przez PHP 4, którego obiektowość pozostawiała wiele do ży-czenia. Nie mniej jednak, od pojawienia się PHP 5, nie można już za-rzucać PHP braku normalnej obiektowości, którą niewątpliwie po-siada. Poczekajmy, aż pojawi się PHP 6, wtedy PHP 4 odejdzie w za-pomnienie i wszyscy, którzy krytykowali PHP stracą swoje argumen-ty i zaczną traktować ten język poważnie.

Dla PHP nadchodzą najlepsze czasy. Zyskuje ono coraz większą po-pularność i możemy mieć nadzieję, że w niedługim czasie zyska ono status taki, jaki ma obecnie na zachodzie. Następstwem tego będą również konferencje i zjazdy podobnych do nas ludzi. Niestety na to wszystko musimy trochę poczekać. Możemy być pewni, że warto.

Społeczność PHP ?

ŁUKASZ SKOWROŃSKIAutor jest studentem informatyki na Uniwersytecie w Białymstoku, pracuje

również jako programista PHP w firmie E-Studio.

Kontakt z autorem: [email protected]

Page 79: PHP Solutions 06 2007 PL

v

Ciao GmbHCiao GmbH jest właścicielem wiodącego porta-lu konsumenckiego w Europie – Ciao.com. Do nowo powstałego centrum rozwoju oprogramo-wania we Wrocławiu poszukujemy doświadczo-nych programistów PHP. Chcesz dobrze zara-biać, pracować w międzynarodowym środowi-sku i w przyjaznej atmosferze – dołącz do nas.www.ciao-group.com/careers_wroclaw.php

Agencja Interaktywna– br-design.plKreowanie oraz obsługa serwisów interne-towych, programowanie aplikacji interneto-wych według indywidualnych potrzeb klienta, realizacja projektów graficznych i prezentacji multimedialnych. www.br-design.pl

Firma Informatyczna „Saulewicz”Wdrażamy technologie internetowe w opar-ciu o serwery linuxowe i rozwiązania „Open Source”. Oferujemy aplikacje bazodaniowe pracujące w środowisku PHP. Prowadzimy konsultacje dotyczące bezpieczeństwa sys-temów sieciowych.www.saulewicz.com.pl.

Agnat Sp. z o.o.Dostarcza pełen wachlarz usług związanych ze stronami WWW. Serwis www.agnat.eu obsłu-guje kilkanaście tysięcy Klientów z całej Polski oraz Unii Europejskiej, wyposażając je w do-meny internetowe, hosting, pozycjonowanie, kreację stron WWW, kampanie reklamowo-pro-mocyjne, oprogramowanie i aplikacje niezbędne do prowadzenia biznesu w sieci.

Masz ciekawy e-pomysł?Potrzebujesz pomocy!Zapewniamy profesjonalną i kompleksową obsługę w zakresie: stron internetowych – systemów zarządzania treścią; sklepów internetowych – projektów graficznych; aplikacji internetowych – drukowania off-setowego.www.intersum.pl

v

protHOSTRewelacyjny hosting o12 już od 49 zł netto/rok (w tym cPanel PL). Rejestracja domen od 1 zł netto. Webdesign i pozycjonowanie. Wszystko czego potrzebujesz.http://o12.pl

HostingElastyczny dobór pakietów, pakiet POCZTA– 40 zł, pakiet START (www, email, 10 domen, php 5, mysql, pgsql) – 150 zł, pakiety KOM-FORT, PROFIT, PROFITSSL, zarządzanie przezcPanel. Rejestracja domen globalnych, krajowych, funkcjonalnych i regionalnych. Ceny od 50 zł.www: http://www.lubman.pl,e-mail: [email protected],

Pren

umer

ata

PRO

Wię

cej i

nfor

mac

ji: patrycja.wadolowska@

software.com.pl

tel.:

022

427

-36-

69

v

DzsoftSiedziba firmy znajduje się na Ukrainie. Naszą ofertę kierujemy szczególnie do osób, które zaj-mują się językiem PHP, gdyż sami specjalizuje-my się w tym, pisząc nasz własny kod. Posia-damy również edytor Perl oraz inne przydatne oprogramowania. Nasi pracownicy to specjaliści, zajmujący się optymalizacją specyficznych po-trzeb języka PHP i Perl.http://www.dzsoft.com

Kei.plKei.pl działa na rynku usług hostingowych od 2000 roku. Do naszych zadowolonych Klientów z dumą możemy zaliczyć wiele przedsiębiorstw sektora MSP, instytucji oraz osób prywatnych. W ofercie Kei.pl znajdują się pakiety hostingowe, a także usługi dla wymagających Użytkowników – platformy e-Biznes oraz serwery fizyczne.http://www.kei.pl

ntp.plPRACA DLA PROGRAMISTY:

Entuzjazm, PHP, MySQL/ Postgress, może być część etatu.

Własne oczekiwania, opis osiągnięć z których jesteście Państwo dumni, krótką informację czemu chcecie Państwo pracować dla naszej firmy oraz CV na adres: [email protected]

Page 80: PHP Solutions 06 2007 PL

Zaprenumeruj swoje ulubione magazyny i zamów archiwalne numery!

Już teraz w kilka minut możesz zaprenumerować swoje ulubione pismo.Gwarantujemy:- preferencyjne ceny- bezpieczną płatność on-line- szybką realizację Twojego zamówienia Bezpieczna prenumerata on-line wszystkich tytułów Wydawnictwa Software!

www.buyitpress.com zamówienie prenumeraty

Page 81: PHP Solutions 06 2007 PL

Prosimy wypełnić czytelnie i przesłać faksem na numer: (22) 427 36 69 lub listownie na adres: Software-Wydawnictwo Sp. z o.o., Bokserska 1, 02-682 Warszawa, e-mail: [email protected]. Przyjmujemy też zamówienia telefoniczne: (22) 427 36 79

Imię i nazwisko............................................................................................ ID kontrahenta..........................................................................................

Nazwa firmy................................................................................................. Numer NIP firmy.......................................................................................

Dokładny adres....................................................................................................................................................................................................................

Telefon (wraz z numerem kierunkowym)................................................... Faks (wraz z numerem kierunkowym) ....................................................

E-mail (niezbędny do wysłania faktury)............................................................................................................................................................................

zamówienie prenumeraty

1 Cena prenumeraty rocznej dla osób prywatnych 2 Cena prenumeraty rocznej dla osób prenumerujących już Software Developer’s Journal lub Linux+3 Cena prenumeraty dwuletniej Aurox Linux

Jeżeli chcesz zapłacić kartą kredytową, wejdź na stronę naszego sklepu internetowego:

www.buyitpress.com

automatyczne przedłużenie prenumeraty

Tytuł Ilość numerów

Ilość zamawianych prenumerat

Od numeru pisma lub miesiąca

Opłata w zł

z VATSoftware Developer’s Journal (1 płyta CD)– dawniej Software 2.0Miesięcznik profesjonalnych programistów

12 250/1801

SDJ Extra (od 1 do 4 płyt CD lub DVD)– dawniej Software 2.0 Extra!Numery tematyczne dla programistów

6 150/1352

Linux+DVD (2 płyty DVD)Miesięcznik o systemie Linux 12 199/1791

Linux+Extra! (od 1 do 7 płyt CD lub DVD)Numery specjalne z najpopularniejszymi dystrybucjami Linuksa 8 232/1982

PHP Solutions (1 płyta CD)Dwumiesięcznik o zastosowaniach języka PHPOd 2008 roku będzie miesięcznikiem. Cena prenumeraty rocznej wyniesie 199 PLN. Do końca roku prenumerata w starej cenie.

12 135

hakin9, jak się obronić (1 płyta CD)Miesięcznik o bezpieczeństwie i hakingu 12 1991/219

.psd (2 płyty CD)Dwumiesięcznik użytkowników programu Adobe Photoshop 6 140

.psd numery specjalne (.psd Extra + .psd Starter Kit) 6 140

Suma

Page 82: PHP Solutions 06 2007 PL

W sprzedaży od grudnia

W następnym numerze PHP Solutions 1/2008 (24)

I wiele innych artykułów, których nie możesz przeoczyć!

TECHNIKA

n MySQL - techniki przyśpieszania zapytań

n Kontrola zasobów FTP przy pomocy PHP

Redakcja zastrzega sobie możliwość zmiany zawartości pisma.

UWAGA!! NOWE TESTY KONSUMENCKIE

n Pozycjonowanie stron WWW

NARZĘDZIA

n Subversion – system kontroli wersji

dla każdego

NOWE ARTYKUŁY W DZIAŁACH

n dla początkujących

n dla zaawansowanych

n kasa dla webmastera

Page 83: PHP Solutions 06 2007 PL
Page 84: PHP Solutions 06 2007 PL