You are on page 1of 84

SPIS TREŚCI

06 AKTUALNOŚCI
Ireneusz Wierzejski

08 OPIS CD

DLA POCZĄTKUJĄCYCH
10 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 Vanilla
Paweł Chwast
Paweł 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ń.

TECHNIKA
22 PHP i WAP
Tomasz Roszko
Tomasz 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 PHP
Artur Chudzik
Artur 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.

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

Dyrektor wydawniczy: Sylwia Pogroszewska

Redaktor naczelny: Patrycja Wądołowska patrycja.wadolowska@software.com.pl

Redaktorzy prowadzący: Anna Kozioł anna.koziol@software.com.pl


Magdalena Sobiś magdalena.sobis@software.com.pl

Projekt okładki: Agnieszka Marchocka

Skład i łamanie: Robert Zadrożny robert.zadrozny@software.com.pl

Kierownik produkcji: Marta Kurpiewska marta.kurpiewska@software.com.pl

Korekta: Agnieszka Bronowicka agnieszka.bronowicka@um.wroc.pl


Wyróżnieni betatesterzy: G. Hibner, H. Woroszył, A. Trafalski

Dział reklamy: adv@software.com.pl


Prenumerata: Marzena Dmowska pren@software.com.pl

Nakład: 6 000 egz.

4 06/2007
ROZWIĄZANIA KASA DLA WEBMASTERA
32 Creole 62 SEO i SEM
Piotr Gradziński Piotr Kenig
Piotr przedstawi Ci, jak pisać skrypty łączące się z różnymi typami Piotr porusza podstawowe aspekty związane z przeprowadzeniem
baz danych - od połączenia poprzez zapytania aż do obróbki wyni- kampanii marketingowej pod kątem działań SEO i SEM dla małych
ków. Do tego celu użyje pakietu Creole oraz pokaże Ci jak wykorzy- i średnich firm.
stać niektóre narzędzia biblioteki Jargon.

38 AJAX w CakePHP ARTYKUŁ WARSZTATOWY


Piotr Gapiński 66 Delphi for PHP
Piotr pokaże Ci praktyczne zastosowanie technologii AJAX w środo- Łukasz Skowroński
wisku framework'u CakePHP. Po analizie przedstawionego kodu bę- Pierwszy z trzech artykułów warsztatowych opisujący pratyczne za-
dziesz mógł wzbogacić własny serwis o dynamicznie prezentowane stosowanie programu Delphi for PHP. Lektura tych artykułów pomo-
dane. Po zapoznaniu się z artykułem, dowiesz się, że dzięki zastoso- że wam w wykonaniu własnej aplikacji i zdobyciu rewelacyjnych na-
waniu framework’ów, takich jak CakePHP możesz zwiększyć funkcjo- gród w ogłoszonym konkursie.
nalność serwisów.

44 Atom TESTY KONSUMENCKIE


Patryk Szlagowski 70 UPS
Patryk 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- WYWIAD
SQL i operacji na plikach. 74 Wywiad z Markiem Sodolskim (Amway)
i Tomaszem Skutnikiem (e-point)
Magdalena Sobiś, Anna Kozioł
NARZĘDZIA Wywiad z Markiem Sodolskim – dyrektorem naczelnym Amway Pol-
46 Google Web Toolkit ska oraz Tomaszem Skutnikiem – dyrektorem badań i rozwoju fir-
Rafał Malinowski my e-point.
Rafał 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- RECENZJE
ogle Web Toolkit. 77 PEAR i Marketing z Google
Paweł Kołodziej, Łukasz Skowroński
54 PayPal – omówienie i zalety
Mariusz Wielkopolski, Mariusz Tytyk
Mariusz pokaże Ci, jak założyć sobie konto w PayPal. Dowiesz się jak FELIETON
zintegrować płatności ze swoją stroną internetową i jak testować 78 Społeczność PHP?
moduł płatności nie używając prawdziwych pieniędzy. Łukasz Skowroński

Adres korespondencyjny:
Software-Wydawnictwo Sp. z o.o., Redakcja używa systemu automatycznego składu
ul. Bokserska 1, 02-682 Warszawa, Polska
tel. +48 22 427 36 86, fax +48 22 427 36 69 Do tworzenia wykresów i diagramów wykorzystano program firmy
www.phpsolmag.org cooperation@software.com.pl

Osoby zainteresowane współpracą prosimy o kontakt:


Dołączoną do magazynu płytę CD przetestowano programem AntiVirenKit firmy cooperation@software.com.pl
G DATA Software Sp. z o.o.
Druk: ArtDruk
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 Wysokość nakładu obejmuje również dodruki. Redakcja nie udziela pomocy
za efekty wykorzystania ich; nie gwarantuje także poprawnego działania programów technicznej w instalowaniu i użytkowaniu programów zamieszczonych na płycie
shareware, freeware i public domain. CD-ROM dostarczonej razem z pismem.

Sprzedaż aktualnych lub archiwalnych numerów pisma po innej cenie niż


Uszkodzone podczas wysyłki płyty wymienia redakcja. wydrukowana na okładce – bez zgody wydawcy – jest działaniem na jego
szkodę i skutkuje odpowiedzialnością sądową.

Wszystkie znaki firmowe zawarte w piśmie są własności odpowiednich firm zostały Pismo ukazuje się w następujących wersjach językowych:
użyte wyłącznie w celach informacyjnych.
polskiej , francuskiej

www.phpsolmag.org 5
Aktualności

Alladyn i strona ZPAV

Php Blue Dragon 3.0.0


Minęły już prawie trzy miesiące od czasu
ogłoszenia, że strona internetowa Związ-
ku Producentów Audio-Video (ZPAV) naru-

P
sza licencję skryptu Alladyn. Jednak przed- olski system CMS rozbudowuje się co- sła, listę użytkowników oraz prywatne wia-
stawiciele Związku jak dotąd nie wyjaśnili raz bardziej. Jest on dostępny na zasa- domości które użytkownicy mogą do siebie
tej sprawy, a chodzi przecież o organizację, dach licencji GNU GPL. Właśnie kil- wysyłać.
która na co dzień zajmuje się ochroną praw
autorskich twórców.
ka dni temu pojawiła się wersja 3.0.0. Ta wer- Dodatkowo został wprowadzony podział
Przypomnijmy więc pokrótce - kilka osób sja została wzbogacona w nowe elementy sys- na grupy który przydaje się na forum do de-
przeglądając źródła witryny ZPAV dostrze- temu takie jak na przykład edytor WYSIWYG finiowania dostępu i moderatorów danego
gło, że korzysta ona ze skryptu o nazwie TinyCE który dostępny jest z panelu admini- działu.
Alladyn, a licencja tej biblioteki wymaga stratora. CMS posiada także opcję przeznaczoną dla
zamieszczenia informacji o jej wykorzysta-
Dzięki niemu można wpisywać treści od ra- redaktorów, każdy użytkownik może zostać ad-
niu, czego w kodzie strony ZPAV nie ma ani
teraz, ani nigdy wcześniej nie było. zu bez potrzeby ich podglądu na stronie. Do- ministratorem jednego działu który przydzieli
Witrynie ZPAV przyjrzeli się także sami datkowe zmiany zostały także wprowadzone mu administrator.System ten doczekał się już
twórcy Alladyna. Spostrzegli oni, iż sko- w klasie do generowania formularzy zwiększa- ponad 450 stron opartych o niego oraz licznej
rzystano na niej ze zmodyfikowanej wersji jąc ich pole. Pojawiły się poprawki pozwalające społeczności.
tego skryptu, na co nie zezwala żadna na pracę systemu w PHP wersji 5 która obec- Można także zakupić wersję CMS w opcji
licencja. Stało się więc oczywiste, że ZPAV,
nie jest wersją stabilną. Premium która zawiera bardziej rozbudowane
który korzystając z pomocy policji, ściga
osoby i firmy łamiące prawo autorskie, sam System jest też dostępny w dwóch językach: menu administratora pozwalające na definio-
to prawo łamie. polskim i angielskim, które można wybrać pod- wanie własnych stron z dowolną treścią, pod-
Po pewnym czasie, zupełnie bez związ- czas instalacji, a następnie zastosować podczas stron dla nich, a także deklarowania modułów
ku z tą sprawą, biblioteka Alladyn została wprowadzania treści. do wprowadzania treści.
upubliczniona na licencji Open Source a jej Sam system w obecnej wersji zawiera po- Moduły działają dokładnie w taki sam spo-
autorzy ogłosili, że chcieliby, aby była ona
jak najczęściej stosowana. Nie wpłynęło to
nad 35 modułów: nowości, proste nowości, sób jak w przypadku darmowej wersji. Jed-
jednak w żaden sposób na fakt, że witry- artykuły, zaawansowane artykuły, pobiera- nak wersja płatna daje o wiele większe możli-
na Związku wcześniej tę licencję naruszy- nie, słownik, FAQ, strony informacyjne, fo- wości w zarządzaniu swoją stroną WWW.
ła, a na stronie ZPAV najprawdopodobniej rum dyskusyjne z możliwością tworzenia Dodatkowo system posiada także edytor
nadal znajduje się wersja biblioteki, która grup i podgrup. TinyMCE zintegrowany ze wszystkimi pola-
została tam zamieszczona z naruszeniem
Posiada on także liczne bloki do prezento- mi do wprowadzania treści.
warunków licencji.
Związek Producentów Audio-Video koja- wania wprowadzonych treści: menu systemo-
rzony jest przede wszystkim z antypiracki- we, najnowsze i najczęściej czytanie nowo-
mi akcjami policji. Warto jednak nadmienić, ści, najnowsze artykuły, pliku do pobrania,
że organizacja statutowo zajmuje się rów- informacje, wyszukiwarkę Google oraz wie-
nież edukacją, a jednym z jej sztandaro- le innych.
wych programów jest akcja „Bądź oryginal-
Dla użytkowników systemu został wypo- Strona domowa: http://phpbluedragon.pl/
ny”. Za jej pomocą ZPAV stara się zaszczepić
przekonanie, iż naruszanie praw autorskich sażony w system rejestracji, logowania, zmia- Strona systemu CMS: http://phpbluedragon.pl/
jest nieetyczne oraz, że należy szanować ny profilu, zmiany hasła, przypominanie ha- php-blue-dragon-cms/
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 PHP4
Cią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 Rysunek 1. Strona domowa systemu Php Blue Dragon CMS

6 06/2007
Aktualności

Kto edytuje Wikipedię

Strona internetowa Student California Institute of Techno-


logy Sam Griffith zaprojektował narzę-
dzie o nazwie WikiScanner, które umożli-

jest czasopismem wia sprawdzenie jakie firmy i organizacje


edytowały artykuły zamieszczane w Wiki-

D
nia 27 lipca Sąd Najwyższy wydał dziennikiem lub czasopismem? Jak najbardziej pedii. WikiScanner identyfikuje autorów
edycji na podstawie adresów IP, z któ-
wyrok potwierdzający zasadność re- tak. Prawo Prasowe w artykule 7. ustęp 2. mó- rych dokonana została zmiana w ency-
jestracji stron internetowych jako wi wyraźnie: „W rozumieniu ustawy: klopedii. Dzięki temu, iż w bazie Wiki-
prasy. Obowiązek rejestracji przewiduje art. 20 1) prasa oznacza publikacje periodyczne, Scannera umieszczono ponad 2 mln róż-
ustawy, a co więcej podtrzymał go również Try- które nie tworzą zamkniętej, jednorodnej cało- nych organizacji i prawie 34.5 mln zapi-
bunał Konstytucyjny. Sam problem rejestracji ści, ukazujące się nie rzadziej niż raz do roku, sanych edycji na stronach Wikipedii, któ-
rych dokonano na przestrzeni ostatnich
witryn internetowych jako prasy pojawił się po opatrzone stałym tytułem albo nazwą, nume-
pięciu lat już wykryto, że zmiany doko-
raz pierwszy na początku roku 2007 roku, kie- rem bieżącym i datą, a w szczególności: dzien- nane były z komputerów należących do
dy Trybunał Konstytucyjny orzekł, że karanie niki i czasopisma, serwisy agencyjne, stałe prze- CIA, IBM, Białego Domu oraz Kurii Waty-
osób które nie dopełniły obowiązku rejestracji kazy teleksowe, biuletyny, programy radiowe i kańskiej.
prasy jest zasadne i zgodne z Konstytucją RP, telewizyjne oraz kroniki filmowe; prasą są tak-
Rewolucja w domenach
ponieważ jak mówi Prawo Prasowe w artyku- że wszelkie istniejące i powstające w wyniku
NASK przygotował dla wydawców inter-
le 20. ustęp 1.: „Wydawanie dziennika lub cza- postępu technicznego środki masowego prze- netowych niespodziankę. Znany już m.in.
sopisma wymaga rejestracji w sądzie wojewódz- kazywania, w tym także rozgłośnie oraz te- w Europie Zachodniej i Stanach Zjedno-
kim właściwym miejscowo dla siedziby wydaw- le - i radiowęzły zakładowe, upowszechniające czonych Domain Name Tasting ma umoż-
cy, zwanym dalej organem rejestracyjnym. Do publikacje periodyczne za pomocą druku, wi- liwić wypróbowanie domeny przed pod-
postępowania w tych sprawach stosuje się prze- zji, fonii lub innej techniki rozpowszechniania; jęciem decyzji o jej zakupie. Po co ktoś
miałby testować domenę? Aby za sym-
pisy Kodeksu postępowania cywilnego o postę- prasa obejmuje również zespoły ludzi i poszcze-
boliczną złotówkę sprawdzić jej atrak-
powaniu nieprocesowym, ze zmianami wyni- gólne osoby zajmujące się działalnością dzien- cyjność mierzoną ilością odwiedzin jaką
kającymi z niniejszej ustawy.” To samo Prawo nikarską.”Tym samym strona internetowa, któ- może ona generować. Wiadomo już, że
Prasowe w artykule 45. stwierdza: „Kto wydaje ra jest aktualizowana częściej niż raz w roku jest testowanie w ramach Domain Name
dziennik lub czasopismo bez rejestracji albo za- albo dziennikiem albo czasopismem. Tasting będzie mogło trwać do 5 dni, a po
tym czasie będzie trzeba się zdecydować
wieszone - podlega grzywnie albo karze ograni- Z faktu zaklasyfikowania strony internetowej
czy jest się zainteresowanym domeną czy
czenia wolności.” jako czasopisma wynika jeszcze jeden obowią- też nie.
Taki zapis w żadnej mierze nie ogranicza zek. Polskie prawo obliguje wydawców do przeka-
wolności słowa, ponieważ jest to jedynie wy- zywania egzemplarzy wydanych dzieł wyznaczo- Wsparcie dla HD w Flash
móg administracyjny zarejestrowania środków nym bibliotekom, a kto tego nie zrobi może zo- Firma Adobe wraz z kolejną udostęp-
nieniem użytkownikom i webmasterom
przekazu, a nie głoszonych tam poglądów i wy- stać ukarany karą grzywny. Ustawa wyraźnie mó-
wersji beta Flash Player 9 poinformowała,
rażanych opinii. Nie ma więc żadnej wątpliwo- wi o publikacjach „zapisanych na nośnikach elek- iż rozpoczyna rozwijanie formatu filmów o
ści, że póki obecne prawo prasowe nie będzie tronicznych” należy więc założyć, że także strony wysokiej rozdzielczości na potrzeby inter-
zmienione, dzienniki i czasopisma trzeba re- internetowe musimy obowiązkowo przekazać, netu. Moviestar będzie obsługiwać stan-
jestrować. Czy jednak strona internetowa jest m.in. do Biblioteki Narodowej. 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 .pl


Kilka 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
Rysunek 3. Trybunał Konstytucyjny mln domen .nl.

www.phpsolmag.org 7
Opis CD

Edytory Szablony stron WWW


Na płycie umieszczone są edytory FOXEdit - edytor do użytku ko- Na płycie znajduje się sześć unikalnych szablonów stron
mercyjnego, oraz kED 2.1.4.0. FOX Edit jest lekkim i bardzo wy- WWW. Prezentowane szablony stron są gotowymi do użycia
godnym edytorem tekstu przeznaczonym głownie dla progra- projektami stworzonymi wprost dla Ciebie. O zaletach korzy-
mistów PHP/XHTML/CSS. Od początku swojego istnienia ce- stania z gotowych szablonów do stworzenia własnej witryny
chą wyróżniającą go spośród innych edytorów jest pełna obsłu- WWW można mówić długo. Przede wszystkim takie rozwiąza-
ga Unikodu, włącznie z automatycznym rozpoznawaniem ty- nie jest o wiele prostrze.
pu kodowania wczytywanych plików tekstowych. Oprócz pod- Dzięki zamieszczonym szablonom WWW szybko i tanio
powiadaczy nazw funkcji i argumentów znanych z dużych śro- stworzysz swoją stronę. Szablon to gotowa strona wypełniona
dowisk programistycznych ciekawą funkcją edytora jest kon- łatwą do edycji grafiką. Wykorzystując prosty edytor HTML i
tekstowe kolorowanie składni, które pomaga tworzyć walidują- program graficzny, możesz przystosować stronę do swoich wy-
ce się dokumenty XHTML. Program nie używa rejestru do prze- mogów. Szablony edytować można w najprostszych progra-
chowywania swoich ustawień, dzięki czemu zawsze możesz go mach obsługujących kod HTML.
mieć ze sobą na swoim PenDrive. Więcej informacji na temat W każdym archiwum znajduje się plik PSD (otwieramy go
dostępnych funkcji edytora można przeczytać na stronie http:// programem Photoshop). W tym pliku możemy zmieniać kolo-
www.fox.com.pl/foxedit/ rystykę strony, dodać tekst lub go usunąć.
kED 2.1.4.0 to tekstowy edytor XHTML. Koloruje składnię Każdy znajdzie coś dla siebie. Szablony reprezentują róż-
dokumentów, konwertuje strony kodowe (Windows-1250, ISO- ne treści i różne może być ich przeznaczenie. Mając szablon,
8859-2, UTF-8, UTF-16), ułatwia wstawianie tabel, grafik, od- wystarczy, że wpiszesz swój tekst w odpowiednie miejsca oraz
syłaczy; umożliwia współpracę z walidatorem Tidy oraz lokalnym ewentualnie dodasz właściwe grafiki, a po chwili masz już cał-
serwerem WWW; zawiera spis znaczników wraz z ich atrybuta- kowicie gotową, profesjonalną witrynę internetową do umiesz-
mi, a ponadto pełną listę właściwości CSS2 i listę kilkudziesięciu czenia w sieci.
funkcji PHP.

Rysunek 1. FOX Edit v 1.00

8 06/2007
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: cd@software.com.pl

Redakcja nie udziela pomocy technicznej w instalowaniu


i użytkowaniu programów zamieszczonych na płytach
CD-ROM dostarczanych razem z pismem.
Dla początkujących

Symfony Framework
Część druga – Moduł użytkownik, posty, osymfony, kontakt
oraz aplikacja Backend
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.

tions.class.php do edycji i na jego końcu dopi-


Dowiesz się... Powinieneś wiedzieć... sujemy następujące linijki:
• Jak nadawać odpowiednie prawa dla modu- • Powinieneś znać podstawy programowania
łów i ich metod; obiektowego w PHP 5 oraz podstawy Propela. public function executerLogout() {
• Jak dodać swój własny helper; Znajomość CSS może pomóc w analizie strony $this->getUser()->setAuthenticated
• Poznasz doskonałe narzędzie symfony admin wizualnej. (false);
generator, dzięki któremu w prosty sposób $this->getUser()->clearCredentials();
stworzysz edycję podstron serwisu; }
• Stworzysz drugą aplikację backend dla admi-
nistratora. Następnie w katalogu templates tworzymy plik
logoutSuccess.php, w którym zamieszczamy in-
formację dla użytkownika o poprawnym wy-
poprawnie będzie mógł edytować swój pro- logowaniu. Kilka linijek i nasza metoda dzia-
fil. Poznamy również możliwość zabezpiecze- ła. Zalogujmy się i sprawdźmy. Oczywiście,
Poziom trudności nia danej metody AddPost w module posty, aby wywołać formularz logowania, wpisujemy
tak aby miał do niej dostęp tylko i wyłącznie w przeglądarce http://symfony/uzytkownik/login.
użytkownik zalogowany, oczywiście będzie Aby wylogować się wpisujemy http://symfony/
mógł edytować tylko swoje posty. Ostatecz- uzytkownik/logout.

W
pierwszej części artykułu prze- nie wprowadzimy nową aplikację backend, Zwróćmy uwagę na podobieństwo przy pro-
brnęliśmy przez instalację i kon- której głównym celem będzie ułatwienie za- cesie logowania. Użyliśmy takiej samej funkcji
figurację Symfony. Zaczęliśmy rządzania przyszłym serwisem. Zapraszamy setAuthenticated(). Różnica jest tylko taka,
również proces tworzenia nowej aplikacji, do artykułu. że jako jej parametr podajemy true albo false.
do której dodaliśmy moduł użytkownika. Z kolei funkcja clearCredentials() służy do
Zaopatrzyliśmy go w możliwość rejestracji Moduł użytkownik usuwania praw użytkownika z sesji credentials.
wraz z potwierdzeniem wysyłanym na e-ma- – metoda logout
il. Wprowadziliśmy również logowanie. Jed- Zajmiemy się najprostszą metodą modułu Moduł użytkownik
nak czym byłby serwis bez możliwości wylo- użytkownik, jaką jest logout, która będzie miała – metoda reminder
gowania, przypomnienia hasła, edycji profi- na celu wyczyszczenie sesji użytkownika utwo- Dodamy kolejną metodę reminder, która po-
lu użytkownika i dodawania do niego treści? rzonej podczas logowania. Otwieramy plik ac- może zapominalskim użytkownikom odzyskać
W tym artykule dowiemy się, jak to wszystko
można zrobić. Listing 1. Sprawdzanie e-maila
Na samym początku dodamy bardzo pro-
stą metodę logout odpowiedzialną za akcję $email = new Criteria();
wylogowania użytkownika, która będzie po- $email->setLimit(1);
legała na wyczyszczeniu sesji, w dalszej części $email->add(UzytkownikPeer::EMAIL, $this->getRequestParameter('email'));
artykułu metoda ta zostanie rozbudowana o $uzytkownik = UzytkownikPeer::doSelectOne($email);
kolejne właściwości. Trochę bardziej skom-
plikowaną metodą będzie reminder, dzię- if ($uzytkownik)
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- // jeśli istnieje użytkownik to dokonujemy zmian
gą e-mailową.
Wprowadzimy również metodę profile, }
dzięki której użytkownik, który zaloguje się

10 06/2007
Symfony Framework

hasło i przypomnieć login pod warunkiem, że } else { bezpieczamy się podwójnie, ponieważ wcze-
pamiętają jakiego adresu e-mail używali pod- // wyświetlanie formularza śniej zajmuje się tym plik reminder.yml. Przy
czas rejestracji. Na końcu pliku actions.class.php return sfView::SUCCESS; okazji będziemy mieli dostęp do ID użytkow-
dodajemy nową metodę o nazwie reminder. } nika, które jest wymagane do poprawnych
Dla przypomnienia: operacji na danych w tabeli użytkownik. Ope-
W miejscu, gdzie wykonywane są instrukcje racja ta nie zajmuje zbyt wiele pamięci i czasu,
public function executeReminder() po poprawnym wysłaniu formularza, wpisu- więc możemy ją spokojnie wykonać. Ostatecz-
{ jemy następujące linie kodu, które mają na ce- nie sprawdzamy czy dany e-mail istnieje, jeśli
// zawartość metody lu generowanie kodu do potwierdzenia zmian tak, to dokonujemy zmian w haśle i potwier-
} oraz nowego hasła: dzeniu, przypisując do nich kolejno zmien-
ne $potwierdzenie i $nowe _ haslo. Następ-
Uzupełniamy ją następującymi liniami: $potwierdzenie = mt_rand(10000,99999); nie wysyłamy e-mail z potwierdzeniem zmian
$nowe_haslo = substr(md5(uniqid(rand(), i nowym hasłem. Na koniec wyświetlamy sza-
if ($this->getRequest()->getMethod() == true)), 0, 7); blon nowe_hasloSuccess.php z katalogu templa-
sfRequest::POST) { tes. Sprawdzanie e-maila przeprowadzamy
// gdy formularz został Kolejnym krokiem będzie sprawdzanie poda- przy pomocy następującego fragmentu kodu
wysłany poprawnie nego e-maila w formularzu, dzięki czemu za- (Listing 1.)

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

$mail = new sfMail(); $mail->send();


$mail->initialize(); $this->setTemplate('nowe_haslo');
$mail->setMailer('sendmail');
$mail->setCharset('iso-8859-2'); // W katalogu templates dodajemy plik reminderSuccess.php
$mail->setSender('lukasz@helionet.com.pl','Redaktor'); // i reminderError.php, w którym umieszczamy formularz
$mail->setFrom('lukasz@helionet.com.pl','Redaktor'); // wysłania nowego hasła:
$mail->addAddress($this->getRequestParameter('email'));
$mail->setSubject('Utworzono nowe hasło dla użytkownika '. <?php use_helper('Validation') ?>
$uzytkownik->getNick().'!'); <?php echo form_tag('uzytkownik/reminder') ?>
<?php echo form_error('email') ?>
$mail->setBody('
Witamy, <div class=”input-default”>
Dokonałeś zmiany hasła. W celu potwierdzenia zmian, <label for=”email”>Podaj swój e-mail przy rejestracji:</label>
prosimy kliknąć poniższy link: <?php echo input_tag('email') ?>
http://symfony/uzytkownik/potwierdzenie/kod/'. </div>
$potwierdzenie.'
Twoje nowe hasło to: '.$nowe_haslo.'.\nLogin: '. <?php echo input_hidden_tag('referer') ?>
$uzytkownik->getNick().' <?php echo submit_tag('przypomnij hasło ->') ?>
Pozdrawiamy,
Redakcja projektu Symfony w akcji </form>
');

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

<?php // szukanie takiego samego e-maila


class myReminderemailValidator extends sfValidator
{ $c = new Criteria();
$c->add(UzytkownikPeer::EMAIL, $email);
public function initialize($context, $parameters = null) $email_user = UzytkownikPeer::doSelectOne($c);
{
parent::initialize($context); // jeśli nie istnieje taki e-mail to zwracamy błąd
$this->setParameter('email_error', 'Invalid input');
$this->getParameterHolder()->add($parameter); if ($email_user) {
return true; return true;
} } else {
$error = $this->getParameter('email_error');
public function execute(&$value, &$error) return false;
{ }
$email_param = $this->getParameter('email'); }
$email = $this->getContext()-> }
getRequest()->
getParameter($email_param); ?>
$email = $value;

www.phpsolmag.org 11
Dla początkujących

Jeśli użytkownik o podanym emailu ist-


nieje, to dokonujemy zmian w haśle, kodzie Listing 5. Metoda profile. Odpowiedzialna jest za aktualizację danych użytkownika
potwierdzenia i statusie konta. Status kon- public function executeProfile()
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- if ($this->getRequest()->getMethod() == sfRequest::POST)
jemy następujące linijki kodu w warunku if {
($uzytkownik):
// zapisywanie danych do tabeli uzytkownik
$c = UzytkownikPeer::
retrieveByPk($użytkownik->getId()); $uzytkownik = UzytkownikPeer::retrieveByPk($this->getUser()->
$c->setPassword($nowe_haslo); getAttribute('user_id'));
$c->setPotwierdzenie($potwierdzenie); $uzytkownik->setStronaWww($this->getRequestParameter('strona_www');
$c->setStatus(0); $uzytkownik->setPodpis($this->getRequestParameter('podpis'));
$c->save();
if ($this->getRequestParameter('haslo'))
Po zmianie danych, wysyłamy e-mail z no- {
wym hasłem i linkiem do potwierdzenia $uzytkownik->setPassword($this->getRequestParmeter('haslo'));
(Listing 2.) }
Następnie w katalogu validate tworzymy
plik reminder.yml, w którym będziemy spraw- // zapisujemy dane do tabeli uzytkownik
dzali zmienną email. Dzięki zastosowaniu kla-
sy myReminderemailValidator (widocznej na $uzytkownik->save();
Listingu 3.) będziemy mogli sprawdzić czy da-
ny e-mail istnieje w bazie danych. // przekierowanie po aktualizacji na profil użytkownika
Oczywiście przy uzupełnianiu pliku remin-
der.yml należy zwrócić szczególną uwagę, aby $this->redirect('uzytkownik/profile');
używać tylko i wyłącznie znaku spacji, nie moż-
na używać tabulatora. Jeśli zdarzy się tak, że } else {
użyjemy tabulatora, to symfony zwróci nam
błąd w trakcie próby sprawdzania e-maila. Na // przekazujemy zmienną uzytkownika do szablonu
Listingu 3. przedstawiamy klasę myReminder $c = new Criteria();
emailValidator, z której korzysta validator $c->add(UzytkownikPeer::ID, $this->getUser()->getAttribute('user_id'));
o nazwie checkdbemailValidator w pliku re- $uzytkownik = UzytkownikPeer::doSelectOne($c);
minder.yml (widocznym na listingu 4.). Plik $this->uzytkownik = $uzytkownik;
z naszą nową klasą (myReminderemailValida- return sfView::SUCCESS;
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:// Listing 6. handleErrorProfile
symfony/uzytkownik/reminder, powinien poja- public function handleErrorProfile()
{

Listing 4. Plik Reminder.yml $c = new Criteria();


$c->add(UzytkownikPeer::ID, $this->getUser()->getAttribute('user_id'));
methods: $uzytkownik = UzytkownikPeer::doSelectOne($c);
post: [email] $this->uzytkownik = $uzytkownik;
names: return sfView::SUCCESS;
email: }
required: true
required_msg: musisz Listing 7. Dodawanie pola formularza
wpisać adres email, którego <?php echo form_error('haslo') ?>
użyłeś podczas rejestracji
nowego konta <div class=”input-default”>
validators: <label for=”haslo”>Podaj hasło, jeśli chcesz zmienić:</label>
[checkdbemailValidator] <?php echo input_password_tag('haslo') ?>
checkdbemailValidator: </div>
class: myReminderemailValidator
param: <?php echo form_error('powtorz_haslo') ?>
email: email
email_error: ten email <div class=”input-default”>
nie istnieje w bazie, musisz <label for=”powtorz_haslo”>Powtórz hasło:</label>
wpisać adres email, który podałeś
przy rejestracji nowego konta <?php echo input_password_tag('powtorz_haslo') ?>

12 06/2007
Symfony Framework

wić się formularz z jednym polem, w które na- = $uzytkownik->getId();. Następnie w wa- poprzez adres http://symfony/frontend_dev.php/
leży wpisać adres e-mail. Spróbujmy wpisać e- runku if ($uzytkownik) { } po linijce uzytkownik/login i logout. Dla przypomnienia
mail, którego nie ma w bazie danych i ten pra- $uzytkownik->addCredentail('subscriber'); jest to w zakładce Vars&Config/Globals.
widłowy, którego użyliśmy przy rejestracji no- dodajemy $uzytkownik->setAttribute('user_ Teraz możemy przejść do naszej nowej meto-
wego konta. id', $user_id);. Dzięki tym zmianom, tuż dy profile (Listing 5.). Dodajemy ją na samym
po zalogowaniu, zostanie utworzony atry- końcu pliku actions.class.php.
Moduł użytkownik but user_id, który będzie zawierał ID użyt- Musimy jeszcze dodać jedną metodę, któ-
– metoda profile kownika. Musimy dodać jeszcze jedną linij- ra będzie przekazywała zmienną użytkownik
Aby użytkownik mógł edytować swój profil, do- kę w metodzie logout, aby atrybut w mo- do szablonu profileError.php. Jeśli tego nie zro-
damy kolejną metodę o nazwie profile. Najpierw mencie wylogowania był niszczony. Po linij- bimy, to w momencie, gdy zostanie przełado-
musimy dodać nowy atrybut podczas logowania, ce $this->getUser()->clearCredentials(); wana strona i jeśli będzie jakiś błąd, to nie bę-
jakim będzie user_id zawierający ID użytkowni- dodajemy $this->getUser()->getAttribute- dziemy mieli już dostępu do zmiennej z sza-
ka. Wobec tego musimy edytować metodę login. Holder()->remove('user_id');. Jeśli chcesz blonu profileSuccess.php gdyż będziemy w pro-
Zaraz po linijce uzytkownik = UzytkownikPeer:: sprawdzić, czy rzeczywiście user_id jest zapisy- fileError.php. Musimy dodać zaraz pod naszą
doSelectOne($uzytkownik); dodajemy user_id wane i usuwane, zobacz w trybie developerskim nową metodą, metodę handleErrorProfile
(Listing 6.) .
Listing 8. Podpis Jak pewnie zauważyliście, powtórzyliśmy
fragment kodu z metody profile. Jest to naj-
<?php echo form_error('strona_www') ?> prostsze wyjście. Dzięki niemu, po urucho-
mieniu szablonu z komunikatem o błędzie, bę-
<div class=”input-default”> dziemy mieli dalej dostęp do zmiennej użyt-
<label for=”strona_www”>Strona www:</label> kownik.
http://<?php echo input_tag('strona_www', $uzytkownik->getStronaWww()) ?> Mamy już metody. Teraz stworzymy szablo-
</div> ny profileSuccess.php i profileError.php, które
z kolei są kopią profileSuccess.php. Szablon pro-
<?php echo form_error('podpis') ?> file będzie składał się na formularz z polami ha-
sło, powtórz hasło, strona www, podpis:
<div class=”input-default”>
<label for=”podpis”>Twój podpis:</label> <?php use_helper('Validation') ?>
<?php echo input_tag('podpis',$uzytkownik->getPodpis()) ?>
</div> Na samym początku dodajemy możliwość wa-
lidacji danych.
Kończymy formularz następującymi trzema linijkami kodu:
<?php echo input_hidden_tag('referer') ?> <?php echo form_tag('uzytkownik/profile') ?>
<?php echo submit_tag('zmień') ?>
Rozpoczynamy formularz z akcją na użyt-
</form> kownik/profile. Następnie będziemy dodawać
pola formularza (Listing 7.).
Listing 9. Zapytanie z sortowaniem według daty utworzenia postu W następnych polach będziemy korzysta-
public function executeIndex() li ze zmiennej użytkownik, którą przekaza-
{ liśmy z metody profile. Dostęp do danych
$posty – new Criteria(); jest bardzo prosty. Żeby odczytać podpis wy-
$posty->addDescendingOrderByColumn(PostyPeer::CREATED_AT); starczy wpisać: $uzytkownik->getPodpis()
$posty = PostyPeer::doSelect($posty); (Listing 8.)
$this->posty = $posty; Następnym krokiem będzie stworzenie pli-
return sfView::SUCCESS; ku profile.yml w katalogu validate. Będzie on
} sprawdzał zmienne haslo, powtorz_haslo,
strona_www i podpis. Zaczynamy od definicji
Listing 10. Walidatory dla zmiennych strona_www i podpis zmiennych:
strona_wwwValidator:
class: sfStringValidator methods:
param: post: [haslo, powtorz_haslo, strona_
min: 4 www, podpis]
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 Rysunek 1. Brak dostępu. Komunikat
max_error: podpis nie może przekroczyć 255 znaków informacyjny dla niezalogowanych użytkowników,
którzy próbują się dostać do modułu profile

www.phpsolmag.org 13
Dla początkujących

Dalej, od słowa kluczowego names, będzie- kownik i tworzymy plik security.yml o zawar- Sprawdźmy teraz, czy nasze zabezpieczenie
my definiować warunki poszczególnych tości: działa. Zalogujmy się i wejdźmy na adres http:
zmiennych. Początkowo haslo i powtorz _ //symfony/uzytkownik/profile. Powinien wy-
haslo oznaczone są jako nie wymaga- profile: świetlić się nasz profil do edycji. Teraz wyloguj-
ne false, ale jest zdefiniowany walidator id_secure: on my się i wywołajmy ponownie ten sam adres. Te-
checkhasloValidator, który ma na celu credentials: [[ subscriber ]] raz wyświetli się komunikat jak na Rysunku 1.
przypilnowanie w razie gdyby użytkow-
nik chciał zmienić hasło poprawności tych Listing 11. Opcja edytuj z możliwością edycji tylko i wyłącznie swojego posta
dwóch pól:
<?php use_helper('Check') ?>
names: <?php foreach($posty as $post) : ?>
haslo: <div class=”tytul”>
required: false <?php echo $post->getTytul() ?>
required_msg: twoje hasło jest <span class=”data”>(<?php echo $post->getCreatedAt() ?>), dodał:
wymagane <?php echo checkNickName($post->getIdUzytkownik()) ?>
powtorz_haslo: </span>
required: false </div>
required_msg: ponów hasło
validators: [checkhasloValidator] <div class=”tresc”>
<?php echo $post->getTresc() ?>
Dalej dodajemy definicje dla strona _ www </div>
i podpis. Zmienna strona _ www ma swój wali-
dator strona _ wwwValidator, który korzysta <?php if($sf_user->isAuthenticated()): ?>
z klasy sfStringValidator, a ma za zadanie
przypilnowaniet minimalnej i maksymalnej <div class=”edytuj”>
długości wpisanych znaków do pola. Zmien- <?php if($post->getIdUzytkownik() == $sf_user->getAttribute('user_id'))
na podpis również posiada swój walidator {
podpisValidator, który działa identycznie, echo link_to('edytuj', 'posty/editpost?id='.$post->getId());
jak w poprzednim przypadku: }
</div>
strona_www:
required: false <?php endif ?>
validators: [strona_wwwValidator] <hr>
podpis: <?php endforeach ?>
required: false
validators: [podpisValidator] Listing 12. Zwrócenie nazwy użytkownika
function checkNickName($user_id)
Tak jak wcześniej wspomnieliśmy zmien- {
na powtorz _ haslo ma swój walidator $c = new Criteria();
chekhasloValidator, który porównuje zmien- $c->add(UzytkownikPeer::ID, $user_id);
ne haslo i powtorz _ haslo używając do tego $check = UzytkownikPeer::doSelectOne($c);
klasy sfCompareValidator: if($check) {
return $check->getNick();
checkhasloValidator: } else {
class: sfCompareValidator return 0;
param: }
check: haslo }
compare_error: hasła nie
zgadzają się Listing 13. Proces dodawania nowego postu
public function executeAddpost()
Na sam koniec dopisujemy walidatory dla {
zmiennych strona _ www i podpis (Listing 10.). if ($this->getRequest()->getMethod() == sfRequest::POST) {
Kolejnym etapem jest wywołanie, w głów- $posty = new Posty();
nym katalogu projektu, polecenia /symfony $posty->setIdUzytkownik($this->getRequestParameter('user_id');
clear-cache, które wyczyści cały cache stro- $posty->setTytul($this->getRequestParameter('tytul'));
ny. Możemy już przetestować edycję profi- $posty->setTresc($this->getRequestParameter('tresc'));
lu poprzez adres http://symfony/uzytkownik/ $posty->save();
profile. $this->redirect('posty');
Musimy nadać odpowiednie prawa dla mo- } else {
dułu profile, aby dostęp miał jedynie użyt- // wyświetlanie formularza dodawania nowego posta
kownik zalogowany subscriber, ponieważ w return sfView::SUCCESS;
tej chwili może się do niego również dostać }
anonimowy użytkownik. Żeby to wykonać }
wchodzimy do katalogu config modułu użyt-

14 06/2007
Symfony Framework

Moduł posty – metoda index


Listing 14. Metoda Editpost i handleErrorEditpost Metoda index w pliku actions.class.php od-
public function executeEditpost() powiedzialna będzie za wyświetlanie po-
{ stów. Przekażemy w niej zmienną posty do
szablonu.
if ($this->getRequest()->getMethod() == sfRequest::POST) { W zapytaniu do bazy danych użyjemy sorto-
// zapis zmian wania według daty utworzenia postu, przy po-
$posty = new Criteria(); mocy addDescendingOrderByColumn() w języ-
$posty = PostyPeer::retrieveByPk($this->getUser()->getAttribute('id_posta')); ku PROPE (Listing 9.).
$posty->setTytul($this->getRequestParameter('tytul')); Następnie tworzymy w katalogu templa-
$posty->setTresc($this->getRequestParameter('tresc')); tes szablon index, czyli plik indexSuccess.php.
$posty->save(); W pliku tym będziemy prezentować posty.
$this->getUser()->getAttributeHolder()->remove('id_posta'); Każdy post będzie składał się z tytułu, daty, na-
$this->redirect('posty'); zwy użytkownika oraz treści. Dodatkowo po
} zalogowaniu wyświetli się opcja edytuj z moż-
else liwością edycji tylko i wyłącznie swojego posta
{ (Listing 11.).
// udostępnianie zmiennej post w szablonie Na samym początku użyliśmy nowego
// wyświetlanie formularza edycji posta helper'a o nazwie Check, czyli pliku Chec-
$c = new Criteria(); kHelper.php, który umieszczamy w katalo-
$c->add(PostyPeer::ID, $this->getRequestParameter('id')); gu lib/helper. Jeśli w katalogu lib nie będzie
$post = PostyPeer::doSelectOne($c); katalogu helper to utwórzmy go. Nowy helper
$this->post = $post; zawiera funkcję checkNickName(), która zo-
$this = $this->getUser(); stała użyta w szablonie index. Zadaniem tej
$post->setAttribute('id_posta', $this->getRequestParameter('id')); funkcji jest zwrócenie nazwy użytkownika
return sfView::SUCCESS; (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
public function handleErrorEditpost() $sf_user->getAttribute('user_id').
{ Mamy gotowe wyświetlanie postów z moż-
// udostępnianie zmiennej post w szablonie editpostError liwością edycji. Teraz musimy dodać metodę,
$c = new Criteria(); która pozwoli użytkownikom zalogowanym
$c->add(postyPeer::ID, $this->getUser()->getAttribute('id_posta')); dodawanie nowych postów.
$post = PostyPeer::doSelectOne($c);
$this->post = $post; Moduł posty – metoda Addpost
return sfView::SUCCESS; Aby użytkownik miał możliwość pisania no-
} wych postów, musimy dodać nową metodę
Addpost w pliku actions.class.php. Metoda ta
Listing 15. Metoda index będzie pobierać z formularza zmienne user_
public function executeIndex() id, tytul i tresc.
{ Następnie będzie przekierowywała na stro-
// udostępnia zmienną osymfony w szalonie nę z listą wszystkich postów przy pomocy
$osymfony = new Criteria(); polecenia $this->redirect('posty'). Pro-
$osymfony->addDescendingOrderByColumn(OsymfonyPeer::ID); ces dodawania nowego postu jest podobny
$osymfony = OsymfonyPeer::doSelectOne($osymfony); jak w przypadku zakładania nowego konta
$this->osymfony = $osymfony; (Listing 13.).
$return sfView::SUCCESS; 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

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

www.phpsolmag.org 15
Dla początkujących

Jeśli już dodaliśmy kolumnę do tabel w pli-


Listing 16. Dodajemy metodę index, następnie tworzymy szablon w katalogu templates ku schema.xml, to musimy po kolei wywołać
public function executeIndex() polecenia z głównego katalogu projektu:
{
./symfony propel-build-model
// udostępnia zmienną kontakt w szalonie ./symfony propel-build-sql
./symfony propel-insert-sql
$kontakt = new Criteria();
$kontakt->addDescendingOrderByColumn(KontaktPeer::ID); Uwaga, po tej operacji wszystkie dane z tabel
$kontakt = KontaktPeer::doSelectOne($kontakt); znikną. Nie będzie też naszego użytkownika.
$this->kontakt = $kontakt; Tworzymy moduły aplikacji backend wpisu-
$return sfView::SUCCESS; jąc po kolei:
}
./symfony propel-init-admin backend
uzytkownik Uzytkownik
pola user_id, które będzie przechowywało Moduł osymfony – metoda index ./symfony propel-init-admin backend
ID użytkownika. Aby przekazać zmienną Aby wyświetlić podstronę symfony, należy do- pozsty Posty
user_id, należy użyć polecenia $sf_user-> dać metodę index do pliku actions.class.php. ./symfony propel-init-admin backend
getAttribute('user_id'). Formularz two- Następnie musimy stworzyć plik indexSuc- osymfony Osymfony
rzymy podobnie, jak w innych przypadkach. cess.php w katalogu templates. Metoda index zo- ./symfony propel-init-admin backend
Dodajemy również plik addpost.yml do kata- stała przedstawiona na Listingu 15. Plik inde- kontakt Kontakt
logu validate, który powinien mieć za zada- xSuccess.php zawiera:
nie wymuszenie wpisania treści w polu tytul Dostęp do tych modułów jest podobny jak
i tresc, jednocześnie pamiętając, że pole <div class=”tresc”><?php echo w aplikacji frontend poprzez adres: http://
treść musi mieć minimum 3 znaki. Nale- $osymfony->getTresc() ?></div> symfony/backend.php/nazwa_modułu. Propo-
ży również zabezpieczyć naszą metodę przed nuję, abyśdodał kilku użytkowników a następ-
użytkownikami niezalogowanymi, tworząc Mamy już wyświetlanie treści z tabeli symfo- nie wszedł na adres http://symfony/backend.
plik security.yml w katalogu config modułu po- ny. Polecam uzupełnić treść podstrony sym- php/uzytkownik, powinna pojawić się lista
sty o zawartości: fony i kontakt przy pomocy aplikacji backend użytkowników, którą będziesz mógł edyto-
opisanej w dalszej części artykułu. wać (zobacz Rysunek 2.).
addpost: Możesz teraz uzupełnić treść w podstronie
is_secure: on Moduł kontakt – metoda index o symfony oraz w kontakcie. Użyj oczywiście
credentials: [[ subscriber ]] Aby wyświetlić podstronę kontakt należy postą- do tego celu aplikacji backend.
pić identycznie, jak w przypadku podstrony sym-
Możemy już sprawdzić dodawanie postu fony. Dodajemy metodę index, następnie two- Podsumowanie
wywołując adres http://symfony/posty/addpost. rzymy szablon w katalogu templates. Jeżeli wyda- W tym artykule dowiedzieliśmy się jak wy-
Następnym krokiem będzie dodanie meto- je Ci się to zbyt skomplikowane, to zamieszczam generować nowe hasło dla użytkownika, któ-
dy umożliwiającej edycję postów przez użyt- w Listingu 16. kod. Plik indexSuccess.php zawiera: ry korzysta z opcji przypomnij hasło. W tym
kownika. celu napisaliśmy metodę reminder w module
<div class=”tresc”><?php echo użytkownika. Nauczyliśmy się jak ustawiać
Moduł posty – metoda Editpost $kontakt->getTresc() ?></div> odpowiednie prawa dla modułów oraz jak
Edycja postu będzie możliwa przy pomocy me- dodać nowe atrybuty. Rozbudowaliśmy na-
tody Editpost. W metodzie tej przy przekazy- Treść kontaktu możemy łatwo uzupełnić przy szą aplikację o możliwość edycji profilu, wylo-
waniu zmiennej post do szablonu użyliśmy no- pomocy aplikacji backend. gowania, dodawania postów i ich edycji, a tak-
wego atrybutu o nazwie id_posta, który jest że dodaliśmy nową aplikację backend. Dzię-
usuwany po poprawnym zapisaniu zmian. Aplikacja backend ki niej możemy z łatwością zarządzać na stro-
Ustawienie tego atrybutu było wymagane Stworzymy teraz nową aplikację backend, nie. Na razie aplikacja ta nie jest zabezpieczona
przy przekazywaniu zmiennej post, w przy- która będzie nam pomagała przy edycji pod- przed wejściem użytkowników anonimowych.
padku błędu, w trakcie wysyłania formularza. stron serwisu jak i zarządzaniu postami oraz Zabezpieczymy ją w następnej części artykułu.
Ostatecznie dodaliśmy dwie metody Editpost użytkownikami serwisu. Aplikację tworzymy Oczywiście cała nasza aplikacja jest na razie w
i handleErrorEditpost oraz dwa pliki w kata- z głównego katalogu projektu przy pomocy częściach. Już w następnym artykule zajmiemy
logu templates o nazwach editpostSuccess.php i polecenia ./symfony init-app backend. Na- się jej składaniem i opisem w stylach CSS, po-
editpostError.php, który jest kopią tego pierw- stępnie będziemy tworzyć dla tej aplikacji mo- znamy również ciekawe i godne polecenia miej-
szego. duły użytkownik i posty. Jeśli chcemy zarzą- sca w internecie na temat frameworka symfony.
Dodaliśmy również zabezpieczenie dla me- dzać podstronami spod tej aplikacji, to musi- Do zobaczenia!
tody Editpost, aby była tylko dostępna dla my w tabeli symfony i kontakt dodać jedną ko-
użytkowników typu subscriber. Dokonaliśmy lumnę:
tego w pliku security.yml, podobnie jak w przy- ŁUKASZ KLEJNBERG
padku addpost. <column name=”id” type=”integer” Autor jest studentem informatyki w Wyższej Szkole
Musimy jeszcze dodać plik editpost.yml required=”true” primaryKey=”true” Informatyki i Zarządzania w Rzeszowie. Pracuje ja-
do katalogu validate. Możemy skopiować za- autoIncrement=”true” /> ko projektant stron WWW. Uczestniczy w projekcie
wartość pliku addpost.yml. Na Listingu 14. uczelnianym tonieproblem.pl opartym na frame-
przedstawiam metody Editpost i handle Dzieje się tak, dlatego, że admin generator worku symfony.
ErrorEditpost. wymaga kolumny z kluczem podstawowym. Kontakt z autorem: lukasz.klejnberg@gmail.com

16 06/2007
Rozwiązania

Vanilla
Alternatywa dla phpBB

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.
by, ten link uruchamia nam wyszukiwa-
Dowiesz się... Powinieneś wiedzieć... nie nowych (jeszcze niezatwierdzonych)
• Jaka jest dobra alternatywa dla najpopular- • Jak umieszczać źródła strony na serwerze użytkowników;
niejszego obecnie skryptu forum phpBB. • Jak tworzyć bazę danych MySQL • inne opcje: zależnie od uprawnień dostę-
pu i rozszerzeń, z których korzystamy,
mogą się tutaj pojawić dodatkowe opcje.
dzanie forum podzielone jest na kilka podsta-
wowych kategorii. Inaczej niż w phpBB mamy Dzięki zakładce Ustawienia możemy sprawnie
Poziom trudności tutaj przejrzyste menu, które umożliwia doko- moderować prowadzone dyskusje.
nywanie zmian w ustawieniach forum.
Grafika
Ustawienia aplikacji Zaimplementowany System szablonów umoż-

V
anilla wywodzi się z projektu o8 stwo- Jest to główny ekran konfiguracyjny Vanilli. Tu- liwia łatwą zmianę wyglądu. Ze strony domo-
rzonego przez Marka O'Sullivana, taj zmieniamy tekst w bannerze, ustawienia anty- wej możemy pobrać sporą liczbę templatek
który pod naciskiem szerokiego gro- spamowe, definiujemy ustawienia ciasteczek (co- i stylów, którymi zarządzamy w panelu admi-
na użytkowników zdecydował się upublicznić okies), oraz zmieniamy podstawowe opcje forum, nistracyjnym.
aplikację na licencji GPL. Po roku Vanilla sta- takie jak wiadomości prywatne, kategorie, itp.:
ła się bardzo popularną aplikacją, a duża spo- Rozszerzenia
łeczność przyczyniła się do powstania wielu • aktualizacje i przypomnienia: tutaj ustala- Możliwości forum możemy zwiększać za po-
pluginów rozszerzających podstawowe możli- my, jak często Vanilla ma nam przypomi- mocą specjalnych rozszerzeń. W przeciwień-
wości forum. nać o aktualizacjach. Możemy sprawdzić stwie do forum phpBB ich in stalacja nie po-
w Lussumo, czy są dostępne nowsze wersje; lega na ręcznej edycji wielu plików, lecz spro-
Podstawowe wymagania • rangi użytkowników: tutaj dodajemy, zmie- wadza się do aktywacji dodatku w sekcji Usta-
Minimalne wymagania, jakie musimy spełnić, niamy i porządkujemy rangi użytkowni- wienia. Taki system eliminuje konieczność
aby zainstalować forum, to: serwer z obsłu- ków i przysługujące im prawa dostępu; spędzania kilkunastu minut w celu zainsta-
gą >= PHP 4.1 i >=MySQL 3.23. Pełny pakiet • ustawienia rejestracji: definiujemy, w jaki lowania rozszerzenia oraz uniezależnia je-
instalacyjny możemy pobrać ze strony domo- sposób mają być rejestrowani nowi człon- go instalację od aktualizacji Vanilli do now-
wej projektu, która dostępna jest pod adresem kowie: jaką otrzymują rangę, czy wymaga- szej wersji. Do dyspozycji mamy ponad 200
http://getvanilla.com/. Dzięki niewielkim wyma- na jest akceptacja administratora itd.; rozszerzeń, które na żądanie modyfikują po-
ganiom możemy tę aplikację zainstalować na • kategorie: dodajemy, zmieniamy i porząd- szczególne elementy aplikacji. Liczba rozsze-
prawie każdym serwerze hostingowym, a pro- kujemy kategorie; rzeń wciąż rośnie.
ces instalacji sprowadza się do wpisania podsta- • rozszerzenia: dodają do Vanilli różne funk-
wowych parametrów niezbędnych do połącze- cje. W tym menu włączamy rozszerzenia Przykładowe rozszerzenia:
nia z bazą danych i utworzeniem konta admi- i znajdujemy nowe ze strony Lussumo; Do najbardziej popularnych rozszerzeń funk-
nistratora. • szablony i Style: tutaj zmieniamy szablon cjonalności możemy zaliczyć chat status. Po-
(plik XHTML), na którym oparte jest fo- kazuje on bieżącą aktywność użytkowników
Podstawowe możliwości rum, lub domyślny styl (CSS i grafikę); w popularnych komunikatorach interneto-
Zainstalowana aplikacja umożliwia rejestra- • języki: możemy zmienić pliki językowe, wych (Gadu-Gadu, Skype). Dzięki wtycz-
cję użytkownikom, którzy po akceptacji przez których używa Vanilla; ce notify forumowicze mogą być na bieżą-
administratora mogą brać udział w dyskusji • prośby o członkostwo: Vanilla nie posia- co (e-mailem) informowani o odpowiedzi na
w utworzonych kategoriach. Interfejs udostęp- da 'listy użytkowników' jak inne popular- post. Ciekawą funkcją jest, iż użytkownik nie
niony użytkownikowi jest bardzo prosty w ob- ne fora. W opcji Szukaj znajdujemy i za- dostanie więcej niż jeden e-mail, dopóki nie
słudze, a wszystkich dostępnych opcji używa rządzamy nowymi użytkownikami. Jeże- odwiedzi forum. Invite-Only System umożli-
się intuicyjnie. Ze strony administratora zarzą- li administrator musi zatwierdzać proś- wia zmianę warunków rejestracji użytkowni-

18 06/2007
Vanilla

ków. Po zainstalowaniu tego rozszerzenia będą Pozycja użytkownika graficznymi, które posłużyć mogą do pobrania
mogły się zarejestrować tylko osoby zaproszo- vna mapie świata odpowiedniej mapy. Do popularnych witryn
ne.Dodatek LatestBlog umożliwia użytkowni- Z biegiem czasu ciągle rośnie popularność Go- umożliwiających tego typu powiązanie nale-
kowi wyświetlanie w swoim profilu pięć ostat- ogle Maps. Rozwiązanie to, dzięki udostępnie- żą między innymi http://www.maxmind.com
nich wpisów z bloga. niu API (http://pl.wikipedia.org/wiki/API_(infor- (wersja komercyjna) oraz http://www.hostip.
matyka)) znajduje wiele bardzo ciekawych za- info udostępniająca API za darmo. Dzięki
Instalacja stosowań. Dzięki temu nasze forum możemy ogromnej społeczności Vanilla mamy dostępne
przykładowego rozszerzenia wzbogacić o mapkę pokazującą lokalizację po- rozszerzenie do naszego forum, które wykona
Bardzo przydatną funkcją w czasie prowa- szczególnych użytkowników w realnym świe- za nas całą pracę. Ze strony http://lussumo.com/
dzenia dyskusji na forum jest możliwość cy- cie. Aby w pełni korzystać z narzędzia udo- addons/ pobieramy plik add-ons IpMap i po roz-
towania wypowiedzi innych użytkowników. stępnionego przez Google niezbędne jest za- pakowaniu kopiujemy na serwer do katalogu
Aby Vanilla udostępniała taką możliwość, ko- rejestrowanie naszej witryny w celu uzyskania rozszerzeń. Edytujemy plik default.php i za-
nieczne jest zainstalowanie odpowiedniego klucza, który umożliwi nam dostęp do serwe- mieniamy w linii 14 wartość zmiennej $Conf
dodatku. Aby to zrobić, wchodzimy na stro- ra map. Możemy tego dokonać na stronie http: iguration['GoogleMapAPI'] przechowującej
nę http://lussumo.com/addons/ i ściągamy Qu- //www.google.com/apis/maps/signup.html wpisu- klucz google maps api, na ten, który otrzyma-
oteText. Następnie rozpakowujemy pobrane jąc adres naszej domeny w formularzu. Ma- liśmy w czasie rejestracji witryny. Wartość
archiwum i wgrywamy je na serwer do kata- py dla określonego rejonu ziemi pobierane są zmiennej $Context->Dictionary["IPMap"]
logu extensions. Pozostaje nam jeszcze tylko z serwera Google po przekazaniu długości i sze- określa nazwę wyświetlaną nad mapką w profi-
aktywowanie rozszerzenia w panelu admini- rokości geograficznej. Oznacza to, iż musimy w lu użytkownika. Dla polskiego forum możemy
stracyjnym. jakiś sposób powiązać numery IP komputerów zmienić jej wartość na Lokalizacja Użytkownika
Po tym kroku opcja cytowania jest do- naszych użytkowników ze współrzędnymi geo- lub dowolną inną pamiętając iż forum korzysta
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
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>';
}
}
Rysunek 2. Widok mapki google w profilu użytkownika

www.phpsolmag.org 19
Rozwiązania

z kodowania znaków utf8 i takie kodowanie wyświetlać różne dodatkowe składniki. I znów Na początek edytujemy plik definicji linków
powinno być ustawione w edytorze plików któ- w bazie add-ons projektu znajduje się wiele pro- i uzupełnimy każdą linię o dodatkowy parametr
rego używamy, w przeciwnym wypadku pol- pozycji do pobrania poczynając od linków do np. image1.jpg,http://www.mojastrona.pl zmie-
skie znaki nie będą się poprawnie wyświetlać. stron w postaci listy, a skończywszy na formu- niamy na image1.jpg,http://www.mojastrona.pl,n
Po uaktywnieniu zainstalowanego rozszerze- larzu wyszukiwania na forum. My skupimy się ajlepsza strona na świecie. Teraz pozostaje nam
nia możemy przejść do widoku profilu dowol- na zastosowaniu rozszerzenia SidepanelImage- już tylko edycja pliku rozszerzenia, w celu wpro-
nego użytkownika i jeśli jego IP znajduje się w Link, które poddamy pewnej modyfikacji. Po wadzenia odpowiednich modyfikacji. Odnajdu-
bazie na stronie http://www.hostip.info zoba- jego instalacji w typowy sposób, mamy moż- jemy kod odpowiedzialny za utworzenie tablicy
czymy mapkę Google z zaznaczonym marke- liwość zaobserwowania jego działania. W le- elementów na podstawie pliku zawierającego na-
rem określającego lokalizację, tak jak to widać wym bocznym panelu strony wyświetla się lo- sze rekordy: list($images[$i], $links[$i])
na Rysunku 2. sowo, z zadeklarowanej wcześniej listy, (w pli- = $row; i zmieniamy go tak;aby możliwe było
ku imglinks.txt) plik graficzny, który jest odczytanie parametru title, który został dodany
Dynamiczny sidebar jednocześnie odnośnikiem do strony. Modyfi- list($images[$i], $links[$i], $title[$i])
Jak dotąd nasze forum jest bardzo statyczne, kacja jaką wprowadzimy będzie zmieniała spo- = $row; Bezpośrednio po linii losującej element
a strona główna nie zawiera żadnej grafiki z wy- sób deklaracji linku, tak, aby odnośnik zawie- do wyświetlenia ($pos = mt_rand(0, $i - 1 );)
jątkiem layout'u strony. Domyślny układ forum rał znacznik TITLE, który jest cennym elemen- następuje przepisanie elementów wiersza tabli-
zaplanowany jest tak by po jego lewej stronie tem przy pozycjonowaniu stron internetowych. 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 rozszerzenie


Moż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://
Rysunek 3. Odnośnik obrazkowy z ustawionym atrybutem title
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-
Rysunek 4. Wstępne założenia dla tworzonego rozszerzenia lu uproszczenia nasze rozszerzenie będzie wy-

20 06/2007
Vanilla

lę nad pozycjami poszczególnych elementów wy-


Listing 3. Kod php wyświetlający obiekt typu Control świetlanych na stronie. Wyjaśnimy teraz krótko,
$to_display = new ShowText($Context); w jaki sposób Vanilla dodaje nasz element do wy-
$Page->AddRenderControl($to_display,$Configuration świetlenia. Obiekt Page zawiera wszystko co ma
['CONTROL_POSITION_BODY_ITEM']-2); być wyświetlone danemu użytkownikowi. Na
treść wyświetlaną składa się szereg obiektów ty-
Listing 4. Kod php utworzonego rozszerzenia pu Control, które są tworzone w trakcie inicjacji
class ShowText extends Control { skryptu. Nasze rozszerzenie ( i wszystkie inne),
function Displayer(&$Context) { dodaje kolejny obiekt typu Control do wyświe-
$this->Name = 'Displayer'; tlenia. Metody obiektu Page pobierają ustawienia
$this->Control($Context); przekazywanego obiektu typu Control i decydu-
} ją co, gdzie i komu ma być wyświetlone. I tak na
function Render() { przykład metoda render obiektu Control zwraca
echo '<div id=\'ShowText\'>'.file_get_contents kod do wyświetlenia. W naszym przypadku jest
('extensions/showtext/something.txt').'</div>'; to zwykły tekst, który zostaje przekazany do Page
} i wyświetlony. Listing 3. zawiera kompletny kod
} php naszego rozszerzenia.
if (in_array($Context->SelfUrl, array Do obiektu Head dołączamy jeszcze plik ze
('index.php', 'categories.php', 'comments.php', 'post.php'))) { stylami, które pozwolą nam kontrolować wy-
$Head->AddStyleSheet('extensions/show_something/style.css'); gląd tekstu, jaki będziemy wyświetlać. Wyświe-
$to_display = new ShowText($Context); tlanie tekstu ograniczone jest jeszcze do kilku
$Page->AddRenderControl stron Vanilla –nie chcemy przecież, by prezen-
($to_display,$Configuration['CONTROL_POSITION_BODY_ITEM']-2); towana treść była wyświetlana w panelu admi-
} nistracyjny. Przykładowe style pokazane są na
Listingu 4.
Listing 5. Zawartość pliku style.css
#ShowText { Vanilla a phpBB
color: grey; Do podstawowych różnic pomiędzy tymi apli-
border: 1px solid black; kacjami należy przede wszystkim system rozsze-
margin: 10px; rzeń, które są największym problemem phpBB.
padding: 10px; 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

świetlać treść pliku something.txt wszystkim Zmienna $to_display zawiera nasz obiekt
użytkownikom, w miejscu, które wcześniej do wyświetlenia, który wyświetlamy za pomo- PAWEŁ CHWAST
wybraliśmy. Mamy już klasę definiującą nasz cą metody render. Pozycję do wyświetlenia usta- Ma 26 lat, mieszka w Legnicy, ukończył Kolegium
obiekt. Pozostaje nam już tylko jego utworze- lamy względem pozycji CONTROL_POSI- Karkonoskie w Jeleniej Górze, gdzie uzyskał tytuł
nie oraz wyświetlenie. Listing 2. przedstawia TION_BODY_ITEM zapisanej w pliku konfi- inżyniera w specjalności inżynieria komputerowa.
kod php wykonujący tę czynność. guracyjnym. Dzięki temu mamy lepszą kontro- Kontakt z autorem: p.chwast@globnet.net

www.phpsolmag.org 21
Technika

PHP i WAP
Tworzenie dynamicznych stron WWW dla WAP

WAP – Wireless Application Protocol, czyli znana wszystkim posiadaczom


telefonów komórkowych technologia bezprzewodowego dostępu do
internetu.

<p>. Kod wystarczający do stworzenia pierw-


Dowiesz się... Powinieneś wiedzieć... szej witryny WAP jest pokazany na Listin-
• Jak stworzyć dynamiczną witrynę WWW dla • Powinieneś znać podstawy programowania gu 1.,a na Rysunku 1. znajduje się wynik je-
WAP. w PHP. go działania.
To oczywiście dopiero początek, albowiem
żaden z klientów nie chce ponieść kosztów
WML – podstawa działania WAP za nawiązanie połączenia z siecią dla zwykłe-
W klasycznych przeglądarkach interneto- go powitania.
Poziom trudności wych, podstawową technologią jest (X)HTML, Tworząc taką witrynę, powinniśmy przede
tak dla witryn wyświetlanych w technologii wszystkim nastawić się na zawartość mery-
WAP, podstawową technologią jest WML. toryczną i praktyczną. Nie należy przejmo-
Jest to język, podobnie jak HTML, oparty wać się ani układem, ani oprawą graficzną,
o strukturę znaczników, całkowicie zgodny dźwiękami i animacjami.

M
imo, że technologia ta od jakiegoś z XML-em i tak naprawdę jest to po prostu Przede wszystkim skupmy się na funkcjo-
czasu nie jest już obiektem wes- specyficzny rodzaj dokumentu XML. Ozna- nalności i ograniczeniu pojemności, gdyż
tchnieniem fanów postępu tech- cza to, że tworząc dokument WML obowią- zbyt duża witryna to jest to, co najbardziej
nicznego, to wciąż jest dostępna w większo- zują nas takie same zasady, jak przy tworze- doskwiera użytkownikom stron tworzonych
ści aparatów komórkowych. Jeżeli chcesz do- niu dokumentów XML. na potrzeby WAP.
wiedzieć się jak stworzyć dynamiczną stro- Istnieją jednak pewne dodatkowe aspekty,
nę WWW, która poprawnie wyświetli się które należałoby uwzględnić. Przede wszyst- Jak stworzyć menu?
w komórce, przeczytaj ten artykuł. kim jest interpretacja zawartości dokumen- Oczywiście niezbędną rzeczą w każdej szanującej
tu jako talii a poszczególnych podstron jako się witrynie jest możliwość wyboru dowolnej
Testowanie kart. Listing 1. pokazuje podstawową kon- dostępnej podstrony. W witrynach WAP mamy
Każdy z nas, tworząc projekt witryny ,od sa- strukcję dokumentu WML wraz z podzia- dwie możliwości rozwiązania problemu nawiga-
mego początku sprawdza wyniki swojej pra- łem na karty. cji. Pierwszą z nich jest możliwość wczytania za-
cy. Znamy także doskonale różne interpreta- W momencie załadowania witryny WAP wartości różnych podstron już za pierwszym po-
cje kodu przez przeglądarki. Niestety sytu- w naszym telefonie, domyślnie zostaje wy- łączeniem z serwerem i zapisanie ich do innych
acja powtarza się także w telefonach komór- świetlana karta pierwsza. Zatem, aby stwo- kart. Drugą możliwością jest łączenie się z ser-
kowych. Na szczęście nie musimy kupować rzyć naszą pierwszą witrynę WAP wystar- werem i wywoływanie innego pliku. Przy czym
każdej wersji telefonu, aby sprawdzić dzia- czy jeśli w karcie pierwszej wpiszemy powi- możliwe są kombinacje obu tych technik. Na
łanie naszej witryny. Większość firm udo- talny tekst. Listingu 2. przedstawiony jest sposób tworze-
stępnia specjalne symulatory, które pomo- Niezbędnym jest także, aby tekst został nia odnośników, z pewnością znany doskonale
gą nam przewidzieć efekt działania stworzo- umieszczony w akapicie, czyli znacznikach z HTML-a.
nej aplikacji.
Oto kilka produktów: Nokia Mobile inter-
net Toolikt , Openwave SDK, Motorola Wireless Podstawowe zasady tworzenia dokumentu XML
IDE/SDK . Istnieją także strony WWW, któ- W dokumencie XML może istnieć tylko jeden główny element. W przypadku witryn WAP jest
re wyświetlają witryny WAP, tak jak w telefo- 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-
nach komórkowych. Oto adres jednej z nich:
chowywać poprawną hierarchię znaczników tzn., nie wolno wykonać następującej opera-
www.igsm.pl. cji: <znacznik1><znacznik2></znacznik1></znacznik2>. Powinna ona wyglądać tak:
Jak tylko zaopatrzymy się w jeden z symula- <znacznik1><znacznik2></znacznik2></znacznik1>. Należy pamiętać, że XML odróżnia
torów, możemy przystąpić do tworzenia pierw- małe litery od wielkich, zatem znacznik <Card> to co innego niż znacznik <card>. Każdy atrybut
szej aplikacji internetowej dostępnej dla nasze- dowolnego znacznika powinien zostać zapisany w cudzysłowach.
go telefonu komórkowego.

22 06/2007
PHP i WAP

Jak wstawić grafikę na stronę? jący wyświetlanie, wygląda następująco: <img Istotą tego rozwiązania jest ustawienie wła-
Grafika dla witryn WAP przedstawiana jest src=”obrazek.wbmp” alt=”” />. ściwego typu MIME dla wyświetlanego ry-
w formie plików WBMP, czyli jednokolorowych W przypadku wyświetlania grafiki w for- sunku.
map bitowych. Spowodowane jest to przez tech- macie WBMP, przy pomocy PHP, mogą wystą-
nologiczne możliwości WAP lub przez szyb- pić pewne problemy, szczególnie jeżeli nie ma- Komunikacja
kość przesyłu danych. Im mniej kolorów i mniej- my dostępu do plików konfiguracyjnych. W ta- użytkownika z witryną
szy rozmiar obrazka, tym szybsze połączenie. kim przypadku pomocny okaże się następują- Chcąc zapewnić możliwość komunikacji użyt-
Chcąc stworzyć obraz w formacie WBMP, mo- cy kod: kownika z witryną, tak jak w przypadku zwy-
żemy posłużyć się aplikacją Adobe Photoshop kłych witryn wyświetlanych przez przeglądarki
7.0, gdzie mamy możliwość eksportu obrazu header(„Content-type: image/und.wap.wbmp”); internetowe, możemy skorzystać z formularzy.
właśnie do formatu WBMP. Sam kod, realizu- echo(file_get_contents('rysunek.wbmp'); Zasada ich tworzenia jest bardzo podobna do tej
znanej z HTML-a.
Listing 1. Podstawowa konstrukcja dokumentu WML Pamiętajmy jednak, że wpisywanie długich
napisów w komórkach jest dość kłopotliwe,
<?xml version=”1.0”?> dlatego nie zmuszajmy do tego użytkownika,
<!DOCTYPE wml PUBLIC ”-//WAPFORUM//DTD WML 1.2//EN” ”http://www.wapforum.org/DTD/ jeżeli nie jest to konieczne.
wml12.dtd”> Przechodząc już ściśle do formularzy, oto ja-
<!-- to nasza talia--> kie elementy możemy wykorzystać: pole teksto-
<wml> we – tworzone za pomocą znacznika input w na-
<card id=”card1” title=”PHPSOLUTION”> stępujący sposób <input type=”text” /> , po-
<p> le hasła – również tworzone za pomocą znaczni-
Twoja pierwsza strona WAP. ka input, przy jednoczesnej zmianie typu <input
</p> type=”password”>.
</card> Pozostałe elementy, takie jak lista wyboru, przy-
<card id=”card2”> cisk opcji i pola wyboru, reprezentowane są przez
<!--Zawartość drugiej karty--> znacznik <select> .
</card> Samo tworzenie formularza jest dość pro-
</wml> stym zadaniem. Aby wyświetlić dane zawar-
te w formularzu używamy zmiennych WML,
Listing 2. Tworzenie odnośników w WML`u które tworzone są po wypełnieniu danych for-
<!-- Nastąpi wczytanie strony powitanie.wml--> mularza. Zmienne w WML poprzedzone są
<a href="powitanie.wml">Powitanie</a> znakiem dolara, a sama nazwa ujęta jest w na-
<!-- Nastąpi wyświetlanie karty o id=card2 --> wiasy i odpowiada nazwie atrybutu pola for-
<a href="#card2">Autor</a> mularza.
<!-- Nastąpi wczytanie strony powitanie.wml i wyświetlenie karty o id=card2 --> Istnieje jeszcze pytanie, jak przesłać dane na
<a href=”powitanie.wml#card2</a> serwer. Oczywiście są dwie metody: GET i POST.
Samo przesyłanie różni się nieco od tej metody
Listing 3. Przesyłanie danych metodą POST którą znamy, albowiem nie mamy do dyspozy-
<anchor> cji parametru action. Jeżeli wykorzystujemy
<go href=”dane.php” method=”post”> metodę GET – co w większości sytuacji jest gor-
<postfield name=”imie” valuve=”$(imie)” /> szym rozwiązaniem, gdyż ogranicza ona moż-
</go> liwości przesyłu danych – wystarczy jeżeli wy-
</anchor> wołamy odpowiedni odnośnik i dopiszemy do

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`u


Istnieje 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.
Rysunek 1. Twoja pierwsza witryna WWW dla WAP

www.phpsolmag.org 23
Technika

adresu url dane, które chcemy przesłać. Może kowych elementów. Na początku musimy wy- Wykorzystanie PHP
to wyglądać tak: <a href=”dane.php?imie=$( korzystać znaczniki <postfield> i nadać im i dynamiczna witryna WAP
imie)”>wyslij</a>. żądane wartości w następujący sposób: <post- Po tym jak już zapoznaliście się z podstawami
Właściwie nie wprowadzamy tu specjalnej fieldname=”imie” value=”$ (imie)”/>. Następ- działania technologii WML, możemy przystąpić
rewolucji. Sprawa ma się nieco inaczej w przypad- nie wykorzystując elementy <anchor> i tworzy- do dynamicznego kreowania zawartości witryny,
ku metody POST, gdyż wymaga ona użycia dodat- my skrypt taki jak na Listingu 3. oczywiście przy pomocy PHP. Aby nabrać wpra-
wy, stwórzmy witrynę, której celem będzie wy-
Listing 4. Dokument WML świetlenie informacji o statusie wprowadzonego
numeru komunikatora gadu-gadu.
<?xml version="1.0"?> Wykonajmy zatem podstawową strukturę
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.2//EN" "http://www.wapforum.org/DTD/ dokumentu WML, w którym zamieścimy treść
wml12.dtd"> wstępną i pole tekstowe, wpiszmy numer gadu-
<wml> gadu, którego chcemy poznać aktualny status.
<!-- to nasza talia--> Całość możemy zaobserwować na Listingu 4.
<card id="card1" title="Sprawdz GG"> i podzieliliśmy na trzy karty. W pierwszej przed-
<p> stawiamy tekst informacyjny, w następnej da-
Witamy na naszej stronie. Dzieki niej bedziesz mogl sprawdzic status podanego przez ne autora skryptu i kartę, w której wpisujemy
siebie numeru GADU-GADU. numer gadu-gadu. W każdej z kart powtarza-
</p> my wyświetlanie menu tak, aby nawigacja by-
<p> ła możliwa na każdej podstronie. Do przesła-
Menu<br /> nia danych wykorzystujemy metodę post opi-
<a href="#card3">Wprowadz numer gg</a> saną wcześniej. Teraz zajmiemy się już tylko
<a href="#card2">Autor</a> i wyłącznie odpowiednimi formułami PHP.
</p> Zacznijmy od tego, w jaki sposób ustawić po-
</card> prawny typ MIME. Wystarczy, jeżeli podacie
<card id="card2" title="PHPSOLUTION"> wskazaną przez nas formę nagłówka:
<p>
Autorem jest Tomasz Roszko header(”Content-type: text/vnd.wap.wml”);
</p>
<p> Teraz możemy pobrać przekazywany numer
Menu<br /> gadu-gadu: $ggnumer=$ _ POST['ggnumber'];
<a href="#card3">Wprowadz numer gg</a> i zadeklarować odpowiednią wersję dokumen-
<a href="#card2">Autor</a> tu XML: echo "<?xml version=\"1.0\"?>";.
</p> Aby pobrać aktualny status wybranego nume-
</card> ru komunikatora gadu-gadu stwórzmy nastę-
<card id="card3" title="Podaj numer"> pującą zmienną:
<p>
Numer gg: $ string ="http://status.gadu-gadu.pl/
<input type="text" name="ggnumber" size="8" title="Numer gg" /> users/status.asp?id =".$ ggnu mer."&styl
</p> =2";
<p>
<anchor> i skorzystajmy z funkcji fopen. Dzięki tym za-
<go href="gg.php" method="post"> biegom otrzymamy informacje w postaci cy-
<postfield name="ggnumber" value="$(ggnumber)" /> fry, która pozwoli nam na określenie aktual-
</go> nego statusu użytkownika. Całość skryptu
Wyslij dane przedstawiona jest na Listingu 5.
</anchor>
</p> Jak rozpoznać klienta
<p> Kolejnym istotnym problemem jest stworze-
Menu<br /> nie funkcji, która pozwoli nam odczytać rodzaj
<a href="#card3">Wprowadz numer gg</a> klienta z jakim mamy do czynienia (może to być
<a href="#card2">Autor</a> np. przeglądarka internetowa lub właśnie tele-
</p> fon komórkowy). Może to być przydatne gdy
</card> tworzona przez nas witryna ma być dostępna za-
</wml> 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'].
WmlScript Możemy porównywać wartość tej zmiennej
Możemy powiedzieć, że jest to uproszczona wersja JavaScript dla języka WML. Zachodzi jednak
ze znanymi przeglądarkami WWW i przeglą-
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 darkami WAP, co pozwoli nam na otworzenie
wykorzystać PHP. Jednakże wszystkich zainteresowanych WmlScript odsyłam do witryny http:// pożądanej witryny. Przy zastosowaniu tej tech-
www.webreference.com/. niki występuje jednak poważny minus, mia-
nowicie, nieustannie powinniśmy aktualizo-

24 06/2007
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.

wać listę dostępnych przeglądarek. Innym spo- wysłać wiadomość w pliku email.php niezbędne
sobem jest sprawdzanie listy obsługiwanych jest odebranie wysłanych metodą POST danych
przez klienta typów MIME. Taką listę zawiera i skorzystanie z wbudowanej funkcji mail. Całość
zmienna PHP $_SERVER['HTTP_ACCEPT'];. skryptu realizującego to zadanie przedstawione
Jeżeli odnajdziemy na liście typ MIME dla jest na Listingu 7. zamieszczonym na płycie.
plików WML, oznacza to będzie że najprawdo- Oczywiście aby stworzyć w pełni funkcjonal-
podobniej klient korzysta z przeglądarki obsłu- ną aplikację niezbędnym jest także sprawdze-
gującej WAP. Obie te metody mogą jednak być nie poprawności wprowadzonych danych, co
zawodne dlatego najlepszym rozwiązaniem jest jednak nie jest istotą tego artykułu.
całkowite rozgraniczenie klasycznej aplikacji
WWW i tej tworzonej dla WAP. Podsumowanie
Pokazaliśmy jak stworzyć witrynę WAP i wyko-
WAP i bramka e-mail rzystać w tym celu PHP. Podany przykład zilu-
Wykorzystując PHP bez większych problemów strował najważniejsze aspekty tworzenia strony
możemy stworzyć jakże pożyteczną aplikację WAP. Pokazaliśmy, jak wykonać menu i przesłać
WAP, której zadaniem będzie wysyłanie wiado- informacje na serwer. Dzięki tym informacjom
mości e-mail. Wystarczy, że przygotujemy no- można bez trudu tworzyć podobne aplikacje,
wą kartę wraz odpowiednimi polami formula- włączając w to system logowania, system new-
rza, tak jak na Listingu 6. (zamieszczony w ma- sów i wiele, wiele innych.
teriałach dodatkowych na płycie).
Po wysłaniu danych formularza przekazane zo-
staną one do strony email.php. Cały proces kon- TOMASZ ROSZKO
strukcji formularza jak i sposobu przesyłania da- Autor jest studentem informatyki na Uniwersytecie
nych do innego pliku na serwerze jest identyczny w Białymstoku.
z tym przedstawianym wcześniej. Następnie aby Kontakt z autorem: tomaszroszko@gmail.com

www.phpsolmag.org
Technika

Delphi i PHP
Komunikacja

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.

Jak pamiętamy, dane przesyłane metodą POST


Dowiesz się... Powinieneś wiedzieć... mają postać:
• W jaki sposób odebrać dane ze skryptu. • Powinieneś znać podstawy języka i środowi-
• W jaki sposób wysłać dane do skryptu. ska Delphi. pole1=wartość&pole2=wartość2.
• Powinieneś znać podstawy języka PHP i HTML.
• Powinieneś znać podstawowe pojęcia związa- Dlatego musimy je przesłać w taki sposób.
ne z protokołem http. Nazwy pól: „text1” i „text2” są nazwami przy-
kładowymi, które następnie zastosujemy
w skrypcie odbierającym dane. Należy pamię-
niśmy im nadać, zostały zaprezentowane na tać, że będą one różne dla każdej strony, która
Rysunku 1. odbiera pakiety z danymi.
Poziom trudności Po umieszczeniu wszystkich elementów, Powyższa linijka tworzy ciąg powstały z po-
kliknijmy tylko raz na komponent IdHTTP łączenia tekstu w cudzysłowie, z tekstem wpi-
i przejdźmy do Object Inspector’a, a następ- sanym w Edit2 i Edit3. Owy ciąg jest następ-
nie – odszukajmy listę Request. Po jej rozwinię- nie wysyłany do skryptu za pomocą funkcji

S
posób komunikacji, opiera się na meto- ciu ukaże się nam kilka atrybutów, interesować POST komponentu IdHTTP. Ostatnim kro-
dzie POST, która umożliwia wysyłanie nas będzie ten o nazwie ContentType. W to pole kiem będzie zapisanie i skompilowanie nasze-
danych przy pomocy nagłówków HTTP. musimy wpisać ciąg: go projektu.
Dane przesyłane tą metodą mają postać: Gdy mamy już gotową aplikację, może-
application/x-www-form-urlencoded. my stworzyć najprostszy plik PHP, który po-
pole1=wartość&pole2=wartość2. służy nam do jej testowania. Propozycja ko-
Więcej o kodowaniu danych możemy przeczy- du znajduje się na Listingu 3. W skrypcie,
Tak więc: nazwa pola jest oddzielona od jego tać w ramce „Kodowanie danych”. dla ułatwienia, zostały zastosowane zmien-
wartości znakiem „=”, natomiast poszczególne ne o takich samych nazwach, jak w naszym
porcje danych oddziela znak „&”. Przykładowy Pisanie kodu programie.
nagłówek z powyższymi informacjami wyglą- Projektowanie aplikacji mamy już za sobą, czas Po zapisaniu pliku PHP i umieszczeniu go
dałby więc tak, jak na Listingu 1. więc na napisanie kilku linijek kodu. Nasz pro- na serwerze, uruchamiamy naszą aplikację, po-
gram będzie miał za zadanie: dajemy odpowiednie parametry i naciskamy
Z Delphi do PHP przycisk POST. Pole tekstowe „Memo” podpisa-
Zacznijmy projektować naszą aplikację, która • pobrać adres strony; ne jako „Kod wynikowy” zostanie automatycz-
prześle dane do skryptu metodą POST . Uru- • pobrać dwie zmienne do wysłania; nie uzupełnione danymi zwróconymi przez
chamiamy Delphi i z menu File wybieramy • wysłać dane; skrypt. Przedstawia to Rysunek 2.
New Application. • odebrać kod wynikowy.
Po instalacji pakietu INDY w Delphi, przy- Listing 1. Przykładowy nagłówek z danymi
będzie nam kilka nowych zakładek na pa- Jego lista zadań jest krótka. Dzięki zastoso- wysłanymi metodą POST
lecie komponentów. Odszukajmy zakład- waniu komponentu IdHTTP, kod również bę-
kę Indy Clients i wybierzmy z niej kompo- dzie krótki. Kliknijmy dwa razy na Button’ie POST /index.php HTTP/1.1
nent IdHTTP. To on umożliwi nam wysyła- i wpiszmy kod, który znajduje się na Listingu 2. Host: www.domena.com
nie danych. Przyjrzyjmy się linijce odpowiadającej za User-Agent: Mozilla/5.0
Umieścimy jeszcze następujące kompo- utworzenie strumienia StreamIn, a szczególnie Content-Length: 28
nenty: 3x Edit, 4x Label, 1x Button, oraz 1x fragmentowi: Content-Type: application/x-www-form-
Memo (wszystkie one znajdują się w zakład- urlencoded
ce Standard). Ich przykładowe rozmieszcze- (Format('text1=%s&text2=%s', [Edit2.Text,Ed pole1=wartość&pole2=wartość2
nie, a także właściwości Caption jakie powin- it3.Text])).

26 06/2007
Delphi i PHP

Przykładowe zastosowanie
Listing 2. Wysyłanie danych z aplikacji do skryptu metodą POST Przykładowym zastosowaniem powyższej
procedure TForm1.Button1Click(Sender: TObject); metody komunikacji może być program, któ-
var ry będzie uploadował wybrane obrazy z na-
StreamIn,StreamOut: TStringStream; szego dysku twardego na darmowy hosting
begin zdjęć ImageShack (dostępny pod adresem
try www.imageshack.us). Zaczniemy od małego
{Tworzymy strumień StreamIn zawierający łańcuch danych, rekonesansu, tak więc otwieramy ową stro-
zostanie on potem wysłany do skryptu} nę. Aby uniknąć żmudnej analizy kodu w
StreamIn := TStringStream.Create(Format('text1=%s&text2=%s', [Edit2.Text,Edit3.Text] celu „wydobycia” szczegółów, skorzystajmy
)); z wtyczki do Firefox’a pod nazwą Web Develo-
{Tworzymy pusty strumień StreamOut. Będzie on odpowiedzialny per (link znajduje się w ramce „W Sieci”). Po-
za odbiór kodu wynikowego skryptu} siada ona funkcję, która modyfikuje wyświe-
StreamOut := TStringStream.Create(''); tlaną stronę pokazując, na przykład, szcze-
{Procedura POST komponentu IdHTTP i jej kolejne parametry: góły formularzy. Zostało to pokazane na Ry-
Adres URL, strumień z danymi, strumień odbierający} sunku 3.
IdHTTP1.Post(Edit1.Text,StreamIn,StreamOut); Co na nim widzimy? Po pierwsze – for-
{Wyświetlamy kod wynikowy ze strumienia w Memo} mularz odwołuje się do strony głównej Ima-
Memo1.Lines.Text:=StreamOut.DataString; geShack.us (fragment form action=””), po
finally drugie- format kodowania danych to multipart/
{Zwalniamy strumienie} form-data (fragment enctype=””), i wreszcie po
StreamIn.Free; trzecie- pole, z którego pobierana jest ścież-
StreamOut.Free; ka do wysyłanego pliku (input name="fileuplo-
end; ad”). Posiadając te informacje możemy rozpo-
end; cząć projektowanie aplikacji.

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


<?php Zacznijmy od stworzenia nowego projek-
$text1=$_POST['text1']; tu. Potrzebne nam będą komponenty: 1x
$text2=$_POST['text2']; Edit, 1x Memo, 1x button, a także komponent
echo "Zmienna \"text1\" to: $text1\n"; //wyświetlamy zmienną „text1” IdHTTP.
echo "Zmienna \"text2\" to: $text2\n"; //wyświetlamy zmienną „text2” 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-
Rysunek 3. Wtyczka Web Developer wyświetlająca szczegóły formularza na stronie ImageShack.us taStream. Jest to specyficzny typ strumienia

Rysunek 1. Przykładowe rozmieszczenie komponentów. Z lewej strony – komponenty ze standardowymi Rysunek 2. Gotowa aplikacja wysyłająca dane do
właściwościami Caption, natomiast z prawej – komponenty posiadające zmodyfikowaną tę właściwość skryptu

www.phpsolmag.org 27
Technika

z danymi, którego implementacja konieczna oraz 2x Memo (wszystkie one znajdują się w OnClose naszej formy, wpiszemy ponownie
jest do wysłania danych, zakodowanych w for- zakładce Standard). Ostatnio użyliśmy kom- kod z Listingu 5. który tym razem jest opisa-
macie multipart/form-data. Aby z niego skorzy- ponentu, który był klientem protokołu HTTP. ny jako:
stać, konieczne jest dodanie do sekcji Uses mo- Pisząc tę aplikację, będziemy musieli stwo-
dułu IdMultipartFormData. Jest on dołączony rzyć serwer HTTP. Odszukajmy więc zakład- {Procedura OnClose}.
do pakietu INDY. Po kompilacji projektu na- kę Indy Servers i wybierzmy z niej komponent
leży w pole Edit wpisać ścieżkę obrazu, któ- IdHTTPServer. Ich przykładowe rozmieszcze- Główne zdarzenia zostały już napisane, czas
ry chcemy uploadować, a następnie nacisnąć nie, a także właściwości Caption jakie powin- teraz na kod, który umożliwi odbieranie da-
przycisk Button. niśmy im nadać, zostały zaprezentowane na nych. Klikamy na komponent IdHTTPServer1
Zachęcam do przejrzenia kodów źródło- Rysunku 5. i przechodzimy do Object Inspector. Odszu-
wych, które zostały dołączone do płyty. Do kujemy Event podpisany jako OnCommand-
aplikacji dodałem również parser, który po- Pisanie kodu Get i wpisujemy kod z Listingu 6.
biera z kodu wynikowego linki do naszego Przyszedł czas na oprogramowanie naszej apli- Aplikacja jest już gotowa, możemy ją zapi-
obrazu, ale to temat na inny artykuł. Przy- kacji. Zacznijmy od aktywacji serwera- klikamy sać i skompilować. Podobnie jak wcześniej,
kład działania aplikacji pokazany jest na Ry- na formie i odszukujemy właściwość OnCre- stworzymy jeszcze plik PHP, z tym, że te-
sunku 4. ate na zakładce Events w oknie Object Inspector raz to on będzie wysyłał dane do serwera.
i wpisujemy tam fragment kodu z Listingu 5. W tym celu posłużymy się najprostszym for-
Z PHP do Delphi... podpisanego jako: mularzem, którego propozycja kodu znajdu-
Teraz nadszedł czas na napisanie programu, je się na Listingu 7. Pamiętajmy, że nasz pro-
który będzie umożliwiał odbieranie zmien- {Procedura OnCreate}. gram działa na porcie 8008 (aby uniknąć ko-
nych wysyłanych przez skrypt. lizji z innymi aplikacjami), więc będziemy
Stworzymy nową aplikację i na formie Deaktywacja serwera odbywać się będzie pod- odwoływać się do niego w następujący spo-
umieścimy komponenty: 2x Label, 1x Edit czas zamykania programu, więc w zdarzenie sób http://AdresIP:NumerPortu, czyli http://
localhost:8008.
Listing 4. Wysyłanie danych z aplikacji do strony ImageShack Teraz musimy jeszcze uruchomić nasz pro-
gram i wypełnić pola formularza, a następnie
procedure TForm1.Button1Click(Sender: TObject); go zatwierdzić. Wynik działania aplikacji, która
var odebrała parametry i zwróciła wynik do prze-
MyData: TIdMultiPartFormDataStream; glądarki znajduje się na Rysunku 6.
begin
{tworzymy specyficzny strumień z danymi} Przykładowe zastosowanie
MyData:=TIdMultiPartFormDataStream.Create; Powyższy sposób komunikacji może być wyko-
try rzystany- np. do zdalnej administracji kompu-
{kolejny krok to dodanie do strumienia, metodą AddFile, kolejno: terem poprzez stronę WWW.
nazwy pola (fileupload),ścieżki pliku, a także typu zawartości Wg definicji serwera aplikacji jest to „pro-
pakietu z danymi(file)} gram działający na zdalnej maszynie obsługu-
MyData.AddFile('fileupload',Edit1.Text,'file'); jący żądania kierowane do aplikacji, do której
{kod wynikowy zostanie wyświetlony w Memo1} dostęp zapewnia. Użytkownik łączy się za po-
Memo1.Lines.Text:=IdHTTP1.Post('http://imageshack.us/',MyData); średnictwem przeglądarki internetowej, kieru-
finally je żądanie do wybranej aplikacji, a całość ope-
{Zwalniamy strumień} racji odbywa się po stronie komputera nale-
MyData.Free; żącego do organizacji, która udostępnia daną
end; aplikację.”(pl.wikipedia.org).Zastanówmy się naj-
end; pierw nad ogólną koncepcją naszej aplika-
cji – zarówno klienta jak i serwera. Klient –
Listing 5. Aktywacja i deaktywacja serwera IdHTTPServer1 w tym przypadku strona WWW – powinien
{Procedura OnCreate} zawierać pola: „Login” oraz „Hasło”, aby nasze-
procedure TForm1.FormCreate(Sender: TObject); go zdalnego systemu nie mogły przechwycić
begin
{Ustawiamy numer portu dla serwera}
IdHTTPServer1.DefaultPort := 8008; Kodowanie danych
{aktywujemy serwer} Jeżeli chcemy wysłać dane do serwera za-
IdHTTPServer1.Active:=True;
wierające elementy formularza, to muszą
one wcześniej zostać zakodowane. Kodo-
end;
wanie application/x-www-form-urlencoded
{- - -} jest kodowaniem domyślnym, które prze-
{procedura OnClose} glądarka wysyła do skryptu; używamy go
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); do wysyłania małych ilości informacji. Nie
begin sprawdza się ono jednak podczas wysyła-
nia dużych ilości danych binarnych lub roz-
{dezaktywujemy serwer}
ległego tekstu. Do tego celu należy użyć ko-
IdHTTPServer1.Active:=False; dowania multipart/form-data.
end; Niezależnie od tego, na jakie kodowa-
{- - -} nie się zdecydujemy, musimy pamiętać o je-
go implementacji w naszym programie.

28 06/2007
Delphi i PHP

niepowołane osoby, a także kilka opcji wybo-


ru, które będą reprezentowały możliwe do wy- Listing 6. Odbieranie danych przez aplikację
konania funkcje przez zdalny system. Po wy- procedure TForm1.IdHTTPServer1CommandGet(AThread: TIdPeerThread;
braniu opcji „Wyślij”, skrypt wyśle parametry ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
do aplikacji – serwera. var
Serwer natomiast, po odbiorze porcji da- StrResult: String;
nych, powinien mieć możliwość ich wali- begin
dacji, w tym danych użytkownika (jego na- {w Memo zostaną umieszczone żądania (request server)}
zwy oraz hasła), który chce skorzystać z jego Memo1.Lines.Add(ARequestInfo.Document);
usług, a także oczywiście mieć możliwość wy- {tworzymy kod wynikowy dla przeglądarki}
konania żądanego polecenia. Po jego wykona- StrResult := '<h1>Testowa strona serwera.</h1>'
niu serwer powinien zwrócić wynik, następ- +'<b>Odebrane dane:</b>'
nie wszystkie operacje powinny być zapisywa- {ARequestInfo.Host zawiera informacje o hoście użytkownika...}
ne w logach. + '<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">
Rysunek 4. Gotowa aplikacja wysyłająca
<br />
obrazy na hosting ImageShack.us i parsująca kod
wynikowy <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


Rysunek 5. Przykładowe rozmieszczenie
<html>
komponentów. Z góry: komponenty
ze standardowymi właściwościami Caption, <form action="http://localhost:8008" method="post">
natomiast u dołu: komponenty posiadające <label for="login"><b>Login</b></label>
zmodyfikowaną tą właściwość <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 />
Rysunek 6. Gotowa aplikacja odbierająca dane
<input type="radio" name="opcje" value="shutdown" checked/>Wyłącz zdalny komputer
od skryptu
<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

www.phpsolmag.org 29
Technika

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


W Sieci
procedure TForm1.IdHTTPServer1CommandGet(AThread: TIdPeerThread;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); • http://www.codegear.com/downloads/
free/delphi
var
• http://www.indyproject.org/
StrResult: String;
• https://addons.mozilla.org/pl/firefox/
login,pass,autoryzacja: boolean; addon/60
begin • http://www.4programmers.net
{w Memo zostaną umieszczone żądania (request server)}
Memo1.Lines.Add(ARequestInfo.Document);
{do logów dodajemy parametry przekazane do serwera} więc do sekcji Uses musimy dodać moduł
Memo1.Lines.Add('Odebrane parametry:'); ShellAPI.
Memo1.Lines.Add(ARequestInfo.Params.Text); Sam kod nie jest trudny do zrozumienia, zo-
{walidacja danych:} stał on oczywiście opatrzony komentarzami,
{czy login (parametr 0) jest poprawny?} dlatego zachęcam do jego przejrzenia. Przyj-
if ARequestInfo.Params[0]='login=admin' rzyjmy się fragmentowi odpowiedzialnemu za
then login:=True else login:=False; walidację danych.
{czy hasło (parametr 1) jest poprawne?} Zmienna ARequestInfo.Params[index] zawie-
if ARequestInfo.Params[1]='pass=password' ra kolejne parametry, do których możemy od-
then pass:=True else pass:=False; woływać się po ich indeksie. Nasz skrypt, który
{identyfikacja} pisaliśmy wcześniej, wysyła kolejno porcje da-
if (login and pass) then autoryzacja:=True nych: login, będący parametrem zerowym, ha-
else autoryzacja:=False; sło, będące parametrem pierwszym, i tak da-
{wypisujemy kod wynikowy} lej. Ważna jest kolejność, jaką zachowujemy.
StrResult := '<b>Odebrane dane:</b>' Wysyłając najpierw hasło, a dopiero potem lo-
+ '<p>Autoryzacja loginu: ' + BoolToStr(login,True) + '</p>' gin do serwera- automatycznie zmieniamy ich
+ '<p>Autoryzacja hasła: ' + BoolToStr(pass,True) + '</p>' indeksy, co powoduje, że dane nie przechodzą
+ '<p>Wykonanie polecenia: ' + BoolToStr(autoryzacja,True) + '</p>'; walidacji.
AResponseInfo.ContentText := StrResult; Możemy oczywiście skorzystać na przykład z
{zwracamy informację do przeglądarki} instrukcji for...to i sprawdzać po kolei wszystkie
AResponseInfo.WriteContent; odebrane skrypty, jednakże, przy tak małej ilo-
{sprawdzenie polecenia} ści danych nie jest to konieczne.
if ((ARequestInfo.Params[2]='opcje=message') and autoryzacja)
then Wynik działania
ShowMessage(StringReplace(ARequestInfo.Params[3],'wiadomość=','',[])) Proces tworzenia aplikacji, zarówno serwe-
else ra jak i klienta, mamy już za sobą. Teraz nad-
if ((ARequestInfo.Params[2]='opcje=shutdown') and autoryzacja) szedł czas na przyjrzenie się rezultatom ich
then działania.
{wywołanie cmd.exe z parametrem shutdown- zamykamy system} Tak więc: uruchamiamy nasze aplikacje- ser-
ShellExecute(Handle,'open','cmd.exe','/c shutdown /s','C:',SW_HIDE) wer i stronę z formularzem. Wypełniamy poda-
else ne pola (niekoniecznie poprawnie, aby zoba-
end; czyć, czy wszystko działa tak jak należy) i wysy-
łamy dane. Przykład działania aplikacji pokaza-
ny jest na Rysunku 7.
Projekt klienta Projekt serwera
Pierwszym krokiem będzie stworzenie stro- Projekt serwera w dużej mierze opierać bę- Podsumowanie
ny WWW, której funkcją będzie wysyłanie pa- dzie się na aplikacji zaprezentowanej na po- Mój niewielki artykuł opisuje tylko wierz-
kietów z danymi do naszej aplikacji. Opierać czątku obecnego rozdziału. Śmiało możemy chołek góry lodowej, jaką jest pakiet INDY.
się ona będzie na prostym formularzu, które- otworzyć tamten projekt i zacząć go mody- Dla jego potrzeb wykorzystałem zaledwie
go kod został zaprezentowany na Listingu 8. fikować. dwa komponenty z ponad ich stuelemento-
Podobnie jak poprzednio, będziemy korzystać Zacznijmy od usunięcia Label-u podpi- wej kolekcji. Pamiętaj, że „teoria śni, prakty-
z portu numer 8008. Jeżeli zamierzamy korzy- sanego jako „Odebrane parametry”, a także ka uczy”. W momencie, gdy sam stworzysz
stać z aplikacji, z innego komputera niż local- komponentu Edit1. Nie będą one nam już i przeanalizujesz aplikacje, zmodyfikujesz
host, niekiedy wymagane będzie odblokowanie potrzebne. ich kody i prześledzisz działanie, będziesz
tego portu na firewall’u. Następnie, tak jak poprzednio, klikamy na mógł w pełni zrozumieć zagadnienia, które
Przyjrzyjmy się Listingowi 8. Jak widać, zo- komponent IdHTTPServer1 i przechodzimy do nimi kierują.
stały w nim zawarte planowane pola: Login oraz Object Inspector’a. Odszukujemy Event pod-
Hasło, a także pola typu „Radio”, które repre- pisany jako OnCommandGet i wpisujemy kod
zentują możliwe do wykonania zadania. Dla z Listingu 9. Pozostałe procedury projektu po- ARTUR CHUDZIK
przykładu umieściłem dwa: możliwość wyłą- zostawiamy bez zmian. Autor w wolnych chwilach zajmuje się progra-
czenia zdalnego komputera, a także opcję wy- Procedura OnCommandGet, którą przed mowaniem, a także administracją portalem We-
świetlenia na nim wiadomości. Skoro ten etap chwilą wpisaliśmy, zawiera przykładowe po- bHat.pl, którego jest założycielem. Obecnie uczy się
mamy już za sobą możemy przejść do projekto- lecenie zamykające system- w tym wypad- w drugiej klasie 1LO w Łańcucie.
wania serwera. ku posłużyliśmy się funkcją ShellExecute, tak Kontakt z autorem: admin@webhat.pl

30 06/2007
Rozwiązania

Creole
Abstrakcja bazodanowa

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.
nie) w jeszcze prostszy sposób. Niektóre po-
Dowiesz się... Powinieneś wiedzieć... jęcia, takie jak DataSet, zostały zapożyczone
• Czym jest Creole. • Powinieneś znać podstawy programowania z Working-Dogs Village z języka Java. Pakiet Jar-
• Jak korzystać z Creole'a. obiektowego w PHP5. gon nie wchodzi standardowo w skład pakietu
• Powinieneś znać pojęcia związane z bazami Creole – należy go zainstalować osobno. W dal-
danych. szej części artykułu zostanie przedstawiona in-
stalacja obu pakietów oraz przykład zastosowa-
nia pakietu Creole.
kietu wzorowano się na podobnych rozwią-
zaniach z języka Java – mowa tutaj o ste- Jak zainstalować
Poziom trudności rownikach JDBC (ang. Java Database Con- i skonfigurować pakiet Creole
nectivity) oraz już istniejących rozwiąza- Instalacja pakietu Creole jest niezwykle pro-
niach z języka PHP – AdoDB, PEAR::DB sta. Możemy przeprowadzić ją na dwa sposo-
i PEAR::MDB. Creole obsługuje popular- by – pierwszy – z użyciem instalatora PEAR

K
ażdy producent baz danych zapewnia ne bazy danych, takie jak: MSSQL, MySQL, lub drugi – ściągając odpowiednie biblioteki
interfejs, za pomocą którego skrypt Oracle, PostgreSQL i SQLite. ze strony projektu. Do poprawnej pracy pakie-
może komunikować się z serwerem. W ramach projektu Creole został stworzo- tów wymagane jest: PHP w wersji 5 oraz jeden
Chcąc, aby nasza aplikacja współpracowała ny pakiet o nazwie Jargon, który jest zbiorem (lub więcej) z obsługiwanych systemów zarzą-
z różnymi systemami zarządzania bazami da- wielu użytecznych klas. Nie jest to inna abs- dzania bazą danych (MySQL, PostgreSQL, MS
nych – RDBMS (ang. Relational DataBase Ma- trakcja bazodanowa, gdyż do komunikacji z ba- SQL Server, SQLite, Oracle, ODBC). W każ-
nagement System), takimi jak MySQL, Postgre- zą Jargon używa klas Creole'a. Jest to API, za dym z tych dwóch przypadków będziemy in-
SQL czy SQLite, należy zaimplementować pomocą którego możemy wykonywać zapyta- stalować pakiet Creole oraz towarzyszący mu
każdy z nich na jej potrzeby. Jednak powstały nia do bazy danych (odczytywanie i zapisywa- pakiet Jargon.
w ten sposób kod, sprawia wiele problemów.
Aby rozszerzyć funkcjonalność aplikacji o ko- Tabela 1. Flagi funkcji getConnection()
lejne systemy, trzeba pisać kolejne implemen- Flaga Opis
tacje ich interfejsów. Tutaj z pomocą przycho- Creole::PERSISTENT Tworzy trwałe połączenie z serwerem.
dzą abstrakcje bazodanowe. Warstwa abstrak-
Creole::COMPAT_ASSOC_LOWER Nazwy pól przekształcane są na małe litery.
cji udostępnia ujednolicony interfejs programi-
styczny dla różnych systemów bazodanowych. Creole::COMPAT_RTRIM_STRING Usuwa białe znaki znajdujące się na końcu obiektów typu
string, np. przy użyciu
Dzięki takiej warstwie, można ukryć szczegóły ResultSet->getString().
implementacji standardu SQL w różnych ser-
Creole::COMPAT_ALL Ustawia wszystkie flagi związane ze zgodnością.
werach i stworzyć interfejs, za pomocą które-
go możemy obsługiwać każdy z nich. W sie-
Tabela 2. Metody klasy Query
ci przykładów takich abstrakcji możemy spo-
tkać wiele – AdoDB, PEAR::DB, PDO, Creole Nazwa metody Opis
i wiele innych. getAssoc() Zwraca tablicę, której indeksem są wartości pierwszej kolumny zbioru wynikowego.
Pakiet Creole powstał jako podprojekt pakie- Wartościami tablicy są wartości pozostałych kolumn (indeksowane numerycznie od 0).
tu Propel, służącego do odwzorowywania klas getCol() Zwraca pierwszą kolumnę wyniku w formie tablicy.
PHP w ramach relacyjnej bazy danych, będą- getOne() Zwraca pierwszą kolumnę pierwszego wiersza wynikowego. Reszta wierszy zo-
cego rozwiązaniem typu ORM (ang. Object-Re- staje pominięta.
lational Mapping). W tej formie pakiet został getRow() Zwraca pierwszy wiersz wynikowy. Reszta wierszy zostaje pominięta.
wykorzystany w wielu framework’ach np. we
getRows() Zwraca wiersze wynikowe w formie tablicy.
Framework’u Symfony. Podczas tworzenia pa-

32 06/2007
Creole

Pierwszy sposób my najpierw udać się na stronę http://creole. Creole w zastosowaniach


– instalator PEAR phpdb.org/trac/wiki/Users/Download i ściągnąć Po krótkim wprowadzeniu i instalacji, możemy
Jeżeli dysponujemy instalatorem PEAR, w na- pakiet z sekcji Current Release oznaczony przejść do tego co najważniejsze, czyli do tego
szym systemie możemy zainstalować oba pa- creole-version o rozszerzeniu .tar.gz lub .zip jak używać Creole'a w naszych skryptach. Ze
kiety wykonując w konsoli następujące pole- w zależności od upodobania (wersja dostępna względu na to, że pakiet został całkowicie na-
cenia: w trakcie pisania artykułu to 1.1.0). pisany w PHP5 jest w pełni obiektowy. Ważne
Nie musimy ściągać osobnego archiwum jest, aby na samym początku włączyć do skryp-
pear channel-discover pear.phpdb.org z pakietem Jargon, gdyż został on już do- tu plik Creole.php.
pear install phpdb/creole łączony do wcześniej ściągniętego archiwum.
pear install phpdb/jargon Następnie należy rozpakować ściągnięte ar- Nawiązywanie połączenia
chiwum i przekopiować foldery classes/creole Do nawiązania połączenia z bazą używamy sta-
Jeżeli instalator nie zwróci żadnych błędów, i classes/jargon do katalogu wskazywane- tycznej metody Creole::getConnection().
oznacza to, że pakiety zostały poprawnie za- go przez zmienną include_path (jej wartość W pierwszym argumencie przekazujemy adres
instalowane. można sprawdzić wywołując funkcję php- w postaci DSN (ang. Data Source Name). Może-
info() ) lub stworzyć powiązania tych fol- my go przekazać jako tablicę lub jako ciąg zna-
Drugi sposób derów do katalogu wskazywanego przez tą ków. W drugim argumencie przekazujemy flagi z
– ręczna instalacja pakietów zmienną. W przypadku jakichkolwiek nie- jakimi ma zostać utworzone nasze połączenie. Na
W przypadku, gdy nie dysponujemy instala- jasności możesz zapoznać się z plikami szczególną uwagę zasługuje tutaj flaga Creole::
torem PEAR, możemy ręcznie przeprowa- INSTALL i README, które są dołączone do PERSISTENT, która umożliwia nawiązanie trwa-
dzić instalację pakietów. W tym celu musi- archiwum. ł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”);
?>

www.phpsolmag.org 33
Rozwiązania

ciu funkcji mysql_pconnect(), przy połączeniu w bazie. Dzięki metodzie executeQuery(), może- rał wyniki naszego zapytania. Do przeglądania
z bazą MySQL. Wszystkie flagi zostały wyszcze- my wysyłać zapytania do serwera. Oprócz nich, wyników możemy użyć pętli foreach, gdyż
gólnione w Tabeli 1. Przykład nawiązywania połą- możemy również zdefiniować sposób indek- został zaimplementowany SPL Iterator. Może-
czenia został przedstawiony na Listingu 1. sowania wyników, używając flag ResultSet: my posłużyć się również bardziej tradycyjny-
:FETCHMODE_ASSOC i ResultSet::FETCHMODE_ mi funkcjami: first(), next(), previous(),
Operacje na danych NUM. Domyślnie wyniki są indeksowane nazwa- last(), relative() (niestety w Oracle wstecz-
Creole posiada metody, za pomocą których mo- mi pól (pierwsza flaga). W odpowiedzi otrzy- ne przewijanie nie jest obsługiwane).
żemy wybierać, dodawać i aktualizować dane mamy obiekt ResultSet, który będzie zawie- Na Listingu 2. został przedstawiony przy-
kład wybierania z tabeli test kolumn id
Listing 4. Używanie wstępnie przygotowanych zapytań i name oraz dwa sposoby wyświetlenia wyni-
ków. Została tutaj zastosowana metoda exe-
<?php cuteQuery() klasy Connection. Istnieją jesz-
$statement = $connection->prepareStatement('SELECT imię, nazwisko, cze dwie takie metody dla klas Statement
telefon FROM adresy WHERE id = ? OR nazwisko = ?'); oraz PrepareStatement, które opiszę za
$statement->setInt(1, 3); chwilę. Wcześniej przyjrzyjmy się drugiemu
$statement->setString(2, 'Marecki'); przypadkowi wyświetlenia wyników. Wyko-
$resultSet = $statement->executeQuery(); rzystano w nim metodę next() oraz meto-
?> dy get*(), gdzie * oznacza typ na jaki ma zo-
stać przekonwertowana wartość pola z wier-
Listing 5. Używanie wstępnie przygotowanych zapytań – przekazywanie tablicy z parametrami sza wynikowego. Oprócz int i string może-
<?php my używać także Blob, Boolean, Clob, Date,
$statement = $connection->prepareStatement('SELECT imie, nazwisko, Float, Time, Timestamp. Metoda get() zwra-
telefon FROM adresy WHERE id = ? OR nazwisko = ?'); ca niesformatowaną wartość pola (najczę-
$resultSet = $statement->executeQuery(array(3, 'Marecki')); ściej typu string). Funkcje get*() i get()
?> jako argument, pobierają nazwę pola lub
jeśli została ustawiona flaga ResultSet::
Listing 6. Obsługa wyjątków SQL Exception FETCHMODE_NUM jego numer (w tym przy-
<?php padku numeracja pól zaczyna się od 1). Na-
try tomiast korzystając z metody getRow(), mo-
{ żemy pobrać wiersz wyniku z aktualnej po-
$resultSet = $connection->executeQuery('SELECT imie, nazwisko FROM adresy'); zycji w zbiorze wyników, w formie tablicy
asocjacyjnej. W drugim wierszu Listingu 2.
foreach($resultSet as $rowNumber => $row) została użyta kolejna metoda z rodziny get
{ – getRecordCount(), dzięki której możemy
echo 'Imie: '.$row['imie'].'<br/>'; się dowiedzieć, ile wierszy wyników zwróci-
echo 'Nazwisko: '.$row['nazwisko'].'<br/>'; ł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-
catch(SQLException $e) menty nieobsługiwane przez klasę Connection
{ – parametry Limit/Offset oraz wstępnie
echo 'Nastąpił błąd podczas wykonywania: '.$e 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
Listing 7. Przykład użycia transakcji i obsługi błędów pomocą metody createStatement(), obiek-
<?php tu Connection. W tak przygotowanym obiek-
try{ cie możemy ustawić wartości Limit i Offset.
$connection->setAutoCommit(false); Klasa ta posiada inną interesującą metodę
$connection->executeUpdate(„UPDATE adresy SET id=3 WHERE nazwisko='Nowak'”); – executeUpdate(), za pomocą której mo-
$connection->executeUpdate('DELETE FROM adresy WHERE id>2'); żemy dodawać, usuwać i aktualizować dane
$connection->commit(); z tabeli (metoda ta dostępna jest we wszyst-
} kich trzech klasach). Wynikiem jej działania
jest liczba zmienionych wierszy. Jest to wygod-
catch(Exception $e) niejsze i efektywniejsze, niż w przypadku me-
{ tody executeQuery(), gdyż tam otrzymujemy
$connection->rollback(); obiekt typu ResultSet. Na Listingu 3. został
echo 'Przerwano transakcję !!! Wystąpił błąd: '.$e->getMessage(); 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-

34 06/2007
Creole

winna być traktowana jako rozszerzenie kla- 7. Używając metody setAutoCommit() z ar- w bloku catch transakcja jest anulowana za
sy Statement. Klasy te nie są połączone ze gumentem false rozpoczynamy transakcję pomocą metody rollback(). Jeżeli nie wy-
względu na pewne ograniczenia języka PHP5. (domyślnie zapytania są automatycznie za- stąpią żadne błędy, transakcja zostaje za-
Na Listingu 4. został przedstawiony przykład twierdzane zaraz po wykonaniu). Dalej wyko- twierdzona poprzez metodę commit(). Ta-
pobierania danych z tabeli test, przy uży- nujemy pewne działania na bazie danych. Je- kie działanie chroni przed konsekwencjami
ciu wstępnie przygotowanych zapytań. Do żeli wydarzy się jakaś awaria lub błąd, wtedy różnych błędów.
stworzenia takiego zapytania należy wywołać
metodę prepareStatement() na obiekcie Listing 8. Pobieranie metadanych na temat tabel bazy
typu Connection. Jako argument przekazu-
jemy nasze zapytanie, jednak w miejscach, <?php
gdzie będziemy dynamicznie podawali $databaseInfo = $connection->getDatabaseInfo();
wartości wstawiamy znak '?'. W rezultacie foreach($databaseInfo->getTables() as $table)
metoda zwróci nam obiekt typu Prepared {
Statement, na rzecz którego możemy wywo- echo 'Tabela: '.$table->getName().'<br/>';
łać metody set() i set*(), gdzie * to typ,
na jaki zostanie dokonana konwersja, za po- foreach($table->getColumns() as $column)
mocą których możemy ustawić dynamiczne {
części zapytania. Mechanizm ten działa do- echo $column->getName().': '.$column->getNativeType().'<br/>';
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 Listing 9. Wykorzystanie obiektu Query do odczytywania danych z bazy
wartość jaka w to miejsce zostanie wstawio- <?php
na. Przy użyciu metody set() zostaną uży- require_once 'creole/Creole.php';
te natywne typy PHP do konwersji. Zamiast require_once 'jargon/Query.php';
metod set() i set*() możemy do funkcji $dsn = 'mysql://user:pass@localhost/database';
PreparedStatement::executeQuery() $connection = Creole::getConnection($dsn, Creole::COMPAT_ALL);
i PreparedStatement:: executeUpdate() prze- $query = new Query($connection, 'SELECT id, imie, nazwisko, telefon FROM adresy');
kazać tablicę, która będzie zawierała wszyst- $resultArray = $query->getAssoc();
kie potrzebne parametry – tak jak przedsta-
wiono to na Listingu 5. foreach($resultArray as $id => $values)
{
Operacje na tabelach echo $id.' : ';
Posługując się pakietem Creole możemy do-
konywać różnych operacji na tabelach. Po- foreach($values as $valueNumber => $value)
lecenia takie jak: CREATE, DROP czy ALTER {
możemy wykonywać przy pomocy metod echo $value.' ';
executeQuery() lub executeUpdate(), jeżeli }
tylko nasz użytkownik posiada do tego upraw-
nienia. echo '<br/>';
}
Obsługa błędów
SQL Exception oraz transakcje ?>
Pakiet Creole został całkowicie napisany
w PHP5, dlatego do obsługi błędów użyto wy- Listing 10. Podział zapytania na strony przy użyciu obiektu klasy PagedQuery
jątków. Klasa odpowiedzialna za obsługę błę- <?php
dów w pakiecie Creole to SQL Exception, któ- require_once 'creole/Creole.php';
ra rozszerza standardową klasę Exception. require_once 'jargon/Query.php';
Za pomocą metody getNativeError() jeste- $dsn = 'mysql://user:pass@localhost/database';
śmy w stanie określić rodzaj błędu ze stro- $connection = Creole::getConnection($dsn, Creole::COMPAT_ALL);
ny RDBMS-a. Na Listingu 6. został zapre- $page = 3;
zentowany przykład obsługi błędów. W przy- $rowsPerPage = 20;
padku rzucenia wyjątku jest on obsługiwany $pagedQuery = new PagedQuery($connection, 'SELECT tytul, tresc FROM newsy', $page,
w bloku catch, w tym przypadku zostaje wy- $rowsPerPage);
pisana treść wyjątku (dzięki temu, że kla- $resultArray = $pagedQuery->getRows();
sa SQLException posiada zaimplementowaną
metodę __toString()). foreach($resultArray as $rowNumber => $row)
W przypadku, gdy zostanie rzucony wy- {
jątek, dalsza część skryptu znajdująca się echo $row['tytul'].'<br/>'.$row['tresc'].'<br/><br/>';
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

www.phpsolmag.org 35
Rozwiązania

Prepared Statements W Sieci


Wstę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, • http://creole.phpdb.org/ – strona
które mają zostać odnalezione w danej tabeli, zostają zastąpione specjalnymi znacznikami. domowa projektu Creole
Zapytanie musi zostać tylko raz przesłane do serwera bazodanowego, gdzie jest przygoto- • http://creole.phpdb.org/docs/api/ –
wywane do wykonania. Przy kolejnych wywołaniach zapytania przesyłamy tylko przezna- dokumentacja API projektu Creole
czone dla niego wartości. Taki mechanizm oszczędza wiele czasu przy przesyłaniu zapyta- • http://pear.php.net/ – strona domowa
nia oraz przy jego realizacji, dzięki wbudowanym mechanizmom serwera. instalatora rozszerzeń PHP
• http://pear.php.net/manual/en/package
.database.db.intro-dsn.php – strona opi-
suje sposób tworzenia poprawnego
obiektu DSN
Transakcje • http://dev.mysql.com/tech-resources/
Transakcje to mechanizm, za pomocą którego możemy wykonywać różne działania na ba- articles/4.1/prepared-statements.html –
zie danych. W mechanizmie transakcyjnym nie zostaną wykonane żadne operacje na fizycz- opis wstępnie przygotowywanych
nych plikach, dopóki transakcja nie zostanie zatwierdzona. W przeciwnym wypadku, wszyst- zapytań w serwerze MySQL
kie wykonane operacje od rozpoczęcia transakcji zostaną cofnięte, bez żadnego uszczerb- • http://pl.php.net/manual/en/
ku dla danych. Najlepiej ilustrującym transakcje przykładem są przelewy bankowe. Wyobraź- language.exceptions.php – obsługa wy-
my sobie hipotetyczną sytuację, kiedy wykonywany jest przelew z konta pana Kowalskiego jątków w PHP
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 rozwiązaniach z PHP – AdoDB i PEAR::DB.
musi spełniać pewne warunki, które opisywane są przez zasady ACID (ang. Atomicity, Consi- Spośród czterech porównywanych abstrak-
stency, Isolation, Durability – Atomowość, Spójność, Izolacja, Trwałość). cji obsługuje relatywnie najmniejszą liczbę
baz danych. Obsługuje jednak najpopular-
niejsze systemy. Natomiast w AdoDB może-
Introspekcja ne w Tabeli 2. Natomiast na Listingu 9. zo- my znaleźć wiele podobieństw do standar-
w bazę danych – metadata stał zaprezentowany przykład użycia takie- du ADO Mircrosoft-u. Oprócz PDO wszystkie
Za pomocą pakietu Creole możemy uzyskać go obiektu. abstrakcje zostały napisane w PHP (4 lub 5),
informacje o aktualnie używanej bazie danych. Drugim z ciekawszych narzędzi pakietu którego centralny podsystem został napisany
Możemy odczytać informacje na temat tabeli, Jargon, jest klasa PagedQuery. Wyobraźmy so- w C. PDO jest właściwie interfejsem komuni-
indeksów, kluczy, kluczy obcych i inne przy- bie bazę newsów. Aby wyświetlić odpowied- kacyjnym i aby uzyskać funkcjonalność ofe-
datne informacje. Mechanizm ten jest podobny nią stronę, z odpowiednią na niej liczbie new- rowaną przez inne abstrakcje, należy zain-
do używanego w pakiecie Hibernate. Przykład sów, musieliśmy się gimnastykować używając stalować dodatkowe biblioteki (np. Open
odczytywania metadanych został zaprezento- parametrów LIMIT i OFFSET. Teraz możemy Power Driver). Dodatkowo AdoDB jest dostęp-
wany na Listingu 8. Odczytujemy tutaj pod- skorzystać z obiektu typu PagedQuery. Na Li- ne również dla Python-a. W Creole'u nieste-
stawowe informacje na temat tabel zawartych stingu 10. został przedstawiony przykład ta- ty nie ma możliwości cache'owania danych.
w bazie, której aktualnie używamy (nazwę ta- kiego rozwiązania. Stronę oraz liczbę wier- AdoDB obsługuje tę możliwość natywnie, na-
beli, nazwę pola oraz jego typ). Dzięki meto- szy pobieranych na stronę możemy określić tomiast do PDO i PEAR::DB należy zainstalo-
dzie getDatabaseInfo() wykonanej na obiek- w konstruktorze obiektu lub po jego utwo- wać dodatkowe biblioteki. W przypadku in-
cie klasy Connection, otrzymujemy obiekt kla- rzeniu przy pomocy metod setPage() oraz nych funkcjonalności, takich jak transakcje,
sy DatabaseInfo, z którego możemy wydobyć setRowsPerPage(). Dla parametru Page do- procedury składowane czy wstępnie przy-
wszystkie interesujące nas informacje. Aby myślna wartość wynosi 1, natomiast dla pa- gotowane zapytania SQL (ang. Prepared Sta-
uzyskać informacje na temat metod, za pomo- rametru RowsPerPage domyślna wartość wy- tements) wszystkie cztery abstrakcje zapew-
cą których możemy pobierać różne metadane nosi 25. Do odczytywania wartości z poszcze- niają ich obsługę. Wyjątek może stanowić
z bazy, należy przejrzeć rozdział creole.metada- gólnych stron używamy metod opisanych pakiet PEAR::DB, który nie obsługuje proce-
ta dokumentacji projektu. w klasie Query. dur składowanych.

Narzędzia Jargon Creole a inne abstrakcje Podsumowanie


Pakiet Jargon to zbiór przydatnych narzędzi, Pierwszymi abstrakcjami bazodanowymi – W artykule przedstawiliśmy w jaki sposób
które zapewniają prostszą obsługę zapisywa- prekursorami – byli Metabase, PEAR::DB używać abstrakcji bazodanowych – w tym
nia i odczytywania danych z bazy. Komuni- i AdoDB. Obecnie w sieci dostępnych jest przypadku Creole'a. Oprócz podstawowej
kacja z serwerem baz danych spoczywa na pa- znacznie więcej rozwiązań tego typu, jak funkcjonalności, poruszyliśmy także kwe-
kiecie Creole, dzięki czemu nie ma potrze- chociażby PDO, MDB, MDB2, DBX. Trudno okre- stię transakcji, obsługi błędów oraz przed-
by implementacji obsługi bazodanowej. Te- ślić, która z nich jest najlepsza. Zależy to od stawiliśmy niektóre narzędzia biblioteki Jar-
raz postaram się przedstawić niektóre z tych wiedzy, upodobań, charakteru projektu do gon. Jest to zarys metod, jakie oferuje nam
narzędzi. którego ma zostać wdrożona oraz od zasobów pakiet Creole. Ich konkretna implementacja
Pierwszym z przydatnych narzędzi będzie jakie będzie miała do dyspozycji. zależy wyłącznie od Ciebie. Więcej pomocy
klasa Query do obsługi zapytań typu SELECT. Spróbuję teraz pokrótce porównać omawiany możesz znaleźć na stronach znajdujących się
Tworząc obiekt typu Query, przekazujemy pakiet Creole z innymi popularnymi abstrak- w ramce „W sieci”.
mu obiekt typu Connection oraz zapyta- cjami – AdoDB, PDO i PEAR::DB. Zastrzegam
nie jakie ma zostać wykonane. Po utworze- jednak, że będzie to krótkie i pobieżne porów-
niu nasz obiekt zawiera zbiór wierszy wy- nanie. PIOTR GRADZIŃSKI
nikowych naszego zapytania. Do manipula- Dużym plusem w kierunku pakietu Cre- Autor jest studentem III roku informatyki stosowa-
cji tym zbiorem otrzymujemy kilka użytecz- ole jest fakt, iż bazuje on na sprawdzonych nej na Uniwersytecie Jagiellońskim.
nych metod, których działanie zostało opisa- rozwiązaniach z języka JAVA (JDBC) oraz Kontakt z autorem: piotr.gradzinski@gmail.com

36 06/2007
Rozwiązania

AJAX w CakePHP
Zwiększenie funkcjonalności serwisu

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.
Script, to o wiele wygodniej jest operować
Dowiesz się... Powinieneś wiedzieć... na danych, które w prosty sposób można
• Poznasz praktyczne zastosowanie technologii • Wymagana jest znajomość Framework'u Cake- przetwarzać w tym języku;
AJAX w środowisku Framework'u CakePHP. Po PHP, umożliwiająca samodzielne skonfiguro- • Cascading StyleSheets (CSS) – kaskadowe
analizie przedstawionego kodu będziesz mógł wanie środowiska Apache, MySQL i PHP. Przy- arkusze stylów to język służący do opisu
wzgobacić własny serwis o dynamicznie pre- datna będzie także znajomość podstaw języ- sposobu wizualizacji stron WWW. Za je-
zentowane dane. ka JavaScript. go pomocą można przypisać atrybuty, takie
jak np.: kolor, wielkość czcionki, margine-
sy do poszczególnych elementów XHTML
iwem łączącym DOM z XHR (opis poni- lub XML;
żej). Innymi słowy, pozwala na aktualiza- • Document Object Model (DOM) – obiektowy
Poziom trudności cję fragmentów stron WWW o dane ode- model umożliwiający nawigację w struktu-
brane dynamicznie za pomocą XHR; rze dokumentu XML oraz modyfikację za-
• XMLHttpRequest (XHR) – obiekt umoż- wartości jego określonych fragmentów;
liwiający wymianę danych między serwe- • JSON (ang. JavaScript Object Notation)

P
rzeładowywana jest cała zawartość – gra- rem WWW i przeglądarką. Pomimo XML umożliwia prostą zamianę obiektów Java-
fika, szablony stylów, informacje pobiera- w nazwie, XHR nie wymusza używania Script do postaci tekstu (tzw. proces seria-
ne ze źródeł danych – mimo, że strona po- tego formatu przy przesyłaniu informacji. lizacji), który może być przesyłany za po-
zostaje prawie niezmieniona! Technologia AJAX Ponieważ, po otrzymaniu danych, ich dal- mocą XHR. Proces odwrotny przebiega
(ang. Asynchronous JavaScript And XML) powsta- sza obróbka odbywa się za pomocą Java- równie sprawnie.
ł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- Rysunek 1. Zasilanie aplikacji danymi – tryb scaffold

38 06/2007
AJAX

Na szczęście nie ma potrzeby, by samodziel- nie ma konieczności przechodzenia mię- o elementy zwiększające jej interaktywność
nie tworzyć kod, umożliwiający połączenie dzy stronami, więc pojęcie poprzednia stro- (i atrakcyjność). Model danych, który wyko-
powyższych technologii. Nie ma również po- na traci swoje znaczenie). rzystamy będzie prosty: pojedyncza tabela po-
trzeby samodzielnego operowania na pozio- wiązana z modelem Task (pol. zadanie). Szcze-
mie obiektu XHR, czy troszczenia się o współ- CakePHP góły związane z implementacją tej części apli-
pracę z różnymi typami przeglądarek inter- Jak już wiemy, obsługa AJAX w CakePHP, kacji znajdują się na Listingach 1. oraz 2.
netowych. W internecie znajduje się wiele go- wymaga obecności biblioteki Prototype oraz Przygotowane struktury nie zawierają jesz-
towych bibliotek rozszerzających JavaScript script.aculo.us. Niestety nie są one częścią cze danych. Uzupełnimy je, wykorzystując
i ułatwiających integrację z PHP. W dalszej framework'u – musimy je samodzielnie po- tryb scaffold, w którym CakePHP automaty-
części artykułu skupimy się na bibliotekach brać z internetu oraz zmodyfikować konfigura- cznie stworzy interfejs, umożliwiający dostęp
Prototype oraz script.aculo.us, których obsłu- cję CakePHP, by ich obecność została uwzględ- do danych za pomocą strony WWW. Tryb ten
ga jest częścią funkcjonalności framework'u niona przy tworzeniu dynamicznych stron jest aktywowany, gdy w kontrolerzejest zdefi-
CakePHP. WWW. niowana zmienna $scaffold. Nie ma potrzeby
Zacznijmy od przygotowania prostego ser- definiowania funkcji obsługi modelu danych
Korzyści ze stosowania wisu, umożliwiającego zapisywanie do bazy – framework zrobi to za nas automatycznie.
technologii AJAX danych informacji wprowadzanych do formu- Utworzymy teraz kontroler TasksControl-
larza. Najpierw przygotujemy wersję działają- ler odpowiadający modelowi danych Task
• AJAX umożliwia wykorzystanie doświad- cą bez AJAX, którą następnie rozbudujemy (Listing 3.).
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
Rysunek 2. Wynik działania przykładowej aplikacja działającej bez AJAX
• 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 Rysunek 3. Przykładowa aplikacja wykorzystująca technologię AJAX

www.phpsolmag.org 39
Rozwiązania

Nasza przykładowa aplikacja jest już goto-


Listing 1. Struktura danych wykorzystywana w przykładowej aplikacji wa. Wystarczy uruchomić przeglądarkę in-
CREATE TABLE `tasks` ( ternetową i wpisać adres IP serwera Cake-
`id` int(10) NOT NULL auto_increment, PHP, razem z nazwą kontrolera np. http://
`title` varchar(60), 127.0.0.1/tasks. Teraz możemy w prosty
`done` int(1) NOT NULL default '0', sposób wprowadzić dane, które później bę-
PRIMARY KEY (`id`) dziemy wyszukiwać za pomocą formularza
) ENGINE=MyISAM; HTML (Rysunek 1.).
Pobieranie danych tak zdefiniowanych struk-
Listing 2. Model danych Task tur powierzymy kontrolerowi TodoControl-
// plik app/models/task.php ler (Listing 3.) oraz domyślnemu widoko-
class Task extends AppModel wi (plik app/views/todo/index.thtml),
{ w którym umieścimy kod generujący formu-
// jeżeli używamy PHP4 musimy zdefiniować zmienną zawierającą nazwę klasy larz WWW (Listing 4.).
var $name = 'Task'; Po zasileniu testowymi danymi, nasza
aplikacja zachowuje się w sposób standar-
// domyślnie nazwa klasy odpowiada nazwie tabeli w liczbie pojedynczej dowy – wprowadzenie informacji do for-
// jeżeli jest inaczej i np. zamierzamy wykorzystać mularza i naciśnięcie przycisku Wyślij, po-
// inną tabelę z bazy danych musimy zdefiniować jej nazwę woduje przeładowanie całej strony i wyświe-
var $useTable = 'tasks'; tlenie tytułów zadań pasujących do zadane-
} go kryterium (Rysunek 2.). Wybierane są za-
dania nie ukończone (Task.done = 0) o na-
Listing 3. Kontroler odpowiadający za zasilanie struktur danych informacjami z formularza WWW zwie identycznej z podanym ciągiem zna-
(tryb scaffold) ków (Task.title = $title), posortowa-
// plik app/controllers/tasks_controller.php ne według kolejności utworzenia (Task.id
class TasksController extends AppController DESC).
{
Wprowadzamy
// jeżeli używamy PHP4 musimy zdefiniować zmienną zawierającą nazwę klasy technologię AJAX
var $name = 'Tasks'; Zastanówmy się teraz jak, w naszym uprosz-
var $uses = array('Task'); czonym przykładzie, wykorzystać technologię
var $helpers = array('Html'); AJAX. Wiemy już, że AJAX umożliwia dyna-
var $scaffold; miczną (przebiegającą w tle) wymianę infor-
} macji między serwerem WWW i przeglądar-
ką internetową. Możemy więc spróbować prze-
// plik app/controllers/todo_controller.php szukiwać bazę danych, w miarę jak użytkownik
class TodoController extends AppController wprowadza dane do formularza. Za każdym ra-
{ zem, gdy zmieni się kryterium wyszukiwania,
// jeżeli używamy PHP4 musimy zdefiniować zmienną zawierającą nazwę klasy przeglądarka automatycznie wyśle zapytanie
var $name = 'Todo'; do naszej aplikacji, która sprawdzi, czy odpo-
var $uses = array('Task'); wiednie rekordy znajdują się w bazie danych.
var $helpers = array('Html','Time'); Przekazana z serwera odpowiedź zostanie wy-
// nie wyświetlaj żadnych informacji świetlona, dając wizualną podpowiedź o rezul-
function index() { tatach poszukiwań.
} Realizacja powyższego schematu funkcjono-
wania aplikacji wymaga od nas kilku dodatko-
function search() wych zabiegów:
{
if (! empty($this–>data)) • musimy cyklicznie badać, czy w formula-
{ rzu pojawiły się nowe dane;
$data = $this–>data; • musimy utworzyć metodę kontrolera, któ-
$title = strip_tags($data['Task']['title']); ra będzie sprawdzała obecność wyszuki-
$tasks = $this–>Task–>findAll( wanych informacji w bazie danych;
array('Task.done' => 0, 'Task.title' => $title), null, 'Task.id DESC'); • musimy znaleźć sposób, by informacje zwra-
$this–>set('todo', $tasks); cane przez serwer pojawiały się w prze-
} glądarce bez konieczności przeładowania
else całej strony WWW.
{
$this–>redirect('/todo/index'); 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

40 06/2007
AJAX

stanu formularza, obsługi obiektu XHR i ak-


Listing 4. Widoki definiujące formularz WWW tualizacji strony WWW o zwrócone informa-
// plik app/views/todo/index.thtml cje. Po naszej stronie pozostanie tylko przygo-
<?php towanie metody kontrolera, odpowiedzialne-
echo $html–>formTag('/todo/search'); go za wyszukiwanie danych (będzie wywo-
?> ływany przy każdej aktualizacji formularza)
<div> oraz powiązanie ze sobą odpowiednich kom-
Wyszukiwanie zadań: ponentów CakePHP i Prototype.
<div> Zacznijmy od początku. Włączenie obsługi
<?php Prototype i script.aculo.us w CakePHP wymaga
echo $html–>input('Task/title', array('id' => 'search')); pobrania bibliotek i umieszczenia ich w kata-
?> logu app/webroot/js. W kolejnym kroku mu-
<?php simy zmodyfikować domyślny szablon serwi-
echo $html–>submit('Wyślij'); su: wymusić kodowanie UTF–8 (niezbędne do
?> poprawnej pracy AJAX) oraz załadować biblio-
</div> teki Prototype oraz script.aculo.us (Listing
<div> 5.). Następnie dołączamy do kontrolera dodat-
</div> kowe moduły, przez umieszczenie deklaracji:
</form>
var $helpers = array('Html',
// plik app/views/todo/search.thtml 'Javascript', 'Ajax');

<h2>Znalezione zadania:</h2> W pierwszym momencie można się przera-


<?php if (count($todo) > 0): ?> zić wielkością kodu, który będzie dołączony
<ul> do generowanych stron WWW. Obydwie bi-
<?php foreach ($todo as $task): ?> blioteki to ponad 200KB dodatkowych da-
<li> nych, które z pewnością nie przyspieszą star-
<?php tu naszej aplikacji. Wielkość przesyłanych pli-
echo $task['Task']['title']; ków można jednak zmniejszyć o ponad poło-
?> wę, kompresując je przed przesłaniem do prze-
</li> glądarki użytkownika (zobacz Kompresowanie
<?php endforeach ?> komponentów).
</ul> Następnym wyzwaniem jest wykrycie zmian
<?php else: ?> w formularzu – chcemy przecież reagować na
<p>Nic nie znaleziono!?</p> każdy znak wprowadzony przez użytkowni-
<?php endif ?> ka. Biblioteka Prototype zawiera gotowe ele-
<?php menty, które nas wyręczą w tej czynności.
echo $html–>link('> powrót do formularza wyszukiwania', '/todo/index'); Chodzi o metodę element:observe(), która
?> pozwala na automatyczne wywołanie funk-
cji JavaScript w przypadku, gdy obserwowa-
Listing 5. Modyfikacja domyślnego szablonu strony CakePHP w celu automatycznego ny element (określany za pomocą identyfika-
wczytywania bibliotek Prototype i script.aculo.us tora DOM ID) uległ zmianie. Nie musimy jed-
<?php echo $html–>charsetTag('UTF–8'); ?> nak umieszczać kodu JavaScript w naszej apli-
<?php echo $javascript–>link('prototype'); ?> kacji – CakePHP zawiera funkcję, która za-
<?php troszczy się o inicjalizację niezbędnych struk-
echo $javascript–>link('scriptaculous.js?load=effects'); 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ść
Kompresowanie komponentów metod obsługujących AJAX w CakePHP ko-
Czas potrzebny na przesłanie kodu HTML do użytkownika, może być znacznie zredukowany za rzysta z tego sposobu, omówimy poszczegól-
pomocą różnego rodzaju buforowania (cache, proxy). Innym czynnikiem, który wpływa na szyb- ne parametry i ich znaczenie dla funkcjonowa-
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
nia aplikacji:
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 • $options['url'] – adres URL akcji Ca-
metod obsługiwanej po stronie klienta. kePHP, która ma zostać wywołana (w na-
Kompresja gzip umożliwia zmniejszenie ilości danych średnio o 60–70%, w zależności od ich szym przypadku – po modyfikacji formu-
rodzaju (typu). Największe redukcje osiągniemy kompresując pliki HTML, szablony CSS oraz kod
larza);
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. • $options['frequency'] – liczba sekund
W chwili obecnej, ponad 90% przeglądarek internetowych, używanych do przeglądania między kolejnymi testami wykrywający-
stron WWW obsługuje kompresję danych. Od strony serwera niezbędna jest konfiguracja odpo- mi zmiany;
wiedniego modułu – w przypadku Apache 1.3 jest to mod_gzip, w Apache 2.x – mod_deflate. • $options['update'] – identyfikator DOM
elementu, który ma zostać zaktualizowa-

www.phpsolmag.org 41
Rozwiązania

ny informacjami otrzymanymi w wyniku


Listing 6. Kod CakePHP umożliwiający reagowanie na zmiany w formularzu WWW działania akcji zawartej w $options['url'];
// plik app/views/todo/index.thtml • $options['with'] – identyfikator DOM
elementu, który ma zostać dołączony do
<!–– informacja o wczytywaniu danych jest domyślnie ukryta (display: none)–> żądania wysyłanego przez AJAX;
<div id="loading" style="display: none; padding: 4px; color: black; • $options['type'] – sposób komunika-
background–color: #FAD163; width:400px"> cji przeglądarki z serwerem aplikacji. Do-
<center>Trwa ładowanie danych...</center> myślnie przybiera wartość 'asynchronous'
</div> (pol. asynchronicznie, w tle), jednak można
<form onsubmit="return false"> wymusić połączenie synchroniczne przez
<p> umieszczenie wartości 'synchronous';
<h2>Wyszukiwanie:</h2> • $options['loading'] – kod JavaScript,
<input type="text" id="search" name="search" /> który będzie wywołany podczas pobiera-
</p> nia danych z serwera;
</form> • $options['loaded'] – kod JavaScript,
<?php który będzie wywołany po zakończeniu
pobierania danych z serwera;
// obserwacja zmian tekstu w formularzu wyszukiwania • $options['complete'] – kod JavaScript,
który będzie wywołany, gdy obiekt XHR
$options = array( zakończył transfer danych;
'update' => 'results', • $options['condition'] – kod JavaScript
'url' => '/todo/search', zawierający warunki, które muszą być
'frequency' => 1, spełnione, zanim obiekt XHR zostanie za-
'loading' => "Element.hide('results')", inicjalizowany;
'complete' => "Element.show('results')" • $options['confirm'] – tekst, który bę-
); dzie wyświetlony w okienku potwierdze-
echo $ajax–>observeField('search', $options); nia rozpoczęcia transferu danych przez
?> obiekt XHR (tzn. przed rozpoczęciem
<!–– miejsce na wyniki poszukiwań domyślnie jest ukryte (display: none) ––> transferu danych);
<div id="results" style="display: none; margin–top: 10px; • $options['before'] – kod JavaScript,
background–color: #EEEEEE; padding: który będzie wywołany, zanim żądanie
4px; border: 1px solid #DDDDDD; width: 400px"></div> dostępu do danych będzie wysłane do ser-
<div style="margin–top: 10px;"> wera WWW;
<?php • $options['after'] – kod JavaScript, któ-
ry będzie wywołany po żądanie dostę-
// link umożliwiający czyszczenie wyników wyszukiwania pu do danych serwera WWW (zdarzenie
// bez przeładowania strony WWW 'after' występuje przed 'loading').

$options = array( Wracając do naszej aplikacji i Listingu 6. Za po-


'update' => 'results', mocą przedstawionego kodu będziemy moni-
'loading' => "Element.hide('results')", torowali formularz (search) co jedną sekundę
'complete' => "Element.show('results')" ($options['frequency'] => 1). W przypad-
); ku wykrycia zmian zostanie wywołana akcja
echo $ajax–>link('Wyczyść listę wyszukiwania!', '/todo/clear', $options); CakePHP, powodująca przeszukiwanie bazy da-
?> nych ($options['url'] => '/todo/search'), któ-
</div> rej wyniki zostaną wyświetlone w przeglądarce
($options['update'] => 'results'). Kolejne
// plik app/views/todo/clear.thtml zmiany w stosunku do serwisu działającego bez
// zawiera informację wyświetlaną przy czyszczeniu wyników wyszukiwania AJAX, dotyczą uniemożliwienia przeładowania
strony, w wyniku wysłaniaformularza. Standar-
<center>Brak danych</center> dowo, klikając na przycisk Wyślij, powodujemy
wczytanie i wyświetlenie strony określonej pa-
// plik app/views/todo/search.thtml rametrem <form action="URL">. W AJAX za-
bezpieczamy się przed tym, umieszczając para-
<?php if (count($todo) > 0): ?> metr <form onsubmit="return false">. Nie-
<ul> wielkie modyfikacje dotknęły także metodę To-
<?php foreach ($todo as $task): ?> do Controller::search(), która teraz umożli-
<li><?php echo $task['Task']['title']; ?></li> wia wybieranie wszystkich danych pasujących
<?php endforeach ?> do ciągu znaków wprowadzonych do formula-
</ul> rza. Jest to możliwe dzięki zastosowaniu opera-
<?php else: ?> tora SQL "LIKE" (Listing 7.).
Nic nie znaleziono!? Modyfikacja formularza spowoduje wysła-
<?php endif ?> nie zapytania do serwera WWW, który w od-
powiedzi prześle listę danych pasujących do

42 06/2007
AJAX

Przygotowana przez nas aplikacja, to tyl-


Listing 7. Uzupełnienie kontrolera o metodę TaksController::search() umożliwiającą przeszukiwanie ko przykład tego, jak prosto można wykorzy-
danych
stać AJAX w CakePHP. Korzystając z faktu, iż
// plik app/controllers/tasks_controller.php oprócz Prototype, mamy do dyspozycji biblio-
class TodoController extends AppController { tekę script.aculo.us (Listing 4.) możemy
var $helpers = array('Html','Javascript','Ajax'); w prosty sposób dodać różne efekty graficzne,
function search() { które będą towarzyszyć wyszukiwaniu danych.
$tasks = array(); Wystarczy zmodyfikować tablicę $options
$this->layout = 'ajax'; z Listingu 6. i dodać kod JavaScript, który wy-
if (! empty($this->params['form']['search'])) { kona się podczas wymiany danych z serwerem
$title = strip_tags($this->params['form']['search']); i po jej zakończeniu (Listing 8.).
// zwracamy maksymalnie 10 wierszy Co oznaczają wprowadzone zmiany?
$tasks = $this->Task->findAll( Podczas czekania na dane z serwera
array('Task.done' => 0, 'Task.title' => "LIKE ${title}%"), null, 'Task.id DESC', 10); ($options['loading']) zostanie ukryty
} fragment strony, zawierający dotychczasowe
$this->set('todo', $tasks); 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ę-
Listing 8. Rozbudowa AJAX o efekty graficzne towarzyszące wyszukiwaniu danych w przykładowej ki temu, nawet gdy transmisja będzie trwa-
aplikacji ła dugo, to użytkownik cały czas będzie wie-
$options = array( dział, co się aktualnie dzieje z aplikacją – nie
'update' => 'results', 'url' => '/todo/search', 'frequency' => 1, 'loading' => zostanie pozostawiony z tzw. pustą stroną.
"Element.hide('results');Element.show('loading')", 'complete' => "Element.hide( Gdy połączenie z serwerem dobiegnie koń-
'loading');Effect.Appear('results')" ca ($options['complete']), to informacja
); o transferze zostanie ukryta (Element.hide
echo $ajax–>observeField('search', $options); ('loading')), a nowe wyniki wyszukiwania
pojawią się w przeglądarce (Effect.Appear('
Listing 9. Przykładowe efekty script.aculo.us, które możemy wykorzystać, by podnieść atrakcyjności results')). Pojawią się w dosłownym zna-
naszej przykładowej aplikacji czeniu – za sprawą efektu graficznego appear
/* przeźroczystość */ (pol. objawiać się, ukazać się) powodującego, iż
Effect.Opacity('results', { duration: 2.0, transition: Effect.Transitions.linear, nowe dane wyłonią ze strony WWW. Oczywi-
from: 1.0, to: 0.5 }); ście nie musimy się ograniczać tylko do dwóch
/* wyróżnienie kolorem */ efektów. Biblioteka script.aculo.us obsłu-
Effect.Highlight('results', { startcolor:'#ff99ff', endcolor:'#999999'}); guje ich kilkanaście, co w połączeniu z faktem,
/* blednięcie, wygaszanie */ że większość z nich jest parametryzowana, da-
Effect.Fade('results', { transition: Effect.Transitions.wobble }) je duże możliwości dostosowania pożądanych
efektów do własnych potrzeb (Listing 9.).

Podsumowanie
W Sieci Budowanie interaktywnych serwisów WWW
• Forum użytkowników CakePHP: http://groups.google.com/group/cake–php wymaga od projektantów posługiwania się co-
• Dokumentacja CakePHP: http://cakephp.org raz to nowszymi technologiami. AJAX umoż-
• Dokumentacja biblioteki Prototype: http://www.prototypejs.org/learn liwia osiągnięcie pożądanych efektów, wyko-
• Dokumentacja biblioteki script.aculo.us oraz przykłady jej wykorzystania: rzystując istniejące standardy, takie jak Java-
http://wiki.script.aculo.us/scriptaculous/
Script, CSS czy DOM. Dzięki niemu strony
• Informacje o Document Object Model (DOM): http://www.w3.org/DOM/
• Informacje o obiektach XMLHttpRequest: http://www.w3.org/TR/XMLHttpRequest/ mogą być bardziej przyjazne dla użytkowni-
• Informacje o JavaScript: http://developer.mozilla.org/pl/docs/ ków i efektywniej prezentować dane. Warto
jednak przeanalizować, czy osiągnięte korzy-
ści będą istotniejsze niż wydłużenie czasu ła-
kryterium wyszukiwania, wprowadzonego będą zagnieżdżone dwie strony WWW! Cake- dowania aplikacji za sprawą dodatkowych bi-
przez użytkownika. Pozostaje już tylko wy- PHP posiada szablon, który powinien być uży- bliotek JavaScript. Mam nadzieję, iż przedsta-
świetlić otrzymane informacje bez przełado- wany przy zapytaniach uruchamianych przez wiony artykuł pokazał, że dzięki zastosowaniu
wywania całej strony WWW. Jak wcześniej AJAX. Znajduje się on w katalogu cake/libs/ framework'ów, takich jak CakePHP, zwiększe-
wspomnieliśmy, brudną robotę wykona za view/templates/layouts/ajax.thtml, a akty- nie funkcjonalności serwisów nie musi się od-
nas metoda AjaxHelper::observeField() – Li- wuje się go poprzez umieszczenie we właści- bywać kosztem wzrostu czasochłonności ich
sting 6. Musimy jednak zwrócić uwagę na ma- wej metodzie kontrolera wywołania: $this– przygotowania.
ły szczegół. Modyfikacja formularza wywo- >layout='ajax' (Listing 7.).
ła akcję CakePHP, która może zwrócić kod Nasza aplikacja jest już gotowa. Wystarczy
HTML wraz z domyślnym szablonem serwisu uruchomić przeglądarkę internetową i wpisać PIOTR GAPIŃSKI
(plik cake/libs/view/templates/layouts/ adres IP serwera CakePHP razem z nazwą kon- Autor w wolnych chwilach zajmuje się programo-
default.thtml), zawierającym całą strukturę trolera np. http://127.0.0.1/todo. Teraz mo- waniem w różnych językach (głównie Rebol, Ruby,
dokumentu HTML. Jeżeli nie zmienimy sza- żemy sami się przekonać, jakie zalety posiada PHP i AmigaE).
blonu, to otrzymamy błędny wynik, w którym technologia AJAX (Rysunek 3.). Kontakt z autorem: piotr–gapinski@wp.pl

www.phpsolmag.org 43
Rozwiązania

ATOM
Piszemy swój pierwszy parser

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.
ba tutaj opisywać nie muszę. Mamy już ta-
Dowiesz się... Powinieneś wiedzieć... belę. Teraz czas zająć się dodawaniem rekor-
• Jak za pomocą php wygenerować działający • Powinieneś znać podstawy obsługi bazy My- dów. Posłużymy się następnym zapytaniem do
kanał informacyjny. SQL i operacji na plikach. naszej bazy danych. Wypełnijmy na razie tabe-
• Poznasz bardzo ogólnikowo składnię kanału lę sześcioma rekordami dla testu:
informacyjnego.
INSERT INTO `newsy` SET `id` = NULL,
`title` = 'News testowy nr 1',
Zapytanie to możemy wykonać z poziomu `news` = 'Nasz news nr 1 do parsera.
strony, jak i poprzez panel phpMyAdmin.
Poziom trudności W celu wysłania zapytania z poziomu stro- Zobaczymy jak działa!
ny, musimy skorzystać z funkcji obsługują- Wysyłamy to zapytanie sześć razy, za każdym
cych łączenie i operacje na bazie. Tego chy- razem zmieniając liczbę porządkową w ty-

J
eszcze niedawno zachwycaliśmy się kana- Linsting 1. Kod config.php
łem typu RSS. Duża liczba osób, nie chcąc
ładować strony, sprawdzała nowości przez <?php
kanał (o ile webmaster się o to postarał). Teraz $nameparser = "/parser.php";
przychodzi czas na małą zmianę. //Ta linijka jest bardzo ważna. Umieszczamy tutaj nazwę pliku z parserem +
Przyszłością kanałów informacyjnych na ra- rozszerzenie + ewentualny katalog nadrzędny!
zie wydaje się być ATOM. Jest to kanał funk- if($_SERVER['REQUEST_URI'] == $nameparser){
cjonalnością bardzo zbliżony do RSS, jednak //adres przeznaczony dla atrybutu link. Tego nie zmieniać!
już po pierwszej styczności z jego konstruk- $adres = 'http://'.$_SERVER['HTTP_HOST'].''.$_SERVER['REQUEST_URI'];
cją każdy dojdzie do wniosku, iż RSS niedłu- //tutaj ustawiamy ilość sekund, po których upłynięciu kanał zostanie skasowany
go odejdzie do lamusa. Autorzy kanału posta- //z cache i pobrany nowy. 604800 czyli tydzień.
rali się o to, aby konstrukcja była jak najbar- $sec = '604800';
dziej czytelna i dostępna dla wszystkich użyt- // deklarujemy datę ostatniej modyfikacji. Tego nie zmieniać!
kowników. Wprowadzono wiele innowacji, ta- $date = date("Y-m-d\TH:i:sP");
kich jak np. nowe tagi. W tym artykule poka- $title = 'Mój pierwszy kanał!'; //definiujemy tytuł kanału
żę Państwu, jak w prosty sposób napisać parser $autor = 'Jan Kowalski'; //autor kanału
w php, który będzie korzystał z danych pobiera- $mail = 'jakis@mail.pl'; //mail autora kanału
nych z bazy MySQL. //adres www strony, dla której jest przeznaczony kanał
$site = 'http://www.example.com';
Przygotowujemy miejsce pracy. $substr = '20'; //długość skróconego newsa
Na początek przygotujmy sobie miejsce pra- $news = '5'; //ilość newsów wyświetlanych na kanale
cy. Nasz parser musi pobierać dane, dlate- $host = 'localhost'; // host bazy danych
go tworzymy tabelę z newsami. Jest to bar- $user = 'user'; // user bazy danych
dzo proste zadanie. Wystarczy jedno zapy- $pass = 'password'; // password usera bazy danych
tanie do bazy: $base = 'base'; // nazwa bazy
} else {
CREATE TABLE `newsy` echo("Brak dostępu!");
(id int not null auto_increment, }
title char(200), ?>
news text, primary key(id))

44 06/2007
ATOM

Utworzyliśmy plik config.php. Jak widzimy,


Listing 2. Kod pliku właściwego parser.php jeżeli wywołamy plik config.php poprzez adres
<?php w przeglądarce, wyświetli nam błąd. Jeżeli za-
include("config.php"); includujemy plik do skryptu php o nazwie „par-
mysql_connect($host, $user, $pass); ser.php”, będziemy mieli pewność, że zmienne
mysql_select_db($base); zostały przekazane skryptowi.
//nasze zapytanie do tabeli z newsami Przyszedł czas na plik parsera. Jak wcze-
$sql = "select `id`, `title`, `news` from `newsy` order by `id` desc limit ".$news.""; śniej napisałem, będziemy korzystać z wycią-
$mysql = mysql_query($sql); gów z bazy danych. Najpierw jednak musimy
if($mysql == TRUE){ się zdecydować na parę istotnych elementów.
$atom1 = '<?xml version="1.0" encoding="iso8859-2"?> Otóż trzeba wiedzieć, jak długi ma być skróco-
<feed xmlns="http://www.w3.org/2005/Atom"> ny news oraz ile newsów ma się subskrybować.
<title>Kanał informacyjny ATOM</title> Pomyślałem, że na potrzeby naszego skryptu 20
<link rel="self" href="'.$adres.'"/> znaków i 5 newsów wystarczy. Tak więc two-
<updated>'.$data.'</updated> rzymy plik parser.php (jeżeli chcemy inaczej na-
<author> zwać ten plik musimy to uwzględnić również w
<name>'.$autor.'</name> config.php!), a w nim umieszczamy kod z Listin-
<email>'.$mail.'</email> gu 2. Zanim jednak wykonamy skrypt i utwo-
<uri>'.$site.'</uri> rzymy plik z kanałem informacyjnym, przyj-
</author> rzyjmy się skryptowi. Trzeba wiedzieć bowiem
<id>'.$site.'</id>'; co się w nim znajduje.
while($news = mysql_fetch_array($mysql)){ Na początku łączymy się z bazą i wysyła-
$substrnews = substr($news['news'], 0, $substr); my zapytanie o pięć najnowszych rekordów.
$atom2 .= '<entry> Oczywiście sprawdzamy czy zapytanie szczę-
<title>'.$news['title'].'</title> śliwie dostało się do bazy i czy coś wróciło. Na-
<link rel="self" href="'.$adres.'"/> stępnie przypisujemy zmiennej $atom począt-
<id>'.$rekord['id'].'</id> kową wartość kanału z określonymi atrybuta-
<updated>'.$date.'</updated> mi po czym wykorzystujemy pętlę while do
<summary>'.$substrnews.'</summary> nadpisania wątkami zmiennej $atom2. Jak wi-
</entry>'; dzimy, w pętli wykonaliśmy operację skraca-
} nia newsa do 20 znaków, tak jak zadeklarowa-
$atom3 = '</feed>'; liśmy to w config.php. Sama pętla while powin-
$atom = $atom1."".$atom2."".$atom3; na wykonać się pięć razy (to też zadeklarowali-
$fopen = fopen('atom.xml', w); śmy). Po wykonaniu while w zmiennej $atom2
fwrite($fopen, $atom); mamy przypisane pięć newsów. Zmienną tą
fclose($fopen); musimy następnie dodać do „całości”, która
if($fopen == TRUE){ będzie tworzyła nam kanał. Na koniec nie po-
echo("Kanał został stworzony!<br/>Adres do niego to: <a href='atom.xml'>atom.xml zostaje nic innego, jak stworzyć plik z warto-
</a>!<br/>"); ścią zmiennej $atomcaly, wykorzystując funk-
}else{ cję fopen(). Dla dopełnienia i pewności, spraw-
echo("Nie udało się stworzyć kanału!<br/>"); dzamy czy utworzenie pliku powiodło się. Je-
} żeli tak - drukujemy napis potwierdzający to
}else{ i podający link do kanału. Analogicznie jeżeli
echo('Zapytanie nie dotarło do bazy!<br/>'); nie - wyświetlamy błąd.
}
mysql_close(); Podsumowanie
?> Osobiście korzystam z tego typu parsera, jed-
nakże z kilkoma dodatkami, takimi jak filtro-
wanie newsów, odpowiednia ich edycja itd.
tule i newsie, zgodnie z numeracją (pomoże on składał z dwóch plików. Jeden, w którym Moim zdaniem ATOM jest dużym krokiem na
nam to później ocenić czy parser działa pra- umieścimy zmienne konfiguracyjne (config) przód i mam nadzieję, że nie zostanie porzuco-
widłowo). i drugi, właściwy plik parsera. Budowa ca- ny przez autorów, tak jak znaczna liczba pro-
Jak widzimy, wartość dodawana do pola news łości będzie bardzo prosta. Uwagę tutaj ra- jektów internetowych. Oczywiście można po-
liczy sobie 48 znaków. Sama liczba nie jest o ty- czej chciałem zwrócić na wykorzystanie php łączyć RSS z ATOM-em dla wygody użytkow-
le ważna, co sprawdzenie, czy skracanie będzie w połączeniu z kanałem informacyjnym, ja- ników. Wszystko zależy od pomysłu i inwencji
działało prawidłowo. Tutaj mamy do czynienia ki jest ATOM. Najpierw tworzymy plik o na- webmastera.
z małymi rozmiarami tekstu i brakiem znaków zwie config.php. Dla bezpieczeństwa doda-
specjalnych, ale o tym za chwilę. my linijki kodu odpowiadające za sprawdze-
nie ciągu znaków przekazywanych w adre- PATRYK SZLAGOWSKI
Bierzemy się do pracy sie (config.php będziemy mogli includować, Autor jest programistą z zamiłowania. Uczy się
– piszemy swojego parsera. otwieranie poprzez podanie adresu nie jest w szkole średniej w Lęborku. Zajmuje się freelan-
Jeżeli mamy już przygotowaną tabelę, na któ- brane pod uwagę ze względów bezpieczeń- cerstwem oraz prowadzeniem własnej strony
rej będziemy pracować, możemy przystąpić stwa). Kod pliku config.php znajdziemy na www.haes-suqad.net.
do tworzenia właściwego parsera. Będzie się Listingu 1. Kontakt z autora: patrykszlagowski@interia.pl

www.phpsolmag.org 45
Narzędzia

Google Web Toolkit


Czyli AJAX na szynach

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.
Wprowadzenie do GWT
Dowiesz się... Powinieneś wiedzieć... Teraz, gdy już wiemy, że Google Web Toolkit
• Jakie są zalety GWT. • Przydatna będzie podstawowa znajomość JAVA. 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-
• pierwsza aplikacja – gdzie pokażemy jak to korzystaniu AJAX. Tak naprawdę GWT składa
działa, ale na razie tylko po stronie klienckiej; się z trzech części, zamkniętych w pojedyn-
Poziom trudności • GWT i RPC / AMFPHP – gdzie przedsta- czych plikach JAR (Java ARchiwe):
wimy bardziej zaawansowany przykład,
w którym komunikujemy się z serwerem; • – to paczka przechowująca
gwt–user.jar
• dodatkowe informacje – gdzie wejdziemy gotowe do wykorzystania w środowisku JS
mocniej w szczegóły, które, mamy nadzie- komponenty i narzędzia;

D
laczego w dzisiejszym świecie Web ję, przekonają do GWT tych jeszcze nie- • gwt–servlet.jar – paczka implemen-
2.0 GWT się liczy? Odpowiedź jest przekonanych. tująca mechanizmy pozwalające na ko-
prosta, daje możliwości wykorzysta-
nia rozbudowanych i dojrzałych narzędzi ję- Listing 1. Uruchamiamy projectCreator
zyka Java, przy pracy z JavaScript–em. Dzię-
ki GWT , możemy teraz refaktorować swój Ja- C:\gwt>projectCreator –overwrite –eclipse SmallBear –ant smallbear –out c:\workspace\
vaScript, debugować go, używać mechanizmu smallbear
podpowiadania nazw i składni. Już samo to, da-
je duże możliwości w pracy z JavaScriptem, ale w wyniku czego powinniśmy zobaczyć:
GWT idzie dalej!
Wyobraźmy sobie, że możemy wykorzystać Created directory c:\workspace\smallbear\src
w JavaScript–cie wszystkie zalety silnie obiek- Created directory c:\workspace\smallbear\test
towego języka wysokiego poziomu, a przy tym Created file c:\workspace\smallbear\smallbear.ant.xml
dalej tworzyć kod zrozumiały dla przeglą- Overwriting existing file c:\workspace\smallbear\.project
darek internetowych. To jest np. możliwość Overwriting existing file c:\workspace\smallbear\.classpath
używania interfejs’ów, typowania zmiennych a następnie aplicationCreator poleceniem:
(a co za tym idzie i przeładowania konstruk- C:\gwt>applicationCreator –overwrite –eclipse SmallBear –out c:\workspace\smallbear
torów czy metod) i wielu, wielu innych. Posia- pl.rmalinowski.client.SmallBear
da cechy, które zawiera język Java, a które nie
są dostępne w JavaScript. Jak to możliwe? To w wyniku czego powinniśmy zobaczyć:
niesamowicie proste, GWT pozwala Ci tłuma-
czyć aplikacje napisane w Javie na JavaScript, Created directory c:\workspace\smallbear\src\pl\rmalinowski
przy zachowaniu pełnej kontroli nad wyniko- Created directory c:\workspace\smallbear\src\pl\rmalinowski\client
wym kodem. W artykule tym dowiesz się, co Created directory c:\workspace\smallbear\src\pl\rmalinowski\public
tak naprawdę to oznacza i dlaczego jest to tak Created file c:\workspace\smallbear\src\pl\rmalinowski\SmallBear.gwt.xml
rewolucyjne. Cała treść podzielona została na Created file c:\workspace\smallbear\src\pl\rmalinowski\public\SmallBear.html
cztery części: Created file c:\workspace\smallbear\src\pl\rmalinowski\client\SmallBear.java
Created file c:\workspace\smallbear\SmallBear.launch
• wprowadzenie do GWT – gdzie poznasz Created file c:\workspace\smallbear\SmallBear–shell.cmd
podstawowe informacje, jak rozpocząć Created file c:\workspace\smallbear\SmallBear–compile.cmd
pracę z GWT;

46 06/2007
GWT

munikację serwera napisanego w Javie z • eclipse tworzy konfiguracje urucha- z nich rozwieje. Na początku stwórzmy nowy
aplikacją napisaną w JS. (My nie używa- miającą projekt eclipsowy w trybie de- projekt w Eclipse. W tym celu klikamy: Menu
my); bug; –> File –> New –> Project.
• gwt–dev–windows.jar lub gwt–dev–linux. • out folder do zapisania plików wyniko- Z wyświetlonych kreatorów wybieramy
jar – serce GWT, mechanizmy tłumaczą- wych (domyślnie bieżący); Java Project , nazywamy go SmallBear i klika-
ca Javę na JS. • overwrite nadpisuje istniejące pliki; my na przycisk Finish, zapamiętując położenie
• ignore ignoruje istniejące pliki, (nie nad- naszego nowo powstającego projektu, (ramka
Aby rozpocząć pracę z GWT musimy: pisuje); Contents pole Direcotry) w naszym przypadku
• className pełna nazwa tworzonej to c:\workspace. Teraz przechodzimy do nad-
• mieć zainstalowaną wirtualną maszynę Ja- startowej klasy aplikacji. pisania tak powstałego zalążka nowego projek-
va (min wersja 1.4), jeśli jej nie masz, ścią- tu, przez szkielet generowany przy użyciu na-
gnij i zainstaluj Sun Java Standard Edition Pierwsza aplikacja rzędzi GWT.
SDK (http://java.sun.com/javase/downloads/ Przechodzimy do stworzenia pierwszej aplika- Uruchamiamy projectCreator poleceniem:
index.jsp); cji w GWT. Jeśli pojawiły się już jakieś nieja- (Listing 1.). Po wykonaniu przedstawionych
• ściągnąć Google Web Toolkit package sności, to ten krok prawdopodobnie większość komend i odświeżeniu projektu w Eclipse,
(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. Rysunek 1. Widok szkieletu aplikacji GWT w Eclipse

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: Rysunek 2. Widok działającej aplikacji w trybie HostedMode

www.phpsolmag.org 47
Narzędzia

szkielet aplikacji GWT powinien wyglądać tak, ru mamy dwa tryby: HostedMode i WebMo- skrypt w Internet Explorerze czy też w Fire-
jak na Rysunku 1. de. Tryb HostedMode jest trybem w pełni za- foksie, będzie on działał tak samo. Aby uru-
Warto w tym miejscu zauważyć, że two- rządzanym przez GWT, oznacza to, że może- chomić aplikację w trybie Hosted wywołu-
rząc aplikację, klasę startową umieściliśmy w my tu debugować uruchamiany kod i śledzić jemy wygenerowany w katalogu domowym
pakiecie client. Jest to zalecane przez develo- kolejne jego kroki, analizując dokładnie to, co projektu skrypt SmallBear–shell, efekt
perów Google i jeśli tego nie zrobimy, skrypt dzieje się z powołanymi do życia zmiennymi oczekiwany widoczny jest na Rysunku 2. Aby
generujący schemat aplikacji powinien po- czy obiektami. uruchomić aplikację w trybie Web urucha-
kazać nam mniej więcej taki komunikat: Tryb WebMode to już domyślny tryb, miamy skrypt SmallBear–compile, który to
(Listing 2.). w jakim będzie pracować nasza aplikacja, czy- jednak nie otworzy nam domyślnej przeglą-
Warto o tym pamiętać, by w przypadku ta- li wskazana przez nas przeglądarka interneto- darki, a jedynie przetłumaczy aplikację Java
kiego przeoczenia nie marnować czasu na za- wa. Developerzy GWT dają nam gwarancję, na JavaScript.
stanawianie się, gdzie popełniliśmy błąd. że aplikacja uruchamiana w trybie Hosted, Wynik tego tłumaczenia widoczny jest
Ponieważ skorzystaliśmy z generatora będzie działała identycznie jak w trybie Web. w katalogu www (jest to domyślny katalog
szkieletu aplikacji, tak przygotowany pro- Warto tu zauważyć, że oznacza to też, że generowania JS – można to zmienić). War-
jekt możemy od razu uruchomić. Do wybo- niezależnie od tego, czy uruchomimy nasz 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
Rysunek 3. Widok działającej aplikacji w przeglądarce Firefox (WebMode)
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-
Rysunek 4. Przeglądanie serwisów – AMFPHP. kacji. Dzięki takiemu zapisowi możemy two-

48 06/2007
GWT

rzyć oddzielnie własną strukturę HTML, wy- Aby w najprostszy z możliwych sposo-
pełniając tylko odpowiednie elementy, w peł- bów zaprezentować działanie powyższe- Listing 2. Komunikat skryptu generującego
schemat aplikacji
ni zarządzanymi przez GWT obiektami. Aby go, zmieńmy bazową aplikację tak, by na
upewnić się, że wszystko jest zrozumiałe, pro- zdarzenie kliknięcia pobierała informa- Please use 'client' as the final
ponujemy dokonać własnych zmian w kodzie, cję o naszym numerze IP z witryny http:// package, as in 'com.
sprawdzając, jak zareaguje (albo czy w ogó- whatismyip.org/. example.foo.client.MyApp'.
le zareaguje) na to aplikacja GWT. Po więcej W tym celu zmieniamy implementację me- It isn't technically necessary,
ciekawych przykładów wykorzystania GWT tody onClick w klasie SmallBear (patrz Li- but this tool enforces the best
odsyłamy na stronę domową projektu: http: sting 5.), tak by w kroku 1. zapytać serwer practice.
//code.google.com/webtoolkit/documentation/ o nasz numer IP, w kroku 2. zareagować na
examples/. Warto obejrzeć dema, zanim przej- odpowiedź serwera, wyświetlając odpowiedź
dziemy do następnego tematu. w kroku 3. – JavaScriptowy alert. To nam wy- link bezpośredni: http://www.5etdemi.com/
starczy, by upewnić się, że komunikacja asyn- uploads/amfphp-1.9.beta.20070513.zip).
GWT i HTTPRequest chroniczna działa. Po ściągnięciu wystarczy rozpakować ar-
Jak na razie pokazaliśmy jedynie, że tłuma- chiwum do katalogu hdocs serwera apache
czenie Javy do JavaScrpt–u działa, ale nie było GWT i AMFPHP i przejść do katalogu bazowego aplikacji,
w tym nic z asynchronicznej komunikacji z ser- Potrafimy już wysyłać i odbierać proste da- czyli {$HTDOC_DIR}/amfphp/services. To
werem (AJAX). Powoli przejdziemy do wywo- ne z serwera. Bardziej skomplikowane struk- tutaj będziemy umieszczali nasze usługi dla
ływania zdalnych metod na serwerze PHP. Za- tury danych trzeba niestety serializować. GWT.
czniemy od odrobiny teorii. My do tego celu będziemy używać forma- Zasada działania AMFPHP jest bardzo pro-
Dla naszych potrzeb, komunikacją z serwe- tu JSON (JavaScript Object Notation), któ- sta, jeśli wywołamy na serwerze www zapy-
rem w GWT, zajmuje się klasa HTTPRequest. ry doczekał się implementacji parserów tanie postaci: http://localhost//amfphpjson/
Posiada ona cztery statyczne metody imple- w większości znanych języków programo- json.php/MyService.myRemoteMethod/arg1/
mentujące asynchroniczną wymianę informa- wania, a napewno w PHP i GWT. Pozosta- arg2 to zostanie ono obsłużone w następu-
cji. W poniższym przykładzie wykorzystamy je nam tylko odebrać komunikat po stronie jący sposób:
tylko jedną z nich: PHP, zdeserializować go, przetworzyć zapy-
tanie i wysłać odpowiedź do GWT. • AMFPHP powoła do życia instancje klasy
asyncGet(String url, Sprawa prosta, ale dla bardziej zaawanso- MyService (której definicja musi znajdo-
ResponseTextHandler handler) wanych aplikacji, gdy serwer implementować wać się w pliku MyService.php w katalogu
będzie wiele zdalnie wywoływanych metod, /services);
gdzie: należałoby przewidzieć możliwość dobrego • sprawdzi, czy myRemoteMethod jest me-
zarządzania takimi metodami. todą ze zdefiniowanym zdalnym dostę-
url to – to URL (musi być adresem Z pomocą przychodzi dojrzała już apli- pem;
bezwsględnym) kacja AMFPHP. AMFPHP w wersji 1.9 na • uruchomi metodę myRemoteMethod z ar-
handler –to obiekt, który zostanie dzień pisania tego artykułu był dostępny gumentami arg1, arg2 odpowiednio dese-
poinformowany w momencie jedynie na blogu twórcy projektu (http:// rializując parametry, jeśli trzeba;
odpowiedzi serwera. www.5etdemi.com/blog/) (dla niecierpliwych • na koniec serializuje i zwraca wynik.

R E K L A M A

www.phpsolmag.org
Narzędzia

Przykład klasy implementującej prosty serwis dę getSum, wpisując w odpowiednie pola wy- smallbear\src\pl\rmalinowski\) dodać do-
dla AMFPHP widać na Listingu 5. W Punk- brane wartości i uruchamiając metodę po- datkowy wpis:
tach:1., 2. i 3. definiujemy odpowiednio na- przez naciśnięcie przycisku call. Wynik spo-
zwę udostępnianej metody, jej opis i zdalny dziewany, widoczny jest na Rysunku 4. Pozo- <inherits name=
typ dostępu. staje teraz wywołać daną metodę poprzez apli- 'com.google.gwt.json.JSON'/>
Punkt 4. to już implementacja metody, kację GWT.
której nazwę zdefiniowaliśmy w Punkcie Po stronie AMFPHP serializacja i deseriali- Poinformuje on kompilator GWT, że do wyge-
1. Dla tak zdefiniowanego serwisu, może- zacja robiona jest automatycznie, po stronie nerowanego JavaScript–u należy dodać wska-
my uruchomić dostarczoną przez AMFPHP GWT musimy obsłużyć ją sami. zaną bibliotekę. Użycie biblioteki wygląda na-
przeglądarkę do testowania usług. Wystarczy Do tego przykładu wykorzystamy wbu- stępująco:
otworzyć plik browser/index.html i powin- dowaną w GWT bibliotekę (com.google.gwt.
niśmy zobaczyć jak AMFPHP widzi nasz ser- json.JSON). • serializacja:
wis (Rysunek 4.). Aby móc ją wykorzystać, musimy do pliku JSONNumber jsonNumber = new
Tu możemy też, po raz pierwszy, sprawdzić SmallBear.gwt.xml (w tym przypadku plik- JSONNumber(12.0);
czy działa on poprawnie. Przetestujmy meto- ten znajduje się w katalogu c:\workspace\ // 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 informacje
Przedstawiony przykład komunikacji GWT
z PHP jest bardzo prosty i dla bardziej za-
Rysunek 5. Debugowanie aplikacji GWT w Eclipse IDE 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.

Debugowanie
Uruchamiają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 jednostkowe
GWT wspiera również testy jednostkowe.
Wraz z narzędziami ProjectCreator i Aplica-
Rysunek 6. Wynik testów jednostkowych w Eclipse IDE tionCreator dostajemy JunitCreator. Jest to

50 06/2007
GWT

narzędzie do automatycznego generowania


testów i osadzenia ich we wskazanym projek- Listing 3. Plik SmallBear.java
cie. Składnia JunitCreator-a to: package pl.rmalinowski.client;
// klasy, które będziemy wykorzystywać w tym przykładzie
• JUnitCreator – junit pathToJUnitJar import com.google.gwt.core.client.EntryPoint;
– module moduleName [–eclipse import com.google.gwt.user.client.ui.Button;
projectName] [–out dir] [–overwrite] import com.google.gwt.user.client.ui.ClickListener;
[–ignore] className gdzie: import com.google.gwt.user.client.ui.Label;
• junit określa ścieżkę do junit.jar (wy- import com.google.gwt.user.client.ui.RootPanel;
magane); import com.google.gwt.user.client.ui.Widget;
• module nazwa testowanego modułu // i jeszcze to co będzie wykorzystywane w następnych przykładach
GWT (wymagane); import com.google.gwt.user.client.HTTPRequest;
• eclipse tworzy konfiguracje integru- import com.google.gwt.user.client.Window;
jący junit z eclipse; import com.google.gwt.user.client.ResponseTextHandler;
• out folder do zapisania plików wyni- import com.google.gwt.json.client.JSONException;
kowych (domyślnie bierzący); import com.google.gwt.json.client.JSONNumber;
• overwrite nadpisuje istniejące pliki; import com.google.gwt.json.client.JSONParser;
• ignore ignoruje istniejące pliki, (nie public class SmallBear implements EntryPoint {
nadpisuje); public void onModuleLoad() {
• className pełna nazwa tworzonej kla- final Button button = new Button("Click me"); //(1)
sy testowej. final Label label = new Label(); //(2)
button.addClickListener(new ClickListener() { //(3)
Aby móc przeprowadzać testy jednostkowe public void onClick(Widget sender) { //(4)
projektu SmallBear uruchamiamy junitCre- if (label.getText().equals("")) //(5)
ator : label.setText("Hello World!"); //(6)
else //(7)
C:\gwt>junitCreator –junit c:\junit\ label.setText(""); //(8)
junit.jar –module pl.rmalinowski. }
SmallBear –eclipse SmallBear –out c: });
\workspace\smallbear pl.rmalinowski. RootPanel.get("slot1").add(button); //(9)
client.SmallBearTest RootPanel.get("slot2").add(label); //(10)
}
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- Listing 4. Plik SmallBear.html
dasz biblioteki junit.jar, możesz ją ściągnąć ze <html>
strony projektu (http://junit.org) lub użyć bi- <head>
blioteki wbudowanej w eclipse: <title>Wrapper HTML for SmallBear</title>
<style>
({$ECLIPSE_DIR}\plugins\ body,td,a,div,.p{font–family:arial,sans–serif}
org.junit_3.8.1\junit.jar) div,td{color:#000000}
a:link,.w,.w a:link{color:#0000cc}
wynik to: Listing 8. Po odświeżeniu projek- a:visited{color:#551a8b}
tu w oknie eclipse, powinniśmy zobaczyć no- a:active{color:#ff0000}
wy katalog test, a w nim wygenerowany test. </style>
Klikając prawym przyciskiem na pl.rmalinow- <script language='javascript' src='pl.rmalinowski.
ski.client.SmallBearTest, a następnie wybie- SmallBear.nocache.js'></script> <!–– (1) ––>
rając Debug as –> Java application rozpoczy- </head>
namy test aplikacji. (Test uruchomić może- <body>
my również, wybierając z menu Run –> De- <iframe src="javascript:''" id="__gwt_historyFrame
bug –> Junit –> SmallBearTest). Do wyboru " style="width:0;height:0;border:0"></iframe> <!–– (2) ––>
mamy dwa rodzaje testów, testy w trybie ho- <h1>SmallBear</h1>
sted i web. Tak jak to zostało już na początku <p>
wspomniane, pierwszy tryb wykonuje aplika- This is an example of a host page for the SmallBear application.
cję bez tłumaczenia jej na JS, a drugi tryb naj- (...).
pierw konwertuje Javę do JS i dopiero wtedy </p>
ją uruchamia. W tym przypadku testy zosta- <table align=center>
ną wykonane już na domyślnym kodzie JS. <tr>
Rysunek 6. przedstawia ekran, prezentujący <td id="slot1"></td><td id="slot2"></td> <!–– (3) ––>
wynik sumaryczny uruchomionych testów. </tr>
</table>
JavaScript Native Interface </body>
GWT nie byłby tak popularny, gdyby zamy- </html>
kał drzwi tym, którzy chcieliby mimo wszyst-

www.phpsolmag.org 51
Narzędzia

ko uruchamiać natywny kod JavaScript. Kie-


Listing 5. Przykład asynchronicznej komunikacji dy zachodzi taka potrzeba? Przede wszystkim
button.addClickListener(new ClickListener() { w przypadku, gdy mamy już napisane spo-
public void onClick(Widget sender) { ro w JS i w nieinwazyjny sposób chcielibyśmy
HTTPRequest.asyncGet("http://whatismyip.org", new ResponseTextHandler() { //(1) połączyć taki kod z GWT.
public void onCompletion(String responseText) { //(2) Inną potrzebą wykorzystania JSNI, jest
Window.alert("My ip is: " + responseText); //(3) 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.
Listing 6. Przykład klasy implementującej serwis wAMFPHP
<?php Podsumowanie
class MyService{ Przedstawiliśmy zaledwie zarys możliwości,
function MyService(){ jakie daje Google Web Toolkit. Nic nie wspo-
$this–>methodTable = array( mnieliśmy o prostocie dodawania dodat-
"getSum" => array( //(1) kowych komponentów do naszej aplikacji,
"description" => "Returns sum of two int", //(2) a pojawia się ich coraz więcej.
"access" => "remote"//(3) 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-
public function getSum($a, $b) { //(4) cisk cofnij, który może dla nas zapamięty-
return $a + $b; 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
Listing 7. Przykład klasy komunikującej się z serwisem AMFPHP i wiele innych informacji można doczytać.
button.addClickListener(new ClickListener() { Na koniec postaramy się jeszcze odpowie-
public void onClick(Widget sender) { dzieć na jedno pytanie. Kiedy warto wybrać
JSONNumber arg1 = new JSONNumber(12.0); GWT?
JSONNumber arg2 = new JSONNumber(100.0); Przede wszystkim, gdy planujemy stworzyć
String url = "http://localhost//amfphp/json.php/MyService.getSum/"+arg1.toString()+ rozbudowaną aplikację kliencką. Przy napraw-
"/"+arg2.toString(); dę małych skryptach, tam gdzie istotna jest
HTTPRequest.asyncGet(url, new ResponseTextHandler() { //(1) wielkość ściąganego przez przeglądarkę kodu,
public void onCompletion(String responseText) { //(2) GWT nie jest dobrym wyborem.
Zawsze, gdy tylko zaczynamy myśleć, jak uła-
try twić użytkownikowi administrowanie naszym
{ sklepem, czy CMS'em.
JSONNumber jsonNumber = (JSONNumber) JSONParser.parse(responseText); Tam gdzie rodzą się pomysły na dynamiczne
Window.alert("Sum = " + jsonNumber.getValue()); pojawianie się list rozwijanych, automatyczne
} uzupełnianie nazw artykułów, czy choćby wa-
lidacja kodów pocztowych, tam też jest miej-
catch (JSONException e) sce dla GWT.
{ Najlepsze jednak jest to, że kod GWT napi-
Window.alert("JSON parse error!"); 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.
});

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 RAFAŁ MALINOWSKI
Created file c:\workspace\smallbear\SmallBearTest–web.launch (http://rmalinowski.pl) – zawodowo pracuje jako
Created file c:\workspace\smallbear\SmallBearTest–hosted.cmd Java EE 5 projektant i programista, bierze udział
Created file c:\workspace\smallbear\SmallBearTest–web.cmd w kilku projektach opensource rozwijanych w tech-
nologii PHP i Flash.

52 06/2007
Narzędzia

PayPal
Łatwy sposób na internetowe płatności

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.

Zakładanie konta
Dowiesz się... Powinieneś wiedzieć... PayPal umożliwia otwieranie kont użytkowni-
• Jak wykorzystać PayPal do obsługi płatności • Powinieneś znać podstawy php oraz html. kom indywidualnym w wieku powyżej 18 lat
na Twojej stronie internetowej. i firmom zdolnym do zawarcia wiążącej praw-
nie umowy, po przejściu procedury rejestracji,
w ramach której muszą: zarejestrować adres
Wypłata środków: bezpłatnie za 500 PLN e-mail (będzie stanowił login) oraz zaakcep-
i więcej, 5 PLN za mniej niż 500 PLN. tować zasady zachowania poufności i warun-
Poziom trudności Narzędzia handlowców: bez ograniczeń. ki umowy. Możemy również podać dane do-
tyczące źródeł, za pomocą których ma być fi-
Konto firmowe nansowane nasze konto PayPal (np. dane ra-
Przeznaczenie: firmy działające online. chunku bankowego, karty debetowej lub kre-

W
arunkiem założenia konta w Pay- Przyjmowanie płatności krajowych: przelew, dytowej).
Pal jest posiadanie adresu e-ma- czek, saldo PayPal – bez ograniczeń, od 1,9% Procedura zakładania konta polega za-
il. System oferuje trzy typy kont. do 3,4% + 1,35 PLN; karta kredytowa i de- tem na wyborze typu konta, podaniu da-
Wszystkie trzy bezpłatnie umożliwiają: otwie- betowa – bez ograniczeń, od 1,9% do 3,4% + nych osobowych/firmy (nazwa firmy, adres,
ranie konta, wysyłanie pieniędzy, dodawanie 1,35 PLN. nr telefonu, adres e-mail) oraz przeczyta-
środków. Transakcje w wielu walutach: bez ograniczeń, niu i zaakceptowaniu umowy. Po zakończe-
od 2,4% do 3,9% + 1,35 PLN za transakcję plus niu rejestracji i zalogowaniu się otrzymuje-
Konto osobiste 2,5% za przewalutowanie). my dostęp do naszego konta. Na uwagę zasłu-
Przeznaczenie: osoby fizyczne głównie kupują- Wypłata środków: bezpłatnie za 500 PLN i guje Status użytkownika – jako użytkownik
ce przez Internet. więcej, 5 PLN za mniej niż 500 PLN. zweryfikowany otrzymamy dostęp rozsze-
Przyjmowanie płatności krajowych: przelew, czek, Narzędzia handlowców: bez ograniczeń. rzony i będziemy mogli wysyłać kwoty o nie-
saldo PayPal – bezpłatna, ograniczona możliwość; Dodatkowo: dostęp dla wielu użytkowników. ograniczonej wysokości, a system PayPal bę-
karta kredytowa i debetowa – ograniczona, płatna
możliwość (opłata 5,4% plus 1,35 PLN).
Transakcje w wielu walutach: ograniczona,
Najważniejsze zalety PayPal
płatna możliwość (opłata: od 2,4% do 3,9% + • obsługa płatności z ponad 100 krajów/regionów;
1,35 PLN za transakcję plus 2,5% za przewa- • akceptacja płatności kartami kredytowymi VISA i MasterCard;
lutowanie). • bezpieczeństwo – szyfrowanie przy użyciu klucza o długości 128 bitów;
Wypłata środków: bezpłatnie za 500 PLN • akceptacja płatności w wielu walutach;
• zwroty wpłat;
i więcej, 5 PLN za mniej niż 500 PLN.
• brak kosztów dla wysyłającego;
Narzędzia handlowców: ograniczona możliwość. • opcja uwzględniania kosztów wysyłki dla sprzedającego;
• prosta integracja ze stroną/sklepem internetowym;
Konto specjalne • środowisko testowe.
Przeznaczenie: osoby fizyczne sprzedające i ku-
pujące przez Internet.
Przyjmowanie płatności krajowych: przelew, Sposoby/scenariusze integracji
czek, saldo PayPal – bez ograniczeń, od 1,9% do
3,4% + 1,35 PLN; karta kredytowa i debetowa • integracja własnego koszyka z systemem PayPal;
• wykorzystanie Koszyka oferowanego przez PayPal;
– bez ograniczeń, od 1,9% do 3,4% + 1,35 PLN.
• użycie przycisku Kup teraz w wypadku sprzedaży pojedynczych przedmiotów;
Transakcje w wielu walutach: bez ograniczeń, • użycie przycisku Subskrypcje i Płatności cykliczne – powtarzające się płatności;
od 2,4% do 3,9% + 1,35 PLN za transakcję plus • użycie przycisku Darowizny – zbieranie darowizn przez Internet.
2,5% za przewalutowanie).

54 06/2007
PayPal

dzie nas przedstawiał jako bardziej wiarygod- niowanie wszystkich tych informacji w jed- dzie mógł wybrać któreś z nich, włożyć do
nych. Aby uzyskać status Zweryfikowany, na- nym miejscu bardzo upraszcza tworzenie sa- koszyka i następnie zamówić. Stronę tą im-
leży dodać do naszego konta kartę kredytową mego sklepu, jak też co nie mniej ważne póź- plementuje skrypt produkty.php przedsta-
i przeprowadzić procedurę jej potwierdzenia, niejsze jego testowanie. Produkty w koszyku wiony na Listingu 2. Na początku skryptu
co w praktyce oznacza zakup przy użyciu tej klienta zapamiętamy w danych sesji – tablicy inicjujemy sesję, aby móc z niej odczytać in-
karty kredytowej w wysokości 6,50 PLN od $_SESSION. Koszyk wyświetlimy na stronie ja- formacje o produktach w koszyku. Następnie
PayPal (kwota w całości zwracana po pierw- ko box – przykładowa implementacja w pliku definiujemy tablicę z przy kładowymi pro-
szej transakcji). koszyk.php zamieszczonym na płycie CD. duktami, które będą wyświetlone na stronie.
Pierwsza strona naszego sklepu będzie wy- Dla każdego produktu wyświetlamy jego na-
Prosty sklep internetowy świetlać przykładowe produkty. Klient bę- zwę, cenę oraz opis.
– przykład integracji
Zazwyczaj 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- 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

www.phpsolmag.org 55
Narzędzia

Listing 2. Plik produkty.php


<?php <td width="483">
include('config.php'); <div align="center">
<table style="width: 483px" cellpadding="0"
// Zainicjowanie sesji: cellspacing="0">
session_set_cookie_params(EXPIRE_TIME); <?php
session_cache_limiter('nocache'); // Wyświetlamy każdą pozycję w tablicy produktów:
session_start(); foreach($products as $product) {

// Definiujemy produkty dostępne w sklepie: // formatujemy cenę: 2 miejsca dziesiętne i przecinek


// nazwa produktu // jako separator
$products[0]['name']='Produkt1'; $price=number_format($product['price'], 2, ',', '');
// cena produktu ?>
$products[0]['price']=10.0; <tr>
// opis <td width="323">
$products[0]['desc']='Opis produktu nr 1'; <p class="produkt"><?=$product['name']?></p>
$products[1]['name']='Produkt2'; </td>
$products[1]['price']=11.0; <td width="160">
$products[1]['desc']='Opis produktu nr 2'; <p class="cena"><?=$price?> <?=$currency?></p>
$products[2]['name']='Produkt3'; </td>
$products[2]['price']=12.0; </tr>
$products[2]['desc']='Opis produktu nr 3'; <tr>
$currency='PLN'; <td width="323">
?> <p class="opis"><?=$product['desc']?></p>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" </td>
"http://www.w3.org/TR/html4/loose.dtd"> <td width="160">
<html> <p class="kup">
<head> <a href="addtobasket.php?product_name=
<meta http-equiv="Content-Type" <?=$product['name']?>&amp;price=
content="text/html; charset=iso-8859-2"> <?=$product['price']?>&amp;currency=$currency">
<meta http-equiv="Content-Language" content="pl"> <img border="0" src="index/phpsol_03.jpg"
<meta http-equiv="pragma" content="no-cache"> width="98" height="26">
<title>Przykładowy sklep internetowy</title> </a>
<link rel="stylesheet" type="text/css" </p>
href="phpsol.css"> </td>
</head> </tr>
<body> <?php
<div align="center"> }
<table style="width: 660px" cellpadding="0" cellspacing="0"> ?>
<tr> </table>
<td width="177"> </div>
<?php </td>
</tr>
// wyświetlenie koszyka </table>
include('koszyk.php'); </div>
?> </body>
</td> </html>

Listing 3. Plik addtobasket.php

<?php $_SESSION['customer_basket'][]=$tmp;
include('config.php'); // i dodajemy ją do koszyka
session_set_cookie_params(EXPIRE_TIME); $_SESSION['sum'] += $_GET['price'];
session_cache_limiter('nocache'); // aktualizujemy sumę cen produktów w koszyku
session_start(); $_SESSION['currency']=$_GET['currency'];
// Sprawdzamy, czy wszystkie wymagane // oraz walutę zakupów
// dane zostały podane: }
if(isset($_GET['product_name']) && isset($_GET['price']) && // na koniec przekierowujemy do głównej
isset($_GET['currency'])) { // strony sklepu:
$tmp['name']=$_GET['product_name']; header("Refresh: 0; url=produkty.php");
// Tworzymy tymczasową tablicę ?>
$tmp['price']=$_GET['price'];

56 06/2007
Narzędzia

Przy każdym produkcie jest też guzik głównej strony, na której zobaczy dodany pro- • cancel _ return podobnie jak poprzed-
umożliwiający dodanie wybranego artyku- dukt w koszyku. nie, ale wykorzystywane wtedy, gdy klient
łu do koszyka. Skrypt wykonujący to zadanie Kiedy klient włożył już coś do koszyka, rozmyśli się i kliknie na stronie PayPal link
zawarliśmy w pliku addtobasket.php przed- może złożyć zamówienie. W tym celu kli- „Back to Merchant”;
stawionym na Listingu 3. Tutaj na początku ka na link prowadzący do skryptu order.php • shopping _ url ustawiamy na główną
również inicjujemy sesję, by mieć dostęp do przedstawionego na Listingu 4. Skrypt wy- stronę naszego sklepu;
informacji o koszyku. Skrypt otrzymuje in- świetla formularz przedstawiający podsu- • business – tutaj podajemy adres e-mail
formację o wybranym produkcie za pomocą mowanie tego, co klient ma w koszyku, oraz skojarzony z naszym kontem w PayPal, na
tablicy $_GET. W prawdziwym sklepie dane umożliwia złożenie zamówienia. Dane z for- które chcemy dostawać wpłaty;
pobierane byłyby z bazy danych, a do skryp- mularza są przesyłane do ostatniego skryptu • item _ name _ 1 – za co jest płatność;
tu przekazalibyśmy jedynie ID wybrane- PayPal.php, który przedstawiliśmy na Listin- • amount _ 1 – suma, którą należy nam prze-
go produktu. Jeśli wszystkie wymagane da- gu 5. Skrypt jest spreparowany w ten sposób, lać;
ne są zdefiniowane, to tworzymy tymczaso- że zawiera kolejny formularz, który ostatecz- • currency _ code – kod waluty.
wą tablicę zawierającą nazwę oraz cenę pro- nie jest odsyłany do witryny PayPal. Zawie-
duktu. Następnie dodajemy ją do tablicy ra pola o nazwach zrozumiałych dla PayPal. Formularz zostaje automatycznie wysłany
$_SESSION[‘customer_basket’]. Dodatko- W tym przykładzie zawarliśmy tylko nie- do PayPal za pomocą JavaScriptu, więc na-
wo aktualizujemy sumę cen wszystkich pro- zbędne minimum zmiennych, które są wy- wet nie wyświetli się w przeglądarce – użyt-
duktów w koszyku, dodając do niej cenę do- magane, aby poprawnie obsłużyć prostą kownik od razu jest przekierowany do witry-
kładanego właśnie produktu oraz zapamiętu- transakcję. Użyte przez nas pola to: ny PayPal.
jemy walutę w jakiej dokonywane są zakupy. Konstrukcja oparta jest na dwóch formu-
Zakładamy przy tym, że wszystkie ceny pro- • upload oraz cmd wymagane przez PayPal; larzach: order.php oraz PayPal.php. Pierw-
duktów wyrażone są w tej samej walucie, • return zawierające adres, pod który zosta- szy z nich jest podsumowaniem transakcji
więc nie musimy ich przeliczać. Na koniec nie przekierowany klient po udanym pro- dla klienta i nie musi zawierać wszystkich
klient zostaje przekierowany z powrotem do cesie płatności; wymaganych przez PayPal pól. Możemy go

Listing 4. Plik order.php

<?php td><td><b>Cena</b></td></tr>
include('config.php'); <?php
session_set_cookie_params(EXPIRE_TIME); foreach($_SESSION['customer_basket'] as $item) {
session_cache_limiter('nocache'); $price = number_format($item['price'], 2, ',', '');
session_start(); ?>
?> <tr>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" <td><?=$item['name']?></td>
"http://www.w3.org/TR/html4/loose.dtd"> <td><?=$price?> <?=$_SESSION['currency']?></td>
<html> </tr>
<head> <?php
<meta http-equiv="Content-Type" content="text/html; }
charset=iso-8859-2"> ?>
<meta http-equiv="Content-Language" content="pl"> <tr style="height: 15px;"><td colspan="2">&nbsp;</td></tr>
<meta http-equiv="pragma" content="no-cache"> <tr>
<title>Przykładowy sklep internetowy</title> <td><b>Suma</b></td>
<link rel="stylesheet" type="text/css" href="phpsol.css"> <td><b><?=$_SESSION['sum']?> <?=$_SESSION['currency']?></
</head> b></td>
<body> </tr>
<div align="center"> <tr style="height: 40px;"><td colspan="2">&nbsp;</td></tr>
<form action="PayPal.php" method="post"> <tr><td colspan="2" style="text-align: center;">
<table style="width: 460px" cellpadding="0" <input type="submit" name="go" value="Zamów"> płac±c przez
cellspacing="0"> <img style="vertical-align: middle;" src="index/
<tr> PayPal.jpg"></td>
<td width="483"> </tr>
<div align="center"> <?php
<h1>Składanie zamówienia</h1><br><br> }
<table style="width: 483px" cellpadding="0" ?>
cellspacing="0"> </table>
<?php </div>
if(!isset($_SESSION['customer_basket'])) { </td>
?> </tr>
<tr><td><p>Brak produktów w koszyku!</p></td></tr> </table>
<?php </form>
} else { </div>
?> </body>
<tr><td><b>Nazwa produktu</b></ </html>

58 06/2007
PayPal

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ści
W przyjętym przez nas najprostszym roz- Rysunek 3. Zakładanie konta testowego PayPal
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 4. Polska strona PayPal

www.phpsolmag.org 59
Narzędzia

Listing 5. Plik PayPal.php W Sieci


<?php
• PayPal w Polsce
include('config.php');
http://www.PayPal.pl/
session_set_cookie_params(EXPIRE_TIME);
• PayPal Developer Center
session_cache_limiter('nocache'); https://developer.PayPal.com/
session_start();
$total=number_format($_SESSION['sum'], 2, '.', '');
?> PayPal Developer Center. W sekcji „Test Acco-
<html> unts” możemy sobie założyć testowe konto.
<body> Ma ono funkcjonalność dokładnie taką samą
<form name= "order" action="<?=PayPal_URL?>" method="post"> jak prawdziwe konto w PayPal, ale operuje na
<input type="hidden" name="upload" value="1"><br> fikcyjnych pieniądzach – możemy go uży-
<input type="hidden" name="cmd" value="_cart"><br> wać do testowania bez ograniczeń. Wszyst-
<input type="hidden" name="return" value="<?=SITE_URL?>info_success.php"><br> kie e-maile, które normalnie PayPal wysyła
<input type="hidden" name="cancel_return" value="<?=SITE_URL?>info_cancel.php"><br> na naszą skrzynkę (np. potwierdzenia wyko-
<input type="hidden" name="shopping_url" value="<?=SITE_URL?>produkty.php"><br> nania transakcji), trafiają do sekcji „Test Ema-
<input type="hidden" name="business" value="<?=PayPal_MAIL?>"> il”, gdzie mamy do nich wgląd. Klikając na
<input type="hidden" name="item_name_1" value="Zakupy w Testowym Sklepie"> link „Help” znajdujący się na samej górze wi-
<input type="hidden" name="amount_1" value="<?=$total?>"><br> tryny po prawej stronie, mamy dostęp do bo-
<input type="hidden" name="currency_code" value="<?=$_SESSION['currency']?>"> gatej dokumentacji samego API PayPal. Tutaj
</form> znajdziemy szczegółowy opis integracji stron
<script type="text/javascript" language="JavaScript"> internetowych z witryną PayPal, a w szcze-
document.order.submit(); gólności dokładny opis wszystkich pól for-
</script> mularza, które możemy wykorzystać. Nie-
</body> stety, jak dotąd całość dokumentacji oraz wi-
</html> tryna developerska dostępne są jedynie w ję-
zyku angielskim.
W jaki sposób możemy przeprowadzić te-
• city – miasto; Jeśli zrezygnowaliśmy z szyfrowania da- sty? Wszystko sprowadza się do tego, żeby
• zip – kod pocztowy; nych, to możemy łatwo zauważyć, że wyge- podmienić adres na który wysyłamy formu-
• country – kod kraju klienta; nerowany kod jest bardzo podobny do te- larz do PayPal. Pokażmy to na naszym przy-
• email – e-mail klienta. go, który obsługiwał nasz koszyk. W ten spo- kładzie. Odszukajmy w tym celu w pliku con-
sób, jeśli chcemy oferować więcej produktów fig.php linijkę:
To tylko najczęściej używane zmienne, pełny z opcją Kup teraz, możemy bardzo łatwo sa-
ich spis znajdziemy w dokumentacji dostępnej mi generować kod dla przycisków. Wystar- define('PayPal_URL','
w PayPal Developer Center. czy podstawić w nim nazwę aktualnego pro- https://www.PayPal.com/cgi-bin/webscr');
duktu do pola item_name oraz cenę do pola
Kup teraz oraz Darowizny amount. i podmieńmy ją na:
Jeśli chcielibyśmy na naszej stronie wysta- Często możemy się spotkać ze strona-
wić na sprzedaż pojedyncze produkty i nie mi, na których autorzy proszą o wsparcie define('PayPal_URL','
martwić się o tworzenie koszyka, możemy za pomocą dobrowolnej darowizny. Rów- https://www.sandbox.PayPal.com
dać użytkownikom możliwość zakupu jedne- nież za pomocą PayPal możemy w łatwy spo- /cgi-bin/webscr');
go produktu naraz. Za pomocą PayPal jest to sób zbierać darowizny. Wystarczy w narzę-
bajecznie proste. Aby tego dokonać logujemy dziach dla handlowców wybrać opcję Da- Od tej pory mimo że wszystko wygląda do-
się do swojego konta PayPal. Następnie prze- rowizny. Dalej postępujemy analogicznie, kładnie tak samo jak wcześniej, transakcje bę-
chodzimy do zakładki Narzędzia handlow- jak dla przycisku Kup teraz. Jedyna różnica dą wykonywane jedynie wirtualnie, a do tes-
ców. Klikamy w link Przyciski Kup teraz znaj- polega na tym, że możemy podać konkret- tów używamy konta testowego, które założy-
dujący się w prawym menu. Teraz wypełnia- ną kwotę, o którą prosimy albo nie podawać liśmy sobie w zakładce „Test Accounts” w ser-
my formularz opisujący sprzedawany przez kwoty. Jeśli jej nie podamy, to każdy użyt- wisie developerskim. Należy jednak pamię-
nas przedmiot. Podajemy jego nazwę, cenę kownik będzie mógł nas wspomóc sumą ja- tać, aby najpierw zalogować się do strony deve-
oraz wybieramy walutę i język. Do wybo- ką będzie uważał za słuszną. loperskiej (np. w drugim oknie przeglądarki)
ru mamy kilka wyglądów przycisku, może- – dopiero wtedy możemy korzystać z testo-
my też skorzystać z własnego obrazka. Na ko- Testowanie wego adresu. Gdy upewnimy się, że wszystko
niec wybieramy, czy dane o sprzedawanym PayPal oferuje całkiem rozbudowane na- działa jak należy, z powrotem ustawiamy wła-
przedmiocie mają być przechowywane w po- rzędzia wspomagające pracę przy budo- ściwy adres, na który będziemy wysyłać for-
staci zaszyfrowanej czy nie. Jeśli wybierzemy wie modułów z niego korzystających. Aby mularz do PayPal.
opcję zaszyfrowaną, to nie będzie można ich skorzystać z oferowanych możliwości, mu-
podejrzeć podglądając źródło strony, na któ- simy założyć sobie konto developerskie.
rej osadzimy za chwile nasz guzik. Teraz jed- W tym celu wchodzimy na adres: https:// MARIUSZ WIELKOPOLSKI
nak wybierzmy opcję niezaszyfrowaną. Kli- developer.PayPal.com/ i klikamy w link „Sign MARIUSZ TYTYK
kamy w przycisk Utwórz przycisk teraz. Do- Up Now”. Następnie wypełniamy formu- Mariusz Wielkopolski, Mariusz Tytyk zajmują się two-
stajemy gotowy kod, który wystarczy wkleić larz przedstawiony na Rysunku 3. Po zało- rzeniem stron www, na stałe związani z firmą redF5.
w wybranym miejscu na stronie. żeniu konta możemy się już zalogować do Kontakt z autorem: mariusz@redf5.com

60 06/2007
Kasa dla webmastera

SEO i SEM
Kampania dla małych i średnich firm

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.

i ile czasu na nich spędziła. Ponadto przy kam- kluczowych oraz „trudności wypozycjonowa-
paniach e-mailowych firmy udostępniają nam nia na dane słowo kluczowe”. Istnieje jednak kil-
Poziom trudności już nawet dokładną statystykę przeczytanych ka sposobów, które umożliwią nam poprawie-
wiadomości, rodzaje linków, które były wybra- nie swojej pozycji przy stosunkowo niedużym
ne przez odbiorców. Wszyscy na pewno zdają nakładzie czasu i kosztów. Na wstępie musimy
sobie sprawę z tego, jak duże pole manewru ma zapoznać się z obowiązującą terminologią:

M
arketing internetowy jest formą kam- później firma posiadająca tego typu informacje
panii promocyjnej towarów i usług o swoim kliencie. Można wyróżnić co najmniej • Bot/Robot – mechanizm mający na ce-
w sieci internetowej, docierającą za- kilka istotnych cech reklamy w Internecie: lu przeszukanie i zindeksowanie strony w
równo do obecnych, jak i przyszłych klientów. celu określenia jej pozycji w wynikach wy-
Wydatki na reklamę internetową rosną w szalo- • rosnąca liczba użytkowników, szukiwania;
nym tempie i największe są w Stanach Zjedno- • teoretycznie nasza reklama może docierać • link – odnośnik do strony internetowej;
czonych. W pierwszym kwartale tego roku wy- do klienta 24h na dobę; • PR/PageRank – matematyczny algorytm
niosły 4,9 mld dolarów, co stanowi 26-procento- • nieograniczony zasięg; stworzony przez Google w celu określenia
wy wzrost w sosunku do tego samego okresu w • możliwości analizy danych; wartości strony internetowej;
2006 roku. W Polsce sytuacja wygląda jak na Ry- • darmowe analizy statystyczne; • BL/Backlink/Link popularity/linki przy-
sunku 1., czyli widoczny jest znaczny wzrost wy- • dowolne formy reklamy – od tekstowej po chodzące – jak sama nazwa mówi, jest to
datków na reklamę internetową. film i dźwięk; liczba linków prowadząca do
Dotychczas znaczącą rolę e-reklamy dostrze- • stosunkowo atrakcyjne ceny. • wybranej strony internetowej;
gały większe firmy, które mogły pozwolić so- • linki wychodzące – liczba linków prowa-
bie na przeprowadzenie odpowiednich badań. SEO (Search engine optimization) dząca do innej domeny niż twoja strona;
Obecnie na polskim rynku coraz więcej firm, Search engine optimization, czyli optymaliza- • SERP (Search engine results position) –
zarówno małych, jak i średnich, zauważa rosną- cja kodu strony internetowej pod względem po- wyniki wyszukiwania;
cą rolę reklamy internetowej. Nasuwa się pyta- lepszenia jej pozycji w wyszukiwarkach. Każdy • DC/DataCenter – nazwa określająca bazę
nie: dlaczego Internet jest idealnym właściciel strony internetowej pragnie, by po danych wyszukiwarki. Często zdarza się,
miejscem na naszą reklamę? W Polsce już wpisaniu określonych słów kluczowych w naj- że wyniki z DC różnią się od siebie;
38% osób korzysta reguralnie z Internetu, a ko- popularniejszych wyszukiwarkach jego stro- • filtr – jest to mechanizm mający na celu
lejne 30% deklaruje, że chciałoby posiadać sta- na widniała w pierwszych wynikach. Działa- ukaranie danej strony internetowej spad-
łe łącze. Jeżeli wzrost gospodarczy utrzyma się nia SEO pozwalają osiągnąć zaskakujące efek- kiem o kilkanaście pozycji w wyniku wy-
na obecnym poziomie, niedługo będziemy mo- ty i zdecydowanie mogą przynieść firmie du- korzystywania nieetycznych technik po-
gli pochwalić się – tak jak Anglicy – obecnością że zyski. Wyobraźmy sobie, iż jesteśmy właści- zycjonowania;
w interaktywnym świecie ponad 60% obywateli. cielami internetowego sklepu komputerowe- • ban – wyrzucenie strony internetowej
Taka sytuacja stwarza firmom olbrzymie go. Każdy użytkownik np. wyszukiwarki Go- z bazy danych danej wyszukiwarki z po-
możliowści promocji różnorodnych produk- ogle, wpisując wodu np. spamowania;
tów. Kolejnym bardzo ważnym aspektem ro- „sklep komputerowy” jako pierwszą pozycję • spam – technika mająca na celu „sztucz-
li Internetu jest znacząca przewaga w badaniu zauważy link i opis naszego sklepu. Jest to bar- ne” podwyższenie pozycji danej strony in-
zachowań klienta. Dzięki różnego rodzaju ogól- dzo istotne, ponieważ przeciętny użytkownik ternetowej;
nodostępnym (bezpłatnym) statystykom może- nie przegląda wiecej niż pierwszych pięć, góra • sitemap/mapa strony – specjalnie sprepa-
my zbadać reakcje klienta na odpowiednie tre- dziesięć linków. Łatwo teraz można wyciągnąć rowana podstrona umożliwiająca lepszą
ści. Statystyki pozwalają nam, jak w żadnych in- wnioski, że dobra pozycja wielokrotnie zwięk- i szybszą indeksację strony internetowej;
nych mediach, ocenić praktycznie w stu procen- sza nasze zyski. • content – tekst na stronie internetowej;
tach popularność serwisu, ustalić czas, jaki osoba Przeprowadzenie kampanii SEO jest to do- • zaplecze – rożnego rodzaju strony, z któ-
poświęciła na zapoznanie się ze stroną interneto- syć kosztowny i długoterminowy proces. Ce- rych pozycjonerzy linkują w celu polep-
wą, dowiedzieć się, które podstrony odwiedziła ny ustalane są m.in w zależności od liczby słów szenia ich pozycji;

62 06/2007
SEO i SEM

• AT/Anchor Text – tekst, pod którym wy- nie go do kodu strony, a następnie – jak to ma dodane, a których bot ma nie sprawdzać i nie za-
stępuje link <a href =”link”>Anchor</a>; na przykład miejsce w przypadku Google – do- pisywać. Przykładowe ustawienie widoczne jest
• keywords – wyrazy, po których będziemy danie do Google's Webmaster Tools. Bardzo na Rysunku 3.
wyszukiwani w wyszukiwarkach. przydatne jest również dolinkowanie do strony Po stworzeniu pliku robots.txt i zapisaniu w
z innych serwisów. Sitemap również wpływa na nim odpowiednich informacji przenosimy go
Podstawową rzeczą, którą powinniśmy przy- lepszą ocenę przez boty, ponieważ w pewnym do katalogu głównego na serwerze, na którym
gotować, jest odpowiedni i unikatowy con- stopniu ułatawia im indeksację contentu. jest nasza strona internetowa. Mod_rewrite jest
tent. Musi on zawierać stosunkowo dużą licz- Kolejnymi dwoma krokami powinno być do- to jeden z modułów serwera Apache służący do
bę słów kluczowych, przy czym w żaden spo- stosowanie pliku robots.txt oraz mod_rewrite. nadpisywania adresów URL (tworzenia przyja-
sób nie powienien odchodzić od tematyki Plik robots jest jednym z pierwszych plików, któ- znych adresów). W celu edycji przechodzimy
strony. Nastepnie należy wybrać odpowied- re są sprawdzane przez robota podczas indeksacji. do katalogu głównego serwera i wyszukujemy
nie słowa kluczowe, które są bardzo istotne. W nim ustala się, które części serwisu mają być plik htaccess. Na początku zapisujemy „Rewri-
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 Rysunek 1. Dane o rozwoju rynku reklamy internetowej w Polsce i Europie Zachodniej (www.bankier.pl)
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- Rysunek 2. Narzędzie Google do zarządzania słowami kluczowymi

www.phpsolmag.org 63
Kasa dla webmastera

teEngine on”, po czym poniżej ustawiamy od- tem, aczkolwiek w odmienny sposób. Kampa- rym możemy na przykład skierować naszą re-
powiednie reguły. W kolejnej linijce ustalamy nia SEM obejmuje wykupienie różnego rodza- klamę wyłącznie w określone województwo,
dyrektywę: ju linków sponsorowanych oraz reklam teksto- czyli w sytuacji, gdy firma oferuje swoje pro-
wych, które przy wyszukiwaniu na określone dukty na terenie województwa warmińsko-ma-
RewriteRule marketing\.html$ seo.html słowa kluczowe występują na pierwszych miej- zurskiego i korzysta z linków sponsorowanych,
scach w wynikach wyszukiwania. jej oferta będzie widoczna dla użytkowników
i robimy [Enter] w celu pozostawienia jednej z terenu Warmii i Mazur. Ponadto linki sponso-
wolnej linii (trzeba pamiętać o pozostawieniu Możliwości SEM rowane są doskonałą metodą na promocję pro-
jednej wolnej linii). Analizując nasz przykład, Działania SEM dają nam o wiele więcej moż- duktu bądź na działania związane z promocją
możemy powiedzieć, że podczas uruchamia- liwości dotarcia do klienta niż SEO. Wyszuki- sezonową. Reklamodawca decyduje o kosztach
nia adresu URL mod będzie wyszukiwać adre- warki udostępniają nam narzędzia, dzięki któ- i ma możliwość sterowania dziennym budże-
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ż Rysunek 4. Przykład linków sponsorowanych w przypadku wyszukiwarki Google
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-

Rysunek 3. Przykładowe ustawienie pliku Rysunek 5. Wyniki wyszukiwania firm pod frazą „budownictwo”, posiadające nazwę w ofercie w
.htaccess www.pf.pl

64 06/2007
SEO i SEM

• 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-
Rysunek 6. Przykładowy link sponsorowany w wyszukiwarce Google
niej pieniędzy. Powinniśmy również zapoznać
się z różnego rodzaju narzędziami, które udo-
W Sieci: stępniane są, jeśli zdecydujemy się na tego ty-
pu usługi. Są to rozmaite analizatory, które po-
• http://forum.optymalizacja.com/ mogą dostosować wybór słów kluczowych do
• http://www.google.com/support/webmasters/ naszych potrzeb i zwiększyć nasze szanse na
• http://katalog.onet.pl/pomoc/index.html
sukces. Najwiekszym minusem linków sponso-
• http://www.highrankings.com/forum/
• http://searchenginewatch.com/ rowanych jest to, że ich odwiedzalność jest du-
• http://www.netsprint.pl/serwis/faq/ żo mniejsza niż wypozycjonowanych linków
„statycznych”. Użytkownicy większość swo-
jej uwagi poświecają na wyniki wyszukiwarek,
tem. Czasem osiągnięcie wysokich pozycji przy Linki Sponsorowane a nie na pojawiającą się reklamę.
pozycjonowaniu dla bardzo obleganych słów Kolejną popularną metodą wykorzystywaną W artykule poruszony jest przykład linków
kluczowych jest właściwie niemożliwe bądź przy kampaniach SEM są linki i teksty spon- sponsorowanych w przypadku Google, ponie-
koszty mogą przerosnąć zyski. Alternatywą jest sorowane w najpopularniejszych wyszukiwar- waż jest to obecnie najbardziej popularna wy-
zastosowanie sponsorowanych linków. kach. Najlepszym przykładem są usługi Ad- szukiwarka w Polsce. Takie usługi świadczo-
words świadczone przez Gooogle. Jest to praw- ne są również przez inne wyszukiwarki na ca-
Yellow Pages dopodobnie najpopularniejszaa i najczęściej wy- łym świecie.
Jedną z płatnych opcji promocji w Internecie są korzystywana metoda. Największym jej plusem
reklamy Yellow Pages. Przykładową witryną te- jest to, że reklamodawca może kontrolować Podsumowanie
go typu jest http://www.yellowpages.pl/, czy http: wszelkie koszty, a opłaty naliczane są w syste- W artykule poruszyliśmy podstawowe metody
//www.pf.pl. Jest to baza firm, w której za od- mie CPC, czyli od kliknięcia na działań SEO i SEM. Jest oczywiście wiele więcej
powiednią opłatą możemy umieścić swoją re- link sponsorowany. Ponadto firma Google możliwości wypromowania swojej firmy, produk-
klamę, ofertę i wizytówkę oraz wykupić linki oferuje niezwykle rozbudowane narzędzie tów czy usług, jak chociażby kampania e-mailowa
sponsorowane czy baner reklamowy. Mogłoby marketingowe. Możemy wybrać bardzo dużą czy banerowa. Trudno jest określić jednoznacz-
się wydawać, że tego typu rozwiązania są już liczbę słów kluczowych, przeprowadzić od- nie, która metoda jest bardziej opłacalna. Gdy ktoś
stosunkowo przestarzałe, ale wciąż dla wielu powiednie statystyki pokazujące nam cenny, a chce szybko wypromować nowy produkt, na pew-
osób stanowią główne miejsce wyszukiwania tym samym popularność różnego rodzaju key- no wybierze zastosowania SEM, natomiast osią-
konkretnych produktów i usług. Jest co naj- wordsów (https://adwords.google.pl/select/Keyword- gnięcie dobrej pozycji, a tym samym stworzenie
mniej kilka aspektów, które przemawiają za ToolExternal). Bardzo dobrym narzędziem, otoczki profesjonalizmu wokół firmy (szczególnie
skorzystaniem z Yellow Pages przy prowa- szczególnie dla średnich firm oferujących swo- firm internetowych) wymaga działań SEO.
dzeniu kampanii SEM. Tego typu katalogi je produkty w regionie, są ustawienia określa-
firm udostępniają dużo łatwiejszą metodę po- jące teren występowania linku sponsorowane-
szukiwania określonych produktów lub usług go, czyli linków sponsorowanych dla użytkow- PIOTR KENIG
na terenie lokalnym. Oferty są posegregowane ników z określonego regionu. Link sponsoro- Piotr Kenig zawodowo zajmującesie projektowaniem
i przejrzyste. Ponadto serwisy YP prowadzą wła- wany składa się z: i tworzeniem stron internetowych. W wolnych chwi-
sną polityke promocji co dodatkowo zwiększa lach stale rozwija swoją wiedzę z zakresu programo-
popularność i prawdopodobieństwo odnalezie- • nagłówka, który może liczyć do 25 zna- wania i marketingu internetowego.
nia naszej oferty. ków; Kontakt z autorem: kenigstudio@gmail.com

www.phpsolmag.org 65
Artykuł warsztatowy

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.

O
dkąd na rynku oprogramowania po- który korzysta z programu i z dostępnych kom- Wygląd interfejsu użytkownika widoczny jest
jawiło się pierwsze narzędzie RAD ponentów. Drugą stroną jest rozwijanie możli- na [Rysunku 1].
dla PHP, o nazwie Delphi for PHP, wości Delphi for PHP poprzez tworzenie no- Po lewej stronie formy mamy dostępny Code-
w umysłach wielu osób pojawiły się pytania. wych komponentów do tej aplikacji. Trzecią Explorer, w którym możemy podejrzeć z czego
Zaczęto dyskutować nad przydatnością tego i zarazem najbardziej zaawansowaną możli- składa się nasza forma. Zaraz pod nim, widzimy
typu narzędzi. wością jest rozwijanie biblioteki VCL. Każ- ObjectInsepctor’a, w którym widzimy wszystkie
Jednak wiele osób wypowiadających się w dys- da chętna osoba może wziąć udział w popra- możliwe opcje konfiguracji, dotyczące zaznaczo-
kusji, nie miało styczności z tym oprogramowa- wianiu błędów, jak i tworzeniu nowych roz- nego elementu lub formy oraz możliwe do ob-
niem i wypowiadało własne opinie w oparciu wiązań. Podział na te trzy grupy użytkowni- służenia akcje związane z obiektem. Natomiast
o ogólnie znane wszystkim stereotypy. Związa- ków można zaobserwować również na stro- po prawej stronie formy widzimy DataExplo-
ne były one bardziej z edytorami WYSWIG dla nie projektu, gdzie każda z grup ma oddziel- rer’a, w którym reprezentowane są informacje
HTML w serii artykułów poświeconych opro- ne strony Wiki. o obsługiwanych w tym momencie bazach danych.
gramowaniu Delphi for PHP stworzonego i roz- W pracy z Delphi for PHP również możemy W naszym przypadku są to MySQL oraz InterBa-
prowadzanego przez firmę CodeGear. wyróżnić trzy różne podejścia. Możemy wyko- se. Pod DataExplorer–em umiejscowiona jest To-
rzystywać je jako zwykły edytor PHP i tworzyć olPallete, w której mamy listę dostępnych do wy-
Poznajmy VCL kod w sposób identyczny jak poprzednio. Mo- korzystania komponentów, które możemy umie-
Przed rozpoczęciem pracy z tym oprogramo- żemy również wykorzystać mix możliwości ścić na formie. Po krótkim zapoznaniu się ze środo-
waniem musimy zadać sobie proste pytanie. PHP oraz VCL. Ostatnim sposobem jest two- wiskiem, powinniśmy pamiętać o ustawieniu ko-
Jak to w ogóle działa? Otóż trzonem całego rzenie aplikacji przy wykorzystaniu wszystkich dowania programu, aby uniknąć później nieprzy-
oprogramowania jest biblioteka VCL. Biblio- możliwości środowiska Delphi for PHP. jemnych niespodzianek w postaci bliżej nieokre-
teka ta jest tak naprawdę freamworkiem, za- Ponieważ Delphi for PHP jest stosunkowo ślonych krzaków zamiast polskich liter. Czynimy
wierającym wiele gotowych komponentów, z nowym projektem, nie ma do niego jeszcze to poprzez opcje w menu Tools–>Options–>Edi-
których możemy zbudować aplikację. W bi- wielu wyspecjalizowanych komponentów, jak tor Options, gdzie musimy zaznaczyć Use UTF–8
bliotece VCL mamy wbudowane inne mniej- to jest w Delphi Builderze, jednak z czasem to create new units and forms. Drugą rzeczą,
sze biblioteki wspomagające tworzenie opro- z pewnością się one pojawią. Należy odnotować o której warto pamiętać, jest zmiana kodowania
gramowania np. NuSoap , qooxdoo , Smarty fakt, iż w przypadku Delphi oraz C++ istnie- w ObjectInspector–>Encoding z domyślnie ustawio-
czy xajax. Jak widzimy przekrój jest całkiem ją firmy, które rozpowszechniają już wyspecja- nej Western European (ISO)|iso–8859–1 na Unico-
spory, ponieważ mamy wbudowany system lizowane komponenty i zarabiają na tym. Ta- de (UTF–8)|utf–8. Po wykonaniu tych czynności
szablonów, jak i biblioteki wspomagające ob- ki rynek, w przypadku Delphi for PHP jeszcze możemy przejść dalej.
sługę ajax, czy też java script. Budowa VCL nie istnieje, ale możemy być pewni, że to tylko Naszym celem będzie stworzenie prostej stro-
przyjmuje strukturę drzewiastą, co oznacza, kwestia czasu. Przed rozpoczęciem pracy z tym ny, którą w następnych artykułach z serii, będzie-
że każdy element jest gałęzią lub liściem po- oprogramowaniem, warto uaktualnić naszą my rozwijać o nowe możliwości. Ponieważ nie ma-
przedniego. Dzięki temu łatwiej jest zorien- bibliotekę VCL. Aktualizacja taka przebiega my jeszcze doświadczenia w wykorzystaniu tego
tować się w możliwościach biblioteki. Syste- w bardzo prosty sposób. Wystarczy tylko po- środowiska, zaczniemy od bardzo prostego projek-
matyka ta ułatwia również naukę osobom, brać bibliotekę ze strony projektu, a następ- tu. Będzie to strona zawierająca księgę gości. Przy
które nie miały z tym wcześniej styczności, nie zastąpić nią stare pliki w folderze Delphi tworzeniu tej strony dodatkowo wykorzystamy
a dla osób, które wcześniej miały okazję po- for PHP. Po tej czynności możemy przystąpić możliwości Smarty, więc znajomość tego systemu
znać VCL w Delphi lub C++ Builderze, bę- już do pracy. szablonów okaże się niezwykle pomocna. Jednak
dzie niezwykle przejrzysta. Należy zaznaczyć, zanim zaczniemy korzystać z oprogramowania,
że całe VCL jest projektem open sourcowym Zaczynamy warto jest je przystosować do własnych potrzeb.
i na dodatek każdy z nas może wziąć udział Pierwsze uruchomienie aplikacji, może zszo-
w procesie jego tworzenia. Delphi for PHP mo- kować osoby nieprzyzwyczajone do środowisk Tworzymy statyczną stronę
żemy poznawać z trzech różnych stron. Pierw- typu IDE. Jednak po przeczytaniu poniższego Przed rozpoczęciem pracy z Delphi for PHP, stwo-
sza i podstawowa, to jako zwykły użytkownik, opisu, każdy powinien poczuć się jak w domu. rzymy nasz szablon, z którego będziemy korzystać

66 06/2007
Delphi for PHP

podczas tworzenia strony. Każdy szablon Smarty, Mamy już wszystkie potrzebne części dla naszej z bazy danych. Na początek umieścimy na na-
aby móc współpracować z naszym oprogramowa- strony. Czas więc złożyć stronę główną w całość. szej formie trzy komponenty Edit. Uczynimy
niem, musi zawierać w sobie określone zmienne. Klikamy w formę, a następnie w ObjectInspec- to przeciągając komponent Edit z Tool Pallete
Najprostszy działający szablon, który nie jest opa- tor–>TemplateEngine, wybieramy z dostępnych bezpośrednio na formę lub poprzez podwój-
trzony żadną grafiką, ale będzie działać, ma postać opcji interesujący nas szablon. W tym wypadku ne kliknięcie. Umieszczenie ich na formie nie
widoczną na listingu 1. jest to jedyny domyślnie dostępny szablon, czy- ma żadnego znaczenia, ponieważ będziemy
Podane na nim zmienne Smarty są niezbęd- li Smarty. Jednak w przyszłości pojawią się kolej- i tak korzystać ze specjalnie przygotowanego
ne do działania. W analogiczny sposób będzie- ne. Następnie musimy wskazać szablon, który zo- szablonu. Rozmiar każdego z komponentów
my dołączać do szablonu niezbędne kompo- stanie połączony z naszą stroną. Aby to zrobić wy- możemy dowolnie modyfikować poprzez roz-
nenty Delphi for PHP, ale o tym później. Po bieramy ObjectInspector–>TemplateFilename, gdzie ciągania przy pomocy myszki lub kliknięcie
ustaleniu podstaw związanych ze Smarty, mo- wskazujemy nasz szablon index.tpl, znajdujący w komponent znajdujący się na formie i wpro-
żemy przejść do połączenia obu systemów się w folderze template. Ostatnim krokiem, który wadzanie wartości w ObjectInsepctor–>Width
i pierwszego wyświetlenia strony. dzieli nas od zobaczenia wyniku naszej pracy jest lub Height. Każdy z wprowadzonych przez nas
Każdy projekt rozpoczynamy zawsze w ten po prostu wciśnięcie opcji w menu Run–>Run komponentów Edit ma przydzieloną dynamicz-
sam sposób, tzn. poprzez kliknięcie w menu File lub po prostu [F9], w efekcie czego zobaczymy na- nie nazwę, widoczną w ObjectInspector–>name.
–>New–>Application. W efekcie otrzymujemy szą piękna stronę widoczną na rysunku 2, na któ- W naszym przypadku będzie to Edit1, Edit2,
projekt z pierwszą formą, na której umieszczać rej wykonanie nie poświeciliśmy nawet pięciu mi- Edit3. Korzystanie z takiego nazewnictwa mo-
będziemy komponenty wykorzystane w naszej nut. Każdy, kto miał wcześniej styczność ze Smar- że być niewygodne. Dlatego zmienimy je edy-
aplikacji.Dobrymnawykiem,przedrozpoczęciem ty wie, że pierwsze uruchomienie Smarty może tując pole ObjectInspector–>name na następują-
pracy z nowym projektem, jest zapisanie go po- nie jednemu sprawić problem, jednak w przypad- ce title, author, content. Nazwy te są zdecydowa-
przez File–>Save Project As. Zapis w tym przy- ku Delphi for PHP obsługa staje się bardzo prosta nie łatwiejsze do zapamiętania oraz wykorzy-
padku będzie dotyczyć dwóch plików. Pierw- i intuicyjna. stania. Do zatwierdzenia formularza potrzebny
szym plikiem będzie plik o rozszerzeniu php, będzie nam również jakiś przycisk. Umieści-
który nazwiemy index.php i zapiszemy w specjal- Tworzymy stronę dynamiczną my jeden komponent Button. W jego przypad-
nie utworzonym przez nas katalogu o nazwie we- Po nacieszeniu oka naszą pierwszą stroną, nad- ku nie będziemy zmieniać parametru name
bpage. Drugim plikiem będzie plik projektu, któ- szedł czas na kolejny krok. Przydałoby się, aby a zmienimy parametr Caption dostępny w Ob-
ry nazwiemy webpage.phprj . Następnie musi- strona wykorzystywała możliwości PHP. Stwo- jectInspector–>Caption, w którym zmieniając
my zmienić jeszcze nazwę formy w ObjectInspec- rzymy więc podstronę zawierającą bardzo prostą
tor–>name na wartość index. Po wykonaniu tych księgę gości. Tworzymy nową formę poprzez
czynności możemy przejść do tworzenia naszej File–>New–>Form i zapisujemy ją jako guestbook.
aplikacji. Założymy, że pierwsza strona ma za- php, a następnie zmieniamy w ObjectInspector
wierać jedynie treść statyczną, bez generowanej –>name na wartość guestbook. W tym przypadku
poprzez PHP treści dynamicznej. Będziemy mu- zaczniemy od zdecydowania, jakie komponenty
sieli skorzystać w tym celu, z wcześniej przygoto- będą nam potrzebne, a następnie umieścimy je na
wanego szablonu, który dołączony jest na płycie. formie. Po tych czynnościach utworzymy nasz sza-
Aby, zachować pewien porządek utworzymy od- blon oraz wyświetlimy stronę z księgą gości i doko-
powiednią strukturę katalogów. W folderze we- namy pierwszego wpisu. Rysunek 2. Nasza pierwsza strona
bpage, utworzymy folder template, który będzie Każda typowa strona księgi gości zawiera for-
przechowywać nasze szablony oraz ich arkusze mularz, poprzez który dodajemy wpisy oraz
stylów i grafiki. wyświetla wcześniejsze posty, odczytując je

Rysunek 3. Komponenty wchodzące w skład


księgi gości

Rysunek 1. Interfejs użytkownika Delphi for PHP Rysunek 4. Prosta księga gości

www.phpsolmag.org 67
Artykuł warsztatowy

wartość zmieniamy napis widoczny na przyci- którym wypełniamy niezbędne dane. Po zaakcep- sób możemy umieszczać wszystkie inne kompo-
sku. Zmienimy w ten sposób domyślny napis towaniu formularza na liście DataExplorer’a poja- nenty dostępne w Tool Palette.
Button1 na Wyślij. Mamy już umieszczone na wi się nasze połączenie. Teraz, aby wykorzystać je Mamy już formularz, ale nie wiemy co sta-
formie komponenty związane z formularzem. do ustanowienia połączenia z bazą danych wystar- nie się po naciśnięciu przycisku wyślij. W tym
Pozostał nam jeszcze do umieszczenia najważ- czy, że przeciągniemy nasz element z listy na for- momencie, wykorzystamy kolejne usprawnie-
niejszy komponent, związany z połączeniem do mę, w efekcie czego otrzymamy już skonfigurowa- nie Delphi for PHP. Oprogramujemy zdarzenie
bazy danych. W naszym przypadku będziemy ny komponent Database. Omówione wyżej dzia- OnClick dla przycisku. Możemy to zrobić rów-
zainteresowani komponentami związanymi z ba- łanie zaoszczędzi nam pracy przy każdorazowym nież na dwa sposoby. Pierwszym jest wybranie
zą danych MySQL. Odpowiedni komponent mo- konfigurowaniu połączenia, na każdej nowej for- w ObjectInspektorze zakładki Events a tam nasze-
żemy umieścić na formie na dwa sposoby. Pierw- mie. Umieszczając ten komponent na formie ze- go zdarzenia. Drugim i znacznie szybszym spo-
szym z nich jest przeciągnięcie komponentu z Tool braliśmy już wszystkie niezbędne elementy do sobem osiągnięcia tego samego celu jest po pro-
Palette o nazwie Database, którego parametry po- działania naszej księgi gości. Efekt dotychczasowej stu podwójne kliknięcie na przycisk umieszczo-
łączenia konfigurujemy następnie za pomocą Ob- pracy widoczny jest na Rysunku 3. ny na formie. Po wykonaniu, jednej z wyżej omó-
jectInspector’a, wprowadzając zgodne z konkret- Zajmiemy się teraz przygotowaniem szablo- wionych akcji, zostaniemy przeniesieni do dru-
nym przypadkiem wartości DatabaseName, Host, nu Smarty, na którym, w wygodny dla nas spo- giego widoku naszej formy. Tym razem operuje-
UserName, UserPassword oraz zmieniając wartość sób, umieścimy formularz. Tworzymy nowy sza- my naszą formą od strony kodu. Możemy prze-
Connected na true. Po wykonaniu tych czynności blon o nazwie guestbook.tpl. Każdy z komponen- mieszczać się pomiędzy obydwoma widokami,
będziemy mieć dostępne połączenie z bazą da- tów umieszczamy w szablonie, poprzez umiesz- poprzez zakładki widoczne u dołu strony o na-
nych. Możemy ten sam cel osiągnąć w inny dużo czenie w nim zmiennej o nazwie komponen- zwach Code oraz Design lub przy pomocy klawi-
bardziej przyjazny sposób. Do tego celu będziemy tu. Dla naszych komponentów o nazwie title, au- sza [F12]. W widoku kodu możemy rozpocząć
musieli wykorzystać DataExplorer, w którym zde- thor, content będziemy musieli zastosować zmien- edycję zdarzenia. W tym przypadku została wy-
finiujemy połączenie z bazą danych MySQL. Czy- ne {$title}{$author} oraz {$content}, co wi- generowana metoda o nazwie Button1Click, we
nimy to poprzez kliknięcie na ikonę delfina przy doczne jest na Listingu 2. Czynność ta jest bardzo wnętrzu której definiujemy naszą akcję. Pożąda-
napisie MySQL prawym przyciskiem myszy i wy- prosta i nie powinna sprawić problemu nawet po- ną akcją, po naciśnięciu przycisku, będzie u nas
branie z podręcznego menu opcji Register Databa- czątkującemu programiście. W miejscu umiesz- zapis do bazy danych wartości przekazanych po-
se. My, jako nazwę połączenia podamy delphi4php. czonych zmiennych Smarty pojawią się kompo- przez formularz. Tabelę, w której będziemy gro-
W efekcie tego działania otrzymujemy okienko, w nenty ułożone na naszej formie. W ten sam spo- madzić wpisy gości, należy utworzyć przy po-
mocy zapytania widocznego na [Listingu 3].
Listing 1. Najprostsza konstrukcja szablonu Smarty współpracująca z Delphi for PHP Gdy dysponujemy już taką tabelą, możemy
przejść do zapisu otrzymanych ze strony da-
<html> nych. Delphi for PHP do komunikacji z bazą
<head> danych korzysta z ADO, dzięki czemu zacho-
<meta http-equiv="content-type" content="text/html; charset=utf-8" /> wując odrobinę samodyscypliny przy tworze-
<title></title> niu zapytań do bazy danych, możemy sprawić,
<meta name="keywords" content="" /> że nasza aplikacja będzie działać zarówno pod
<meta name="description" content="" /> MySQL jak i np. Oracle jedynie po zmianie ste-
{HeaderCode} rownika. Realizacja zapisu do bazy danych jest
</head> widoczna na [listingu 4]. Po zapisie do bazy da-
<body> nych należy również wyczyścić wartość pól tek-
{$StartForm} stowych, co robimy przy pomocy metody set-
{$EndForm} Text(), dla której przekazujemy puste stringi.
</body> – (czy na pewno stringi)?
</html> Jak łatwo zauważyć, stworzony kod jest zwy-
kłym kodem PHP, a co za tym idzie, nie musi-
Listing 2. Umieszczanie komponentów z Delphi for PHP w szablonie Smarty my uczyć się jakiegoś nowego języka, aby móc
<form action="" method="post"> korzystać z tego oprogramowania. W reakcji na
Tytuł<br/> wciśnięcie przycisku, co równoznaczne jest za-
{$title}<br/> akceptowaniu formularza, przygotowujemy za-
Autor:<br/> pytanie SQL. Zabezpieczamy zmienne przeka-
{$author}<br/> zane w tablicy $_POST, a następnie zapisujemy
Wpis:<br/> je do bazy danych. Za komunikację z bazą da-
{$content}<br/> nych odpowiada egzemplarz ADO o nazwie
{$Button1}<br/> $dbdelphi4php1 i to właśnie za jego pośrednic-
</form> twem musimy wykonywać wszystkie interak-
cje. Kod jest bardzo prosty, a napisanie go rów-
Listing 3. Zapytanie tworzące tabele z wpisami gości naszej strony nież nie zabrało nam dużo czasu.
create table `guestbook`( Mamy już zapis do bazy danych. Nadszedł
`id` int unsigned not null auto_increment primary key, czas na wyświetlenie wpisów zgromadzonych
`title` char(255) not null, w bazie na naszej stronie. Aby wyświetlić jakieś
`author` char(255) not null, dane pobrane z tablicy, będziemy musieli sko-
`content` text not null, rzystać ze specjalnego zdarzenia OnTemplate,
`date` datetime not null utworzonego w celu współpracy z szablonami.
); Zdarzenie to jest dostępne jedynie dla formy.
Znajdziemy je w ObjectInspectorze w zakładce

68 06/2007
Delphi for PHP

zard. Pojawi się wtedy kreator, w którym właściwie


Listing 4. Zapis do bazy danych w reakcji na kliknięcie przycisku naszym jedynym zadaniem jest określenie ścieżki
function Button1Click($sender, $params) zapisu oraz klikanie next. Jednak po wykonaniu
{ tej akcji musimy jeszcze pamiętać o przeniesieniu
$query='INSERT INTO `guestbook` (`title`,`author`,`content`,`date`) szablonów oraz grafik, bo tego Delphi for PHP już
VALUES (?,?,?,NOW())'; za nas nie zrobi. Drobną niespodzianką jest rów-
$title=addslashes(htmlspecialchars($_POST['title'])); nież nie przenoszenie w tym procesie folderu
$author=addslashes(htmlspecialchars($_POST['author'])); Smarty z biblioteki VCL, ale tak naprawdę trudno
$content=addslashes(htmlspecialchars($_POST['content'])); jest określić, czy jest to działanie zamierzone, czy
$array=array($title,$author,$content); też niewielkie nie dopatrzenie. Nie mniej jednak
$this->dbdelphi4php1->Prepare($query); pamiętajmy, aby zrobić to samemu. Po wykona-
$this->dbdelphi4php1->execute($query,$array); niu tych czynności, musimy jedynie przenieść na-
$this->title->setText(''); szą stronę na serwer i możemy już wtedy wysyłać
$this->author->setText(''); link do znajomych.
$this->content->setText('');
} Podsumowanie
Korzystając z Delphi for PHP stworzyliśmy w bar-
Listing 5. Zebranie informacji o wpisach gości i wysłanie ich do szablonu Smarty dzo prosty sposób prostą stronę, której główną
function Unit6Template($sender, $params) atrakcją jest księga gości. Stworzenie takiej stro-
{ ny w tradycyjny sposób wymagałoby dużo więk-
$query="SELECT * szego nakładu pracy, a co za tym idzie i czasu.
FROM `guestbook` Sprawny użytkownik, wykorzystując to opro-
ORDER BY `date` DESC"; gramowanie, byłby w stanie stworzyć taką stro-
$result=$this->dbdelphi4php1->execute($query); nę w czasie pięciu minut. Tradycyjnymi meto-
foreach($result as $guest) dami nie byłoby to możliwe. Delphi for PHP po-
{ zwala na tak szybka pracę, ponieważ nie zmusza
$guests[]=$guest; nas do implementowania dobrze znanych i czę-
} sto powielanych rozwiązań. Najlepszym przy-
$template=$params['template']; kładem tego typu jest dostęp do bazy danych.
$template->_smarty->assign('guests',$guests); W tradycyjnych metodach programowania, mu-
} sielibyśmy oprogramować połączenie. Natomiast
w Delphi for PHP całe nasze działanie polega je-
Listing 6. Wyświetlenie wszystkich wpisów znajdujących się w naszej księdze gości dynie na wprowadzeniu danych dostępowych
{section name=i loop=$guests} oraz na przeciągnięciu komponentu na formę.
<div class="post"> Możemy jasno określić, że tak naprawdę wszyst-
<p class="date">{$guests[i].date|truncate:10:''}</p> kie działania zostały ograniczone do niezbędne-
<h1 class="title">{$guests[i].title}</h1> go minimum, jakie musi wykonać użytkownik.
<div class="entry"> To samo podejście możemy zaobserwować rów-
{$guests[i].content}<br/> nież podczas wykorzystywania szablonu Smar-
<span style="font-size:0.8em;padding:5px;">{$guests[i].author}</span> ty. Zazwyczaj przed pierwszym uruchomie-
</div> niem Smarty, musieliśmy tworzyć klasę dziedzi-
</div> czącą po głównej klasie Smarty, aby ustawić da-
{/section} ne konfiguracyjne, jednak w przypadku Delphi
for PHP nie musimy się o to martwić. W arty-
kule tym mamy do czynienia z bardzo prostym
Events. Po wyborze tego zdarzenia zostanie wy- Konstruując tę pętlę zebraliśmy wszystkie przykładem, dzięki czemu łatwiej będzie nam
generowana metoda GuestbookTemplate, w któ- elementy potrzebne do działania naszej księgi rozpocząć swoja przygodę z tym oprogramowa-
rej zawrzemy cały kod odpowiedzialny za wy- gości. Pozostało jedynie połączenie wszystkiego niem. Wykorzystaliśmy tutaj jedynie podstawo-
świetlenie wpisów. Kod odpowiedzialny za ze- w całość. Szablon zapisaliśmy pod nazwą guest- we elementy, a należy pamiętać, że do wykorzy-
branie informacji i wysłanie ich do naszego sza- book.tpl w folderze template. Łączymy go z pli- stania i przetestowania zostało jeszcze całe mnó-
blonu widoczny jest na [listingu 5]. kiem guestbook.php, tak samo jak poprzednio, stwo komponentów korzystających np. z ajaxa,
Za utworzenie uchwytu do szablonu odpo- a następnie uruchamiamy oraz dodajemy przy- co powinno tym bardziej zachęcić do pozna-
wiada fragment kodu $template=$params['tem kładowy wpis o dowolnej treści. Efekt naszej nia tej aplikacji. Chcąc skorzystać z ajax–a wca-
plate']; natomiast za utworzenie nowej zmien- pracy widoczny jest na [rysunku 4]. le nie musimy go znać. Jedyne co naprawdę mu-
nej w szablonie odpowiada kod $template–>_ W ten sposób ukończyliśmy nasz pierwszy pro- simy u mieć, to po prostu klikać oraz czytać do-
smarty–>assign('guests',$guests);. Możemy jekt. Jednak powinniśmy jeszcze wiedzieć, któ- kumentację, która coraz intensywniej rozwija się
w ten sposób przekazać do szablonu dowolną licz- re pliki skopiować, aby umieścić go na serwerze. na stronie biblioteki VCL.
bę własnych zmiennych, które następnie musimy Dobrą wiadomością jest to, że nie musimy się o to
wyświetlić. Jako, że do szablonu przekazaliśmy ca- martwić, ponieważ Delphi for PHP ma wbudowa-
łą tablicę wyników, będziemy musieli obsłużyć ją ny w sobie dodatek, który za nas zbierze niezbęd- ŁUKASZ SKOWROŃSKI
przy pomocy pętli wbudowanej w Smarty o na- ne elementy i umieści je w wybranym przez nas Autor jest studentem informatyki na Uniwersytecie
zwie section. Fragment szablonu odpowiedzialny katalogu, który następnie musimy przenieść na w Białymstoku, pracuje również jako programista
za wyświetlenie zawartości tej tablicy jest widocz- nasz serwer. Aby skorzystać z tej funkcjonalności PHP w firmie E-Studio.
ny na [Listingu 6]. musimy wybrać w menu Tools–>Deployment Wi- Kontakt z autorem: lukas.skowronski@gmail.com

www.phpsolmag.org 69
Testy konsumenckie

Testy konsumenckie
UPS

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.

lowalność zespołu baterii, umożliwiająca wy- dodatkowych oraz port komunikacyjny DB-9
dłużenie czasu autonomii w przypadku ocze- zabudowane są na tylnym panelu. Istotnym
kiwanej, zwiększonej dostępności usługi oraz elementem wyróżniającym tą rodzinę zasila-
konstrukcja pozwalająca na instalację zasila- czy, jest wbudowany wejściowy układ PFC,
cza jako wolnostojący lub w szafie 19”, w za- który zapewnia wysoki cosφ = 0,97 i ogra-
leżności od wymagań klienta. Ze względu na nicza poziom zniekształceń wprowadzanych
dużą skalę projektu potrzebna była wyso- do sieci. Ma to wpływ na coraz częściej po-
ka niezawodność urządzenia. Przy wyborze strzeganą tzw. ekologię sieci zasilającej. Bar-
sprzętu, braliśmy pod uwagę zarówno jakość dzo szeroki zakres napięć wejściowych oraz
zasilacza, jak i dostępność serwisu. Mając złe częstotliwości pozwala na znaczne wydłu-
doświadczenia wiedzieliśmy, że tanie i pro- żenie czasu eksploatacji baterii, której ży-
ste rozwiązania po pewnym okresie ulegają wotność w dużej mierze zależy od ilości cy-
awariom. Przez to, nie tylko generują koszty kli wyładowania i ładowania. Zaletą jest też
Tomasz Idczak napraw, ale wstrzymują realizacje usługi dla łatwa wymiana baterii „na gorąco”, co nie
klienta, czego rezultatem jest utrata przycho- wymaga odłączania w tym czasie odbiorów
Kierownik technologii zasilania i klimatyzacji Netia S.A.
dów oraz dobrego wizerunku operatora. klienta. Zasilacze GXT2U wyposażone są w

N
etia S.A. jest największym niezależ- Po przeprowadzeniu analizy dostępnych gniazdo, do zainstalowania karty sieciowej
nym operatorem telefonii przewo- na rynku zasilaczy oraz ich cen, wybrana zo- SNMP/WEB, zapewniające zdalną kontrolę
dowej w Polsce. Świadczy stacjonar- stała rodzina jednofazowych zasilaczy UPS i diagnostykę zasilacza oraz przesyłanie tra-
ne usługi telekomunikacyjne w całym kraju. GXT2U700-3000 o mocach od 700VA i pów alarmów do centrum nadzoru opera-
Oferta Netii, obok usługi głosowej obejmuje 3000VA firmy Liebert, wchodzącej w skład tora. Umożliwia to podjęcie adekwatnych
dostęp do Internetu po liniach analogowych Grupy Emerson Network Power. działań do rodzaju awarii, co jest szczegól-
i cyfrowych, hosting, usługi 0800, 0700, Zasilacze GXT2U zbudowane są w opar- nie istotne przy dużej ilości instalacji i znacz-
0300 oraz zaawansowane usługi Netia Frame ciu o technologię VFI, na bazie podwójnej nej rozległości sieci. Z zastrzeżeń, jakie moż-
Relay, Integralnet, łącza dzierżawione i usłu- konwersji i przeznaczone są do ochrony kry- na mieć do zasilacza to poziom hałasu, któ-
gi dla operatorów Netia Carrier. Netia współ- tycznych odbiorów przed wszystkimi rodza- ry może dochodzić do 55dBA z tyłu, w odle-
pracuje z czwartym operatorem telefonii ko- jami zakłóceń, jakie mogą pojawić się od stro- głości 1m od urządzenia i może być uciążli-
mórkowej PLAY przy budowie sieci UMTS. ny sieci energetyki zawodowej. Uniwersal- wy w przypadku długiego przebywania w je-
Obecnie z usług dostępu do Internetu Netii na konstrukcja UPS pozwala na jego mon- go sąsiedztwie.
korzysta blisko 140 tysięcy klientów, a celem taż w szafie 19”, w której, w podstawowej Wybór zasilaczy UPS GXT2U700 był ko-
firmy jest pozyskanie miliona internautów konfiguracji zajmuje tylko 2U lub pionowo, lejnym krokiem współpracy Grupy Netia z
do roku 2009. jako wolnostojący na specjalnej podstawie. Emerson Network Power. Pierwsza umowa
Podczas realizacji projektu szerokopa- Do zasilacza mogą być dołączane dodatko- ramowa na dostawę i montaż systemów za-
smowego radiowego dostępu do Internetu we, zewnętrzne moduły baterii akumulato- silania napięciem stałym podpisana została
dla klientów biznesowych, pojawił się wy- rów. Od jednego do czterech, każdy o wyso- w 1997r. Cena adekwatna do jakości zasila-
móg zapewnienia zasilania awaryjnego o na- kości 2U, przedłużający czas podtrzymania cza, była dodatkowym elementem na etapie
pięciu 230V dla terminali instalowanych u zasilania odbiorów, co pozwala spełnić zróż- wyboru. Dobry produkt, krótki czas dosta-
klientów. nicowane oczekiwania naszych klientów. Za- wy, dostępność serwisu naprawczego, kom-
W pierwszym etapie wyspecyfikowane zo- silacz charakteryzuje nowoczesny design, na petentne wsparcie techniczne oraz dobre do-
stały podstawowe wymagania dla zasilacza płycie czołowej świecące się diody w przej- świadczenia z dotychczasowej współpracy,
UPS, takie jak: zakres mocy pozornej, topo- rzysty sposób obrazują aktualny stan pracy pozwalają na przyznanie wysokiej oceny w
logia zasilacza, czas autonomii, autostart po zasilacza. odniesieniu do całego projektu.
powrocie zasilania oraz możliwość zdalnego Gniazdo zasilania sieciowego, cztery gniaz-
Ocena:: «««««
Ocena «««««
nadzoru. Dodatkowymi wymogami były ska- da wyjściowe typu IEC320, gniazda baterii

70 06/2007
UPS

łu bezpieczeństwa sieciowego (oprogramowa- nych w naszej firmie, solidne i bezawaryjne, z


nie oraz sprzęt – MKS VIR, Symantec, F–Se- możliwością zarządzania poprzez sieć kompu-
cure, SonicWall) oraz działu rozwiązań tele- terową, z co najmniej dwuletnią gwarancją i pol-
komunikacyjnych (połączenie VOIP oraz PBX skim serwisem. Zasilacze Emerson Network Po-
– Avaya, Funkwerk). Dynamicznie rozwijają- wer z grupy PSI oraz GXT2 w zakresie mocy od
cym się działem są produkty tzw. personal ID 1440 do 3000 VA, spełniają z nadwyżką nasze
– skanery, systemy RFID, drukarki termicz- wymagania, ponieważ oprócz wyżej wymienio-
ne – Symbol, Zebra, Motorola, O'Neal. Nasza nych funkcji, oferują możliwość dokładania ba-
firma pomaga swym partnerom, za pośrednic- terii dodatkowych wydłużających czas podtrzy-
twem spersonalizowanych stron WWW, wspar- mania zasilania oraz możliwość montażu w sza-
cia inżynierów systemowych oraz poprzez orga- fie 19" – wszystko to w standardowej cenie urzą-
nizację różnego rodzaju szkoleń – także w róż- dzenia. Zdecydowanie spełniły one zadanie pod-
nych miastach Polski. W związku z tym, poja- trzymywania serwerów dla aplikacji, poczty in-
wiła się potrzeba posiadania niezawodnych sys- ternetowej oraz strony WWW dla naszych part-
temów informacyjnych – zarówno od strony nerów. UPS-y z rodziny PSI znalazły zastosowa-
sprzętu komputerowego (serwery, macierze dys- nie do serwerów montowanych w szafach 19"
ków), jak i zasilania awaryjnego pozwalającego – zastosowana technologia line–interactive jest
na ciągły i bezpieczny dostęp do danych, a tak- wystarczająca do zasilania wszelkiego rodzaju
że zabezpieczenie przed ich utratą w razie bra- komputerów – także serwerów. Mają też moż-
Tomasz Pawelski ku zasilania. W ramach rozwijania naszej ofer- liwość zarządzania nimi za pośrednictwem por-
Product Manager 3Com, Allied Telesis, APC, Liebert ty poznaliśmy między innymi produkty Emer- tu USB lub RS232, dołączone jest również opro-
RRC Poland Sp. z o.o.
son Network Power, jako element zabezpiecze- gramowanie do zdalnego zamknięcia serwerów

F
irma RRC Poland Sp. z o.o. istnieje na nia sieci komputerowych od strony ich zasilania. w razie braku zasilania. UPS-y z rodziny GXT2 z
rynku polskim od 1992 roku. Zaczy- Ich oferta, z punktu widzenia zaplecza badaw- powodu zastosowania w nich technologii on–li-
nała jako dystrybutor rozwiązań firmy czo–rozwojowego oraz oferty produktowej, wy- ne (zerowy czas przełączania na baterie) służą
3Com. Jako RRC Enterprise Networking jest dała nam się atrakcyjna zarówno pod względem do zasilania zewnętrznych macierzy dyskowych
obecnie dystrybutorem technologii informa- zastosowanych rozwiązań, jak i poziomu cen, w oraz urządzeń wrażliwych nawet na najmniejsze
tycznych, głównie z zakresu rozwiązań siecio- porównaniu z konkurencją o podobnym pozio- zaniki napięcia. Używane są w wersji wolnosto-
wych oraz serwerowych. W ofercie firmy są pro- mie technologicznym. Emerson Network Power jącej, istnieje możliwość, w razie potrzeby, doku-
dukty takich firm jak Cisco Systems, 3Com, Al- to ogólnoświatowy dostawca rozwiązań związa- pienia do nich zestawu do zainstalowania w sza-
lied Telesis, Zyxel czy Funkwerk. Oferta serwe- nych z zasilaniem – od małych zastosowań biu- fie 19". Zasilacze pracują cicho, co nie jest bez
rowa oraz storage oparta jest na sprzęcie IBM. rowych czy domowych do wielkich centrów da- znaczenia dla pracujących w pobliżu ludzi.
W zeszłym roku zapoczątkowany został roz- nych. W kręgu naszych zainteresowań znalazły
Ocena
Ocena:: «««««
«««««
wój dwóch nowych nisz technologicznych: dzia- się zasilacze awaryjne do serwerów zainstalowa-

klimatyzacji precyzyjnej marki Hiross oraz silacze awaryjne od 0 do 30 kVA. Pozostałe


UPS-y marki Liebert. Obecnie wszystkie pro- oferowane rozwiązania to, m.in. siłownie dla
dukty oferowane są pod jedną marką – Emer- operatorów telekomunikacyjnych, straży gra-
son. Typowe zastosowania klimatyzacji precy- nicznej czy policji. Emerson kupił te produk-
zyjnej to centrale telekomunikacyjne. Emer- ty poprzez akwizycję: przejmując część fir-
son Network Power jest dostawcą klimatyzacji my Ericsson i firmy Nortel. Obecnie, wspól-
precyzyjnej dla Telekomunikacji Polskiej SA, nie z partnerem technologicznym, polską fir-
Polkomtela, Polskiej Telefonii Cyfrowej, Netii i mą Telzas, obsługuje Polkomtela. Kolejne pro-
Energisu. Wyposaża również większość serwe- dukty to duże rozwiązania związane z trans-
rowni oraz centrów danych w Polsce. misją i zabezpieczenia przeciwzwarciowe.
Niemal wszystkie zarejestrowane w Polsce Różnego typu szafy i obudowy – są to rozwią-
banki: PKO SA, PKO BP, Kredyt Bank, Bank zania do montażu różnych urządzeń. Kluczo-
Millenium, Raiffeisen Bank Polska, a także wym elementem pozostaje jednak zasilanie.
ministerstwa oraz różne instytucje samorzą- Niektóre urządzenia produkowane są na za-
dowe, mają urządzenia Emerson Network Po- sadzie OEM dla innych producentów, np. za-
wer. Emerson dostarcza także urządzenia dla silacze do różnego typu sprzętu, kable USB i
przemysłu, np. dla kopalni, cementowni, elek- światłowodowe – oferowane w szerokiej ska-
trowni, zakładów energetycznych oraz w prze- li na rynku, często pod markami dystrybuto-
myśle drukarskim, czego przykładem jest Pań- rów. „Prawdopodobnie znacie Emerson bar-
Ustosunkowanie
Cezary Gutowski
stwowa Wytwórnia Papierów Wartościowych. dziej, niż wam się wydaje” – mówi Dyrek-
Kierownik Sprzedaży UPS-ów małej i średniej mocy Spółka jest wiodącym dostawcą klimatyzacji tor Generalny Emerson w Polsce – Małgorza-
w Emerson Network Power precyzyjnej na obszarze Polski, zaopatruje ok. ta Kasperska.
40% rynku. Opinie naszych klientów są dla nas powo-

E
merson Network Power, część koncer- UPS-y obsługują zakres mocy od 0 do 800 dem do dumy. Rekomendacje od tak znakomi-
nu Emerson Electric, to spółka zareje- kVA. Marka Liebert znana jest z UPS-ów tych firm jak Netia S.A. czy RRC Poland Sp. z
strowana w Polsce od 2000 r., choć ofe- o dużej mocy, czyli głównie specjalistom z o.o., liderów w swoich branżach, nie tylko wy-
rowane przez nią produkty znane są na pol- branży elektrycznej, którzy zajmują się roz- różniają nas na rynku ale i obligują do ciągłe-
skim rynku już od lat 70, w tym urządzenia wiązaniami o większej skali. Nowością są za- go doskonalenia naszych produktów i usług.

www.phpsolmag.org 71
Testy konsumenckie

UPS-y Emerson Network Power marki Lie- Trudno też o lepszą rekomendację niż to, syfikujemy działania, mające na celu dotarcie
bert, to sprzęt z najwyższej półki, biorąc pod że jeden z największych w Europie Środkowej z naszą ofertą do klientów z sektora MŚP na
uwagę kryteria takie jak: jakość i niezawod- i Wschodniej dostawców produktów siecio- obszarze całej Europy. Rozbudowanie kanału
ność. Nie spoczywamy jednak na laurach. Do- wych i telekomunikacyjnych, mający w swej partnerskiego pełni dla nas kluczową rolę w
wodem są kolejne udogodnienia dla naszych ofercie między innymi UPS-y – firma RRC realizacji tego zadania.
obecnych i przyszłych klientów. Najnowszą – na swój własny użytek wybrała właśnie UPS- W roku 2007 planujemy w Polsce, na Litwie,
propozycją jest oferta „3 lata przez 3 miesią- y spod znaku Liebert, marki należącej do Emer- Łotwie i Estonii podpisać umowy z wiodącymi
ce” polegająca na wydłużeniu do 3 lat okresów son Network Power. dystrybutorami IT oraz rozpoczniemy rekru-
gwarancyjnych na wybrane UPS-y GXT2 i PSI Warto podkreślić, że UPS-y które oferuje- tację partnerów do przygotowanego programu
zakupione do końca października 2007. Nie my obecnie w Polsce, i dedykujemy szczegól- resellerskiego. Podstawowe wartości jakie ofe-
przez przypadek, właśnie te modele wybra- nie małym i średnim przedsiębiorstwom, ce- rujemy, to relatywnie wysoka dla tego segmen-
li, jako element systemu bezpieczeństwa biz- chuje ta sama jakość i niezawodność, z której tu marża i produkty zaliczane, ze względu na
nesu, rekomendujący nas klienci – Netia S.A. znane są nasze rozwiązania typu Power, sto- parametry takie jak jakość i niezawodność, do
i RRC Poland. sowane w największych centrach danych na tych „z najwyższej półki”.
To, w jaki sposób reagujemy na potrzeby na- świecie. Można porównać je do polisy, któ- Cezary Gutowski od stycznia 2007 r. objął
szych partnerów, opracowujemy indywidualne ra gwarantuje ciągłość funkcjonowania urzą- stanowisko Kierownika Sprzedaży zasilaczy
rozwiązania, doradzamy i dbamy o bezpieczeń- dzeń o krytycznym znaczeniu dla każdego awaryjnych UPS małej mocy marki Liebert
stwo aplikacji o krytycznym znaczeniu, spra- biznesu. (do 30 kVA) w polskim oddziale Emerson Ne-
wia, że pozostają z nami na lata. Przykładem Emerson Network Power to firma, która od twork Power. Jest odpowiedzialny za rozwój
zaufania, które procentuje, jest ponad 10-letnia wielu lat, na całym świecie, dostarcza rozwią- sprzedaży zasilaczy UPS Liebert w kanałach
współpraca firmy Emerson Network Power z li- zania zasilania awaryjnego i klimatyzacji dużej dystrybucyjnych branży informatycznej oraz
derem rynku telekomunikacyjnego w Polsce, skali, o krytycznym znaczeniu dla klientów z elektrycznej.
firmą Netia S.A. każdego sektora gospodarki. Obecnie inten-

Bardzo istotną część oferty AJM, stanowią naszego obecnego partnera oraz szeroka ofer-
produkty firmy ATEN - czołowego producen- ta produktowa. Zasilacze UPS ETA charakte-
ta przełączników KVM na świecie. Od 1997 ryzują się bardzo dobrym współczynnikiem ce-
r. jesteśmy jej autoryzowanym dystrybutorem. na / jakość. Producent oferuje je w kilku pod-
Obok podstawowej linii produktów, oferujemy stawowych odmianach, o mocach od 720VA
także, stworzoną przez ATEN, linię zaawanso- do 250kVA. Wszystkie modele charakteryzu-
wanych systemów KVM, dostępnych pod mar- ją się zwartą, solidną konstrukcją oraz estetycz-
ką ALTUSEN. nym wyglądem. Oferta jest na tyle atrakcyjna,
AJM Electronics to także szafy instalacyjne, że pozwala zaspokoić praktycznie każdą potrze-
których oferta jest z roku na rok bogatsza. Ofe- bę naszych klientów.
rujemy przede wszystkim rozwiązania GFlex w Nie bez znaczenia jest fakt, że ETA to uzna-
wielu odmianach. Jesteśmy wyłącznym przed- ny gracz na rynku, który budzi zaufanie. Zna-
stawicielem tej marki w Polsce. Dostępne są u cząco ułatwia nam to zwiększenie sprzedaży.
nas szafy wiszące, stojące, dzielone o różnych Dodatkowo, oparte na długoletnim doświad-
głębokościach i wersjach wykonania, szafy z bo- czeniu, rozwiązania ETA umożliwiają dosto-
Robert Gałka gatym wyposażeniem. sowanie się do szerokich potrzeb instalatorów
Marketing Manager Klienci AJM mogą się także zaopatrywać w i wykonawców. W razie konieczności możemy
AJM Electronics Sp. z o.o.
elementy aktywne sieci, takie jak: switche, ro- liczyć na pomoc i wsparcie techniczne ze stro-

A
JM Electronics powstało w 1992 ro- utery, modemy, karty sieciowe, elementy sie- ny naszego partnera. Bardzo duże znaczenie we
ku. Od początku działalności zajmo- ci wi-fi, etc. W naszej ofercie znajdują się m.in. wzajemnej współpracy odgrywa sprawnie dzia-
waliśmy się dystrybucją wszelkiego urządzenia: SURECOM, D-Link, IP-Time, Edi- łający serwis oraz elastyczność i terminowość
rodzaju złącz, kabli i akcesoriów teleinforma- max oraz GFlex. dostaw. Z uwagi na to, że AJM prowadzi dys-
tycznych. Na rynku polskim staliśmy się zna- AJM Electronics jest także dystrybutorem pre- trybucję szaf instalacyjnych w standardzie 19”,
ni dzięki szerokiej ofercie komponentów siecio- paratów czyszczących i konserwujących firmy zależało nam na wzbogaceniu oferty o zasilacze
wych, którą stale rozwijamy. Jednocześnie po- AMBERSIL, stanowiącej część amerykańskiego UPS do tych szaf. Dzięki ETA bardzo szybko i
dejmujemy kroki, mające na celu zbudowanie i koncernu chemicznego CRC, sprzedającego swo- sprawnie udało się rozwiązać ten problem.
umocnienie naszej pozycji na innych polach. je produkty w ponad 120 krajach świata. Z całym przekonaniem możemy stwierdzić,
AJM od kilku lat jest przedstawicielem zna- AJM Electronics zajmuje się zaopatrzeniem iż nawiązanie kontaktu, a potem współpracy z
nej, niemieckiej firmy TELEGÄRTNER, pro- hurtowym firm teleinformatycznych, instala- poznańskim producentem, było słusznym po-
ducenta najwyższej jakości podzespołów do torskich, banków, zakładów przemysłowych, sunięciem. Zasilacze awaryjne nie są naszym
sieci, opartych na skrętce miedzianej i świa- biur, sklepów komputerowych, szkół, wyższych sztandarowym produktem, ale stanowią ważne
tłowodach, złączy telekomunikacyjnych wy- uczelni. uzupełnienie oferty. Musimy przyznać, że ETA
sokiej częstotliwości oraz kabli telekomuni- W celu zapewnienia kontrahentom możli- doskonale wywiązuje się z roli dostawcy i part-
kacyjnych i sieciowych. Dla Partnerów TELE- wości kompleksowego zaopatrywania się w na- nera. Niedawno podjęliśmy decyzję o wspól-
GÄRTNERA regularnie prowadzimy szkole- szej firmie, podjęliśmy decyzję o wprowadze- nych działaniach marketingowych. Pozwoli
nia, po zakończeniu których, uzyskują oni au- niu do oferty zasilaczy UPS. Kontakty targo- nam to zwiększyć obroty, a przy okazji dodat-
toryzację, pozwalającą na udzielanie 25-letniej we ułatwiły nam nawiązanie współpracy han- kowo promować markę.
gwarancji na sieci wykonane w systemie TELE- dlowej z poznańską firmą ETA. O tym, a nie
Ocena : «««««
GÄRTNER. innym wyborze zadecydowało doświadczenie

72 06/2007
UPS

i in.); monitorów, projektorów, akcesoriów tworzyły między naszymi firmami atmosfe-


komputerowych, podzespołów; oprogramo- rę partnerstwa, dzięki czemu współpracuje
wania sieciowego wraz z instalacją okablowa- się nam lepiej.
nia strukturalnego; oprogramowania do ob- Firma ETA zdobywała swoją pozycję od lat.
sługi firm oraz wykonanie pełnej infrastruk- Działając na tym samym rynku i obserwu-
tury sieciowej Serwis sprzętu komputerowe- jąc się od lat, nawiązaliśmy współpracę z fir-
go i sieci, obejmujący: naprawy sprzętu kom- mą ETA już na początku lat 90. Chcieliśmy
puterowego; konserwację sprzętu; analizę i wprowadzić systemy UPS do naszej oferty.
monitorowanie pracy sieci; wydłużone go- Obecnie firma ETA znana jest w całej Polsce i
dziny pracy serwisu interwencyjnego; sprzęt ma silną pozycję w naszym regionie.
zastępczy niezbędny do utrzymania pracy Produkty i usługi firmy ETA w pełni speł-
przedsiębiorstwa. niają nasze oczekiwania, a współpraca ukła-
Powyższe produkty nie wyczerpują na- da się dobrze. Do największych plusów moż-
Mariusz Gołębiowski szej oferty. Na życzenie klienta dostarczamy na zaliczyć: sprawny serwis, niska awaryjność,
sprzęt i oprogramowanie zależnie od jego po- szeroka oferta, satysfakcjonująca polityka ce-
Hardsoft–Telekom
trzeb. Dlaczego wybraliśmy produkt firmy nowa względem dystrybutorów, wiedza i do-

F
irma Hardsoft–Telekom powstała w ETA? Firma ETA jest znana na naszym rynku świadczenie w zakresie zaawansowanych sys-
sierpniu 1992. Od początku działalno- od wielu lat, jako producent systemów zasila- temów zasilania o dużej mocy. Jedynym mi-
ści zajmowała się sprzedażą systemów nia UPS. Oprócz rozpoznawalności marki, o nusem, który można wskazać, jest dość długi
i podzespołów komputerowych. Obecnie za- naszej współpracy zdecydowały dobra jakość czas oczekiwania na dostawę w przypadku za-
trudnia ok. 25 pracowników, a jej działalność produktów i sprawny serwis. Rozwiązania fir- mówień większych partii towaru.
opiera się głównie o sprzedaż hurtową i obsłu- my ETA sprawdzają się u naszych klientów, Wydaje mi się, że cena jest adekwatna do ja-
gę informatyczną przedsiębiorstw. Specjali- którzy chwalą produkty jako konkurencyjne kości usług, choć trudno nie zauważyć, że dla
zujemy się w następujących zagadnieniach: cenowo i solidne. Niemałe znaczenie ma też klienta staje się ona często decydującym czyn-
Kompleksowa dostawa systemów kom- obsługa serwisowa. nikiem w procesie zakupu. Szczególnie widać
puterowych, opartych na platformie Micro- Firma ETA zatrudnia dobrych specjali- to na rynku małych UPS–ów. Tu, działając w
soft, Novell, Linux obejmująca dostarcza- stów, przez co zapewnia serwis gwarancyj- mocno konkurencyjnym środowisku, coraz
nie: sprzętu komputerowego (IBM, HP, Fujit- ny i pogwarancyjny na wysokim poziomie. częściej zmuszeni jesteśmy to stosowania naj-
su–Siemens, Apple, Maxdata, AVAN – mar- Do przyjemnych należy również kontakt z tańszych rozwiązań. Niestety jakość, czy ob-
ka własna); urządzeń sieciowych (3COM, CI- działem handlowym firmy ETA. Pracowni- sługa serwisowa w takich przypadkach scho-
SCO, Linksys); urządzeń peryferyjnych (HP, cy, dzięki posiadanej wiedzy handlowej i zna- dzi na drugi plan.
OKI, Kyocera, Lexmark, Minolta i in.); syste- jomości produktów łatwo nawiązywali z na-
Ocena : ««««
mów zasilania awaryjnego (APC, ETA, Ever mi współpracę. Wspólne działania z ETĄ wy-

wisem urządzeń służących ochronie sprzę- zakresu ogrzewania, powstały zasilacze z se-
tu elektronicznego przed zakłóceniami i za- rii CO, współpracujące z kotłami grzewczymi,
nikami napięcia w sieci zasilającej. W naszej kominkami z płaszczem wodnym itp.
ofercie znajdują się zasilacze awaryjne (UPS) Chcąc utrzymać status wiarygodnego do-
o mocy od 320 VA do 250 kVA, jak również stawcy Systemów Zasilania Awaryjnego oraz
listwy zasilające oraz agregaty prądotwórcze. dostarczania klientowi wyrobów zgodnych z
Nasze produkty można nabyć w całym kraju, jego wymaganiami, za najważniejsze uzna-
poprzez sklepy partnerskie oraz dystrybuto- jemy ciągłe podnoszenie kwalifikacji na-
rów. Zawsze staramy się pomóc naszym klien- szego zespołu. Priorytetem jest zadowole-
tom w doborze UPS–a. nie każdego Klienta. Właśnie wprowadzi-
Zapewniamy również montaż i serwis liśmy do sprzedaży nowy produkt, zasilacz
wszystkich naszych urządzeń. Dużą wagę ETA UPS Protelek 650, przeznaczony na ry-
przykładamy do jakości oferowanych produk- nek masowy. Jest to mały zasilacz do domo-
tów. Dzięki temu możemy pochwalić się naj- wego lub biurowego użytku, za bardzo przy-
dłuższą na rynku, pięcioletnią gwarancją na stępną cenę.
zasilacze awaryjne z serii „multisystem”. Potwierdzeniem naszych starań w zakre-
Nasze udokumentowane, wieloletnie do- sie jakości, są opinie dystrybutorów, z który-
świadczenie w projektowaniu i produkcji za- mi współpracujemy od kilkunastu lat. Jest to
silaczy awaryjnych, pozwala nam zapewnić dla nas największą nagrodą, a zarazem moty-
najwyższy poziom obsługi klienta. Potwier- wacją do dalszej pracy.
dzeniem naszych kwalifikacji, a także sku- Ciągle poszerzamy naszą ofertę. Praca nig-
Ustosunkowanie teczności w zarządzaniu, jest wdrożony sys- dy nie kończy się na sprzedaży, służymy rów-
Karol Pietrowski
Dyrektor ds. sprzedaży i marketingu
tem jakości ISO–9001 certyfikowany w 2003 nież pomocą w czasie eksploatacji urządzeń.
SPEiI ETA przez TÜV. Nasz serwis cechuje szybkość reakcji i wy-
Atutem naszej firmy jest posiadanie wła- kwalifikowana kadra. Wszystkie te elementy

S
półdzielnia Pracy Elektroniki i Infor- snego działu konstrukcyjnego, dzięki które- wpływają na jego bardzo pozytywną ocenę.
matyki ETA powstała w 1988 roku. mu możemy na bieżąco pomagać klientom w
Od początku naszej działalności zaj- przypadku nietypowych rozwiązań. Właśnie
mujemy się projektowaniem, produkcją i ser- w odpowiedzi na powtarzające się pytania z

www.phpsolmag.org 73
Wywiad

Wywiad
z Markiem Sodolskim
i Tomaszem Skutnikiem

Marek Sodolski – dyrektor PHP Solutions: Kiedy kończy się praca warów, bo logistyka jest czymś, bez cze-
pracownika – informatyka, a zaczyna wi- go e-commerce w ogóle nie istnieje. Doda-
naczelny firmy Amway Polska zja organizatora – przedsiębiorcy? Skąd jąc do tego świetnie zorganizowane syste-
przekonanie, że z sieci komputerów my back office’owe na AS/400 osiągnęliśmy
Tomasz Skutnik – dyrektor można „wycisnąć” o wiele więcej niż robią znakomity czas obsługi zamówień, który
działu badań i rozwoju firmy to „teraz” inni ludzie? wynosi od 24 do 48 godzin, gdzie dostęp-
e-point SA. Marek Sodolski (Amway): Osoby, które ność towarów jest szacowana na poziomie
dzisiaj rozpoczynają działalność gospo- 95%. Dla osób z branży logistycznej ten
darczą lub podejmują pracę w firmach są wynik wiele mówi. Doskonale działająca
znacznie lepiej przygotowane i wykształ- infrastruktura logistyczna plus zorganizo-
cone, niż ci, których początek kariery za- wany system sprzedaży stały się idealnym
wodowej przypadał na lata dziewięćdzie- i naturalnym podłożem do wprowadzenia
siąte. Teraz każdy pracownik jest poten- kompleksowego rozwiązania e-commer-
cjalnie kreatorem nowych pomysłów i no- ce. Uważaliśmy, że e-biznes świetnie uzu-
wej wartości dodanej. W tym duchu stara- pełni tradycyjny model sprzedaży bezpo-
my się pracować w firmie Amway – każdy średniej.
pomysł, który w znaczący sposób mógł-
by wpłynąć na działanie firmy jest mile wi- PS: Jaki był z góry założony cel?
dziany. Uważam, że najciekawsze pomy- MS: Celem projektu było wprowadzenie
sły rodzą się w dyskusji, podczas spotkań zunifikowanego narzędzia zarządzania
z ludźmi o różnym stopniu doświadczenia. sprzedażą, a jednocześnie, dla setek ty-
Stawiamy tak naprawdę na „teamwork”, na sięcy sprzedawców bezpośrednich – na-
pracę wielu osób, które mogą wnieść coś rzędzia zarządzania własnym biznesem.
świeżego do projektu. Osobiście jest mi Chcieliśmy wdrożyć nowoczesną, przyja-
niezmiernie miło, że mogłem koordyno- zną użytkownikowi, bezpieczną, i atrak-
wać pracą nad projektem e-commerce, ale cyjną wizualnie aplikację e-biznes, która
to nie znaczy, że to tylko moja autorska wi- byłby rozwinięciem systemu działającego
zja go kształtowała. wcześniej w Europie Wschodniej – systemu
VEBSO. Nowa wersja aplikacji musiała speł-
PS: Skąd pomysł na udział w takim pro- niać standardy informatyczne stosowane
jekcie, jakim jest platforma e-commerce? w naszej firmie globalnie, dlatego poszuki-
MS: E-commerce to naturalna kontynuacja waliśmy partnera, która doskonale zna roz-
Amway – lider sprzedaży budowy otoczenia biznesowego dla róż-
nego typu działalności. Jest jednym z lo-
wiązania IBM, zarówno jeśli chodzi o ser-
wery aplikacji, bazy danych, jak i hardware.
bezpośredniej i e-point gicznych etapów rozwoju systemów za- Zależało nam również na jak najszybszym
rządzania i wspomagania działań przedsię- wdrożeniu systemu, czas jest bowiem nie-
SA – czołowy polski biorstwa. W naszym przypadku e-commer- ubłagany w rozwiązaniach informatycz-
ce nie pojawił się nagle, „deus ex machina”, nych. Systemy starzeją się bardzo szybko
developer systemów ale był kolejną fazą rozwoju różnego ty- i jeśli proces wdrożenia trwa zbyt długo, to
IT budowanych w oparciu pu zaawansowanych systemów zarządza- okazuje się potem, że system jest nieade-
nia dużą ilością danych, połączonych z sys- kwatny do oczekiwań rynku.
o Javę – zjednoczyły siły, temami IT. Pracujemy w oparciu o system
IBM AS/400, który pozwala na kalkulacje PS: Jak wyglądała realizacja projektu?
by stworzyć nowoczesny wyników biznesowych firmy i naszych dys- MS: Zespół, który bezpośrednio pracował
e-commerce – nową trybutorów w czasie rzeczywistym, zbiera-
jąc te dane z całego świata. Od lat rozwi-
nad projektem był nieliczny, jednak zaple-
cze merytoryczne bardzo duże. Każde roz-
platformę Amway Online. jamy różnego rodzaju narzędzia związane wiązanie weryfikowane było przez stwo-
z obsługą klienta, m.in. dostarczaniem to- rzony przez Amway zespół ekspertów w da-

74 06/2007
Wywiad

nej dziedzinie. Na każdym etapie prac do ni. I dotrzymaliśmy słowa - wszystko to, innym razem proponujemy alternatywne
weryfikacji włączani byli również użytkow- co zaprezentowaliśmy na etapie przygoto- rozwiązania. Kluczowy obszar, w którym
nicy, którzy oceniali m.in. prototyp. W trak- wania projektu, zostało zrealizowane. Fir- jest najwięcej do przedyskutowania to in-
cie realizacji projektu zespoły w każdym z ma Amway dostała taki produkt i zmieściła tegracja z systemami back office’owymi.
krajów były zaangażowane na różnych eta- się w takim budżecie i w takim czasie, jaki Konieczne było przejście całego procesu
pach – analizy, tworzenia specyfikacji, te- uzgodniliśmy na samym początku. ustalania protokołów przesyłania danych,
stowania oraz podczas samej implementa- MS: Otrzymaliśmy od firmy e-point znacz- aby zamówienia sprawnie przepływały.
cji systemu. Każde wdrożenie było wspar- nie więcej niż się spodziewaliśmy. E-po- Wydaje mi się, że udało nam się osiągnąć
te pracą grupy projektowej, która kontak- int wniosła dużo wartości dodanych i wie- naprawdę bardzo wartościowy konsensus
towała się z użytkownikami, przeprowa- le ciekawych pomysłów, które wzbogaci- co do tego, jak system ma działać. I zawsze
dzała dla nich i dla pracowników szkolenia. ły dotychczas funkcjonujące rozwiązania współpraca przy tego rodzaju projektach
Ten system pracy ”bezpośredniej” spraw- e-commerce. Niewątpliwie pomogło nam nie obywa się bez tarć. Wystarczy jednak
dził się, ponieważ nie wszytko można za- doświadczenie. W pracach nad projektami dobra wola z obu stron plus chęć dokoń-
łatwić mailem, telefonem czy wideokonfe- e-commerce znajomość tej branży jest nie- czenia projektu i wszelkie tego typu pro-
rencją. To było wyzwanie. Zarówno e-po- zbędna. Firma e-point znalazła się na bar- blemy „w różnicach poglądów” przestają
int, jak i my nie prowadziliśmy wcześniej dzo krótkiej liście firm, które naszym zda- mieć znaczenie. Najważniejsze było to, że
takiego projektu i wzajemnie się uczyli- niem mogłyby podjąć się tego zadania. By- wszyscy pracowaliśmy w imię osiągnięcia
śmy. To był proces doskonalenia swoich liśmy przekonani, że znajomość techno- wspólnego celu.
umiejętności, czasem nauki od podstaw, logii, organizacja pracy, a także otwarte i MS: Nam pomaga doświadczenie w sprze-
który w ciągu dwóch lat doprowadził do kreatywne podejście będą podstawowymi daży bezpośredniej. To jest biznes oparty na
tego, że rozszerzając projekt na kolejne umiejętnościami. Takie założenie sprawiło, pracy z ludźmi, który zakłada, że do każde-
kraje mieliśmy jasno podzielone role. Ca- że zaprosiliśmy e-point do złożenia oferty. go partnera, który pragnie z nami współpra-
ły projekt trwał dwa lata. Tam, gdzie działał Nie jest tajemnicą, że na rynku e-biznesu cować, a jest ich w Polsce dziesiątki tysięcy,
już poprzedni system - VEBSO wprowadza- w Polsce jest kilka firm oferujących podob- podchodzimy z szacunkiem. Mamy świado-
liśmy nowy system w ciągu sześciu miesię- ną jakość rozwiązań. Istniały jednak pew- mość, że każdy może wnieść coś wartościo-
cy. W tym czasie udało nam się tego doko- ne warunki brzegowe, które zadecydowa- wego, niezależnie od wielkości firmy. Jeste-
nać w ośmiu krajach. ły, że zaprosiliśmy tylko i wyłącznie e-point śmy specjalistami od sprzedaży bezpośred-
z Polski oraz kilka firm zagranicznych. Jed- niej, ale to firma e-point jest specjalistą od
PS: Wiemy, że odnieśli Państwo ogromny nym z warunków była znajomość techno- systemów informatycznych.
sukces dzięki współpracy Amway'a oraz logii i dobre relacje z IBM w Polsce oraz w
firmy e-point S.A. Stąd pytanie - jak innych krajach europejskich, bo nasza fir- PS: Ile wersji oprogramowania dzieliło
doszło do zjednoczenia sił na potrzeby ma od lat stosuje ich rozwiązania, zarówno podstawowy system od zaakceptowane-
tego projektu? Skąd wybór akurat firmy back office jak i e-commerce. go przez klienta?
e-point? TS: Wszystko zależy od tego, jak na to pa-
Tomasz Skutnik (e-point): Firma e-point PS: Jak układała się Państwa współpraca? trzeć. Zanim system pojawił się w produk-
została wybrana z jednego prostego po- Czy była zgodna, bez żadnych sprzeci- cji, było kilka wersji testowych. Od momentu
wodu: była najlepsza technicznie. Przed- wów? Czy dochodziło do pewnych różnic wejścia w fazę produkcyjną również powsta-
stawiliśmy najlepszą ofertę w zakresie ar- w poglądach i ostrej wymiany zdań? ło kilka wersji. W tej chwili, licząc od wdroże-
chitektury technicznej i procesu dostar- TS: Zawsze na początku klient czegoś nia produkcyjnego, było kilkanaście wersji,
czenia wysokiej jakości rozwiązania. My- oczekuje, a my staramy się to zrozumieć przy czym są to tzw. wersje bug fix’owe, czyli
ślę, że byliśmy najbardziej konkurencyj- i pomóc. Pewne sugestie uwzględniamy, 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-
Rysunek 1. Zdjęcie z 21. Światowego Kongresu IPMA w Krakowie pewniania wysokiej jakości naszych roz-

www.phpsolmag.org 75
Wywiad

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 realizacji
zamówień, jak i korzystanie z biblioteki
wiedzy przydatnej do prowadzenia włas-
Rysunek 2. Zdjęcie z 21. Światowego Kongresu IPMA w Krakowie, Marek Sodolski, dyrektor naczelny nego biznesu, pozyskiwania informacji
Amway Polska (w środku), Marcin Żuchowicz, Prezes Zarządu e-point SA (pierwszy z prawej)
o produktach, działaniach marketingowych
wiązań. Po pierwsze, jest platforma One Oprócz tego systemy były testowane lo- firmy czy aktualnych promocjach.
Web, którą stworzyliśmy na własny uży- kalnie. Jest wersja zasadnicza, trzon syste- Z systemu mogą również korzystać klien-
tek w celu wdrażania właściwie wszyst- mu – wspólny dla wszystkich krajów, na- ci finalni i indywidualnie przeglądać ofertę
kich rozwiązań e-commerce realizowanych tomiast funkcjonalność była sprawdzana produktów oraz dokonywać zamówień na
dla naszych klientów. Jest to rdzeń, na ba- indywidualnie – lokalnie, po dwóch stro- konto opiekującego się nimi niezależnego
zie którego budujemy kolejne rozwiązania nach front i back-endu. Proces testowa- przedsiębiorcy Amway. Użytkownicy plat-
– w sposób szybki i niewielkim kosztem. nia był dość skomplikowany, szczególnie, formy mają do dyspozycji skrzynki mailo-
Druga to zintegrowane testowanie właści- że istniały zależności czasowe pomiędzy we, za ich pomocą mogą komunikować się
wie od samego początku procesu produk- krajami. Zespół testujący dostawał aplika- zarówno z firmą, swoimi klientami, jak i mię-
cyjnego, od momentu wdrożenia projek- cję w miejscu, gdzie miała być ona wdro- dzy sobą. Amway Online jest jak wirtualne
tu, kiedy testowanie polega na przeglądzie żona. Niezwykle istotne było, aby osoby biuro – służy do zarządzania biznesem i re-
specyfikacji, a także w trakcie sprawdzania wdrażające na front i back-endzie mogły lacjami na wszystkich trzech poziomach: fir-
czy specyfikacje te są spójne. W momen- od razu odpowiadać na pytania lokalnych ma – sprzedawca bezpośredni – klient. Jest
cie implementacji systemu zawsze mamy użytkowników, pomagając im w tym pro- więc to rozwiązanie zarówno B2B, jak i B2C.
zarezerwowany czas i zespół ludzi, aby od cesie. Ten zabieg znacznie usprawnił całą
początku pisać testy jednostkowe i od razu fazę testowania, pomógł lepiej zrozumieć, PS: Jakie mają Państwo plany na
korzystać z odpowiednich narzędzi prze- jak system działa, jakie ma zalety, czasem przyszłość? Czy przewidują Państwo
znaczonych do testowania. jakie ograniczenia dla osób pracujących dalszy rozwój platformy?
Obecnie używamy narzędzia IBM Ratio- w poszczególnych biurach. MS: Najbliższe plany to wdrożenie systemu
nal Functional Tester, które symuluje użyt- e-commerce na rynkach Europy Zachodniej,
kownika korzystającego z przeglądarki, kli- PS: Wiadomo, iż każda realizacja wy- w oparciu o rozwiązanie zastosowane w
kającego w system. Krótko mówiąc testo- maga zastosowania odpowiedniego Europie Wschodniej. Platforma okazała się
wanie zaczynamy od momentu napisa- zabezpieczenia. Jakie Państwo spektakularnym sukcesem, stąd też zainte-
nia przez nas pierwszej linijki kodu. Pro- zastosowali? resowanie jej wdrożeniem na zachodzie Eu-
dukt musi przejść wiele testów, w tym te- TS: Sama architektura hostingowa jest za- ropy. Poza tym będziemy wprowadzać no-
stów nowych funkcjonalności, zanim zo- bezpieczona wielowarstwowo – poprzez fi- we funkcjonalności, na przykład bardziej
stanie zaakceptowany przez klienta i wej- re wall naszego dostawcy internetu oraz fi- zaawansowane zarządzanie relacjami z
dzie do użytku. re wall’e front-endowe. Ponadto, wszystkie klientami – pojawią się elementy CRM-u.
MS: System e-point jest zintegrowany serwery pracują na warstwach http, aplika- Już wkrótce zaoferujemy naszym nie-
z naszymi systemami. Po testach, system cyjnych i bazy danych, podzielonych na sie- zależnym przedsiębiorcom prowadzenie
jest przekazywany do nas i są sprawdza- ci VLAN i są one zabezpieczone dodatko- księgowości on-line, a także e-learning,
ne elementy wspólne, tzn. czy funkcjonal- wo fire wall’em. Aplikacja sama w sobie ma czyli system prowadzenia szkoleń i mo-
ność front -endowa działa z naszymi syste- mnóstwo mechanizmów z zabezpieczenia- nitorowania ich wyników poprzez platfor-
mami back-endowymi. W naszej firmie jest mi przed nadużyciami aplikacyjnymi – został mę. Chcemy również wykorzystywać plat-
wyspecjalizowany zespół Quality Assuran- stworzony proces przeglądu kodu. Mamy formę do prowadzenia badań opinii i mo-
ce - testerów, którzy sprawdzają wszyst- odpowiednio podzielone strefy bezpieczeń- nitorowania zadowolenia klientów – oczy-
kie rozwiązania back-endowe i front-en- stwa, dlatego osoby chcące dokonać włama- wiście również on-line.
dowe standardowo, niezależnie od kraju nia już na samym początku napotkają barie-
czy systemu. ry nie do pokonania. PS. Dziękuję za rozmowę.

76 06/2007
Recenzja

PEAR. Programowanie w PHP

Wydawnictwo: Helion
Autorzy: Stephan Schmidt, Stoyan Stefanov,
Carsten Lucke, Aaron Wormus
Cena: 44,00 zł
ISBN: 978-83-246-0897-3
Ocena: 4

Język PHP swoją popularność zawdzięcza m.in. szerokiemu dostę- Książka ta jest skierowana zarówno do osób które z pakietem
powi do rozszerzeń i bibliotek. Najważniejszym ich źródłem jest PEAR nie miały do czynienia, jak i do tych, którzy znają i używa-
PEAR – internetowe repozytorium rozszerzeń. Przy jego pomocy ją tych bibliotek. Napisana jest przystępnym językiem. Pokazuje
możemy wykonać niemal każdą operację w PHP. Książka „PEAR. krok po kroku na przykładach jak wydajnie i skutecznie używać
Programowanie w PHP” pokazuje, jak wykonywać codzienne za- jej na co dzień. Wszelkie wprowadzenia poparte są prostymi przy-
dania z użyciem klas z pakietów PEAR. Można przeczytać, jak ob- kładani. Wszystkie przykłady oparte są na PHP5, pokazano rów-
sługiwać bazy danych za pomocą pakietu MDB2 oraz jak wyświe- nież różnice z PHP4. Osoby, które jeszcze nie miały do czynienia
tlać tabele, kalendarz, arkusz kalkulacyjny, data grid, czy jak wyge- z pakietami PEAR, w łatwy sposób zapoznają się z nimi i z me-
nerować dokument PDF. Pozwala na zapoznanie się z pracą z do- todologią ich używania. Natomiast osoby znające i korzystające
kumentami XML – tworzenie, analizowanie oraz przekształcanie. z dobrodziejstw tych pakietów, poszerzą swoją wiedzę i w razie po-
Można zobaczyć, jak przekształcać obiekty PHP na format XML trzeby szybko odnajdą pożądany przykład.
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. Zrecenzował: Paweł Kołodziej

Marketing z Google.
Jak osiągnąć wysoką pozycję.
Techniki pozycjonowania a spam

Wydawnictwo: Wydawnictwo Naukowe PWN


Autor: Paweł Kobis
Cena: 44,90 zł
ISBN: 978-83-01-15133-1
Ocena: 5

Umieszczenie strony WWW na pierwszej stronie wyników w wy- Plusem książki jest zwrócenie uwagi na wpływ standardów W3C,
szukiwarce Google, dla znaczącej części użytkowników interne- na pozycjonowanie strony. Poza tym, warto zauważyć fakt poru-
tu, wydaje się czymś niesamowicie skomplikowanym. Wielu re- szenia tematyki spamu, ponieważ, jak się przekonamy w trakcie
zygnuje z samodzielnej próby wypozycjonowania strony, zlecając lektury, granica pomiędzy spamem a rozwiązaniami legalnymi jest
tą czynność wyspecjalizowanym firmom. Jednak jak pokazuje Pa- bardzo płynna. Do książki dołączona jest również płyta CD z opro-
weł Kobis w swojej książce, umieszczenie serwisu w top 10, w wy- gramowaniem wspomagającym pozycjonowanie stron WWW.
nikach wyszukiwania, nie jest wcale takie trudne. W „Marketing z Dzięki oprogramowaniu takiemu jak: Web CEO lub SEO Studio,
Google” zapoznamy się z różnymi punktami widzenia na techni- w szybki sposób będziemy w stanie zorientować się, jakich słów
ki i sposoby pozycjonowania. W trakcie lektury dowiemy się nie- kluczowych użyć oraz jak poprawić naszą stronę, aby była lepiej
zbędnych rzeczy związanych z optymalizacją strony WWW. Dzię- odbierana przez wyszukiwarki. Podsumowując, książka jest pozy-
ki temu będziemy wiedzieć, jak właściwie formatować treść w me- cją godną polecenia dla każdego, kto potrzebuje wiedzy związanej
tatagach, takich jak title lub description, aby strona została do- z SEO do własnoręcznego pozycjonowania lub do wynegocjowania
brze odebrana przez wyszukiwarkę, jak i przez osoby poszukujące jak najlepszej oferty z firmą, która zrobi to za nas.
konkretnej treści. Autor bardzo dokładnie opisuje, jak osiągnąć cel
i wyprowadzić naszą stronę na sam szczyt wyników wyszukiwania. Zrecenzował: Łukasz Skowroński

www.phpsolmag.org 77
Felieton

Społeczność
PHP ?

O
statnimi czasy miałem okazję być uczestnikiem różnych setkach, ale np. z kilkudziesięciu osobową grupą fanatyków, którzy
konferencji i zjazdów grup programistów wielu języków przyjechali z różnych części Polski tylko po to, aby dowiedzieć się
programowania. Powstało wtedy w mojej głowie pewne czegoś ciekawego i nowego oraz spotkać się z innymi ludźmi o po-
pytanie: Dlaczego nie były to zjazdy programistów PHP? Naturalne dobnych zainteresowaniach. Każdy z nas czuje się z pewnością ta-
jest, że grupy ludzi starają się spotkać, aby rozmawiać o swoich pa- kim fanatykiem, jednak nie każdy jest chętny do przejechania kil-
sjach i zainteresowaniach, więc dlaczego to nie działa w przypad- kuset kilometrów tylko dla dwóch godzin rozmowy. Jestem zdania,
ku programistów PHP? Przecież każdy z nas ma mnóstwo przyjem- że dla tej atmosfery spotkań jednak warto jest pokonać przeciwno-
ności z tworzenia zarówno stron WWW, jak i innego oprogramowa- ści takie jak długa droga, czy niesprzyjająca pogoda. Myślę, że jeże-
nia wykorzystującego lub wręcz bazującego na PHP. Osobiście, jeżeli li ktoś raz pojawi się na konferencji to z pewnością będzie pojawiać
tylko spotykam znajomą mi osobę, zajmującą się programowaniem się i na kolejnych. Przecież każdy z nas lubi poczuć się czasem mą-
na potrzeby internetu, zawszę zamienię kilka zdań na temat pozna- drzejszym lub też wyznaczyć sobie kolejne cele do osiągnięcia po-
nych nowinek. Spotkana osoba bardzo chętnie podejmuje rozmo- przez poznanie własnych słabych stron czy luk w wiedzy. Niestety w
wę, również dzieląc się swoimi doświadczeniami i spostrzeżenia- Polsce nie istnieją żadne, cyklicznie powtarzające się zjazdy społecz-
mi. Dlaczego więc nie istnieją zloty programistów PHP? Można tu- ności PHP, jak to jest np. w przypadku programistów Javy, które od-
taj podać kilka powodów takiego stanu rzeczy. Pierwszy i chyba naj- bywają się co dwa tygodnie w Warszawie. Moim zdaniem, ilość pro-
bardziej oczywisty to pieniądze. Organizacja takiego spotkania wią- gramistów PHP jest znacznie większa niż Javy, ale nie można tego
że się z kosztami. Zastanówmy się więc, kto mógłby zarobić na ta- zaobserwować, ponieważ trudno mówić o społeczności, która nigdy
kim zjeździe? Zarobić mogłyby wszystkie firmy hostingowe, ponie- się nie spotyka. Zaryzykowałbym stwierdzenie, że niemal każdy zaj-
waż stwarza to świetną okazję do zaprezentowania swoich usług. mujący się programowaniem na poważnie, miał styczność z PHP w
Rynek usług hostingowych jest już mocno przesycony i reklama np. mniejszym bądź większym stopniu. Wg mnie wystarczy to do stwier-
poprzez sponsorowanie imprezy, pokazałaby przyszłym odbiorcom, dzenia, że dobrze zorganizowana i rozreklamowana konferencja po-
u kogo warto postawić nasz serwis. Obecnie firmy hostingowe sta- święcona temu językowi, zrzeszyłaby ogromne ilości ludzi. Za gra-
rają się reklamować swoje usługi, nieraz nie trafiając do właściwe- nicami naszego państwa mają miejsce takie zjazdy, co łatwo można
go odbiorcy. Przy zorganizowaniu konferencji, promowane usłu- zauważyć na stronie będącej biblią dla każdego programisty PHP. W
gi trafiłyby tylko do zainteresowanych osób, przez co reklama sta- USA takich zjazdów jest mnóstwo, a w innych krajach (zazwyczaj za-
łaby się opłacalna. Zarobić na takim zjeździe mogłyby również fir- chodnich) również ich nie brakuje. Taki stan rzeczy może wyjaśnić,
my zajmujące się rozpowszechnianiem oprogramowania wspoma- dlaczego w Polsce, która przecież nie jest małym krajem, jedynie
gającego pracę w PHP, czyli np. firmy tworzące różnego rodzaju edy- dwadzieścia trzy osoby posiadają certyfikat Zend, a ma on przecież
tory. Istnieje kilka polskich firm zajmujących się tworzeniem takie- swój prestiż. Wpływ na taką sytuację ma zapewne też opinia wyro-
go właśnie oprogramowania, jak również wiele zagranicznych, ma- biona przez PHP 4, którego obiektowość pozostawiała wiele do ży-
jących swoje przedstawicielstwa w Polsce. Zarobić na takim zlocie, czenia. Nie mniej jednak, od pojawienia się PHP 5, nie można już za-
choć może nie w dosłownym znaczeniu, mogłyby również firmy po- rzucać PHP braku normalnej obiektowości, którą niewątpliwie po-
szukujące pracowników na stanowisko programistów i webmaste- siada. Poczekajmy, aż pojawi się PHP 6, wtedy PHP 4 odejdzie w za-
rów. Obecne zapotrzebowanie na programistów jest ogromne i taki pomnienie i wszyscy, którzy krytykowali PHP stracą swoje argumen-
właśnie zjazd pomógłbym firmom w przedstawieniu się jako dobrzy ty i zaczną traktować ten język poważnie.
pracodawcy i zachęceniu do pracy właśnie u nich. Na końcu zarobi- Dla PHP nadchodzą najlepsze czasy. Zyskuje ono coraz większą po-
liby również sami uczestnicy, choć w ich przypadku byłoby to raczej pularność i możemy mieć nadzieję, że w niedługim czasie zyska ono
pogłębienie wiedzy, zorientowanie się w nowościach na rynku oraz status taki, jaki ma obecnie na zachodzie. Następstwem tego będą
wymienienie opinii. Może to się przełożyć w dalszej perspektywie na również konferencje i zjazdy podobnych do nas ludzi. Niestety na to
lepsze zarobki. Zwróciliśmy już uwagę na komercyjną stronę takich wszystko musimy trochę poczekać. Możemy być pewni, że warto.
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- ŁUKASZ SKOWROŃSKI
szukiwanie zysku. Zjazdy takie pozwalają na poznanie nowych tech- Autor jest studentem informatyki na Uniwersytecie w Białymstoku, pracuje
nologii i skonfrontowanie opinii na ich temat z innymi uczestnika- również jako programista PHP w firmie E-Studio.
mi. Nie mamy wtedy do czynienia z ogromną grupą ludzi, liczoną w Kontakt z autorem: lukas.skowronski@gmail.com

78 06/2007
Ciao GmbH
Ciao 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-

Prenumerata PRO
biać, pracować w międzynarodowym środowi-

Więcej informacji: patrycja.wadolowska@software.com.pl tel.: 022 427-36-69


sku i w przyjaznej atmosferze – dołącz do nas.
www.ciao-group.com/careers_wroclaw.php

Agencja Interaktywna
– br-design.pl
Kreowanie 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.

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

Kei.pl protHOST
Kei.pl działa na rynku usług hostingowych od Rewelacyjny hosting o12 już od 49 zł netto/rok
2000 roku. Do naszych zadowolonych Klientów (w tym cPanel PL). Rejestracja domen od 1 zł
z dumą możemy zaliczyć wiele przedsiębiorstw netto. Webdesign i pozycjonowanie. Wszystko
sektora MSP, instytucji oraz osób prywatnych. czego potrzebujesz.
W ofercie Kei.pl znajdują się pakiety hostingowe, http://o12.pl
a także usługi dla wymagających Użytkowników
– platformy e-Biznes oraz serwery fizyczne.
http://www.kei.pl

ntp.pl Hosting
PRACA DLA PROGRAMISTY: Elastyczny dobór pakietów, pakiet POCZTA
– 40 zł, pakiet START (www, email, 10 domen,
Entuzjazm, PHP, MySQL/ Postgress, może php 5, mysql, pgsql) – 150 zł, pakiety KOM-
być część etatu. FORT, PROFIT, PROFITSSL, zarządzanie przez
cPanel. Rejestracja domen globalnych, krajowych,
Własne oczekiwania, opis osiągnięć z których funkcjonalnych i regionalnych. Ceny od 50 zł.
jesteście Państwo dumni, krótką informację www: http://www.lubman.pl,
czemu chcecie Państwo pracować dla naszej e-mail: biuro@lubman.pl,
firmy oraz CV na adres: praca@ntp.pl

Dzsoft Agnat Sp. z o.o.


Siedziba firmy znajduje się na Ukrainie. Naszą Dostarcza pełen wachlarz usług związanych ze
ofertę kierujemy szczególnie do osób, które zaj- stronami WWW. Serwis www.agnat.eu obsłu-
mują się językiem PHP, gdyż sami specjalizuje- guje kilkanaście tysięcy Klientów z całej Polski
my się w tym, pisząc nasz własny kod. Posia- oraz Unii Europejskiej, wyposażając je w do-
damy również edytor Perl oraz inne przydatne meny internetowe, hosting, pozycjonowanie,
oprogramowania. Nasi pracownicy to specjaliści, kreację stron WWW, kampanie reklamowo-pro-
zajmujący się optymalizacją specyficznych po- mocyjne, oprogramowanie i aplikacje niezbędne
trzeb języka PHP i Perl. do prowadzenia biznesu w sieci.
http://www.dzsoft.com
www.buyitpress.com

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!
zamówienie prenumeraty

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: pren@software.com.pl. 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)............................................................................................................................................................................


automatyczne przedłużenie prenumeraty

Tytuł
Ilość Od numeru Opłata
Ilość
zamawianych pisma lub w zł
numerów
prenumerat miesiąca z VAT
Software Developer’s Journal (1 płyta CD)
– dawniej Software 2.0 12 250/1801
Miesięcznik profesjonalnych programistów
SDJ Extra (od 1 do 4 płyt CD lub DVD)
– dawniej Software 2.0 Extra! 6 150/1352
Numery tematyczne dla programistów

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 PHP
Od 2008 roku będzie miesięcznikiem. Cena prenumeraty rocznej
12 135
wyniesie 199 PLN. Do końca roku prenumerata w starej cenie.

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

Jeżeli chcesz zapłacić kartą kredytową, wejdź na


stronę naszego sklepu internetowego:
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
www.buyitpress.com
W następnym numerze PHP Solutions 1/2008 (24)

W sprzedaży od grudnia

TECHNIKA UWAGA!! NOWE TESTY KONSUMENCKIE


n MySQL - techniki przyśpieszania zapytań n Pozycjonowanie stron WWW

n Kontrola zasobów FTP przy pomocy PHP

NARZĘDZIA NOWE ARTYKUŁY W DZIAŁACH


n Subversion – system kontroli wersji n dla początkujących

dla każdego n dla zaawansowanych

n kasa dla webmastera

I wiele innych artykułów, których nie możesz przeoczyć!

Redakcja zastrzega sobie możliwość zmiany zawartości pisma.

You might also like