You are on page 1of 84

Spis treści

AKTUALNOŚCI 6
Krzysztof Trynkiewicz

Będziemy z Wami przez cały rok! OPIS CD 10


Patrycja Wądołowska

R edakcja magazynu PHP Solutions postanowiła, że będzie ze swo-


imi Czytelnikami przez 12 miesięcy w roku! Oprócz numerów pe-
riodycznych planujemy Starter Kity o Flash i WEB2.0 oraz cztery nume-
DLA POCZĄTKUJĄCYCH
Tworzymy aplikacje okienkowe
ry Extra o Xoops, eZpublish, Typo3 i Mambo!
z PHP-Qt 12
Chcielibyśmy również, abyście Drodzy Czytelnicy mieli jeszcze
większy udział w tworzeniu pisma, które jest dla Was. Planujemy jesz- Thomas Moenicke
cze więcej testów konsumenckich. Na pewno bedziemy zwracać się do Thomas wskazuje jak pisać w PHP programy ko-
Was z prośbą o opinię jako konsumentów. W nastepnym numerze po- rzystając z Qt na przykładzie kalkulatora. Obja-
dejmiemy temat relokacji serwerów. Piszcie do nas! śnia również podstawowe zagadnienia związane
Możliwe, że w huku strzelających fajerwerków przyjdą Wam do gło- z Qt-kolejnym standardem GUI, na którym opie-
wy pomysły na felietony, bądź też wśród noworcznych postanowień ra się m.in. KDE
zrodzi się w Was potrzeba zaprenumerowania magazynu. Świetnie!
Przygotujemy jeszcze więcej wspaniałych prezentów do prenumeraty
oraz mnóstwo ciekawych artykułów, których nie można przegapić! PROJEKTY
Jeśli jednym z Waszych życzeń jest współuczestniczyć w tworze-
niu pisma, możemy je spełnić! Dołączcie do grona współpracowników PunBB-nowoczesne forum
jako betatesterzy! dyskusyjne 18
Wreszcie, jeśli pragniecie, aby na twarzy bliskiej Wam osoby
Piotr Maliński
uśmiech gościł nie tylko w czasie otwierania prezentu gwiazdkowe-
Piotr uczy sztuki integrowania punBB z ze-
go, ale przez cały rok, zprezentujcie jej prenumeratę roczną magazy-
wnetrznymi skryptami. Obrazuje również migra-
nu PHP Solutions, a my dołożymy wszelkich starań, żeby każdy numer
cje danych z innych skryptów forum.
coraz bardziej cieszył.
Nasi Drodzy, życzymy Wam białych, spokojnych i wesołych świąt,
spędzonych w rodzinnej atmosferze, w domu przepełnionym zapachem
ciasta i gałązek świerkowych. W Nowym Roku, spełnienia marzeń, wie- DLA ZAAWANSOWANYCH
le pomyślności oraz radości z każdego numeru magazynu PHP Solu-
Xajax – łatwy AJAX 24
tions.
Paweł Grzesiak
Paweł pokazuje jak w szybki sposób wdra-
żać nowe pomysły w tworzeniu stron opartych
o AJAX dzięki XAJAX-rozwiązaniu zorientowa-
nemu na programistów PHP, które uwzględznia
mionimum programowania w JavaScript.
Patrycja Wądołowska
patrycja.wadolowska@software.com.pl Budowanie obiektów z requestu
przy pomocy Reflection API 34
Piotr Szarwas

Nasz magazyn ukazuje się w dwóch językach! Reflection API to zestaw klas i funkcji, przy po-
mocy których programista może zdobyć infor-
mację o budowie dowolnej klasy, obiektu lub
polskim francuskim funkcji, wbudowanej lub napisanej w PHP, Piotr
prezentuje nam jego możliwości.

Warstwowy model aplikacji 40


Paweł Klimczyk
Paweł zdradza sposób na proste zarządzanie
kodem aplikacji. Nowoczesnie patrzy na tworze-
nie średnich i dużych aplikacji.

Jeśli jesteś zainteresowany zakupem licencji na wydawanie naszych pism prosimy o kontakt:
Monika Godlewska monikag@software.com.pl tel.: 48 22 887 12 66, fax: 48 22 887 10 11

4 www.phpsolmag.org PHP Solutions Nr 1/2007


Spis treści
NARZĘDZIA
LIZ DB – zaawansowane możliwości
bazy MySQL5 44
Łukasz Budnik Pytania dotyczące Strona WWW/Forum
prenumeraty strona www: www.phpsolmag.org
Łukasz wskzuje jak sprawnie pisać programy tel. (22) 887 14 44 Tu znajdą Państwo informacje
bazodanowe począwszy od prostych zapytań a e-mail: pren@software.com.pl dotyczące aktualnych i przyszłych
skończywszy na wywołaniach procedur składo- Software Wydawnictwo Sp. z o.o. numerów magazynu PHP Solutions.
wanych dzięki LIZ DB, które jest narzędziem na- dział prenumeraty
pisanym w PHP5. ul. Bokserska 1 Forum: www.phpsolmag.org/newforum
02-682 Warszawa Zachęcamy do dyskusji na naszym
forum. Czekamy na propozycje
Wielojęzyczna konfiguracja stron CD tematów, które chcieliby Państwo
z użyciem eZ publish 52 tel. (22) 887 14 44
znaleźć w najbliższym numerze pisma.
e-mail: cd@software.com.pl
Zapraszamy także do wymiany
Łukasz Serwatka Software Wydawnictwo Sp. z o.o.
poglądów z innymi fanami PHP.
Łukasz ilustruje jak zainstalować eZ publish z Defekty CD/DVD
obsługa kilku języków, zmieniać ustawienia i
ul. Bokserska 1 Cena
02-682 Warszawa Prenumerata: 135 zł
konfigurację systemu pod kątemj wielujezyków.
Przelew na konto nr:
Opisuje też tworzenie własnych rozszerzeń ję- Zamówienia 46 1440 1299 0000 0000 0391 8238
zykowych dla eZ publish. /Numery archiwalne Nordea Bank Polska S.A.
tel. (22) 887 14 44 II Oddział w Warszawie
e-mail: pren@software.com.pl
TESTY KONSUMENCKIE sklep on-line: www.shop.software.com.pl

Testy konsumenckie firm Kontakt z redakcją


e-mail: redakcja@phpsolmag.org
hostingowych 60 Software Wydawnictwo Sp. z o.o.
Redakcja PHP Solutions
Opinie klientów firm NetArt i Miracle Systems. ul. Bokserska 1
02-682 Warszawa

TRIKI W PHP 68
Listingi wszystkich opisywanych programów zostały zamieszczone na naszej stronie
internetowej www.phpsolmag.org/pl.
Łukasz Sosna

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

Patrycja Wądołowska Redaktor naczelny: Sylwia Pogroszewska


Redaktor: Patrycja Wądołowska patrycja.wadolowska@software.com.pl
Rozmowa z Rafałem Mrzygłockim – twórcą i po-
mysłodawcą serwisu ILOGGO. Kierownik produkcji: Marta Kurpiewska marta@software.com.pl
Projekt okładki: Agnieszka Marchocka
Skład i łamanie: Sławomir Zadrożny slawekz@software.com.pl

RECENZJE 76 Stali współpracownicy: Krzysztof Trynkiewicz chris.tynkiewicz@gmail.com

Łukasz Witczak, Marcin Stefaniak Dział reklamy: adv@software.com.pl


Prenumerata: Marzena Dmowska pren@software.com.pl
Nakład: 6 000 egz.

FELIETON Adres korespondencyjny: Software-Wydawnictwo Sp. z o.o.,


ul. Bokserska 1, 02-682 Warszawa, Polska
Własne życie 78 tel. +48 22 887 10 10, fax +48 22 887 10 11
www.phpsolmag.org cooperation@software.com.pl
Aleksander Cynarski
Dołączoną do magazynu płytę CD przetestowano programem AntiVirenKit firmy G DATA Software Sp. z o.o.

Redakcja dokłada wszelkich starań, by publikowane w piśmie i na towarzyszących mu nośnikach informacje

KLUB TECHNICZNY i programy były poprawne, jednakże nie bierze odpowiedzialności za efekty wykorzystania ich; nie gwarantuje
także poprawnego działania programów shareware, freeware i public domain.
Uszkodzone podczas wysyłki płyty wymienia redakcja.
Zend Platform 2 80 Wszystkie znaki firmowe zawarte w piśmie są własnością odpowiednich firm
i zostały użyte wyłącznie w celach informacyjnych.
Ian Morse
Redakcja używa systemu automatycznego składu
Ian przedstawia Zend Platform 2 – dobrze za- Do tworzenia wykresów i diagramów wykorzystano program firmy

projektowaną i wysoce wydajną warstwę ser- Osoby zainteresowane współpracą prosimy o kontakt: cooperation@software.com.pl
werową. Druk: ArtDruk

Wysokość nakładu obejmuje również dodruki. Redakcja nie udziela pomocy technicznej w instalowaniu
i użytkowaniu programów zamieszczonych na płytach CD-ROM dostarczonych razem z pismem.
ZAPOWIEDZI 82 Sprzedaż aktualnych lub archiwalnych numerów pisma po innej cenie niż wydrukowana na okładce
– bez zgody wydawcy – jest działaniem na jego szkodę i skutkuje odpowiedzialnością sądową.

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


Zapowiedzi artykułów, które planujemy w na-
polskiej , francuskiej
stępnym wydaniu naszego pisma.

PHP Solutions Nr 1/2007 www.phpsolmag.org 5


Aktualności

Konferencja phptech 2007


Wielkimi krokami zbliża się jedna z największych
Recepty dla deweloperów PHP-GTK2
konferencji o PHP: phptech 2007. Najbliższa
edycja będzie miała miejsce w Chicago. Między
16, a 18 maja zostanie tam przedstawionych po-
W poprzednim numerze informo-
waliśmy o zbliżeniu się poziomu
ukończenia dokumentacji PHP-GTK2
nad 35 prezentacji. Wstęp na konferencję kosz-
tuje wprawdzie aż 700 USD, jednak z pewno- do 50%. Już teraz jednak można w In-
ścią warto poświęcić trochę pieniędzy choć raz
w roku, by otrzymać świeżą porcję nowinek ze ternecie znaleźć zapiski wielu osób na
świata PHP prosto od największych wybitności temat tworzenia aplikacji tym narzę-
z nim związanych. Bilety na poprzednią edycję
zostały w pełni wyprzedane już na miesiąc przed
dziem. Wyzwaniem jest jednak, by na-
konferencją, toteż rejestrować się na obecną pisać aplikację w pełni wykorzystują-
można już teraz. Organizatorzy zapowiadają du-
cą nie do końca jeszcze opisane funk-
żą ilość prezentacji typu BYOL (ang. Bring Your
Own Laptop), podczas których widownia będzie cje. Przed podobnym problemem sta-
mogła pisać kod wraz z prelegentem i testować nął autor php-gtk2 CookBook. Sam do-
go na udostępnionym, oficjalnym serwerze kon-
ferencyjnym. Materiały prezentacyjne zostaną szedł do wielu istotnych wniosków, ze- ne przy instalacji PHP-GTK2 na systemie
opublikowane na stronie konferencji, jeśli więc brał wiadomości z wielu blogów, wyse- Linux oraz Windows, a także linki do list
nie mamy czasu lub pieniędzy, wciąż możemy
poznać szczegółową treść wykładów.
lekcjonował i skatalogował. dyskusyjnych, for, i blogów ludzi związa-
http://hades.phparch.com/ceres/public/tek Rezultatem jest zbiór ponad 100 prak- nych z tym rozszerzeniem PHP. Na witry-
tycznych porad, przydatnych przy two- nie projektu znajdziemy ponadto przykła-
Konferencja PHP
w Vancouver rzeniu aplikacji w PHP-GTK2. Wszystkie dowe aplikacje, manual i turoriale. Strona
Mniejsza konferencja będzie natomiast mia- odpowiedzi na najczęściej zadawane ta stanowi repozytorium najważniejszych
ła miejsce w Vancouver między 12, a 14 lu- pytania są opatrzone zrzutami ekranów, informacji o PHP-GTK2, jest to pierwszy
tego 2007. Organizatorzy zapowiadają wie-
le wybitności, które zaprezentują wczesne wer- a przeglądać je możemy używając wy- przystanek dla wszystkich wielbicieli tego
sje wykładów przygotowanych na konferen- szukiwarki (strona jest świetnie zindek- typu aplikacji okienkowych.
cję php|tech. Cena wstępu nie została jeszcze
sowana przez Google), według tematyki,
ustalona, jednak powinna być dużo niższa, niż
w poprzednim przypadku. Szczegóły na temat lub określonego widgetu. Początkujący http://www.kksou.com
tej konferencji są podawane na bieżąco na stro- programiści znajdą tu informacje pomoc-
nie jej organizatorów.
http://vancouver.php.net

Kobiety w PHP?
Jak najbardziej! HotScripts – największa skryptoteka PHP
Na początku października tego roku, kobie-
ty programujące w PHP wreszcie ujawniły się.
Wraz z rozpowszechnieniem się wiadomości,
o powstaniu grupy dyskusyjnej przeznaczo-
W iększość deweloperów PHP jeśli
nie odwiedziła, to przynajmniej sły-
szała o HotScripts. Praktycznie każda apli-
nej głównie dla płci pięknej, deweloperzy PHP
ze zdumieniem odkryli, że kobiet w tym świat- kacja napisana w tym języku (chociaż nie
ku nie brakuje. Autorki projektu zostały podda-
ne wywiadowi, który teraz możemy przeczytać tylko – HotScripts kataloguje także aplika-
na stronie głównej projektu. Jeśli interesuje nas cje Flash, ASP i wiele innych) trafia do te-
trochę świeższe podejście do programowania
i mamy ochotę przeczytać ciekawy
go repozytorium. Tym samym, na witrynie
wywiad, warto odwiedzić adres http:// http://hotscripts.com znajdziemy ponad 11
www.phpwomen.org/wordpress/2006/10/22/ 000 skatalogowanych aplikacji PHP. Każ-
interview-with-founding-women/, jednak główną
siłą organizacji pozostaje forum, dostępne pod da z nich opatrzona jest opisem, przydzie-
adresem http://www.phpwomen.org/forum/ lona do odpowiednich kategorii. Podana
http://www.phpwomen.org
jest także jej licencja (oraz, ewentualnie,
Horda naciera na PHP cena) wraz z odnośnikiem do strony pro- nie mamy do wyboru blisko 100 kategorii!
Na popularności zyskuje ostatnio projekt o intry- jektu. Ogrom tych informacji pozwala na Na tym jednak potęga HotScripts się nie
gującej nazwie Horde. Jego podstawą jest fra-
mework o takiej samej nazwie, natomiast ilość sprawne wyszukanie żądanego skryptu w kończy. Serwis ten oferuje także recenzje
modułów na nim zbudowanych jest godna po- jednej z wielu kategorii: systemy blogowe, oraz download ponad 50 książek i 45 arty-
dziwu. Mamy więc do wyboru książki adresowe,
notatnik, harmonogram, menedżer plików oraz CMSy, chaty, organizery plików muzycz- kułów związanych z PHP, linkuje do ponad
klasy np. do sprawdzania i filtrowania e-ma- nych, fora, ankiety, liczniki, galerie... Łącz- 100 stron skupiających społeczność PHP,
ili, generujące kod oparty o technologię AJAX.
Projekt rozwija się dość prężnie, średnio co
zawiera informacje o 150 programach po-
miesiąc publikowana jest nowa wersja frame- mocnych przy pisaniu kodu, popartych po-
worka, wnosząca istotne modyfikacje. Całość nad tysiącem tutoriali, listą 35 agencji fre-
udostępniana jest na licencji GNU LGPL.
http://www.horde.org elancingowych, a wreszcie: linkami do
450 innych stron związanych z PHP. Na-
Łączymy PHP i ColdFusion leży więc pamiętać, że skryptorium, to je-
Fusebox to framework oparty o architekturę
MVC, mający na celu połączenie aplikacji PHP dynie mała część serwisu HotScripts. Od-
i ColdFusion. Jak zachwalają autorzy, jego
wiedzając witrynę, pamiętajmy, by i nasze
głównym atutem jest szybkość wykonywania
kodu. Framework jest udostępniany na darmo- dzieło umieścić w największym repozyto-
wej licencji i z pewnością przypadnie do gustu rium skryptowym świata!
deweloperom, którzy znają już ColdFusion, lecz
potrzebują możliwości oferowanych przez PHP.
http://www.fusebox.org http://hotscripts.com

6 www.phpsolmag.org PHP Solutions Nr 1/2007


Aktualności

Gdzie szukać pomocy? PHP od podstaw


Niektórzy z nas na pewno dopiero zaczyna-

J uż kilka numerów temu wspomi-


naliśmy o forum SitePoint (http://
sitepoint.com), jako doskonałym miejscu
ją swoją przygodę z PHP. Inni, mimo wpra-
wy w pisaniu, wciąż napotykają trudności przy
nowych zagadnieniach (np. zagadnienia po-
łączenia ODBC w PHP). W3Schools (http:
na poznanie ciekawych ludzi, ich pomy- //www.w3schools.com), specjalizujące się w
pisaniu elektronicznych podręczników na te-
słów, a nade wszystko: znalezieniu solu- maty związane z Internetem, udostępniło bar-
cji na dręczące nas problemy związane z dzo dobry projekt, skierowany na początkują-
cych użytkowników, a traktujący o PHP. Pod-
PHP. Forum to, choć ma aż 141 tysięcy ręcznik ten można traktować jak poszerzenie
użytkowników, traktuje o wielu aspektach manuala PHP. Znajdziemy tu więc opisy pę-
tli i instrukcji warunkowych, ale też przykłady
Internetu, tworzenia stron i ich marketin-
tworzenia systemu uploadu plików na serwer,
gu. Jeśli trudno nam znaleźć tam rozwią- ste-bin, czyli miejsce, w które możemy objaśnienia na temat połączeń PHP z różny-
zanie naszego problemu, możemy spró- wkleić nasz kod PHP, nie narażając się na mi typami baz danych, czy parsowania plików
XML. Całość napisana jest przystępnym języ-
bować na forach ukierunkowanych ści- oskarżenia o zapychanie kanału bądź wąt- kiem. Dodatkowo, na stronie W3Schools znaj-
ślej na PHP. Naszym pierwszym przy- ku na forum. Dodatkowo, wklejając kod do dziemy kilka innych ciekawych pozycji pod-
ręcznikowych oraz propozycje hostingów, po-
stankiem może być forum PHP Editors takiego systemu, umożliwiamy innym jego rady na temat tworzenia stron i różnego ty-
(http://www.php-editors.com), mające bli- edycję, a składnia jest odpowiednio wcię- pu statystyki.
http://www.w3schools.com/php/default.asp
sko 10 tysięcy zarejestrowanych progra- ta i pokolorowana, my zaś otrzymujemy
mistów PHP. Jeśli nie powiedzie nam się i łatwy do rozpowszechnienia link z kodem Szukamy gotowców,
tam, lub zależy nam na czasie, warto tak- źródłowym. W Internecie znajdziemy wie- czyli skryptoria PHP
że zadać pytanie na PHP Developers Ne- le skryptów typu paste-bin, my polecamy Każdy deweloper PHP musi czasami się-
gnąć po kawałki cudzego kodu. Czy to w ce-
twork (http://forums.devnetwork.net) mają- ten z http://www.phpriot.com/resources/ lach edukacyjnych, by oszczędzić czas, lub
cym 25 000 użytkowników oraz na Coding phpaste/. z braku pomysłu, szukamy gotowych rozwią-
zań często pojawiających się problemów. Do-
Forums (http://www.codingforums.com) z
tychczas, w kategorii skryptoriów, niewzrusze-
bazą blisko 50 000 użytkowników. W przy- http://www.phpriot.com/resources/ nie królował serwis HotScripts (http://www.hot-
padku, gdy niezbędna jest natychmiasto- phpaste/ scripts.com), mający w swoim repozytorium
ponad 10 000 skatalogowanych aplikacji PHP.
wa pomoc, powinniśmy skierować się na http://www.sitepoint.com/forums Na rynek profesjonalnych repozytoriów wkro-
jeden z serwerów sieci IRC, np. EFNet, http://www.php-editors.com/forums czył jednak konkurent – ScriptSearch. W swo-
ich zasobach posiada on już ponad 2 000
odwiedzając kanał #php. W każdym z po- http://forums.devnetwork.net aplikacji, a dodatkowo na witrynie projektu
wyższych przypadków, przyda się tzw. pa- http://www.codingforums.com znajdziemy zbiór artykułów, tutoriali i linków
związanych z PHP.
http://www.scriptsearch.com/PHP

php Interactive php directory

C
PHP Directory to projekt, w założeniu które-
zy nie często spotykamy się z pro- go jest skatalogowanie najistotniejszych linków
stymi problemami, których rozwiąza- powiązanych z tym językiem. W tym repozyto-
rium znajdziemy informacje o grupach dysku-
nia nie jesteśmy całkowicie pewni, mimo, syjnych, artykułach, pismach, newsach, aplika-
że zawiera ono ledwie kilkanaście linijek cjach IDE, konferencjach, publikacjach i wie-
kodu? Napisanie tego kodu nie stano- lu innych zagadnieniach kluczowych dla dewe-
loperów PHP. Stąd trafimy też na blogi wybit-
wi problemu, ale czas potrzebny na po- ności ze światka PHP. Chociaż PHP Directo-
łączenie się z serwerem, upload plików ry dopiero się rozwija, już teraz stanowi dosko-
nały zbiór linków dla głodnego informacji pro-
i ich egzekucja w przeglądarce to zbęd- gramisty.
ne sekundy, które odrywają nas od głów- no wywołana sesja skryptu. Dzięki takie- http://www.phpdirectory.com
nego toku myślenia przy programowaniu mu rozwiązaniu, w jednym oknie prze-
Miniaturki w PHP
większej aplikacji. Z pomocą przychodzi glądarki możemy sprawdzić kilka warian- z phpThumb()
php Interactive, umożliwiający wykonanie tów naszego kodu. Każdej zakładce mo- phpThumb() to rozwinięty skrypt, generujący
kodu PHP bezpośrednio z poziomu prze- żemy nadać unikalną nazwę. Interfejs miniaturki. Wynikowy obrazek może być więk-
szy lub mniejszy od oryginału. Obróbce może
glądarki. Po instalacji pakietu, wystarczy php Interactive zawiera także podręczną zostać poddana całość grafiki lub jej fragment.
wejść na nasz ustalony adres, by ujrzeć wyszukiwarkę, podobną do tej z http:// Dodane mogą zostać tło i obramowanie. Źró-
dłowy plik może być na serwerze zdalnym, lo-
stronę, na którą możemy wkleić nasz php.net, która niejednokrotnie przyda się kalnym, lub w bazie danych. Tworzenie obra-
kod PHP. Rezultat jego działania otrzy- w razie otrzymywania nieoczekiwanych zów GIF jest możliwe z lub bez biblioteki GD.
mamy po naciśnięciu jednego przycisku. wyników. Skrypt do działania nie wyma- Podobnie sprawa ma się z formatem BMP i bi-
blioteką ImageMagick. W przypadku posiadania
Ponieważ często zdarza się, że kod PHP ga żadnego dodatkowego oprogramo- zainstalowanej wersji tej ostatniej, możliwa jest
zwraca tekst zamknięty w znaczniki, de- wania (np. bazy danych), chociaż kata- generacja obrazu w każdym przez nią obsłu-
giwanym formacie. Poza tymi formatami, ma-
weloperzy projektu php Interactive udo- log z nim warto zabezpieczyć przed pu- my do wyboru PNG, JPEG i ICO. Dodatkowo,
stępnili dwie możliwości podejrzenia wy- blicznym dostępem. Projekt jest udostęp- autor udostępnił wiele przydatnych filtrów (roz-
mycie, cień, zaokrąglanie krawędzi, wyostrza-
ników wykonania kodu (ang. output): czy- niany na zasadach określonych w licen- nie, poziom kontrastu, sephia, negatyw itd.)
sty tekst (RAW), lub tekst sformatowany cji GNU GPL. oraz funkcję cachingu. Wygenerowane obrazy,
(HTML). Dodatkowo, do naszej dyspo- zgodne ze standardem EXIF, mogą być zapisy-
wane, eksportowane, bądź użyte bezpośrednio
zycji zostały oddane specjalne zakładki Licencja: GNU GPL. w innych aplikacjach.
(ang. tabs), każda z nich działa jak osob- http://www.hping.org/phpinteractive http://freshmeat.net/projects/phpthumb

PHP Solutions Nr 1/2007 www.phpsolmag.org 7


Aktualności

Alternatywa dla Planet PHP Shell w PHP


W
W poprzednim numerze pisaliśmy o centrum
aktualności ze świata PHP, jakim jest Planet
szyscy znamy procedury instalacji
PHP (http://www.planet-php.org/). PHP Develo- większości nowych skryptów PHP:
per to podobny projekt, agregujący informacje autorzy radzą nam pobrać archiwa za po-
z wielu źródeł (także blogów). Jego przewagą
jest niewątpliwie popularny tag-cloud, który ob- mocą aplikacji wget, rozpakować je i roz-
razuje i ułatwia wyszukiwanie najciekawszych począć instalację i konfigurację z poziomu
wiadomości. Dodatkowo, na stronie PHP Deve-
loper znajdziemy odnośniki do ciekawych arty- przeglądarki. Pierwsze dwa zadania wy-
kułów o PHP, tutoriali oraz informacje o nadcho- konujemy zazwyczaj przez shell (opcjo-
dzących wydarzeniach i konferencjach.
Licencja: BSD.
nalnie ftp), jednak nie zawsze przecież
http://www.phpdeveloper.org mamy czas i sposobność, by z niego sko-
rzystać (choćby z powodu blokady odpo-
Generator wątków RSS
RSS Writer Class to skrypt, umożliwiający pro- wiednich portów). Z pomocą przychodzi chomienia skryptu pod PHP5, mogą wy-
stą generację plików XML w standardzie RSS PHP Shell – skrypt, umożliwiający wy- stąpić problemy z autentykacją – kilka so-
0.9, 0.91, 1.0 i 2.0. Pozwala na dodawanie
opcjonalnych znaczników graficznych, zaś udo-
konywanie poleceń przez interfejs www, lucji tego problemu można znaleźć w In-
stępniany jest na licencji BSD. Dodatkowo, do a skierowanych bezpośrednio do powło- ternecie. PHP Shell doskonale sprawdza
pakietu dołączony został szablon XSL, by uła-
ki systemu operacyjnego, na którym pra- się w manipulacji dużymi zbiorami plików
twić podglądanie wyników jako stron HTML w
przeglądarkach obsługujących XML. cuje serwer http. Sam autor określa go ja- i szybkiego rozpakowywania archiwaliów.
http://freshmeat.net/projects/rsswriterclass ko odpowiednik połączenia telnet z lek- Efekty wykonywanych poleceń zostają
Świetny generator plików PDF ką dawką SSH. By uruchomić aplikację, zwracane do naszego okienka – dotyczy
CPDFWriter to klasa napisana w PHP5, służą- wystarczy wgrać pliki na serwer (nie za- to także błędów. PHP Shell, odpowied-
ca do generacji plików PDF, a oparta na projek-
pominając o zmianie loginu oraz hasła!) nio zabezpieczony, potrafi skrócić czas w
tach TCPDF i FPDF. Do zasobów możemy do-
dać grafiki (GIF, JPG, PNG), elipsy, efekty prze- i przejść pod odpowiedni adres. Powita przypadku potrzeby instalacji i testowania
zroczystości, wypełnienia (także graficzne- nas raczej skromne okienko, do którego wielu skryptów w krótkim czasie, a w po-
go i gradientowego) i wiele innych, dzięki cze-
mu tworzone arkusze wyglądają na prawdę im- możemy wpisać różne przydatne komen- łączeniu z aplikacjami wcześniej zapro-
ponująco. Kolejną zaletą klasy jest jej licencja dy, np. ls, free, df, du i wiele innych. PHP jektowanymi, a pozostającymi po stronie
– GNU LGPL.
http://freshmeat.net/projects/cpdfwriter Shell ma jednak pewne ograniczenia: nie serwera, może stanowić doskonały po-
http://www.palos.ro/index.php?page=opensou uda nam się uruchomić w nim żadnej apli- most z naszym zdalnym serwerem na
rce_active
kacji graficznej, ani wprowadzić treści do porcie serwera http.
Manipulacja archiwaliów tych już uruchomionych.
z poziomu PHP Kod skryptu został napisany pod Licencja: GNU GPL.
Autor powyższego projektu stworzył także roz- PHP4 i działa jedynie z wyłączonym try- http://mgeisler.net/php-shell
szerzenie do PHP5, ułatwiające edycję archi-
waliów ZIP, TAR, GZ, BZ2, BZ, TGZ, TBZ. Mo- bem Safe Mode. W przypadku próby uru- http://freshmeat.net/projects/phpshell
żemy tworzyć nowe archiwa, jak i edytować
już istniejące: dodawać, usuwać, zmieniać na-
zwy, kopiować pliki i foldery spakowane, a tak-
że edytować ich atrybuty. Buforowanie zawarto- Tiki CMS
T
ści może odbywać się na dysku lokalnym lub w iki CMS to szybko rozwijający się
pamięci. Dodatkowo, dla bardzo szybkiej kom-
presji, do pakietu włączono funkcje kompresji i system zarządzania treścią o otwar-
dekompresji algorytmu LZF, które działają w pa- tym kodzie. Autorzy zachwalają, że na-
mięci operacyjnej komputera. psArchive zawie-
ra także obszerną dokumentację. daje się tak do aplikacji portalowych, jak
http://www.palos.ro/index.php?page=opensou na prywatne strony. Kod rozwija 256 pro-
rce_active
gramistów, zaś społeczność reprezentu-
Nowa biblioteka Flashowa je ponad 10 000 zarejestrowanych użyt-
SDK dla PHP kowników. Tiki CMS korzysta z systemu
FreeMovie to projekt mający być alternatywą szablonów Smarty i oferuje między inny-
dla SDK Macromedii, oferujący potężne API dla
operacji na plikach SWF. Głównymi atutami bi- mi moduły artykułów, newsów, for dys-
blioteki są: konwersja czcionek TrueType do fil- kusyjnych, newsletterów, blogów, galerie datkowo, na stronie http://doc.tikiwiki.org/
mów Flash, obsługa wielu formatów graficznych
oraz zaawansowane funkcje do rysowania,
graficzne, trackery, ankiety, quizy, system tiki-index.php?page=Features dowiemysię,
operowania na dźwięku oraz animacjach. Pa- wymiany bannerów, chat, webmail, kalen- czy Tiki to CMS dla nas – każdy z modu-
kiet jest rozpowszechniany na licencji XFree86, darz, mapy, statystyki, strony WAP, wątki łów ma przypisaną ocenę odnoszącą się
która pozwala na używanie go za darmo nawet
w komercyjnych projektach. RSS, systemy kategorii, shoutbox, skórki, do prostoty instalacji, administracji, stabil-
http://freemovie.sourceforge.net live support, wikipedię, i wiele innych. Na ności i jakości. Dzięki temu możemy jesz-
PHP Shell Terminal stronie projektu znajdziemy wiele przydat- cze przed pobraniem pakietu dowiedzieć
Jeśli nie odpowiada nam aplikacja PHP Shell, nych materiałów: artykuły, fora dyskusyj- się, ile pracy będziemy musieli włożyć, by
szerzej opisywana w tym wydaniu aktualności,
neitp. oraz filmy demonstracyjne. CMS dostosować system do naszych potrzeb.
ale podoba nam się sama idea, możemy się-
gnąć po konkurencję. PHP Shell Terminal swo- dostępny jest w wielu wersjach języko-
im wyglądem ma na celu upodobnienie się do wych: angielskiej, polskiej, czeskiej, duń- Licencja: GNU LGPL.
KDE, zaś jego funkcjonalność jest zbliżona do
wspomnianego wcześniej skryptu. skiej, niemieckiej, francuskiej, holender- http://tikiwiki.org
Licencja: GPL. skiej, włoskiej, japońskiej, portugalskiej, http://freshmeat.net/projects/tiki
http://sourceforge.net/projects/phpterm
słowackiej, hiszpańskiej i szwedzkiej. Do-

8 www.phpsolmag.org PHP Solutions Nr 1/2007


Opis CD

MySQL Serwer 5.0

T utorial pokazujący krok po kroku jak


zainstalować oraz skonfigurować
MySQL Serwer. Przedstawia również
jak wykorzystywać dodatkowe narzędzia
zawarte w MySQL GUI Tools Bundle for
5.0. Dowiemy się również jak połączyć
się z zainstalowanym serwerem baz da-
nych. Niezwykle popularna, szybka, wie-
lowątkowa baza danych umożliwiająca
udostępnianie zasobów wielu użytkowni-
kom i wykorzystująca język SQL. Umoż-
liwia budowanie wieloserwerowych baz
danych, którymi łatwo się zarządza i uak-
tualnia. Produkt stanowi doskonałą kon-
kurencję dla innych baz danych opar-
tych na technologii SQL (m.in. firmowa-
nych przez Microsoft i Oracle). Aktualiza-
cja MySQL do wersji 5.0

Nowe e-booki
T ematy bezpieczeństwa sieci zawsze
są aktualne. Każdy specjalista z za-
kresu oprogramowania nie uniknął kwestii
związanych z programowaniem sieciowym.
Zarówno PHP i MySQL są nie odłącznym
elementem tej dziedziny.
Dopełniając się odpowiednio sta-
nowią poważne narzędzie o wielkich
możliwościach. Na płycie zamieścili-
śmy parę pozycji o powyższej tematy-
ce, które warto przejrzeć:

• Built Your Own Database Driven


Website Using PHP&MySQL 8.1.4
Documentation
• MySQL 5.1. Reference Manual

Pełna wersja kursu HTML – premiera kolejnej edycji


Z przygotowanego specjalnie dla czytel-
ników naszego magazynu kursu moż-
na dowiedzieć się jak wygląda typowy do-
kument HTML, w jaki sposób zachęcić in-
ternautów aby odwiedzili daną stronę, co
to są podstrony. Jak również w jaki sposób
wpisuje się tekst na stronach WWW, jakie
są zasady poprawnego wpisywania zna-
ków interpunkcyjnych w tekście kompute-
rowym. Z kursu można wynieść też wiedzę
na temat znaczników i atrybutów oraz jaki
sposób układać tekst na ekranie, jaki spo-
sób zmienić wygląd tekstu, jak zmienić tło
strony czy też jaki sposób wstawić obra-
zek na stronę WWW.
Autor: Sławomir Kokłowski
Kontakt: koklowski@poczta.onet.pl

10 www.phpsolmag.org PHP Solutions Nr 1/2007


Na CD
Przetestuj dowolne skrypty
bez instalacji!

HITY
Pełna wersja kursu HTML
- MySQL Serwer 5
- XAJAX: Łatwy AJAX
dla programistów PHP
E-BOOKS
- Built Your Own Database Driven
Website Using PHP and MySQL
- PostgrSQL 8.1.4 Documentation
- MySQL 5.1 Reference Manual
na naszej stronie internetowej pod adresem www.phpsolmag.org/pl

na naszej stronie internetowej pod adresem www.phpsolmag.org/pl


Wszystkie listingi z artykułów zostały zamieszczone

Wszystkie listingi z artykułów zostały zamieszczone


Dla początkujących

Tworzymy aplikacje
okienkowe z PHP-Qt
Stopień trudności: lll
Thomas Möenicke

Wraz z pojawieniem się PHP-GTK, PHP zawitał


na desktopach jako prosty i wygodny język do
tworzenia obiektowo zorientowanych aplikacji
okienkowych. Pora się zmierzyć z Qt– kolejnym
standardem GUI, na którym opiera się m.in.
KDE. Dzięki PHP-Qt jest to proste zadanie...

C
hoć PHP-Qt znajduje się we cie dla standardu D-BUS pod Linuk-
wczesnej fazie rozwoju, zaim- sem i Uniksem. Wspomniane wersje Qt
plementowano w nim już naj- umożliwiają również integrację aplikacji
ważniejsze technologie, co umożliwia z konkurencyjnym wobec KDE środowi-
tworzenie prostych aplikacji. Pokażemy skiem GNOME.
później, jak pisać w PHP programy ko- W najnowszej wersji PHP-Qt zosta-
rzystające z Qt na przykładzie kalkulato- ło zaimplementowanych 75 należących
ra. Zacznijmy jednak od ogólnego omó- do Qt klas. Następne wydanie, nad któ-
wienia Qt. rym trwają prace, ma zawierać prawie
Qt zawiera bibliotekę klas, a także wszystkie spośród wspomnianych 400
narzędzia ułatwiające tworzenie aplika- klas. Biblioteka Qt ma rozwinięty, doj-
cji oraz internacjonalizację. W tej pierw-
szej znajduje się ponad 400 klas odpo- Co powinieneś wiedzieć:
W SIECI wiedzialnych za tworzenie graficznych Powinieneś znać podstawy programo-
interfejsów użytkownika (GUI, ang. Gra- wania obiektowego. Przydatna będzie
phical User Interface), wygląd aplikacji również znajomość ogólnych zasad
1. http://php-qt.berlios.de tworzenia interfejsów graficznych (GUI)
– strona domowa PHP-Qt
okienkowych (layout), obsługę SQL-a, w Qt lub innych systemach widgetów
2. http://docs.trolltech.com/4.1 sieci, XML-a, internacjonalizację, współ- (np. wxWidgets czy GTK).
– dokumentacja Qt pracę z OpenGL i wiele innych. Qt4.1
3. http://www.trolltech.no
– strona główna firmy i 4.2 zawierają również silnik obsługi Co obiecujemy:
Trolltech PDF-ów, wsparcie dla tworzenia grafiki Pokażemy, jak korzystając z PHP-Qt
4. http://www.trolltech.com/ utworzyć w PHP aplikację korzystającą
products/qt/learnmore/ SVG, frameworki: Graphics-View oraz
z Qt (kalkulator) i objaśnimy podstawo-
classchart – klasa Qt 4.1 undo (cofanie operacji), arkusze sty- we zagadnienia związane z Qt.
lów dla widgetów (kontrolek) czy wspar-

12 www.phpsolmag.org PHP Solutions Nr 1/2007


PHP-Qt Dla początkujących

rzały model obiektowy, a jej API jest ele- type casting). Kalkulator będzie umoż-
ganckie i przejrzyste, co ułatwia two- liwiał wykonywanie podstawowych ope-
rzenie aplikacji i czyni je przyjemniej- racji arytmetycznych. Będzie miał pa-
szym. Firma Trolltech (twórca Qt) roz- mięć do przechowywania liczb, wyświe-
powszechnia Qt4 na podwójnej licen- tlacz, klawiaturę numeryczną oraz przy-
cji (komercyjnej lub GNU GPL) dla plat- ciski służące do kasowania pojedyn-
form X11 (X-Window), MacOS X i MS czych cyfr lub całych wpisanych warto-
Windows. ści oraz wykonywania obliczeń.
Przejdźmy teraz do naszego kal- Rysunek 1. Kalkulator stworzony w PHP-Qt
kulatora (zob. Rysunek 1), na podsta- Aplikacje wPHP-Qt:
wie którego pokażemy, jak stosować zaczynamy Zaczynamy od utworzenia nowej in-
główne koncepcje Qt, takie jak sygnały Zanim jednak przejdziemy do kalkulato- stancji $app klasy QApplication. Dziedzi-
(ang. signals), sloty (ang. slots), dzie- ra, musimy wiedzieć, jak utworzyć okno czy ona z QCoreApplication i jest głów-
dziczenie, definiowanie wyglądu (lay- główne aplikacji. W tym celu przyjrzyj- ną klasą Qt, zarządzającą ustawieniami
out), łańcuchy, przeciążenie metod my się prostszemu przykładowi z Li- oraz interakcją z użytkownikiem (control
(overloading) oraz zmiana typów (ang. stingu 1. flow). Możemy przekazać parametry $ar-
gc i $argv do jego konstruktora.
Następnie tworzymy obiekt $window
Instalacja i szybki start klasy QWidget, która z kolei jest klasą ba-
Obecna wersja PHP-Qt pracuje wyłącznie pod Linuksem; planowane wydanie (port) dla zową dla wszystkich widgetów (kontro-
Windows nie zostało jeszcze ukończone.
lek). Jej zadaniem jest ich prezentacja na
Na dołączonej do pisma płycie CD PHP Solutions Live! umieszczamy zainstalowa-
ne, gotowe do pracy PHP-Qt wraz z omawianym przez nas przykładem. Jeśli chcesz za- ekranie oraz odbieranie zdarzeń. Z jej pól,
instalować PHP-Qt na swoim komputerze, musisz pobrać źródła najnowszego wydania slotów i metod mogą korzystać wszystkie
tej biblioteki pod adresem http://php-qt.berlios.de i rozpakować je na twardym dysku.. obiekty, które z niej dziedziczą. Obiekt
Opiszemy instalację wersji 0.0.3. Poza samym PHP-Qt potrzebne będą:
$window będzie głównym oknem naszej

Ÿ źródła parsera PHP5.1 (lub nowszego), aplikacji. Ustawimy jego rozmiar metodą
Ÿ źródła PHP-Qt, resize() na 200 (szerokość) i 120 pikse-
Ÿ pliki nagłówkowe Qt 4.1 i skompilowana biblioteka Qt. li (wysokość).
Kolejnym obiektem, który utworzy-
Zalecana jest kompilacja PHP z użyciem prefiksu (parametr --prefix), aby zachować my, będzie przycisk (ang. button) $quit
obecną na dysku wersję PHP (jeżeli takową posiadamy). Jak zwykle, zaczynamy od wy- klasy QPushbutton. Przypiszemy mu na-
konania polecenia configure:
pis Quit, który się na nim ukaże i za-
./configure –prefix=/usr/local/php-5.1.1 gnieździmy go w oknie $window: w taki
make właśnie sposób umieszczamy kontrolki
w oknach. Następnie ustawimy współ-
make install (wykonujemy tę operację zalogowani jako root)
rzędne przycisku $quit (kolumna, wers,
Następnie przechodzimy do katalogu php_qt i wpisujemy:
szerokość, wysokość) używając jego
./configure metody setGeometry(). Ostatnią rze-
--with-php_qt[=/path/to/qtheaders] czą, którą zrobimy z naszym przyci-
--with-qtlib[=/path/to/qtlib]
skiem, bedzie przypisanie mu sygna-
--with-php-config=/usr/local/php-5.1.1/bin/php-config
łu clicked() odpowiadającego za je-
Ostatni parametr wskazuje skrypt php-config, drugi ścieżkę dostępu do skompilowanej bi- go kliknięcie myszką oraz slotu quit():
blioteki Qt, a pierwszy – pliki nagłówkowe Qt. Możemy teraz skompilować kod źródłowy w ten sposób kliknięcie tego przycisku
wykonując make install (musimy być zalogowani jako root). Po udanej kompilacji oraz będzie powodowało zakończenie dzia-
instalacji powinniśmy móc uruchomić tutoriale dołączone do pakietu PHP-Qt poleceniem: łania aplikacji . Dodajmy, że slot quit()
jest wbudowaną metodą klasy QAppli-
/usr/local/php-5.1.1/bin/php-qt/tutorials/t1/main.php
cation. Przypisując nazwę obiektu $app
Jesteśmy gotowi, aby napisać nasz pierwszy program: jak zwykle będzie to Hello World określamy też przynależność przycisku
(przykład z tutoriala 1), którego efekt działania pokazujemy na Rysunku 2: $quit do naszej aplikacji.
Teraz pozostało wyświetlenie okna
if(!extension_loaded('php_qt')) {
na ekranie ($window->show() oraz uru-
dl('php_qt.' . PHP_SHLIB_SUFFIX);
} chomienie głównej pętli naszej aplika-
$app = new Qapplication($argc,$argv);
$hello = new QPushButton("Hello world!");
$hello->show();
$app->exec();

Rysunek 2. Hello World w PHP-Qt

PHP Solutions Nr 1/2007 www.phpsolmag.org 13


Dla początkujących PHP-Qt

cji ($app->exec()). Zostanie ona za- że klasy Calculator i Button są do- Okno główne:
trzymana jeżeli główny widget (okno) stępne w pakiecie PHP-Qt (examples/ dziedziczenie
zostanie zniszczony lub po wywoła- calculator/calculator.php). Tam też mo- Jak już wspomnieliśmy, okno główne
niu exit(). żemy od razu przetestować jego dzia- Calculator jest klasą pochodną wobec
łanie. QDialog, tak więc wszystkie metody, sy-
Tworzymy kalkulator Przejdźmy teraz do skryptu ma- gnały i sloty tej drugiej są dziedziczone.
Przyjrzyjmy się teraz budowie kalkula- in.php. Na samym początku sprawdza- Możemy je przystosować do naszych po-
tora. Składa się on z dwóch klas: Cal- my, czy rozszerzenie php_qt zostało za- trzeb i tworzyć nowe, np. te, które odno-
culator (calculator.php) i Button (but- ładowane i jeśli nie, ładujemy je. Następ- szą się do przycisków.
ton.php) oraz głównego skryptu ma- nie dołączamy plik calculator.php i po- Potrzebujemy metod obsługujących
in.php, który uruchamia całą aplikację dobnie jak w naszym poprzednim przy- działania użytkownika, czyli slotów. Bę-
(Listing 2). Plik calculator.php zawie- kładzie, tworzymy instancję $app kla- dą nimi: digitClicked() (kliknięcie klawi-
ra 390 linijek kodu, więc nie będziemy sy QApplication. Potem inicjujemy okno sza cyfry), unaryOperatorClicked () (klik-
go szczegółowo omawiać: skupimy się główne kalkulatora, które u nas jest in- nięcie przycisku .....................), additive-
na tych fragmentach, które będą nam stancją $calc klasy Calculator, pokazu- OperatorClicked () (kliknięcie przycisku
potrzebne do wyjaśnienia jego działa- jemy je ($calc->show() i uruchamiamy dodawania), multiplicativeOperator-
nia. Kompletny skrypt main.php, a tak- pętlę główną aplikacji ($app->exec()). Clicked () (kliknięcie przycisku mnoże-
nia), equalClicked () (kliknięcie przycisku
Listing 1. Prosty przykład działania Qt: okienko zawierające przycisk Quit równa się), pointClicked() (kliknięcie
przycisku kropki), changeSignClicked ()
$app = new QApplication($argc,$argv); (kliknięcie przycisku +/- służącego do
zmiany znaku), backspaceClicked () (klik-
$window = new QWidget();
$window->resize(200,120);
nięcie backspace, czyli kasowanie cy-
fry), clear() (czyszczenie wpisanej lub
$quit = new QPushButton("Quit", $window); wyliczonej wartości), clearAll() (czysz-
$quit->setGeometry(10, 40, 180, 40); czenie całego wyświetlacza), clearMem-
ory() (czyszczenie pamięci kalkulatora),
$quit->connect($quit,SIGNAL("clicked()"),$app,SLOT("quit()"));
read _ Memory () (odczyt pamięci kalkula-

$window->show(); tora), setMemory() (ustawianie wartości w


$app->exec(); pamięci kalkulatora) i addToMemory() (do-
dawanie wartości w pamięci kalkulatora).
Listing 2. Główny plik kalkulatora (main.php) Nazwy wszystkich slotów będą zapisane
<?php w tablicy $slots (Listing 3), dzięki której
if(!extension_loaded('php_qt')){ biblioteka Qt będzie je mogła obsłużyć.
dl('php_qt.'.PHP_SHLIB_SUFFIX); Potrzebne będą też metody, które nie
} są slotami: createButton(), która tworzy
require_once('calculator.php');
przyciski, abortOperation() do wycofa-
$app=new Qapplication($argc,$argv);
$calc = new Calculator(); nia działania oraz calculate(), która bę-
$calc->show(); dzie obliczać wynik.
$app->exec();
?> Sygnały i sloty – szczegóły
Przejdźmy teraz do bardziej szczegó-
Listing 3. Deklarujemy sloty w tablicy $slots – jest to wymagane przez Qt
łowego omówienia zagadnienia sygna-
private $slots = array( łów i slotów. Jak już wiemy, są one jed-
"digitClicked()", ną z podstawowych koncepcji w Qt,
"unaryOperatorClicked()",
a ich zadaniem jest łączenie wydarzeń
"additiveOperatorClicked()",
"multiplicativeOperatorClicked()",
(np. kliknięcia myszką przycisku doda-
"equalClicked()", wania – tym zajmują się sygnały) z me-
"pointClicked()", todami, które je obsługują (np. dodawa-
"changeSignClicked()", nie dwóch liczb, co z kolei jest zadaniem
"backspaceClicked()",
"clear()",
"clearAll()",
"clearMemory()",
"read_Memory()",
"setMemory()",
"addToMemory()"
);
private $signals = array("");

Rysunek 3. Główny widget w Qt

14 www.phpsolmag.org PHP Solutions Nr 1/2007


PHP-Qt Dla początkujących

slotów). Slot jest wywoływany po wysła- momencie zniszczenia obiektu, które- slocie. Przyciski są tworzone z uży-
niu przez widget połączonego z nim sy- go one dotyczą. Obecna wersja PHP- ciem wspomnianej już metody create-
gnału. Qt nie obsługuje jeszcze slotów z pa- Button(), która wymaga dwóch para-
Sloty to zwyczajne metody w mode- rametrami: funkcjonalność ta jest pla- metrów: opisu, który zostanie wyświe-
lu obiektowym PHP5, które mogą być nowana w najstępnych wersjach tej bi- tlony na klawiszu oraz slotu. Slotami
publiczne (public), chronione (protec- blioteki. będą metody wymienione w zmiennej
ted) lub prywatyne (private) i może- Wszystkie spośród używanych przez $slots z Listingu 3, które będą połą-
my je bezpośrednio wywoływać (nieko- nas przycisków są obiektami klasy QPush- czone z sygnałem clicked() odpowied-
niecznie wskutek wystąpienia zdarze- Button, która dziedziczy z QAbstractBut- nich przycisków (np. slot additiveOper-
nia). Naturalną koleją rzeczy jest ich łą- ton. Z tej drugiej dziedziczą również in- atorClicked() połączymy z sygnałem
czenie z sygnałami. Jeden sygnał mo- ne klasy przycisków, takie jak Q3Button, clicked() przycisku dodawania).
że być podpięty do wielu slotów, a jeden QCheckBox czy RadioButton. Sposób rozmieszczenia przycisków
slot – do wielu sygnałów. Co więcej, mo- Wyświetlaczem kalkulatora będzie reprezentujących cyfry przedstawia-
żemy łączyć sygnały między sobą. Bar- pole tekstowe – obiekt $display klasy my na Listingu 4. Korzystając z meto-
dzo ważne jest to, że w Qt klasa, któ- QLineEdit, która. reprezentuje pojedyn- dy addWidget() obiektu $this->main-
ra może korzystać z sygnałów i slotów, czą linię tekstu z możliwością edycji. Jak Layout() klasy QGridLayout, każdemu z
musi dziedziczyć po QObject. Więcej na w prawdziwym kalkulatorze, przy inicja- nich przypisujemy konkretną kolumnę i
ten temat możemy przeczytać w drugim cji tej klasy wpisujemy wartość 0 (ja- wers, np. equalButton (przycisk równa
tutorialu Qt. ko parametr wysłany do konstruktora). się) będzie miał położenie (5,5). Meto-
Przyjrzyjmy się jeszcze raz pro- Tekst zawarty w tym polu odczytamy da addWidget wymaga podania trzech
stemu przykładowi z Listingu 1, któ- korzystając z metody $display->text(), parametrów: obiektu (np. przycisku),
ry składa się wyłącznie z okna główne- zaś do wpisania go użyjemy metody wersu i kolumny. Dodatkowo, możemy
go i przycisku Quit powodującego za- setText(). zdefiniować dwa opcjonalne parame-
kończenie działania aplikacji. Wszystkie try: rowSpan i colSpan, które pozwalają
widgety dziedziczące z QWidget, w tym Definiowanie wyglądu na łączenie kilku wersów lub kolumn w
nasz przycisk QPushButton, wysyłają sy- (layoutu) okienka jedną, podobnie jak ma to miejsce w ta-
gnały przy wystąpieniu dowolnego wy- Zdefiniujmy teraz wygląd (layout) nasze- belach HTML-owych.
darzenia. W naszym przykładzie jest to go kalkulatora. Określa on sposób or-
sygnał clicked(), wysyłany przez przy- ganizacji widgetów w oknie. Podstawo- Przeciążenie metod
cisk, który klikniemy myszką. Więcej wą klasą służącą do definiowania lay- (overloading)
o sygnałach i slotach można przeczytać outu (menedżerem layoutu, ang. layout Powiedzieliśmy, że parametry rowSpan
w tutorialu 7 PHP-Qt. Do łączenia slo- manager)jest QLayout, z której dziedzi- i colSpan są opcjonalne. Przyciski w
tów z sygnałami służy metoda connect() czą inne, takie jak QHBoxLayout, QVBox- naszym kalkulatorze, poza backspace-
danego widgetu, np.: Layout czy QGridLayout. Główną zale- Button, clearButton () i clearAllBut-
tą menedżerów layoutu jest to, że auto- ton(), są dodawane do layoutu metodą
connect($quit,SIGNAL("clicked()"), matycznie rozmieszczają one elementy addWidget() jedynie z trzema parame-
$app,SLOT("quit()")) w oknie, wymagając od programisty je- trami (obiekt, wers i kolumna). Opcjo-
dynie podania podstawowych parame- nalność rowSpan i colSpan nie jest
Metody SLOT() i SIGNAL() są wymaga- trów (np. kolumny i wersu). osiągana przez przypisywanie im war-
ne, aby zdefiniować sloty i sygnały – bez W naszym kalkulatorze użyjemy tości domyślnych w deklaracji metody
ich użycia nie będzie to możliwe. Metody klasy QGridLayout, która traktuje okno addWidget(), tylko przez przeciążenie
te odpowiadają makrom SIGNAL i SLOT aplikacji jako siatkę (ang. grid) podzie- (ang. overloading) tej metody. Parame-
z Qt dla C++. loną na wiersze i kolumny. Przyciski na- trem o wartości domyślnej jest nato-
Aby rozłączyć sloty i sygnały, mo- szego kalkulatora są pogrupowane wg miast Alignment, ustawiony standardo-
żemy użyć metody disconnect(), ale funkcji: operatory [[unary]], dodawania i wo na 0. Nagłówki metody addWidget()
przeważnie nie jest to wymagane, mnożenia, cyfry oraz inne (np. kasowa- z rowSpan i colSpan przetłumaczone na
gdyż Qt rozdziela je automatycznie w nie cyfr). Każda z grup ma po jednym PHP wyglądają następująco:

Listing 4. Rozmieszczamy (w pętli) przyciski odpowiadające za cyfry QGridLayout::addWidget


w kalkulatorze ($widget, $fromRow,
$fromColumn, $rowSpan,
for ($i = 1; $i < $this->NumDigitButtons; ++$i)
$columnSpan, $alignment = 0)
{

$row = ceil(((8 - ($i+1))) / 3) + 2; A oto wersja bez parametrów pozwalają-


$column = ceil((($i-1) % 3)) + 1; cych na łączenie wersów i kolumn:
$this->mainLayout->addWidget($this->digitButtons[$i],
(int) $row, (int) $column);
QgridLayout::addWidget

} ($widget, $row,
$column, $alignment = 0)

PHP Solutions Nr 1/2007 www.phpsolmag.org 15


Dla początkujących PHP-Qt

Na koniec nadajemy okienku tytuł PHP ton("")) i zwraca obiekt docelowy (tej stosowanie wobec wszystkich napi-
Solutions Calculator. samej klasy, co obiekt podany jako dru- sów, które chcemy wyświetlać. PHP-
gi parametr). Qt automatycznie konwertuje wszyst-
Zmiana typów (ang. type Następnie odczytujemy liczbę wpi- kie łańcuchy PHP na obiekty klasy
casting) saną przez użytkownika. W tym ce- QString.
Zobaczmy teraz, w jaki sposób klasa Cal- lu skorzystamy z metody text() kla- Większość metod Qt również zwra-
culator odnajduje przycisk wciśnięty sy obiektu $display (naszego wyświe- ca łańcuchy tego typu. Korzystanie
przez użytkownika. W tym celu przyjrzy- tlacza). Otrzymany rezultat będzie ty- z QString daje wiele rozmaitych moż-
my się metodzie unaryOperatorClicked() pu QString, a my potrzebujemy liczby, liwości manipulacji łańcuchami, takich
(Listing 5). na której będziemy mogli wykonywać jak ich liczenie, łączenie, zastępowa-
Do określenia, który przycisk zo- działania. Przekonwertujemy więc łań- nie, kasowanie, dzielenie czy konwer-
stał wciśnięty służy metoda sender() cuch na liczbę przy użyciu metody to- sja standardów (ASCII/Unicode/UTF8/
– zwraca ona obiekt, który wysłał sy- Double(): jeśli konwersja się nie powie- UTF16/Latin1 oraz typy numeryczne i
gnał. Metoda ta należy do klasy QOb- dzie, wynikiem będzie 0.0 i wywołana niektóre operatory). Wszystkie łańcu-
ject (z której dziedziczy każdy wid- zostanie metoda abortOperation() kla- chy przechowywane w Qt są domyśl-
get, również przycisk), a dostęp do sy Calculator. nie typu Unicode: stosowanie tego ty-
niej jest możliwy dzięki $this. Widzimy pu wobec łańcuchów podawanych jako
już, dlaczego klasa Calculator dzie- QString: obsługa parametry metod gwarantuje, że będą
dziczy z QDialog, która z kolei jest kla- łańcuchów w Qt wyświetlane poprawnie.
są pochodną wobec QObject. Dokład- Przyjrzyjmy się teraz możliwościom
niejsze informacje na temat dziedzicze- Qt w dziedzinie łańcuchów. Biblioteka Podsumowanie
nia klas w Qt znajdują się pod adresem ta oferuje szerokie możliwości obsłu- Zademonstrowaliśmy podstawowe moż-
http://www.trolltech.com/products /qt/ gi standardu unicode, łańcuchów i po- liwości PHP-Qt i na ich podstawie moż-
learnmore/classchart/. jedynczych znaków. Ułatwia też kon- na ocenić, że rozwój tej biblioteki zmierza
No dobrze, ale metoda sender() wersję typów znaków oraz internacjo- w dobrym kierunku.
zwraca obiekt klasy QObject, a nam nalizację. Obecnie, twórcy tego pakietu zaj-
jest potrzebny przycisk. Użyjemy więc Na Listingu 5 korzystamy z meto- mują się integracją ze SMOKE (któ-
funkcji qobject _ cast(), która zamie- dy tr(), która należy do klasy QObject ry zostanie użyty w następnych wer-
ni obiekt typu QObject na takowy. Wy- i klas pochodnych wobec niej. Zwra- sjach PHP-Qt i jest dołączony w obec-
maga ona podania dwóch parametrów: ca ona tłumaczenie podanego łańcu- nym wydaniu tego pakietu; jego celem
istniejącego obiektu oraz nowej, anoni- cha lub ten sam łańcuch, jeżeli nie ma jest utworzenie powiązań (ang. bin-
mowej instancji (w tym przypadku But- dla niego tłumaczenia. Zaleca się jej dings) pomiędzy PHP a Qt/KDE) oraz
przenosinami PHP-Qt do działające-
Listing 5. Zastosowanie metod qobject_cast i tr() klasy QObject go w systemie Subversion repozyto-
rium KDE.
function unaryOperatorClicked()
Nic więc nie stoi na przeszkodzie,
{
$clickedButton = qobject_cast($this->sender(), new Button(""));
aby wprowadzić do PHP-Qt pozostałe
$clickedOperator = $clickedButton->text(); klasy należące do Qt i KDE. Co wię-
$operand = $this->display->text()->toDouble(); cej, PHP-Qt ma być dostępne nieza-
$result; leżnie od KDE i nie wymagać żadnych
pakietów oprócz parsera PHP i biblio-
if ($clickedOperator->toAscii() == $this->tr("Sqrt")->toAscii()) {
if ($operand < 0.0) {
teki Qt. Lista mailingowa i repozyto-
$this->abortOperation(); rium Subversion pozwalają natomiast
return; śledzić rozwój pakietu PHP-Qt, który z
} każdą wersją staje się coraz lepszy. n
$result = sqrt($operand);

} else if ($clickedOperator->toAscii()==$this->tr("x\262")->toAscii()) {
$result = pow($operand, 2.0);
O autorze
} else if ($clickedOperator->toAscii()==$this->tr("1/x")->toAscii()) {
if ($operand == 0.0) { Thomas Mönicke studiuje informa-
$this->abortOperation(); tykę na Politechnice Brandenburskiej
return; w Cottbus. Jest autorem biblioteki PHP-
} Qt. Tworzy aplikacje GIS- i webowe dla
$result = 1.0 / $operand; Niemieckiego Instytutu Archeologiczne-
} go, a także pracuje nad systemem P2P
do widekonferencji o nazwie BRAVIS.
$this->display->setText(QString::number($result));
$this->waitingForOperand = true; Kontakt z autorem:
} thomas.moenicke@kdemail.net

16 www.phpsolmag.org PHP Solutions Nr 1/2007


Projekty

PunBB – nowoczesne forum


dyskusyjne
Stopień trudności: lll
Piotr Maliński

Obecnie skryptów umożliwiających prowadzenie


forum dyskusyjnego jest bardzo wiele. Różnią
się dostępnymi możliwościami jak również
interfejsem samego forum. Najbardziej znane
jest chyba phpBB lecz od pewnego czasu
nie cieszy się dobrą opinią ze względu na
powtarzające się problemy z bezpieczeństwem.
Możemy wybrać również IPB o bogatej
funkcjonalności i wysokim standardzie lecz
musimy pamiętać iż jest to projekt komercyjny.

M
ożemy też wypróbować też Rozwój
SMF jak wiele innych skryp- Bieżąca stabilna wersja to 1.2.14 a ko-
tów. Co jednak mamy zro- lejne wydania z tej serii ukażą się wy-
bić gdy chcemy lekkie, funkcjonalne łącznie w przypadku odkrycia błędów
i proste w zarządzaniu forum? Roz- lub luk bezpieczeństwa. Aktualizacje
wiązaniem jest punBB, skrypt rozwi- bezpieczeństwa ukazują się nie póź-
jany od 2003 roku przez Rickarda An- niej niż 48 godzin od zgłoszenia. Infor-
derssona. PunBB korzysta z bazy da- macje o odkrytych błędach i konieczno-
nych, do wyboru może to być MySQL, ści aktualizacji są podawane na stronie
W SIECI PostgreSQL lub SQLite. Skrypt mo- projektu oraz na specjalnej liście dys-
że działać zarówno pod PHP z serii kusyjnej.
4.3 jaki i PHP5. Instalacja skryptu jest Obecnie trwają prace nad punBB
1. http://www.punbb.org
– Strona punBB; bardzo prosta. 1.3, nową wersją rozwojową, która wpro-
2. http://www.punres.org Wystarczy pobrać archiwum ze stro- wadzi nowe funkcjonalności takie jak:
– Strona z modyfikacjami
i skórkami;
ny projektu, rozpakować i przenieść na
3. http://punbb.tox.pl nasz serwer i otworzyć w przeglądarce
– Polskie Wsparcie punBB; plik install.php. Pojawi się prosty, intu- Co obiecujemy:
4. http://www.tibiaswe.com/foru Poznasz podstawy PHP i HTML.
– Jedno z największych for icyjny instalator. Jeżeli chcemy prowa-
dyskusyjnych opartych o dzić forum w języku innym niż angielski
punBB;
to wystarczy pobrać ze strony punBB Co powinieneś wiedzieć:
5. http://www.phpclasses.org/ Umiejętność integrowania punBB z ze-
browse/package/2765.html odpowiedni pakiet językowy i umieścić wnętrznymi skryptami a także umiejęt-
– Forum Integrator, klasa
ułatwiające integrację punBB
go w katalogu lang a następnie ustawić ność migracji danych z innych skryptów
i phpBB; go domyślnym w panelu admina i profilu forum.
administratora.

18 www.phpsolmag.org PHP Solutions Nr 1/2007


PunBB Projekty

l
łatwy w zarządzaniu system rozsze- nuksa (Gentoo). Każdy z testowych skryp- szerzony system użytkowników i upraw-
rzeń (tzw. Wtyczek); tów posiadał dwie kategorie oraz jeden te- nień obecnych w konkurencyjnych roz-
l
przyjazne linki dla wyszukiwarek; mat z jedną odpowiedzią. W celu otrzyma- wiązaniach.
l
usprawniony interfejs forum. nia powtarzalnych wyników autor wyko-
rzystał funkcję xdebug_peak_memory_usage Wdrożenia
Pierwsza stabilne wydanie z tej serii prze- w celu pomiaru maksymalnego zużycia PunBB mimo iż w sieci nie jest powszech-
widziane jest jeszcze na bieżący rok. pamięci przez wykonujący się kod forum nie znane zostało wdrożone w wielu ser-
dyskusyjnego. Wyniki zestawione są po- wisach. TibiaSwe to jedno z największych
Możliwości forum niżej. for opartych o ten skrypt mogące poszczy-
Tabela 1 prezentuje dostępne jaki brakują- Maksymalne zużycie pamięci: cić się ponad 320 tysiącami postów. Fo-
ce względem innych skryptów funkcjonal- rummatrix – serwis zajmujący się porów-
ności punBB. Zestawienie pochodzi z da- l
punBB (1.2.10): 0,742095 MB; nywaniem różnych skryptów tego typu ja-
nych serwisu forummatrix.org. l
phpBB (2.0): 1,699279 MB; ko forum dostępne w serwisie dla użyt-
l
IPB (2.0): 3,683769 MB; kowników również wybrał punBB. Twórcy
Wydajność l
SMF (1.1 RC 2): 3,769836 MB. tego serwisu wybrali punBB ze względu
Autor artykułu przeprowadził proste testy na system użytkowników i uprawnień, któ-
wydajnościowe z wykorzystaniem profilera Bardzo dobre wyniki punBB można czę- ry bardzo łatwo wykorzystać w zewnętrz-
Xdebug (wersja 2.0.0 beta 5) pracującego ściowo uzasadnić brakiem komponentów nych skryptach oraz jest łatwy w zarzą-
z PHP 5.1.2 pod kontrolą 64 bitowego li- takich jak prywatne wiadomości czy roz- dzaniu od strony forum.

Tabela 1. Wady i zalety punBB Migracja danych


Obsługa MySQL, PostgreSQL i SQLite Wsparcie utf-8 Na stronie skryptu znajdziemy również na-
rzędzie o nazwie „PunBB Migration To-
Bbcode, emotikony, cytowanie Wsparcie Oracle
ol” umożliwiające migrację danych z kilku
Przejście do ostatniego postu Załączniki znanych skryptów. By skorzystać z narzę-
Przekierowanie jako forum Zagnieżdżone fora dzia wystarczy rozpakować je i umieścić
Kanały RSS/Atom, powiadomienia email Forum archiwum/kosz katalog converters w katalogu z instala-
Awatary, rangi, sygnatury Reputacja/ocena użytkownika cją punBB, a następnie otworzyć w prze-
glądarce zawarty w tym katalogu plik in-
Użytkownicy na forum Prywatne wiadomości (jako dodatek)
dex.php. Na dzień dzisiejszy wspierany
Przenoszenie tematów, przyklejone dzielenie tematów (jako dodatek)
jest import danych z:
tematy
Wyszukiwanie pełnotekstowe i zaawan- Własne tagi BBcode l
Invision Power Board 1.3;
sowane l
Invision Power Board 2.0;
Lista nieprzeczytanych tematów Edytor szablonów l
MiniBB 1.7d;
Statystyki Ankiety (jako dodatek) l
phpBB 2.0;
Banowanie użytkowników, adresów IP Przyjazne linki (jako dodatek) l
PHPNuke 7.4;
Flood control Ostrzeżenia
l
vBulletin 3.0.0;
l
YabbSE 1.5.5;
Czyszczenie forum Archiwizacja
l
SMF 1.0.5;
Import danych z innych for dyskusyjnych l
SimpleBoard 1.7d;
l
PHP-Fusion.

Konwerter jest równie prosty w obsłudze


co samo forum. Nasza ingerencja ograni-
cza się do wybrania nazwy skryptu z któ-
rego chcemy importować dane oraz pre-
fiks jego tabel oraz opcjonalnie dane bazy
danych jeżeli tabele skryptu znajdują się w
innej bazie niż tabele punBB.

INTEGRACJE
W łatwy sposób możemy uzyskać dostęp
do systemu użytkowników oraz bazy da-
nych (bieżącego połączenia). W tej kwestii
IPB z projektem IPB SDK jest nie do po-
Rysunek 1. Strona spinkBB - generatora arkuszy CSS dla punBB bicia, ale mimo to możliwości punBB oka-

PHP Solutions Nr 1/2007 www.phpsolmag.org 19


Projekty PunBB

żą się wystarczające dla większości sytu- Zaczynamy od zainstalowania gale- $pun->login($_POST['username'],


acji. Jednakże możemy napotkać proble- rii CPG ustawiając ten sam login i hasła $_POST['password']);
my jako że uzyskanie dostępu do zaso- administratora jaki podaliśmy dla punBB;
bów punBB polega na dołączeniu pliku Następnie w katalogu z galerią umiesz- Otwieramy logout.php i dodajemy po:
include/common.php forum. Dołączenie czamy plik punbb.php klasy Forums Inte-
elementu forum może doprowadzić do ko- grator i rozpoczynamy integrację; $referer = 'index.php';
lizji nazw funkcji i zmiennych. W pliku login.php wyszukujemy: kod:
include 'punbb.php';
Dostęp do elementów if ( $USER_DATA = $cpg_udb- $pun = new punbb

punBB >login( addslashes($_POST['username']), ('/ścieżka/do/punbb/');


By uzyskać dostęp do tablic z danymi bie- addslashes($_POST['password']), isset eval($pun->set_define());
żącego użytkownika, ustawieniami forum ($_POST['remember_me']) ) ) { $pun->set_variables($pun_user,
czy podstawowymi tłumaczeniami wystar- $pun_config);
czy kilka linijek kodu co przedstawia listing I poniżej dodajemy: $pun->logout();
1. Stała PUN_ROOT oznacza ścieżkę do ka-
talogu ze skryptem forum (bezwzględną include 'punbb.php'; Otwieramy register.php i wyszukujemy
ścieżkę systemową lub ścieżkę względną $pun = new punbb('/ścieżka/do/punbb/'); wiersz zawierający zapytanie:
względem położenia pliku skryptu w któ- eval($pun->set_define());
rym wykonujemy ten kod) $pun->set_variables($pun_user, $sql = "INSERT INTO
Oprócz tablic zyskujemy dostęp do $pun_config); {$CONFIG['TABLE_USERS']} ".
innych elementów punBB. Kolejnym ele-
mentem jest zmienna $db przechowująca
Listing 1. Dostęp do podstawowych elementów punBB
obiekt, za pomocą którego możemy ope-
rować na bazie danych. Przykład widzi- define('PUN_ROOT', 'upload/');
my na listingu 2. Jeżeli chcemy stworzyć // ścieżka do skryptu forum
require PUN_ROOT.'include/
aplikację obsługującą wszystkie trzy ba-
common.php';
zy to możemy przyjąć rozwiązanie punBB echo '<pre>
– pisanie w razie potrzeb trzech zapytań PUN_CONFIG:<BR>';
dla każdej bazy danych. Pomocna może print_r($pun_config);
okazać się zmienna $db_type przecho- echo '<HR>
PUN_USER:<BR>';
wująca nazwę używanej przez skrypt ba-
print_r($pun_user);
zy danych. echo '<HR>LANG
Możemy też pod patrzeć kod punBB i COMMON:<BR>';
wykorzystać pewne elementy w naszych print_r($lang_common);
skryptach. Przykładowo formularz logowa- echo '<HR>BANS:<BR>';
print_r($pun_bans);
nia logujący użytkownika na forum i prze-
kierowujący na stronę formularza wyglą- Listing 2. Wykonywanie zapytania z pomocą obiektu $db
dałby tak jak na listingu 3.
IF($result = $db->query($query))
Klasa „Forums {
while ($row = $db->fetch_assoc
Integrator” ($result))
Dostępna na phpclasses.com klasa uła- {
twia integrację punBB jak i phpBB. Oprócz print $row;
zaprezentowanego powyżej kodu kopiu- }
je część kodu forum w celu umożliwienia }

bezpośredniego logowania czy rejestro-


wania użytkowników. Pełną dokumentację
znajdziemy wraz z pakietem.

PUNBB I COPPERMINE
GALLERY
CPG to skrypt galerii internetowej rozpro-
wadzanej na licencji GNU GPL. Na jego
przykładzie zaprezentujemy jak dokonać
prostej integracji skryptu z forum punBB
za pomocą klasy Forums Integrator. Lo-
gowanie, wylogowanie i rejestracja w na-
szej coppermine gallery wywoła identycz-
ny efekt na naszym forum punBB. Rysunek 2. Prosty interfejs importera danych

20 www.phpsolmag.org PHP Solutions Nr 1/2007


PunBB Projekty

"(user_regdate, user_active,
user_actkey, user_name, Listing 3. Formularz logowania z przekierowaniem
user_password, user_email,
<form id="login" method="post" action="'.PUN_ROOT.'login.php?action=in"
user_profile1, onsubmit="return process_form(this)">
user_profile2, user_profile3, <input type="hidden" name="form_sent" value="1" />
user_profile4, <input type="hidden" name="redirect_url" value="'.
user_profile5, user_profile6) ". $_SERVER['SCRIPT_NAME'].'" />
<B>Login</B><BR />
"VALUES (NOW(), '$active',
<input type="text" name="req_username" size="15" maxlength="25"
'$act_key', /><BR /><BR />
'" . addslashes($user_name) . "', '" . <B>Password</B><BR />
addslashes($encpassword) . "', '" . <input type="password" name="req_password" size="15" maxlength=
addslashes($email) . "', '$profile1', "16" /><BR /><BR />
<input type="submit" name="login" value="Login" />
'$profile2', '$profile3', '$profile4',
</form>
'$profile5', '$profile6')";

Poniżej dodajemy: global $CONFIG, $db, do funkcji (czy klasy) obiektu klasy inte-
$pun_config, $pun_user; grującej jako argumentu.
include 'punbb.php'; //, $PHP_SELF;
$pun = new punbb('/ścieżka/do MIGRACJA FORUM:
/punbb/'); Integracja gotowa, operacje logowania, jakilinux.org
eval($pun->set_define()); wylogowania i rejestracji wykonają te sa- Administratorzy serwisu jakilinux.org po-
$pun->set_variables($pun_user, me operacje w punBB automatycznie. By stanowili rozpocząć migrację forum opar-
$pun_config); systemy użytkowników pozostały zsyn- tego o skrypt phpBB by Przemo. Obecnie
$pun->register($user_name, chronizowane zmieniamy lub usuwamy forum zawiera ponad 4000 postów i 500
$password, $email); odnośniki rejestracji i logowania na fo- użytkowników. Autor serwisu, Borys Mu-
rum na te z CPG. sielak tak uzasadnia podjętą decyzję:
Wyszukujemy: W powyższym kodzie użyliśmy „Plusem phpBB jest spora liczba
trzech metod klasy punBB – login, funkcji i popularność. Niestety, system
function check_user_info(&$error) logout i register, umieszczając wywoła- ten zupełnie nie sprawdza się, gdy wy-
{ nie tych metod w miejscach, w których magana jest jakakolwiek elastyczność.
global $CONFIG; //, $PHP_SELF; Coppermine Gallery wykonuje te sa- Kod phpBB jest trudny w modyfikacji
me operacje. Ostatnia zmiana, dodanie – system zaprojektowany został z uży-
I zastępujemy: trzech zmiennych punBB jako global- ciem przestarzałych metod (dotyczy to
nych była konieczna by wykorzystywa- zarówno rdzenia aplikacji jak i części od-
function check_user_info(&$error) ne elementy punBB działały poprawnie. powiedzialnej za wygląd). W odróżnieniu,
{ Innym rozwiązaniem byłoby przekazanie kod punBB napisany jest w sposób przej-

R E K L A M A

PHP Solutions Nr 1/2007 www.phpsolmag.org 21


Projekty PunBB

rzysty – umożliwia on praktycznie dowol- wowe opcje. Po wprowadzeniu modyfika- Przykład:


ne przeprojektowanie interfejsu użytkow- cji zauważono że dane kontaktowe Gadu-
nika, dzięki umiejętnemu zastosowaniu Gadu i Tlen.pl uległy importowi z phpBB function __construct()
arkuszy styli (CSS) przez jego twórców. by Przemo, a to za sprawą iż w tej mody- {
Pewne niedostatki funkcjonalności (doty- fikacji phpBB zastąpiono te same pola ko- global $pun_user;
czy wersji podstawowej aplikacji) rekom- munikatów profilu użytkownika. parent::Controller();
pensowane są natomiast przez świetny Kolejnym etapem było udostępnie- $this->pun = $pun_user;
mechanizm wtyczek.” nie bieżącej wersji do testów zespołowi unset($pun_user);
Za migrację odpowiedzialny był autor prowadzącemu serwis oraz przygotowa- }
niniejszego artykułu. nie skórki przez grafików.
Plan migracji obejmował: Czy jestem zalogowany?
CODE IGNITER i punBB Oto metoda kontrolera zwracająca war-
l
Import danych z phpBB do punBB; Code Igniter to prosty lecz funkcjonalny tość logiczną oznaczającą stan bieżą-
l
Konwersja kodowania z latin2 do framework PHP. Nie oferuje aż tylu moż- cego użytkownika, True dla zalogowa-
utf-8; liwości co Prado czy Symfony lecz wielu nego i False dla wylogowanego użyt-
l
Zainstalowanie dodatków do punBB programistów bardzo go sobie ceni. kownika:
zapewniających tą samą lub lepszą Integracja punBB ma tą wadę że po-
funkcjonalność jak w phpBB by Prze- lega na dołączeniu pewnych plików forum, function _check_login()
mo; co w przypadku Code Ignitera stwarza je- {
l
Stworzenie własnej skórki. den problem. Otóż pomocnik url zawie- IF($this->pun['group_id'] =
ra funkcję redirect. punBB również za- = 3) return false;
Kodowanie danych zmieniono poprzez wiera taką funkcję i dochodzi do konflik- IF($this->pun['username'] =
zmianę kodowania pliku zrzutu bazy da- tu. Musimy zmienić nazwę funkcji, którą = 'Guest') return false;
nych, który następnie zaimportowano na znajdziemy w pliku system/helpers/url_ IF($this->pun['password'] =
testowym serwerze. Import danych czy- helper.php. = 'Guest') return false;
li treści forum jak i kont użytkowników IF($this->pun['id'] == 1)
przeprowadzono za pomocą „PunBB Integracja: return false;
Migration Tool”. Migracja przebiegła bez W kontrolerach, które mają korzystać z return true;
problemów mimo iż phpBB by Przemo integracji przed kodem klasy wystarczy }
zawierało liczne modyfikacje. dodać:
Kolejnym etapem była instalacja od-
powiednich dodatków – systemu pry- define('PUN_ROOT',
Ostatnie 10 aktywnych
watnych wiadomości (Private_Messa- 'ścieżka/do/punbb/'); tematów
ge_Mod), ankiety (Easy_Poll) oraz do- require PUN_ROOT. W tym przypadku wystarczy skorzystać z
konano modyfikacji kodu punBB w ce- 'include/common.php' biblioteki Code Ignitera i wykonać proste
lu zamiany pól profilu użytkownika doty- zapytanie do bazy danych:
czących komunikatorów AOL IM i Yahoo W konstruktorze należy ustawić zmienną
Messenger na Gadu-Gadu i Tlen.pl. Na pun_user jako globalną: $query = $this->db->query
obecnym etapie nie wykonywano innych ("SELECT * FROM PREFIX_topics
zmian poza dodaniem ogólnodostępnych global $pun_user; ORDER BY last_post
modyfikacji dodających brakujące podsta- $this->pun = $pun_user; DESC LIMIT 10");

KONIEC
Niniejszy artykuł zaprezentował możliwości,
zalety i wady punBB. Zachęcam wszystkich
do sprawdzenia tej aplikacji w swoich roz-
wiązaniach. n

O autorze
Piotr Maliński jest studentem Politech-
niki Warszawskiej na kierunku Techno-
logia Chemiczna. Od czterech lat zaj-
muje się tworzeniem aplikacji w PHP jak
i od niedawna w Pythonie. Jest również
autorem serwisów o nazwie „Biblioteka
Riklaunima”.
Kontakt: riklaunim@gmail.com
Rysunek 3. Forum jakilinux.org po migracji danych prezentujące dwie skórki punBB

22 www.phpsolmag.org PHP Solutions Nr 1/2007


Dla zaawansowanych

XAJAX łatwy AJAX


Stopień trudności: lll
Paweł Grzesiak

Na fali fascynacji AJAX-em powstało wiele


bibliotek mających jednocześnie ułatwić i
przyspieszyć proces projektowania witryn
internetowych. Prezentujemy XAJAX,
rozwiązanie zorientowane na programistów PHP,
uwzględniające minimum programowania w
JavaScript.

A
JAX to podejście do tworzenia wolucją jest tu bowiem fakt, że zmiany w
aplikacji internetowych polegają- aplikacjach internetowych Google doko-
ce na połączeniu możliwości ist- nują się nieomal w czasie rzeczywistym.
niejących już technologii w nową jakość. Wszystko to właśnie dzięki AJAX.
Termin AJAX użył po raz pierwszy Jes-
se James Garrett w swoim artykule pt. Źródła inspiracji?
„Ajax: A New Approach to Web Applica- Od strony użytkownika korzyści są wi-
tions” opublikowanym na początku roku doczne gołym okiem. Dla zwykłego in-
2005. Jego tekst był próbą odpowiedze- ternauty witryna wykorzystująca AJAX
W SIECI nia na pytanie, które wówczas zadawa- to strona, która niekoniecznie musi się
ło wiele ludzi, niekoniecznie profesjonal- przeładować by zmienić swoją zawar-
nie związanych z tworzeniem stron www. tość. W taki sposób można najkrócej
1. http://www.xajaxproject.org/
– strona główna projektu Pytanie to brzmiało i brzmi nadal – czym wyjaśnić ideę AJAX. Niestety, rozumo-
XAJAX. jest ta rewolucyjna technologia wprowa-
2. http://wiki.xajaxproject.org/
– dokumentacja wiki do pro-
dzona przez Google?
jektu. Z perspektywy czasu można powie- Powinieneś wiedzieć:
3. http://adaptivepath.com/ dzieć, że to właśnie Google zapoczątko- Wymagana jest dobra znajomość PHP
publications/essays/ oraz nabyte pewne podstawowe umiejęt-
archives/000385.php wało światowy boom na AJAX, prezentu-
– artykuł Ajax: A New Appro-
ności posługiwania się JavaScript.
jąc przełomowe na dzień dzisiejszy pro-
ach to Web Applications.
dukty. Aplikacje internetowe zaoferowane
4. http://developer.mozilla.org/
pl/docs/AJAX przez Google charakteryzują się ponad-
Obiecujemy:
– więcej informacji o samej
Szybki start w tworzeniu stron opartych o
technice AJAX na stronach
przeciętnymi wartościami użytkowymi, AJAX. Szybkie wdrażanie nowych pomy-
Mozilla Developer Center. ale to co je wyróżnia od innych, to wyso- słów dzięki XAJAX.
ki stopień interakcji z użytkownikiem. Re-

24 www.phpsolmag.org PHP Solutions Nr 1/2007


XAJAX Dla zaawansowanych

wanie wyłącznie w kontekście same- kacja, tkwiąc uwięziona w przeglądar- cy do miana internetowego Worda. In-
go AJAX-a nie daje prawdziwego obra- ce internetowej? Odpowiedź jest dość ne duże korporacje internetowe też nie
zu zastosowania tej techniki. Najlepiej prosta – działa, i to wcale nie najgo- próżnują. Yahoo ze swoim serwisem
więc zasięgnąć przykładów, kierując się rzej. Czy już czas zmienić swoje przy- zdjęciowym Flickr (http://www.flickr.com)
w stronę działających aplikacji Google. zwyczajenia i pisać dokumenty w edy- także aktywnie wykorzystuje możliwości
Rysunek 1 prezentuje aplikację Google torze tekstu umieszczonym na stronie AJAX. Choćby obracanie zdjęć bez ko-
Spreadsheets (http://spreadsheets.goog www? Rysunek 2 to przykład aplikacji nieczności przeładowania to tylko jed-
le.com), która nie tylko wyglądem, lecz i internetowej niemal żywcem przeniesio- na z robiących wrażenie na użytkowni-
funkcjonalnością przypomina typowy ar- nej z pakietu biurowego. Writely (http:// kach funkcji.
kusz kalkulacyjny. Co więc robi ta apli- writely.com) to produkt Google aspirują-
Jak to działa?
AJAX (ang. Asynchronous JavaScript and
XML) wykorzystuje do pracy komplet ist-
niejących technologii. Najczęściej do stwo-
rzenia aplikacji AJAX wykorzystuje się ta-
ki zestaw:

• HTML/XHTML – odpowiedzialny za
budowę struktury strony www.;
• CSS – oprawa graficzna witryny;
• JavaScript – realizacja żądań po
stronie klienta (wysyłanie/pobieranie/
przetwarzanie w ograniczonym stop-
niu);
• DOM – obiektowy dostęp do struktury
dokumentu (X)HTML;
• XML – pełniący tu rolę protokołu trans-
portowego (do wymiany pakietów da-
nych);
• PHP (lub dowolny inny język skryp-
towy: ASP/JSP/Ruby) – realizacja
żądań po stronie serwera (wysyłanie/
odbieranie danych/przetwarzanie da-
Rysunek 1. Google Spreadsheets, internetowy arkusz kalkulacyjny
nych ograniczone przez możliwości
serwera), głównie obejmuje wymianę
informacji z bazą danych (np. Postgre-
SQL, MySQL, SQLite);
• XMLHttpRequest – interfejs dzięki któ-
remu możliwe jest wysłanie i odbiera-
nie danych przez przeglądarkę w cza-
sie rzeczywistym (bez konieczności
przeładowania strony).

Typowa strona www oparta jest o mecha-


nizm żądań i odpowiedzi realizowanych
pomiędzy aplikacją kliencką (przeglądar-
ki) a serwera www przy użyciu protoko-
łu HTTP. Rysunek 4 ilustruje metodę, w
której przeglądarka wysyła żądanie me-
todą GET lub POST i oczekuje odpowie-
dzi ze strony serwera. Serwer odpowia-
da wysyłając użytkownikowi kompletny
kod strony, zawierający kod HTML, CSS,
jak również JavaScript – przy każdym
wywołaniu strona się przeładowuje.
Przy zastosowaniu techniki AJAX po-
Rysunek 2. Writely, internetowy edytor tekstu od Google czątek procesu wygląda dokładnie w ten

PHP Solutions Nr 1/2007 www.phpsolmag.org 25


Dla zaawansowanych XAJAX

Stronę w AJAXie raz,


proszę
Rolą web designera jest spełnianie po-
trzeb klientów. Jako projektant stron www
spotkałem się wielokrotnie z klientami,
których podstawowym wymogiem wo-
bec strony było wykorzystanie technolo-
gii AJAX. Klientów urzeka sposób, w jaki
dobrze zaprojektowany AJAX pozwala po-
prawić interakcję z użytkownikiem, zapew-
nić mu szybki i intuicyjny dostęp do funk-
cji na stronie. Google dociera do ogromnej
rzeszy internautów. Klient zapytany wprost
o AJAX zapewne nie będzie zdawał sobie
sprawy z istnienia takiej technologii. Gdy
jednak zapytam go o serwisy, które powi-
nienem przyjąć za wzór, często uzyskuję
odpowiedź zbieżną z moimi przewidywa-
niami. Serwisy, które podobają się wszyst-
kim (wyróżniają się) generalnie wykorzy-
stują w mniejszym, bądź większym stop-
niu możliwości AJAX.
Rysunek 3. Flickr, serwis zdjęciowy od Yahoo! Z AJAXem jest jednak podobnie jak z
innymi nowinkami. Wśród programistów
sam sposób, jak przy metodzie klasycz- na wysłaniu i pobraniu danych. Za każ- zawsze znajdują się konserwatyści, uwa-
nej – patrz rysunek 5. Strona zostaje w dym razem nie wymaga to od przeglą- żający AJAX za nic nadzwyczajnego oraz
pełni załadowana. Gdy użytkownik stro- darki przeładowania. AJAX może rów- liberałowie, mniej lub bardziej zafascyno-
ny wykonania określoną akcję (kliknie na nie i dobrze pracować w pełni w tle prze- wani techniką i skorzy do jej wdrażania.
przycisk), pałeczkę przejmuje JavaScript. glądarki. W takiej sytuacji użytkownik na- Prędzej, czy później każdy z nich będzie
Odpowiedni skrypt napisany w tym języ- wet nie spostrzeże, iż dane, które wpisu- zmuszony do tworzenia aplikacji AJAX.
ku najpierw pakuje odpowiednie da- je do formularza są defacto wysyłane do Większość obecnie tworzonych stron
ne wejściowe (parametry, które chcemy serwera. w żaden sposób nie przypomina aplikacji
przekazać) do formatu XML, a następ- Możliwości, jakie daje zastosowanie w rodzaju Google Spreadsheets, czy Wri-
nie tworzy instancję klasy XMLHttpRequ- techniki AJAX pozwalają zatem na two- tely. Dlatego też rzadziej używamy w sto-
est. To właśnie ta klasa okazuje się klu- rzenie witryn, które swoim wyglądem i za- sunku do nich terminu strona www. Stro-
czowa. XMLHttpRequest pozwala na wy- chowaniem przypominają tradycyjne pro- na powinna raczej pełnić rolę informacyj-
syłanie i odbieranie przez przeglądarkę gramy komputerowe. ną (dostarczać treści), a zadaniem tych
żądań w formie osobnej sesji, niezależ- Wywołania AJAX mogą być obsługi- aplikacji jest wyłącznie realizacja konkret-
nej od aktualnie wyświetlonej strony. W wane: nej usługi. Klienci indywidualni i korpora-
ten sposób do serwera trafia żądanie o cyjni zainteresowani stworzeniem nowego
określonych parametrach i do pracy za- • Synchronicznie – w określonych od- rozwiązania w sieci, zdecydowanie najrza-
biera się skrypt przygotowany do wyge- stępach czasu (przydatne przy zapisie dziej decydują się na stworzenie tego ty-
nerowania odpowiedzi. To właśnie do kopii aktualnie pisanego dokumentu); pu usługi. Trudno więc pisać o technologii
skryptu pracującego po stronie serwera • Asynchronicznie – na żądanie (uru- AJAX w kontekście odsuniętym od realiów
(napisanego np. w PHP) dostarczone chamiane na akcję użytkownika). rynku. Strony internetowe potrzebują prze-
są informacje. Na podstawie dostarczo-
nych danych realizowana jest określo-
na procedura, np. na bazie danych (np.
zmiana wartości w bazie, dodanie no-
wego rekordu). Gdy operacja dobiegnie ����������
końca, skrypt tworzy odpowiedź i odsy-
ła ją do skryptu JavaScript, który pier- ������������
����������
�����������
wotnie wywołał akcję. Na podstawie te-
����������������
go, co skrypt otrzyma, dokonywana jest ����������������������
określona akcja. Zazwyczaj polega ona
na zamianie zawartości elementu html o
określonym identyfikatorze (id) na nowy,
nadesłany z serwera. AJAX pozwala na
dokonanie wielokrotnej akcji polegającej Rysunek 4. Schemat działania klasycznej strony www

26 www.phpsolmag.org PHP Solutions Nr 1/2007


XAJAX Dla zaawansowanych

AJAX posiada wady, z których główne to:

• Wciśnięcie w przeglądarce przycisku


����������
wstecz nie powoduje odwrócenia żad-
nego z procesów AJAX. Taka jest nie-
���������������������������������������
stety wada tej technologii, która pod
tym względem przegrywa z przyzwy-
������������
czajeniami internautów;
����������
�����������
• Elementy stron wstawiane przez AJAX
nie są indeksowane przez wyszukiwarki;
�������� ����������
�� • Wyłącznie obsługi JavaScript powodu-

�������������� je, że AJAX przestaje działać.
�������������������
������������ �������������

Powyższe rady nie dotyczą oczywiście


aplikacji internetowych, które zbudowano
kompleksowo w oparciu o AJAX, takich
Rysunek 5. Schemat działania strony opartej o AJAX jak opisywany Writely, czy G. Spreadshe-
ets. W takich sytuacjach wyłączenie ob-
myślanej dawki technologii AJAX. W myśl • AJAX doskonale nadaje się do two- sługi JavaScript powoduje całkowitą nie-
tego twierdzenia dochodzimy do wniosku, rzenia przełączników, np. „dodaj to dostępność usługi.
że AJAX mógłby być wykorzystany na wi- zdjęcie do obserwowanych”, któ-
trynie firmowej, czy na forum dyskusyj- re aktualizują bazę i zmieniają napis Biblioteki
nym. Czemu nie. na przełączniku – „usuń z obserwo- W celu ułatwienia pracy przy tworzeniu
Jest wiele sytuacji, w których zasto- wanych”. Dzięki AJAX można umoż- aplikacji internetowych opartych o AJAX
sowanie techniki AJAX ma ogromne zna- liwić szybkie dokonywanie zmian, np. programiści sięgają po gotowe bibliote-
czenie. Witryny i portale tematyczne, ser- zmiana tytułu artykułu bez koniecz- ki. Nie ma nic w tym złego, bo bibliote-
wisy usługowe i informacyjne napotykają ności klikania na „wyślij” i przełado- ki realizują większość krytycznych funk-
na co najmniej kilka sytuacji, w których wania strony. W momencie, gdy użyt- cji, będąc odpowiedzialne za faktyczny
użycie AJAX mogłoby pomóc w zapew- kownik przestanie pisać, uruchamia- transport danych pomiędzy klientem a
nieniu wyższej funkcjonalności strony. ne jest żądanie AJAX a treść tytułu serwerem. Biorąc pod uwagę ciągły pro-
Kluczem do poprawnego wdrażania zapisywana do bazy. Pomimo oczy- ces udoskonalania i popularność niektó-
technik AJAX jest przestrzeganie kilku re- wistej korzyści dla użytkownika, ko- rych bibliotek, można śmiało stwierdzić,
guł przy projektowaniu: nieczne jest zapewnienie oprogra- że tworzenie całej aplikacji od zera mi-
mowania, które zadziała przy wyłą- ja się z celem, podwyższając w dodatku
• Ładowanie dużych partii tekstu za po- czonej obsłudze JS. budżet produkcyjny.
mocą AJAX, np. kolejnych części dłu-
giego artykułu jest niezgodne ze sztu-
ką. Kolejne partie tekstu nie zostaną
zaindeksowane przez wyszukiwarkę,
a użytkownik i tak nie odczuje znacz-
nego przyspieszenia ładowania nowej
treści.
• Większość witryn techniki AJAX po-
winno traktować jako dodatek do do-
tychczasowej funkcjonalności stro-
ny. Zapewni to lepszą funkcjonalność
strony, ale nie zmniejszy dostępno-
ści witryny, wówczas gdy klient po-
siada wyłączoną obsługę JavaScript.
W tym celu konieczne jest zapewnie
odpowiedniego zaplecza programi-
stycznego po stronie serwera, które
sprawi, że strona nie będzie całko-
wicie bezużyteczna. Znacznie bez-
pieczniej jest stworzyć kompleksowy
serwis bez użycia AJAX, a następ-
nie dodać do niej AJAX. W ten spo-
sób bez AJAX strona może popraw- Rysunek 6. XAJAX to narzędzie do szybkiego wdrażania AJAX na strony tworzone
nie funkcjonować; w oparciu o PHP

PHP Solutions Nr 1/2007 www.phpsolmag.org 27


Dla zaawansowanych XAJAX

• XAJAX jest aplikacją zorientowaną


obiektowo. Rozszerzanie funkcjonal-
ności oraz separowanie kodu od da-
nych jest tu zadaniem bardzo łatwym.
XAJAX łatwo też wdrożyć do już istnie-
jących systemów. Stworzenie dodatko-
wych klas do obsługi ajax sprawia, iż
programista zapomina całkowicie o tej
technologii skupiając się na najbardziej
dla niego istotnej logice biznesowej;
• XAJAX pracuje poprawnie na prze-
glądarkach z rodziny Mozilla (Fire-
fox, Mozilla lub inna oparta o silnik
Gecko), Internet Explorer i Safari;
• Istnieje możliwość bardzo łatwego i
szybkiego zastępowania istniejących
wartości nowymi. W ten sposób łatwo
zmienić nie tylko porcję wyświetlane-
Rysunek 7. Wygląd gotowego systemu zakładek
go aktualnie tekstu, ale także i styl
Możemy rozróżnić dwa rodzaje biblio- miany danych) generuje skrypt Java- css elementów, czy zaznaczyć pola
tek wspomagających programowanie, ze Script odpowiedzialny za obsługę żą- checkbox lub radio formularzy;
względu na nacisk, który położono na pro- dań. W momencie, gdy nastąpi żądanie, • XAJAX posiada przyjazny mechanizm
gramowanie w: uruchamiany jest ten skrypt, który po- umożliwiający debugowanie napisane-
przez obiekt XMLHttpRequest komuni- go wcześniej kodu. W formie okien Ja-
• JavaScript; kuje się z obiektem xajax mieszczącym vaScript, XAJAX informuje o aktualnie
• PHP. się po stronie serwera. Ten wywołuje już podejmowanych przez bibliotekę dzia-
tylko funkcję PHP odpowiedzialną za re- łaniach. To przyspiesza programowa-
Położenie większego nacisku, na któ- alizację żądania. Gdy funkcja PHP zo- nie i wyklucza przypadkowe błędy;
ryś z powyższych języków programowa- stanie zrealizowana, xajax zwróci odpo- • XAJAX oferuje bardzo prosty mecha-
nia może wydawać się nieco niejasne. wiedź w formie dokumentu XML. Ta zo- nizm obsługi formularzy. Przy użyciu
W bibliotece, w której nacisk położono na stanie przetworzona parser xajax pracu- jednej funkcji otrzymujemy tablicę z
PHP zadania programisty ograniczają się jący po stronie klienta (JavaScript). Od- danymi, które następnie można obro-
w zasadzie wyłącznie do pisania nowych powiedź zostanie zwrócona przez tenże bić, wrzucić do bazy danych lub zwró-
funkcji obsługi żądań po stronie serwera. skrypt JavaScript – zazwyczaj w formie cić użytkownikowi informację o błędnie
Biblioteka poradzi już sobie z resztą ge- aktualizacji danych na stronie. wypełnionych polach;
nerując odpowiednie skrypty JavaScript XAJAX posiada wiele interesujących • Przy obsłudze żądania możliwe jest
do obsługi. Oczywiście nie obędzie się cech i właściwości: zwrócenie dodatkowej funkcji Java-
całkowicie bez JavaScriptu, lecz stosu-
nek kodu pisanego w PHP do JavaScript
będzie jak jeden do pięciu. Biorąc pod
uwagę, iż większość programistów trak-
tuje JavaScript jak trudne do kontrolowa-
nia dziecko, warto postawić na biblioteki
z tej rodziny. Taki jest też XAJAX, biblio-
teka, której poświęcono tej artykuł.

XAJAX
XAJAX to biblioteka udostępniana w for-
mie klasy PHP. Oparta o otwarty kod źró-
dłowy udostępniana jest na licencji LGPL.
Oznacza to, iż można na niej opierać apli-
kacje, za które dostaniemy zapłatę.
Jak to działa? XAJAX składa się z
dwóch bibliotek – napisanej w PHP oraz
napisanej w JavaScript. Każda z nich
przyjmuje na siebie część zadań. Biblio-
teka XAJAX pracująca w formie obiektu
PHP dla każdej funkcji PHP (która ma
mieć możliwość asynchronicznej wy- Rysunek 8. Wygląd gotowego systemu dodawania do obserwowanych

28 www.phpsolmag.org PHP Solutions Nr 1/2007


XAJAX Dla zaawansowanych

Script, która zrealizuje bardziej za- nie obserwujemy migania charaktery- dzie UTF-8. To zapewnia poprawną
awansowane zadanie (np. wyśle stycznego dla aplikacji XAJAX opar- obsługę narodowych znaków diak-
formularz, gdy ten zostanie spraw- tych o model synchroniczny; trycznych;
dzony przez AJAX na obecność • Dla każdej z funkcji PHP może zostać • XAJAX bardzo łatwo integruje się z
błędów); przypisana inna metoda obsługi (POST wszelkimi systemami szablonowymi.
• XAJAX porównuje dane, które mają lub GET). To pozwala zwiększyć nieco Od strony systemu szablonowego ko-
zostać uaktualnione na stronie, z tymi, bezpieczeństwo całej aplikacji i zapo- nieczne jest dodanie wyłącznie jednej
które już w danym miejscu się znajdu- biega przypadkowym błędom; zmiennej. W jej miejsce zostaną wy-
ją. Jeżeli nic nie ulega zmianie, xajax • Dane przesyłane pomiędzy klientem generowane odwołania do skryptów
nie podejmuje działań. W ten sposób a serwerem są kodowane w standar- JavaScript odpowiedzialnych za reali-
zację żądań;
• XAJAX w bardzo dobry sposób ra-
Listing 1. Kod źródłowy systemu zakładek
dzi sobie z wszelkimi skryptami Java-
<?php Script. Kod źródłowy strony przed i po
require('lib/xajax.inc.php'); wprowadzeniu tej biblioteki w życie nie
function tabarea($tabId) {
różni się znacząco.
sleep(1);
$objResponse = new xajaxResponse();
for($x=1; $x<=6; $x++) { Instalacja XAJAX
$x == $tabId ? $className = 'active' : $className = ''; Zadaniem tego artykułu jest zaprezento-
$objResponse->addScript("document.getElementById('tab".$x."'). wanie praktycznych rozwiązań, które moż-
className='$className'");
na niemal od zaraz wdrożyć na własną
}
$objResponse->addAssign("maintabarea", "innerHTML", stronę. Zanim jednak przystąpimy do pro-
implode('', file('tpl/tab_content_'.$tabId.'.html'))); gramowania, warto zapoznać się ze struk-
return $objResponse->getXML(); turą biblioteki oraz dostępnymi metodami.
} XAJAX można pobrać ze stro-
$xajax = new xajax();
ny mieszącej się pod adresem: http://
$xajax->registerFunction('tabarea');
$xajax->processRequests(); www.xajaxproject.org/. Dokumentację do
?> projektu w formie wiki można odnaleźć
<html> pod adresem: http://wiki.xajaxproject.org/.
[..] Do prawidłowej implementacji XAJAX
<?=$xajax->printJavascript()?>
potrzebne są trzy pliki. Dwa z nich pracu-
</head>
<body> ją po stronie serwera. Są to następujące
<script type="text/javascript"><!-- skrypty PHP:
xajax.loadingFunction = function(){xajax.$('loading')
style.display='block';}; • xajax.inc.php – główna klasa biblio-
function hideLoadingMessage() { xajax.$('loading').
teki;
style.display='none'; }
xajax.doneLoadingFunction = hideLoadingMessage; • xajaxResponse.inc.php – klasa do ge-
// --></script> nerowania odpowiedzi;
<div class="content"> • Po stronie klienta pracuje jeden skrypt
<ul class="tabs" id="maintab"> JavaScript;
id="tab1" class="active"><a href="?show=
• xajax.js – klasa do obsługi żądań po
tab1" onclick="xajax_tabarea('1'); return false;">Tab 1</a></li>
<li id="tab2"><a href="?show=tab2" onclick= stronie klienta;
"xajax_tabarea('2'); return false;">Tab 2</a></li>
id="tab3"><a href="?show=tab3" onclick= Przyglądając się kodowi źródłowemu xa-
"xajax_tabarea('3'); return false;">Tab 3</a></li> jax.js łatwo zauważyć, iż został on po-
id="tab4"><a href="?show=tab4" onclick=
zbawiony biały znaków. Ze względu na
"xajax_tabarea('4'); return false;">Tab 4</a></li>
id="tab5"><a href="?show=tab5" onclick= utrudnienia w dokonywaniu zmian w takim
"xajax_tabarea('5'); return false;">Tab 5</a></li> skrypcie udostępniono wersję z typowym
id="tab6"><a href="?show=tab6" onclick= formatowaniem – xajax_uncompressed.js.
"xajax_tabarea('6'); return false;">Tab 6</a></li> Do późniejszej kompresji posłuży bibliote-
</ul>
ka xajaxCompress.php.
<div class="insider">
<div id="loading">Ładowanie...</div> Wymagania sprzętowe odnośnie bi-
<div id="maintabarea"> blioteki:
<? include('tpl/tab_content_1.html') ?>
</div> • Serwer Apache lub IIS (Windows XP/
</div>
2003);
</div>
</body> • PHP 4.3.x lub 5.x;
</html> • Przeglądarka IE 5.5, Firefox 1.0, Sa-
fari 1.3, Opera 8.5.

PHP Solutions Nr 1/2007 www.phpsolmag.org 29


Dla zaawansowanych XAJAX

Opis podstawowych
Listing 2. Kod źródłowy systemu zakładek
metod
Zaletą biblioteki XAJAX jest możliwość <?php
bardzo szybkiego startu. Podczas co- mysql_connect('localhost', 'root', 'root');
mysql_select_db('test');
dziennej pracy z XAJAX wykorzystamy
require('lib/xajax.inc.php');
stosunkowo niewielką ilość metod, będą-
cych częścią dwóch klas PHP. Warto po- function fetchObserve($id) {
krótce nakreślić charakterystykę najważ- return @mysql_result(mysql_query('SELECT 1 FROM
niejszych z nich. obserwowane WHERE article_id = "'.$id.'"'), 0);
}
Klasa xajax (xajax.inc.php):
function checkObserve($id) {
if(fetchObserve($id))
• debugOn() / debugOff() – włącza /
wyłącza przydatny tryb usuwania błę- // zaprzestan obserwowania
dów;
return 'Nie obserwuj';
• registerFunction($nazwaFunkcji)
else
lub registerFunction(array($nazwa-
Funkcji, $nazwaKlasy, $nazwaMetody)) //rozpocznij obserwowanie
– rejestruje funkcję PHP, do której będzie
można odwołać się poprzez JavaScript; return 'Obserwuj';
}
• processRequests() – uruchamia silnik
function observe($id) {
odpowiedzialny za obsługę przycho-
dzących wywołań; if(fetchObserve($id))
• printJavascript() / getJavascript
– wyświetla / zwraca kod JavaScript, mysql_query('DELETE FROM obserwowane
WHERE article_id = "'.$id.'"');
który musi zostać umieszczony w sek-
cji head strony. else

Klasa xajaxResponse (xajaxResponse. mysql_query('INSERT INTO obserwowane


inc.php): VALUES ("", "'.$id.'")');

$objResponse = new xajaxResponse();


• addAssign($idElementu, $atrybut, $objResponse->addAssign($id,
$dane) – pozwala na zamianę wartości "innerHTML", checkObserve($id));
elementu HTML o id $idElementu;
• addScript($kodJs) – uruchamia kod return $objResponse->getXML();

JavaScript umieszczony w zmiennej


}
$kodJs; $xajax = new xajax();
• getXML() – zwraca odpowiedź do $xajax->registerFunction('observe');
przeglądarki użytkownika; $xajax->processRequests();
• Część XAJAX odpowiedzialna za ?>
<html>
kod JavaScript (xajax.js) także posia-
<head>
da swój zestaw metod. Wykorzystuje [..]
się je w kodzie HTML strony: <?=$xajax->printJavascript()?>
</head>
• xajax_NazwaFunkcji($p1, <body>
<div class="content">
$p2,...) – wywołuje zarejestro-
<h3>Tematy zbliżaj±cych się artykułów</h3>
waną funkcję PHP o nazwie Na- <p style="color: red;">Klikaj±c na [..]</p>
zwaFunkcji, przekazując parame- <h5>51: Użyteczność[..]</h5>
try $p1, $p2,....; <p>[..]</p>
• xajax.getFormValues($idFormul <p><a href="" onclick="xajax_observe('51');
return false;" id="51"><?=checkObserve('51')?></a></p>
arza) – pobiera wszystkie dane,
<h5>50: Okiełznać[..]</h5>
które użytkownik wpisał do formu- <p>[..]</p>
larza o id $idFormularza. <p><a href="" onclick="xajax_observe('50');
return false;" id="50"><?=checkObserve('50')?></a></p>
Zakładki <h5>49: SEO[..]</h5>
<p>[..]</p>
Jednym z najbardziej praktycznych i naj-
<p><a href="" onclick="xajax_observe('49');
popularniejszych efektów stosowanych na return false;" id="49"><?=checkObserve('49')?></a></p>
stronach www są obecnie zakładki. Choć </div>
podobny mechanizm można zrealizować </body>
bez użycia techniki ajax, pokażemy jak

30 www.phpsolmag.org PHP Solutions Nr 1/2007


XAJAX Dla zaawansowanych

stworzyć zakładki, do których dane są po- ich wszędzie tam, gdzie dojdzie do zmian sługi JavaScript strona pracowała w mia-
bierane dopiero w momencie kliknięcia na na stronie. Podstawowym kontenerem, do rę poprawnie. Stąd linki do kolejnych za-
nieaktywną zakładkę. którego trafia tekst jest maintabarea. Jak kładek posiadają parametry ?show=tabx.
Tworzenie systemu zakładek rozpo- łatwo zauważyć poprzedza go kontener Oczywiście z uwagi na brak miejsca, w
czynamy od zbudowania podstawowe- loading, który domyślnie jest schowanych. powyższym kodzie brakuje obsługi takiej
go kodu XHTML, składającego się z kilku W momencie, gdy XAJAX przystępuje do sytuacji.
kontenerów oraz listy punktowanej (druga załadowania nowej zawartości, pojawia Poszczególne funkcje w XAJAX wy-
połowa listingu 1). Przy użyciu stylów CSS się informując użytkownika o trwającym wołuje się stosując konstrukcję xajax_
dokonujemy zmiany wyglądu poszczegól- procesie ładowania. Bez takiej informacji NazawFunkcji (Parametry). Jak łatwo za-
nych elementów, tak, by przypominały za- użytkownik może poczuć się zdezorien- uważyć, ilość kodu JavaScript zastosowa-
kładki. XAJAX rozpoznaje elementy po ich towany. Dokument XHTML jest skonstru- nego w tym przykładzie jest znikoma. Za-
identyfikatorach, stąd istotne jest dodanie owany tak, by nawet po wyłączeniu ob- stosowany dodatkowy parametr przy wła-
ściwości onclik – return false powoduje, iż
przeglądarka nie podąża za linkiem (ele-
Listing 3. Kod źródłowy systemu logowania – część pracująca po stronie serwera
ment href). Parametr przekazywany do
<?php funkcji xajax_tabarea pozwala rozróżnić
mysql_connect('localhost', 'root', 'root'); poszczególne zakładki, które odczytamy z
mysql_select_db('test'); plików szablonowych.
define ('XAJAX_DEFAULT_CHAR_ENCODING',
Pierwsza połowa Listingu 1 zawie-
'ISO-8859-2');
require('lib/xajax.inc.php');
ra kompletny kod potrzebny do obsługi
wszystkich zdarzeń. Programowanie roz-
if($_SERVER['QUERY_STRING'] == 'wszystko_ok_loguj') { poczynamy od załadowania części biblio-
echo 'yeah! zalogowany'; teki XAJAX napisanej w PHP. Opuśćmy
na chwilę deklarację funkcji tabarea, by
return 0;
przyjrzeć się instancji klasy xajax miesz-
} czącej się zaraz poniżej. Wszystkie funk-
function loginform($d) { cje, które mają być zbierane przez bi-
$objResponse = new xajaxResponse(); bliotekę JavaScript xajax muszą zostać
$email = $d['aEmail'];
uprzednio zarejestrowane. Nazwa funk-
$pass = $d['aPass'];
cji jest oczywiście zgodna z nazwą wystę-
// pytam baze o istnienie loginu pującą w kodzie XHTML. Metoda proces-
sRequest() generuje odpowiedni kod Ja-
$data = @mysql_fetch_array(mysql_query vaScript, który jest odpowiedzialny za ob-
('SELECT email, password, registered FROM
sługę żądań. Skompletowany w ten spo-
uzytkownicy WHERE email="'.$email.'"'));
sób kod JS wrzucamy sekcji HEAD do-
if(!$email OR !$pass) kumentu XHTML, korzystając z funkcji
$out = 'Proszę podać e-mail i login.'; printJavascript(). Wynik działania tej
else { funkcji to dołączenie do strony części bi-
if($email != $data['email']) {
blioteki XAJAX napisanej w JavaScript.
$out = 'Konto o podanym adresie nie istnieje.';
} else {
Funkcja zwraca ponadto do kodu źródło-
if($pass != $data['password']) wego strony także wszystkie inne dane
$out = 'Hasło do konta jest nieprawidłowe.'; potrzebne bibliotece do obsługi żądań.
else { Ponieważ w systemie zakładek ma-
if($data['registered'] == '0')
my do czynienia wyłącznie z jedną funk-
$out = 'Użytkownik nie potwierdził rejestracji.';
else {
cją, do jej obsłużenia musimy odpowied-
$out = 'Proszę czekać. <b>Logowanie</b>...'; nio stworzyć jedną funkcję PHP. Nazwa
$objResponse->addScript('document.loginform.submit();'); tej funkcji musi być zgodna z zarejestro-
} waną nazwą oraz nazewnictwem używa-
}
nym w kodzie strony. Zawartość funk-
}
}
cji tabarea to już praca na zupełnie in-
$objResponse->addAssign("logblad", "innerHTML", $out); nej klasie. XajaxResponse odpowiada za
generowanie odpowiedzi dla klienta. Pa-
return $objResponse->getXML(); rametr wejściowy funkcji $tabId to liczba
z zakresu 1-6. W kolejnych plikach mie-
}
$xajax = new xajax();
szących się w katalogu tpl umieszczona
$xajax->registerFunction('loginform'); jest zawartość kolejnych zakładek. Oczy-
$xajax->processRequests(); wiście w tym miejscu można posłużyć
?> się bazą danych lub bardziej skompliko-
wanym skryptem do pobierania danych,

PHP Solutions Nr 1/2007 www.phpsolmag.org 31


Dla zaawansowanych XAJAX

np. z bazy tekstowej. Tworząc nową in-


stancję obiektu XajaxResponse przystę-
pujemy do zamiany zawartości elementu
DIV o identyfikatorze maintabarea. Wy-
korzystujemy metodę addAssign, która
dokona zamiany pobierając dane z jed-
nego z plików szablonowych. Po klik-
nięciu zakładki chcielibyśmy by zmienia-
ła się ona na aktywną. Zakładka jest ak-
tywna, jeżeli przypisana do elementu LI
klasa to active. Przy każdej zmianie za-
kładki konieczne jest ponowne ustawie-
nie klasy active. W tym celu, dla wszyst-
kich zakładek dokonujemy zresetowa-
nia wartości. Tylko zakładce, która jest
aktualnie aktywna przypisujemy klasę
active. Wysłanie danych z powrotem do
użytkownika odbywa się przy użyciu me-
tody getXML(). Funkcja usypiająca skrypt
sleep użyta została by pokazać w zwol-
nieniu działanie skryptu – pojawiający
się element ładowanie.

Dodaj do obserwowanych Rysunek 9. Wygląd gotowego systemu logowania


Kolejny przykład może wydawać się
banalny, lecz jego zastosowanie jest
nie do podważenia. Zakładamy, iż użyt- Listing 4. Kod źródłowy systemu logowania – część pracująca po stronie klienta
kownik jest zalogowany na naszej stro-
nie. Chcemy mu umożliwić dokonywa- <html>
<head>
nie szybkich wyborów, polegających na
[..]
dodawaniu wybranych zdjęć, artyku- <?=$xajax->printJavascript()?>
łów, filmów do listy swoich ulubionych. </head>
W klasycznym wydaniu oznacza to ko- <body>
nieczność przeładowania strony. AJAX moj@email.pl<br/>
mojehaslo<br/>
pozwala taką operacje przeprowadzić
<div class="bar">
w tle. Użytkownik klika na element, któ- <h3>Zaloguj się</h3>
rym jest zainteresowany. Baza danych <form action="?wszystko_ok_loguj" method="post" class=
jest uaktualniana, a jego przycisk z do- "login" name="loginform" id="loginform" style="margin:0;">
daj do obserwowanych automatycz- <table>
<tr>
nie zamienia się na usuń z obserwo-
<td><label for="name">E-mail:</label></td>
wanych. <td class="f"><input type="text" name=
Mechanizm widoczny na Listingu 2 "aEmail" value=""></td>
jest bardzo zbliżony do tego, który ob- </tr>
serwowaliśmy w pierwszym przykła- <tr>
<td><label for="name">Hasło:</label></td>
dzie. Posiadamy trzy przełączniki, od-
<td class="f"><input type="password" name=
wołujące się do funkcji o nazwie ob- "aPass"></td>
serve. Ładując po raz pierwszy stronę </tr>
pobieramy z bazy danych informacje o <tr>
aktualnie ustawionych przełącznikach. <td></td>
<td style="text-align: right;"><div id=
Jeżeli rekord dla danego identyfikato-
"logblad"></div><input type="submit" value=
ra artykułu istnieje, wówczas przełącz- "Loguj" onclick="xajax_loginform
nik został już włączony. W ten sposób (xajax.getFormValues('loginform'));
powstaje strona pamiętająca poprzed- return false;"></td>
nie ustawienia użytkownika. Klikając </tr>
</table>
na przycisk na stronie, z bazy danych
</form>
pobierana jest informacja o aktualnym </div>
stanie przełącznika i podejmowana jest </body>
akcja – dodanie lub usunięcie rekordu </html>
z informacją.

32 www.phpsolmag.org PHP Solutions Nr 1/2007


XAJAX Dla zaawansowanych

Logowanie ginform znajduje się metoda xajax.get- cie dołączenia biblioteki xajax.js do sekcji
Proces logowania na stronie www prze- FormValues, gdzie jej parametrem jest head strony. Pozostałe czynności związa-
biega szablonowo. Gdy użytkownik wy- identyfikator przypisany do formularza. ne z JS ograniczają się już tylko do two-
pełni formularz, ten wysyłany jest meto- To właśnie ta linijka jest esencją tego rzenia odwołań do funkcji PHP. XAJAX
dą POST do serwera – użytkownik jest lo- przykładu. Do funkcji loginform widocz- spisuje się dobrze, nawet gdy pod uwa-
gowany. Co się jednak dzieje, gdy wpisa- nej na Listingu 3 trafiają wszystkie dane gę wziąć kwestię obsługi rodzimych zna-
ny przez niego login lub hasło są niepra- wprowadzone przez użytkownika w for- ków diaktrycznych. Bibliotekę tą można
widłowe? Użytkownik trafi czas, otrzymu- mie tablicy asocjacyjnej $d. Na podsta- uznać za idealną dla wszystkich tych pro-
jąc komunikat o niepoprawnych danych wie danych, które wprowadził użytkow- gramistów PHP, którzy cenią sobie stałość
dopiero po przeładowaniu strony. Stwórz- nik pobieramy z bazy danych użytkowni- i przewidywalność środowiska programi-
my zatem system logowania, który po ków informacje. W tym przykładzie może stycznego jakim jest język PHP. Umiejęt-
wciśnięciu przycisku loguj sprawdzi po- rozpatrujemy zbyt dużą ilość przypadków nie napisany kod PHP do obsługi XAJAX
prawność wprowadzonych danych. Jeże- w których użytkownik popełnia błąd, lecz pozwala na bardzo szybkie zmiany, dzię-
li będą one poprawne, formularz zostanie ma to na celu pokazanie jak szybko i ła- ki czemu nakłady dodatkowej pracy przy
wysłany metodą POST, a użytkownik zo- two przekazać użytkownikowi informację usuwaniu usterek są minimalne. W arty-
stanie zalogowany. Jeżeli dane będą nie- o niepoprawnym wprowadzeniu danych. kule udało się pokazać tylko najpopular-
poprawne, użytkownik bez konieczności Dopiero, gdy informacje są w pełni po- niejsze metody oferowane przez bibliote-
przeładowania strony otrzyma informację prawne, następuje logowanie. Polega ki XAJAX. Więcej informacji o pozostałej
o niepoprawnym loginie, bądź haśle. Ten ono na wyświetleniu informacji proszę funkcjonalności biblioteki można znaleźć
sposób rozumowania zapewnia, że nawet czekać oraz uruchomieniu skryptu, który w dokumentacji. n
przy wyłączonej obsłudze AJAX użytkow- automatycznie wyśle formularz.
nik będzie mógł skorzystać z usługi.
W poprzednich przykładach pominę- Podsumowanie O autorze
liśmy kwestię kodowania. Problem nie XAJAX to biblioteka, która pozwala pro-
był zauważalny. By dane przesyłane z gramiście przejść od nauki do programo- Paweł Grzesiak jest projektantem wi-
serwera poprzez XAJAX miały popraw- wania po zaledwie kwadransie. Popraw- tryn internetowych z sześcioletnim do-
ne kodowanie, należy ustalić domyślny ne działanie oraz pełnia automatyzacja świadczeniem. Zajmuje się tworzeniem
rozbudowanych witryn w oparciu o sys-
standard kodowania. sprawia, iż implementacja technik opar-
tem CMS własnego autorstwa. Jest au-
Mechanizm działania tego przykładu tych o AJAX staje się nieskomplikowana torem ponad 50 publikacji w Magazynie
uwzględnia nową właściwość, a miano- i przez to osiągalna dla każdego. W XA- Internet, Internet Maker oraz phpSolu-
wicie pobieranie danych, które użytkow- JAX-ie urzeka nie tylko prostota i efektyw- tions. Obecnie pracuje nad książką, która
ukaże się nakładem wydawnictwa Helion
nik wprowadził do formularza. Na koń- ność działania, lecz także mała inwazyj-
pod koniec tego roku.
cu Listingu 4 widoczne jest odwołanie do ność w kod już istniejących aplikacji. Przy-
skryptu JS odpowiedzialnego za obsłu- kładem na to jest kod JavaScript, o któ- Kontakt: pawel@grzesiak.com.pl
gę żądania. Wewnątrz funkcji xajax_lo- rym praktycznie zapomina się w momen-

R E K L A M A

PHP Solutions Nr 1/2007 www.phpsolmag.org 33


Dla zaawansowanych

Budowanie obiektów z requestu


przy pomocy Reflection API
Stopień trudności: lll
Piotr Szarwas

Tworząc projekty informatyczne


często spotykam się ze stwierdzeniem
przypominającym poniższe zdanie „napisz to
tak, aby nie trzeba było modyfikować kodu jak
pojawią się nowe wymagania”. Jak to bywa
z wieloma prostymi stwierdzeniami można
je podsumować kolejnym dobrze znanym
powiedzeniem „łatwiej powiedzieć trudniej
zrobić”. Na całe szczęście da się tak zrobić.

I
stnieją techniki programistyczne uła- li istnieje taka potrzeba można przy je-
twiające tworzenie kodu, którego go pomocy powołać do życia instancję
prawie nie trzeba modyfikować w dowolnej klasy, wykonać publiczną me-
momencie, gdy pojawią się jakieś nowe todę dowolnego obiektu lub wykonać
wymagania. Wiele z tych technik opisy- dowolną funkcję. Reflection API bywa
wałem w poprzednich artykułach( Serwi- bardzo przydatnym narzędziem w każ-
ce Data Objects czyli uniwersalny stan- dej sytuacji, gdy z pewnych powodów
dard dostępu do danych cześć pierwsza podczas tworzenia kodu nie możemy
i druga, Wzorce projektowe w akcji czy- bezpośrednio wywołać jakieś metody
li czyli ciąg dalszy niezbędnika dewelo- lub funkcji. Na przykład dlatego, że nie
pera PHP, Zenda Framework,Budujemy znamy jej nazwy lub listy parametrów,
własny kontener IoC, czyli jak to się robi a wiemy, że poznamy je dopiero pod-
w Hollywood), w tym chciałbym się sku- czas wykonywania programu. Najczę-
pić na Reflection API i możliwościach ściej ma to miejsce w przypadku frame-
jego zastosowania w aplikacjach webo- worków gdzie nieznajomość klas i funk-
wych.

Czym jest Reflection Co powinieneś wiedzieć:


Należy znać zasady projektowania obiek-
API towego w PHP 5.
Reflection API to zestaw klas i funkcji
przy pomocy, których programista mo-
Co obiecujemy:
że zdobyć informację o budowie dowol- Pokażemy jak budować aplikacje odpor-
nej klasy, obiektu lub funkcji, wbudowa- ne na zmiany wymagań.
nej w PHP lub napisanej w PHP. Jeże-

34 www.phpsolmag.org PHP Solutions Nr 1/2007


Reflection API Dla zaawansowanych

cji aplikacji zbudowanej na danym fra- publicznych metod sprawdzając dodat- ro w wersji 5.0. Zapewne dlatego jest ma-
meworku jest czymś naturalnym. Rza- kowo czy metoda istnieje i jest publiczna. ło znane. Od momentu swojego pojawie-
dziej można znaleźć zastosowanie dla Pełne opisanie czym jest Reflection API i nia się jest stale rozbudowywane o nowe
Reflection API w typowych aplikacjach. do czego można by je zastosować mo- klasy i metody. Dlatego jeżeli na prawdę
Aby lepiej je zrozumieć przyjrzyjcie się gło by zapewne stanowić pokaźny roz- będziecie chcieli korzystać z tego narzę-
prostemu przykładowi (Listing 1), w któ- dział jakiejś książce, dlatego nie oczekuj- dzia polecam używanie ostatniej stabilnej
rym front kontroler aplikacji ma za zada- cie, że zmieści się on w jednym artyku- wersji PHP jaka jest dostępna. Jeżeli nie
nie na podstawie zewnętrznych parame- le. Wszystkich zainteresowanych zazna- macie takich możliwości na stronach PHP
trów powołać do życia jakąś klasę i wy- jomieniem się ze szczegółami API od- znajdziecie dokładne informacje o tym,
wołać na niej metodę command z para- syłam do dokumentacji na stronie http:// które funkcjonalności API są dostępne w
metrami. www.php.net/manual/en/language.oop5. której wersji. Dodam, że cały kod napisa-
Oczywiście przykład ten nie pokazu- reflection.php. Znajdziecie tam też wiele ny na potrzeby tego artykułu był urucha-
je wszystkich możliwości Reflection API, przykładów pokazujących jak stosować miany w środowisku PHP 5.1.6 i niestety
pokazuje jednak sedno jego możliwości – Reflection API. nie wiem jak zachowa się we wcześniej-
powoływanie do życia dowolnych obiek- Reflection API jest stosunkowo świe- szych wersjach PHP.
tów i wywoływanie na nich dowolnych żym elementem PHP, pojawiło się dopie- Używając Reflection API należy pa-
miętać, że ma ono swoją cenę, jego uży-
cie może mieć wpływ na pogorszenie wy-
����� dajność całej aplikacji. Tak więc używajcie
������ ����� go z rozwagą. Na potrzeby tego artykułu
�������������� przeprowadziłem prosty test. Napisałem
������ � dwa kawałki kodu, w jednym na obiekcie

������ � wywoływałem metodę bezpośrednio, w
� ���� drugim przy pomocy Reflection API. Na-

�����

������ stępnie kod ten umieściłem w pętli for, któ-
�������
������ � ����� ra była wywoływana milion razy. Wynik nie
� �������� był zastraszający, okazało się że wywoły-

���������������� wanie bezpośrednie jest średnio dwa ra-
�����������������
�������������� zy szybsze. Jeżeli więc w kodzie aplikacji
�������������������� będzie niewiele wywołań tego typu, efekt
pogorszenia wydajności może być prawie
zauważalny.
Rysunek 1. Schemat procesu mapowania danych pochodzących z formularza na
obiekty biznesowe
Świat przed Reflection
API
Zanim powstało Reflection API, we
���� wcześniejszych wersjach PHP było wy-
posażone w kilka funkcji, które moż-
na by nazwać namiastką Reflection
��������
�������������������� ��������� API. Właściwe Reflection API zbiera te
����������������������� ������� wszystkie funkcje w jedną całość doda-
����������
jąc wiele nowych i udostępnia w posta-
ci zestawu klas. Ponadto w sam język
�������� ����� były i są ciągle wbudowane elementy
�������������������������� ��������� ������ przypominające swoim działanie Reflec-
�������������������������� ������� ����
�������������� ���������� ������� tion API. Na przykład porównując przy-
kład z front kontrolerem zamiast „$reflO-
bject->getInstance()” moglibyśmy od-
�������� ����� wołać się do możliwości PHP i ten sam
������������������ ��������� ������
������� ���� efekt uzyskać przy pomocy następują-
�������������������������
���������� ������� cego kodu „new $className()”, albo za-
miast metody invoke moglibyśmy zasto-
���� sować składnię „$object->{$methodName
($parameter)}. Podejście bez Reflection
API ma jednak dwa bardzo duże ograni-
Rysunek 2. Schemat blokowy algorytmu budowy obiektów biznesowych aplikacji czenia. Po pierwsze jest mniej elastycz-
z danych pochodzących z formularza, wraz z przykładowym przebiegiem ne gdyż wymaga dokładnej znajomości

PHP Solutions Nr 1/2007 www.phpsolmag.org 35


Dla zaawansowanych Reflection API

ilości parametrów zarówno w przypadku Budowanie obiektów kasowany wszystko zależy od akcji po-
konstruktora jak i metody, którą chce- z requestu wiązanej z danym formularzem. Proces
my w ten sposób wywołać. Po drugie Spróbujmy teraz zdobytą wiedzę o Re- mapowania jest konieczny gdyż chcemy
w przypadku błędu PHP przerwie wyko- flection API wykorzystać do rozwiązania oddzielić funkcje biznesowe aplikacji od
nywanie kodu i zwróci Fatal Error, które- pewnego problemu. Wyobraźcie sobie, specyfiki warstwy prezentacji WWW. Wy-
go nie możemy kontrolować. Jeżeli za- że na wielu stronach waszej aplikacji wy- konywanie mapowania ręcznie jest bar-
stosujemy Reflection API każde niepo- stępuje formularz, za każdym razem in- dzo żmudnym zajęciem podczas, które-
wodzenie będzie sygnalizowane przy ny. Formularz ten w kodzie mapowany go może pojawić się wiele błędów. Do-
pomocy wyjątku, który możemy złapać jest do obiektu, a obiekt jest dalej wali- datkowo jeżeli, któryś z obiektów lub for-
i obsłużyć. dowany, zapisywany, modyfikowany lub mularzy ulegnie zmianie, mapowanie też

Listing 1. Implementacja prostej klasy front kontrolera, której przy pomocy Listing 2. Klasy biznesowe
Reflection API powoływane są obiekty klas akcji, a następnie na każdym z nich wykorzystywane w przykładzie. Ich
wywoływana jest metoda command charakterystyczną cechą jest to że
dostęp do ich atrybutów odbywa się
class FrontController { poprzez settery i gettery
public function doService
(HttpRequest $request){ class Group {
if ($request==null){ private $name;
return null; public
} function __construct() {
$className = $request-> }
getVar(); public function
$classObj = $this->create setName($name){
Object($className); $this->name = $name;
return $this->invoke }
Method($classObj,"command" public function getName(){
,$request); return $this->name;
} }
private function create }
Object($className){ class News {
if ($className==null){ private $title;
return null; private $author;
} private $date;
//Zakładamy że plik z klasą jest już załadowany private $content;
$relfObj = new public
ReflectionClass($className); function __construct() {
if (!$relfObj->isInstantiable()){ }
return null; public function setTitle
} ($title){
//Zakładamy że konstruktor $this->title = $title;
nie ma parametrów }
return $relfObj-> public function getTitle(){
newInstance(); return $this->title;
} }
private function invoke public function setAuthor
Method($object,$method ($author){
Name,$parameters){ $this->author = $author;
if ($object==null || $method }
Name==null){ public function getAuthor(){
return null; return $this->author;
} }
//Zakładamy że plik z klasą public function setDate($date){
jest już załadowany $this->date = $date;
$relfObj = new Reflection }
Object($object); public function getDate(){
return $this->date;
if (!$relfObj->hasMethod }
($methodName)){ public function setContent
return null; ($content){
} $this->content = $content;
return $relfObj->getMethod }
($methodName)->invoke public function getContent(){
($object,$parameters); return $this->content;
} }
} }

36 www.phpsolmag.org PHP Solutions Nr 1/2007


Reflection API Dla zaawansowanych

musi uleć zmianie, tak więc aplikacja nie


Listing 3. Zawiera kod prostszej wersji metody bind jest odporna na tego typu zmiany. Spró-
bujmy więc zautomatyzować proces ma-
class SimpleBinder {
public static function bind($request, $object){ powania, tak aby był on niezależny od
if($request==null || !is_array($request) || $object==null){ zawartości formularza i budowy obiek-
return null; tu do którego dany formularz jest mapo-
} wany. Oczywiście wykorzystamy do tego
//Tworzymy obiekt Reflection API
zadania Reflection API. Aby zobrazować
$reflectionObject = new ReflectionObject($object);
//Pobieramy informacje o wszystkich metodach obiektu cały problem lepiej posłużyć się przy-
$methods = $reflectionObject->getMethods(); kładem, w którym news będzie doda-
foreach($methods as $method){ wany do bazy danych. Formularz new-
//Sprawdzamy czy metoda jest publicznym setterem sa zawiera następujące pola: grupa, ty-
$methodName = $method->getName();
tuł, autor, data, treść. Formularz ten bę-
if (substr($methodName,0,3)=="set" && $method->isPublic()){
//Na postawie settera tworzymy nazwę pola dzie mapowany do dwóch obiektów: gru-
$fieldName = strtolower($methodName[3]).substr($methodName,4); py i newsa (Rys.1).
//Sprawdzamy czy w requescie jest zmiena o nazwie pola Kod mapujący składa się z jednej me-
if (isset($request[$fieldName])){ tody bind, która ma dwa parametry. Pierw-
$method->invoke($object,$request[$fieldName]);
szy to request, w którym są zgromadzone
}
} dane z formularza, drugi to obiekt do któ-
} rego mamy przepisać dane z formularza,
} w naszym przypadku będzie to instancja
} klasy Grupa lub News (Listing 2).
Listing 4. Klasy biznesowe wykorzystywane w przykładzie
bind($request, $object);
class Address {
private $country; Zmienna $request jest jedynie sumą
private $town;
tablic $_GET i $_POST. Zasada działania
private $street;
private $zipCode;
metody jest następująca (Rys.2):
private $flatNumber;
public function setCountry($country){ l przy pomocy Reflection API pobie-
public function getTown(){ ramy z obiektu informację o wszyst-
return $this->town;
kich publicznych setterach, w naszym
}
public function setStreet($street){
przypadku będą to wszystkie settery
$this->street = $street; obiektów klas Group i News;
} l dla każdego setera sprawdzamy czy
public function getStreet(){ w requescie jest zmienna, która od-
return $this->street;
powiada nazwie settera z pominię-
}
public function setZipCode($zipCode){
ciem ciągu „set ” i zmianą pierwszej
$this->zipCode = $zipCode; litery na małą w pozostałej części
} settera, czyli setTitle zmieni się na
public function getZipCode(){ title;
return $this->zipCode; l przy pomocy Reflection API wywo-
}
public function setFlatNumber($flatNumber){
łujemy odpowiedniego setter z odpo-
$this->flatNumber = $flatNumber; wiednią wartością z requestu;
} l proces powtarzamy aż ostatni setter
public function getFlatNumber(){ zostanie ustawiony.
return $this->flatNumber;
}
}
Jak łatwo zauważyć zaproponowany al-
class Person { gorytm ma tylko dwa wymagania, jeże-
private $nameFirst; li chcemy ustawić jakąś zmienną musi-
private $lastName; my mieć zdefiniowany dla niej settera i
private $address;
nazwa parametru w requescie musi być
public function __construct() {
$this->address = new Address();
poprzez swoją nazwę skorelowana z set-
} terem. Nie są to założenia, które wpro-
public function setFirstName($firstName){ wadzają jakieś dodatkowo utrudnienia.
Można nawet powiedzieć, że bardziej
pomagają niż utrudniają, bo wprowadza-
ją potrzebę stosowania się do ogólnie
przyjętych konwencji programistycznych

PHP Solutions Nr 1/2007 www.phpsolmag.org 37


Dla zaawansowanych Reflection API

związanych z dostępem do atrybutów wszystkich metod w postaci obiektów ty- tu, na przykład bez problemu może-
obiektu poprzez settery i gettery. pu ReflectionMethod. Dla każdego obiek- cie dodać lub usunąć dowolne pole z
Cały kod metody bind przedstawiony tu ReflectionMethod sprawdzamy czy w obiektu newsa i kod bindera pozosta-
jest na Listingu 3. Jak widać nie jest dłu- requescie istnieje klucz odpowiadający nie bez zmian. Niestety nasz binder
gi. Na samym początku sprawdzamy czy nazwie settera. Jeżeli tak to przy pomocy ma jedną poważną wadę, nie obsługu-
parametry metody są poprawne, następ- metody invoke obiektu ReflectionMethod je ustawiania zmiennych na zagnież-
nie inicjalizujemy obiekt ReflectionObject, ustawiamy wartość spod tego klucza. dżonych obiektach. Co mam na myśli?
który zawiera metainformacje o naszym Metoda bind jest odporna na wiele Wyobraźcie sobie prosty przykład, ma-
obiekcie. Wydobywany z niego tablicę zmian związanych z zawartości obiek- my obiekt klasy Person (Listing 4) za-
wierający w sobie obiekt klast Address.
Listing 4a. Klasy biznesowe wykorzystywane w przykładzie Zakładając, że z requestu nie przycho-
dzą obiekty, a jedynie łańcuchy znako-
$this->firstName = $firstName; we nie możemy obsłużyć ustawienia
} atrybutów dla obiektu klasy Address.
public function getFistrName(){
Ich charakterystyczną cechą jest to że
return $this->firstName;
} dostęp do ich atrybutów odbywa się
public function setLastName($lastName){ poprzez settery i gettery.
$this->lastName = $lastName; Dodatkowo klasa Person w swoim
} konstruktorze inicjuje obiekt klasy Ad-
public function getLastName(){
drese dzięki temu metoda getAddress
return $this->lastName;
} zawsze zwróci obiekt Dlatego na ko-
public function setAddress($address){ lejnym listingu (Listing 5) umieszczo-
$this->address = $address; na jest wersja algorytmu, który roz-
} wiązuje ten problem. Do poprzednich
public function getAddress(){
dwóch założeń związanych z jego dzia-
return $this->address;
} łaniem dodałem jeszcze dwa. Pierw-
} sze, które mówi jak nazywać zmienne,
które są zagnieżdżone. Jeżeli chce-
Listing 5. Zawiera kod wersji metody bind umożliwiającej mapowanie my ustawić taką zmienną musimy po-
zagnieżdżonych obiektów
dać do niej pełną ścieżkę w posta-
class ComplexBinder { ci „obciętych” nazw getterów i sette-
public static function bind($request, $object){ rów oddzielonych kropkami. Na przy-
if($request==null || !is_array($request) || $object==null){ kład dla atrybutu street w obiekcie ad-
return null;
dress w requesie będzie musiał istnieć
}
//Tworzymy obiekt Reflection API
klucz address.street, co w normalnym
$reflectionObject = new ReflectionObject($object); odwołaniu w kodzie odpowiada nastę-
foreach($request as $attrName => $attrValue){ pującemu wywołaniu getAddress()-
//Zakładamy że możemy składać zagnieżdzone obiekty >setStreet($wartość). Drugie, któ-
$dotPosition = strpos($attrName,".");
re mówi że obiekty wewnętrzne mu-
if ($dotPosition===false){
//Jeżeli atrybut nie jest zagnieżdzony to sprawdzamy
szą być wstępnie inicjowane (tak jak
czy obiekt ma opowiedniego settera i ustawiamy ma to miejsce na listingu pokazującym
dla niego wartość obiekt Person (Listing 4)). To założenie
$setterName = "set".ucwords($attrName); wynika z faktu, że bez wstępnej inicja-
$setterObj = $reflectionObject->getMethod($setterName);
lizacji wywołanie kodu getAddress()-
if ($setterObj!=null && $setterObj->isPublic()){
>setStreet($wartość) nie powiodło-
$setterObj->invoke($object,$attrValue);
} by się bo getAddress zwróciłoby war-
} else { tość NULL.
//Jeżeli mamy doczynienia z zagnieżdzonym atrybutem Jak widać tym razem algorytm nie
to pobieramy ten atrybut i na nim ustawiamy odpowiednią wartość
jest już taki prosty. Ze względu na ko-
$getterName = "get".ucwords(substr($attrName,0,$dotPosition));
$getterObj = $reflectionObject->getMethod($getterName);
nieczność obsłużenia zagnieżdżonych
if ($getterObj!=null && $getterObj->isPublic()){ atrybutów zmieniliśmy sposób iteracji tym
$nestedObject = $getterObj->invoke($object); razem wykonujemy ją po każdym kluczu
self::bind(array(substr($attrName,$dotPosition+1) znajdującym się w requescie. Dla każdej
=>$attrValue),$nestedObject);
pary klucz, wartość z requesta sprawdza-
}
}
my czy w kluczu występuje kropka. Jeże-
} li nie to klucz traktujemy jako niezagnież-
} dżony atrybut i próbujemy ustawić odpo-
} wiadającą mu wartość na obiekcie. Jeże-
li obiekt jest zagnieżdżony, czyli posia-

38 www.phpsolmag.org PHP Solutions Nr 1/2007


Reflection API Dla zaawansowanych

dający w nazwie kropkę, to z części na- Tym razem nie będzie inaczej, ale jako, PHP. Możliwości zastosowania Reflec-
zwy przed pierwszą kropką tworzymy na- że przedstawiony do tej pory kod jest tion API można wymieniać długo. M.in.
zwę gettera i przy jego pomocy pobiera- oderwany od całości frameworku chciał- można budować formularze z obiektów,
my obiekt odpowiadający getterowi. Na- bym w kliku zdaniach napisać gdzie jest listy prezentujące dane, automatycznie
stępnie na tym obiekcie wywołujemy me- on umieszczony w Flexi. Metoda bind budować pytania zapisujące i modyfi-
todę bind. Zwróćcie uwagę, że w dzięki będzie częścią abstrakcyjnej klasy akcji, kujące dane w bazie. n
rekurencyjnemu wywołaniu metody bind dzięki czemu w każdej klasie akcji dzie-
nasz algorytm obsługuje dowolnie dłu- dziczącej po tym obiekcie programista
gie ścieżki. Może na przykład mieć struk- będzie mógł wywołać tą metodę. Do-
turę obiektów, której odpowiada ścieżka: datkowo jeżeli ktoś nie będzie chciał ko-
obiekt1.obiekt2.obiekt3.atrybut1. rzystać z abstrakcyjnej klasy akcji meto- O autorze
da będzie dostępne w klasie FLReflec- Piotr Szarwas ma wieloletnie doświad-
Flexi tionUtils. czenie w programowaniu i tworzeniu apli-
Mam nadzieje, że część z was śledzi kacji WWW (PHP, Java). Jest konsultan-
całą serię artykułów o wzorcach i do- Podsumowanie tem w jednej z największych polskich
firm IT, a także doktorantem na Wydzia-
brych praktykach programistyczny i wie Przedstawiony powyżej przykład jest le Fizyki Politechniki Warszawskiej. Od
że cały kod, który pojawia się w ramach tylko namiastką możliwości Reflecion dawna pisze artykuły dla PHP Solutions.
tych artykułów jest publikowany na sour- API. Mam jednak nadzieje, że udało mi
Kontakt z autorem:
ceforge pod szyldem frameworka o na- się zwrócić waszą uwagę na ten bar-
piotr.szarwas@gmail.com
zwie Flexi (http://flexi.sourceforge.net/). dzo pożyteczny moim zdaniem element

R E K L A M A

PHP Solutions Nr 1/2007 www.phpsolmag.org 39


Dla zaawansowanych

Warstwowy model aplikacji


Stopień trudności: lll
Paweł Klimczyk

Projektowanie aplikacji ma swój początek w póź-


nych latach 60-tych XX wieku. Podstawowym
niepisanym modelem aplikacji – w raczkującej
wtedy inżynierii programowania – był model
monolityczny.

W
modelu tym istnieje tylko lach z warstwy danych. Warstwa serwi-
umowne podzielenie aplika- sów udostępnia zestawy funkcji pośred-
cji na części i hierarchię. Do- niczące między warstwą biznesową,
konywanie zmian w takim modelu jest a interfejsem użytkownika. Ostatnia war-
dość uciążliwe z powodu dużych powią- stwa – prezentacji – służy do wizualiza-
zań występujących wewnątrz kodu. Był cji danych, które zostały przetworzone
to podstawowy powód dla którego po- przez niższe warstwy modelu.
wstał model warstwowy. W tym artykule opiszę sposób imple-
mentacji aplikacji modelu warstwowego
Opis warstw modelu na przykładzie katalogu samochodowe-
Model będący przedmiotem niniejszego go, który następnie rozszerzę o kolejny
artykułu składa się z kilku warstw. Klu- obiekt – motocykl. Przed rozpoczęciem
czowym krokiem jest logiczne ich zdefi- omawiania modelu warstwowego na kon-
niowanie w stadium projektowania apli- kretnym przykładzie należy utworzyć ta-
kacji. Przykładowy i dość często stoso-
wany model składa się z czterech war-
stw(rysunek 1): dostępu do danych, biz-
Co obiecujemy:
Nowoczesne spojrzenie na tworzenie
nesowej, serwisów i interfejsu użytkow- średnich i dużych aplikacji. Sposób na
nika. W warstwie dostępu do danych proste zarządzanie kodem aplikacji.
powinny znajdować się modele (obiek-
ty, tablice asocjacyjne itp.), z których Co powinieneś wiedzieć:
będziemy korzystać w aplikacji. War- Zaawansowane techniki programowania.
Podstawy baz danych. Logiczne myśle-
stwa biznesowa to zbiór funkcji wyko-
nie w czasie procesu projektowania.
nujących określone zadania na mode-

40 www.phpsolmag.org PHP Solutions Nr 1/2007


Model aplikacji Dla zaawansowanych

Tabela 1. Warstwa dostępu do danych wywania (baza danych, pliki) powin- gdzie szukać/poprawiać/dodawać funk-
ny mieć swoje odzwierciedlenie mo- cje do konkretnych obiektów. Przykłado-
Presentation Layer
delowe w warstwie DAL. Przykładową wa implementacja warstwy BLL znajduje
Services Layer implementację warstwy DAL można się na Listingu 2.
zobaczyć na Listingu 1. Kod na listingu 2 zawiera kilka pod-
Business Logical Layer Plik zawiera definicję klasy Car. stawowych funkcji ułatwiających mani-
Nazwy składowych są takie same jak pulację obiektem i listą obiektów Car.
Data Access Layer
nazwy pól w bazie danych. Na tym Nazwy funkcji zostały dobrane zgodnie
belę, gdzie będą przechowywane dane etapie implementacji nie ma jeszcze z ich działaniem. Funkcja AddCar do-
samochodów. żadnych funkcji – są definiowane w daje obiekt do bazy danych, DeleteCar
warstwie BLL. usuwa z bazy, UpdateCar aktualizuje
CREATE TABLE Cars informacje, GetCarById odczytuje infor-
( Warstwa biznesowa macje o samochodzie o identyfikatorze
idCar INTEGER NOT NULL Celem tworzenia warstwy biznesowej idCar podanym w parametrze. Wszystkie
AUTO_INCREMENT, jest budowa zestawu funkcji używa- wymienione powyżej funkcje wykonują
model VARCHAR(25) NOT NULL, jących danych z warstwy DAL. Funk- operacje na pojedynczym obiekcie Car.
engineNumber VARCHAR(50) cje te powinny wykonywać podstawowe Jedyny wyjątek w klasie carManager sta-
NOT NULL, zadania, np. uzyskać konkretny obiekt, nowi funkcja GetCarList, która zwraca
wieght VARCHAR(16) NOT NULL, do którego odwołują się warstwy wyż- listę obiektów. Funkcja ta będzie następ-
color VARCHAR(20) NOT NULL, sze, uzyskać listę obiektów bądź wyko- nie używana do dostarczenia danych na
PRIMARY KEY(idCar) nać na obiekcie jakiekolwiek przekształ- potrzeby przeglądania wszystkich skata-
); cenie (edycję) zapisane następnie w wy- logowanych w bazie samochodów.
branej przez programistę formie. Do- Klasa carManager korzysta z klasy
Warstwa brym zwyczajem jest grupowanie od- sqlManager, która jest interfejsem po-
dostępu do danych powiednich funkcji w klasy managerów. średniczącym między aplikacją, a źró-
Warstwa dostępu do danych (DAL – Przykładowo carManager będzie klasą dłem danych. Klasa sqlManager zosta-
Data Access Layer) to najniżej leżąca warstwy biznesowej zawierającą funk- ła zdefiniowana osobno, ponieważ jej
warstwa modelu. Zawiera ona obiek- cje odnoszące się do wszystkich opera- funkcje mogą być z powodzeniem użyte
ty reprezentujące dane wykorzystywa- cji na obiekcie Car. Dzięki takiemu roz- w innych klasach warstwy BLL, których
ne w programie. Wszystkie informacje, wiązaniu programista, bądź zespół pro- istnienie w obecnej fazie projektu nie zo-
nie zależnie od sposobu ich przecho- gramistów będzie odruchowo wiedział stało przewidziane.

Listing 1. Przykładowa implementacja warstwy DAL


Warstwa serwisów
Warstwa serwisów (Service Layer) jest
car.inc interfejsem dla warstwy prezentacji.
<?php Jej zadaniem jest zarówno dostarcze-
class Car
nie warstwie BLL zwalidowanych obiek-
{
tów, które mają np. zostać zapisane w
var $id;
var $model; bazie danych, jak również udostępnie-
var $engineNumber; nie warstwie prezentacji danych, któ-
var $weight; re zostały np. posortowane bądź prze-
var $color;
filtrowane. Ma to znaczenie w przypad-
}
ku występowania w aplikacji grup użyt-
?>
kowników, bądź innych warunków, które
muszą być spełnione przez prezentacją
danych. W wielu przypadkach nakłada
się ona na warstwą logiczną aplikacji,
w takim przypadku można zrezygno-
wać z modelu czterowarstwowego na
rzecz jego trójwarstwowego odpowied-
nika. Przykładowa warstwa serwisów
używana w katalogu samochodowym
została przedstawiona na Listingu 3.
Jak można zauważyć funkcje są dość
podobne w nazewnictwie i działaniu do
funkcji warstwy BLL. W funkcji addCar
Rysunek 1. Warstwa prezentacji została wprowadzona prosta walidacja

PHP Solutions Nr 1/2007 www.phpsolmag.org 41


Dla zaawansowanych Model aplikacji

otrzymanych od użytkownika danych. należy zatroszczyć się o ich wizuali-


Listing 2. Implementacja warstwy BLL
Użyte zostały funkcje ShowInfo oraz Sho- zację użytkownikowi. Zadanie to jest
carManager.inc wError, których celem jest komunikacja realizowane w warstwie prezenta-
<?php z użytkownikiem. cji. Programista nie musi przejmować
/*
się jak wyciągnąć potrzebne dane.
Car Manager
*/
Warstwa prezentacji Wystarczy, że wywoła odpowiednią
require_once 'sqlManager.inc'; Kiedy stworzone są już solidne fun- – stworzoną wcześniej w warstwie
class carManager damenty (BLL) do wykonywania ope- serwisów – funkcję. Na Listingu 4
{ racji na danych(DAL) przy użyciu została przedstawiona przykładowa
function GetCarByID($idCar)
odpowiednich interfejsów (Serwisy) implementacja warstwy prezentacji.
{
$sqlManager= new sqlManager();
$sqlManager->createConn(); Listing 3. Przykładowa warstwa serwisów
return $sqlManager->QueryObj
("SELECT * ?php
FROM cars where idCar=".$idCar); require ($config["ManagerDir"].
} "carManager.inc");
function GetCarList() class carService
{ {
$arr = array(); function getCarById($idCar)
$sqlManager= new sqlManager(); {
$sqlManager->createConn(); $carManager = new carManager;
$obj=$sqlManager->QueryArray return $carManager-
("SELECT * >GetCarByID($idCar);
FROM cars"); }
while ($row = function getCarList()
mysql_fetch_object($obj)) { {
$arr[]=$row; $carManager = new carManager;
} return $carManager->GetCarList();
return $arr; }
} function deleteCar($idCar)
function UpdateCar($car) {
{ $carManager =
$sqlManager= new carManager;
new sqlManager(); return $carManager-
$sqlManager->createConn(); >DeleteCar($idCar);
$sqlManager->updateObj }
(sprintf("UPDATE cars SET function updateCar($car)
`model`='%s' , {
`engineNumber`='%s' , `weight`= $carManager = new carManager;
'%s' , `color`='%s' WHERE $carManager->updateCar($car);
`idCar`='%s'", ShowInfo
$car->model,$car->engineNumber, ("Car successfully updated!");
$car->weight,$car->color,$car return;
->idCar)); }
} function addCar($car)
function DeleteCar($idCar) {
{ if(strlen($car->model)
$sqlManager= new sqlManager(); <3 || strlen($car->
$sqlManager->createConn(); engineNumber)<3 || strlen
$sqlManager->deleteObj(sprintf ($car->weight)<3
("DELETE FROM cars where idCar= || strlen($car->color)<3)
%s",$idCar)); {
} ShowError("Fill all data!");
function AddCar($car) }
{ else
$sqlManager= new sqlManager(); {
$sqlManager->createConn(); $carManager =
$sqlManager->addObj(sprintf new carManager;
("INSERT INTO $carManager->addCar($car);
cars ( `idCar` , `model` , ShowInfo
`engineNumber` , `weight` , ("Car successfully added!");
`color`) VALUES ( }
'', '%s', '%s', '%s', '%s')",$car- return ;
>model,$car- }
>engineNumber,$car->weight, }
$car->color)); ?>
?>

42 www.phpsolmag.org PHP Solutions Nr 1/2007


Model aplikacji Dla zaawansowanych

Jak widać przedstawienie listy ska- dokonać. Aplikacja o charakterze mo- projekcie służącym za przykład wyko-
talogowanych samochodów jest dziecin- nolitycznym z pewnością będzie mno- rzystania modelu warstwowego zosta-
nie prostym zadaniem. Sprowadza się żyć pytania w stylu:„Dlaczego funk- ły pominięte aspekty bezpieczeństwa,
do stworzenia obiektu serwisu i wywoła- cja getCarById zwraca sformatowa- graficznej prezentacji danych, a funk-
nia jego metody getCarList. W efekcie w ny tekst HTML, a nie obiekt? I gdzie cjonalność katalogu przedstawia wie-
zmiennej carArray otrzymujemy listę sa- ona jest w ogóle zdefiniowana?!”. Na- le do życzenia. Jest to zamierzone
mochodów zapisanych w bazie danych. tomiast w przypadku aplikacji warstwo- działanie, mające na celu nie zaciem-
Efekt działania warstwy prezentacji widać wej zapewne od razu – nawet średnio- nianie głównego tematu artykułu. Po-
na Rysunku 2. zaawansowanemu programiście – rzu- wyższe aspekty zostały świadomie
ci się w oczy logiczne ułożenie całe- pominięte. n
Ewolucja aplikacji go projektu. W związku z czym, będzie
Projekty programistyczne często nie mu zdecydowanie łatwiej dodać nową
posiadają sztywno narzuconych granic funkcjonalność.
funkcjonalności. Jest to podyktowane
różnymi względami, niekoniecznie zro- Podsumowanie O autorze
zumiałymi przez zespół programistycz- Przedstawiony w tym artykule spo- Paweł Klimczyk jest pasjonatem tech-
ny. Z biznesowego punktu widzenia w sób modelowania aplikacji jest prze- nicznym. W kręgu głównych zaintere-
aplikacji, która posłużyła za przykład znaczony zdecydowanie dla aplikacji sować komputerowych znajduje się:
do tego artykułu przydałby się rów- średnich bądź dużych. Użycie mode- tworzenie aplikacji webowych (asp.net,
php), wszelakie aspekty bezpieczeń-
nież katalog innych środków transpor- lu warstwowego w aplikacjach mniej- stwa i administracja serwerowa syste-
tu, np. motocykli bądź rowerów. Oczy- szych można porównać do celowania mów Linux. Aktualnie pracuje w firmie o
wiście w każdym modelu aplikacji (np. z armaty do muchy, aczkolwiek należy globalnym zasięgu – TRW Automotive –
warstwowym lub monolitycznym) jest w fazie projektu przemyśleć, czy cza- na stanowisku programisty i rozwija apli-
kacje wewnętrzne firmy.
możliwość dodania takiej funkcjonal- sem mały z pozoru projekt nie nosi
ności. Kluczowym aspektem jest tutaj znamion większego serwisu. Uważny Kontakt z autorem: pawel@klimczyk.pl
czas, w jakim programista może tego czytelnik z pewnością zauważył, że w

R E K L A M A

PHP Solutions Nr 1/2007 www.phpsolmag.org 43


Narzędzia

LIZ DB
– zaawansowane możliwości bazy MySQL 5
Stopień trudności: lll
Łukasz Budnik

MySQL 5 nowe możliwości Pewnie część z nas


miała już styczność z nową wersją najpopular-
niejszej bazy opensource'owej MySQL oznaczo-
ną numerem 5. MySQL 5 wprowadziło szereg
nowych opcji. Najważniejsze z nich dla projek-
tantów baz danych, na co narzekało wielu,
to możliwość wykorzystywania składowanych
procedur i funkcji.

W
PHP5 nie ma jeszcze odpo- wersji PHP4. Głównie z powodu używa-
wiedniego modułu, który by nia zaawansowanej obiektowych, in-
umożliwiał pracę z nowymi terfejsów oraz mechanizmu wyjątków
opcjami bazy MySQL 5. Tak – możemy dla sygnalizowania sytuacji nieprawi-
oprogramować wszystko samemu, tyl- dłowych i błędów. LIZ DB jest dostęp-
ko czy trzeba nam wymyślać ponownie nym na sourceforge.net. Możemy ścią-
koło? Czy wszystko musimy robić ręcz- gnąć najnowszą wersję kodów źródło-
nie? Oczywiście, że nie. Możemy sobie
ułatwić pracę korzystając z gotowej bi-
blioteki. Co obiecujemy:
Nauczysz się korzystać z zaawansowa-
LIZ DB – z wszystkiego nej biblioteki LIZ DB, dzięki niej nauczysz
się pisać szybko programy bazodanowe
po trochu: Java, .NET począwszy od prostych zapytań, zapy-
Podtytuł tego paragrafu może być dość tań przygotowanych a skończywszy na
mylący. Pewnie każdy z nas pomyślał, że wywołaniach procedur składowanych.
Zapoznasz się z nowymi możliwościa-
musi mieć PHP5 z mnóstwem dodatko-
mi MySQL 5, poznasz metody tworze-
wych modułów. Otóż nie – potrzebujemy nie składowanych procedur i funkcji oraz
oczywiście PHP5 z tylko jednym (z punk- dowiesz się jak i kiedy stosować je w
tu widzenia LIZ DB) modułem – MySQLi. praktyce.
Moduł ten wypiera starszą implementacje
MySQL w PHP i jest dostępny również w Co powinieneś wiedzieć:
Powinieneś mieć ogólną wiedzę z obiek-
wersji PHP4.
towości PHP5, powinieneś dobrze znać
LIZ DB jest narzędziem napisanym MySQL (nie koniecznie MySQL 5).
w PHP5 i nie będzie chodził na starszej

44 www.phpsolmag.org PHP Solutions Nr 1/2007


LIZ DB Narzędzia

wych wraz z obszernymi przykłada- ków najważniejsze to, że powstał bardzo także składnie tworzenia takich proce-
mi ze strony głównej projektu: http:// dobry i o dużych możliwościach silnik do dur i funkcji.
sourceforge.net/projects/lizdb, dodatko- obsługi baz danych MySQL 5.
we informacje można znaleźć na stro- Po przeczytaniu tego artykułu LIZ DB – biblioteka
nie http://www.komputery-internet.net/ uzmysłowimy sobie, że zaawansowa- do obsługi MySQL 5
php/. ne możliwości baz danych wcale nie są LIZ DB to narzędzie napisane w nowym
Twórca tej biblioteki oprócz tego, że takie straszne jak by się mogło wyda- obiektowym PHP5. Jakie są jego możli-
jest programistą PHP jest również progra- wać i bez problemu możemy z nich ko- wości? Są spore! Oto najważniejsze:
mistą Java i MS .NET, w których również rzystać, nawet jeśli dopiero zaczynamy
oprogramowuje bazy danych. LIZ DB za- programować w PHP5. • pobieranie danych na różne sposoby
wiera parę zapożyczeń koncepcji z JDBC W ostatniej części tego artyku- – Select (zbiory rekordów), SelectOne
oraz .NET. ły omówimy jakie należy nadać prawa (pojedynczy rekord), SelectColumn
Można powiedzieć, że z każdej tech- użytkownikom MySQL aby móc two- (zbiór kolumn);
nologii wybrane zostało to, co najlepsze. rzyć, zamieniać i oczywiście wykony- • pełne wsparcie i wykonywanie in-
A co dla nas, jako końcowych użytkowni- wać procedury składowane. Omówimy strukcji DML (INSERT, UPDATE, DE-
LETE) oraz DDL (CREATE, ALTER,
CHANGE, DROP);
Nowe możliwości MySQL 5 • przygotowywanie i wykonywanie za-
pytań w stylu Java'y: setInt(1, $pa-
• Procedury i funkcje składowane (ang. Stored Procedures) – procedury i funkcje ram), setString(2, $param), setBlob(3,
umieszczane na serwerze, mogą wykonywać skomplikowane operacje, które z punktu
$param) etc.;
widzenia programisty sprowadzają się do wykonania jednej operacji – wywołania pro-
• zarządzanie i wspomaganie zaawan-
cedury, znacznie więcej na ten temat w artykule
• Wyzwalacze (ang. Triggers) – procedury wykonywane gdy zachodzą pewne zdarze- sowanych transakcji: commit, roll-
nia w bazie (np. wstawienie, edycja czy usunięcie rekordu) back, savepoint, rollback do założo-
• Widoki (and. Views) – mechanizm poprawiający bezpieczeństwo danych, jeśli ma- nych savepointów;
my tabelę pracownicy i nie chcemy aby każdy mógł ją przeglądać (np. kolumnę • przygotowywanie i wykonywanie
z płacami), wówczas tworzymy widok jako polecenie: CREATE VIEW „w _ pracownicy” procedur i funkcji składowanych
AS SELECT id _ p, imię, nazwisko, dział, pozycja, staż FROM pracownicy. Na- z pełną obsługą parametrów we
stępnie odbieramy prawa SELECT do tablicy pracownicy i nadajemy je do widoku wszystkich możliwych kierunkach:
„w _ pracownicy” IN, INOUT, OUT w stylu .NET;
• Bazę i schematy meta danych (ang. metadata, Information Schema) – w bazie • logowanie, na różnych poziomach,
information _ schema – znajdziemy informacje o bazie i jej schematach, znajdu-
wszystkich wykonywanych zapytań;
ją się tu np. definicje wyzwalaczy: obsługiwane zdarzenie, baza, tabela i ewentual-
ne kolumny do monitorowania i ciało wyzwalacza, definicje procedur i funkcji – tabe-
la ROUTINES, w której przechowywane są charakterystyki, informacje o bezpieczeń- LIZ DB definiuje interfejsy klas służących
stwie oraz oczywiście ciała procedur i funkcji do połączeń do bazy, zapytań przygoto-
• Możliwość dołączania i odłączania silników bazy na zasadzie pluginów, dodano tak- wywanych (ang. prepared statements),
że nowe silniki: archiwizacje (ang. Archive) – jest to silnik, który przechowuje dane w procedur składowanych i dostarcza ich
postaci skompresowanej dzięki czemu zajmują one mniej miejsca na dysku twardym implementację właśnie dla MySQL5.
oraz rozproszone (ang. Federated) – które umożliwiają stworzenie tablicy, która wi- Omówię po kolei każdy z interfejsów.
doczna jest dla użytkowników jako lokalna a w rzeczywistości przechowująca dane Spis interfejsów oraz klas ich implemen-
na innym serwerze tujących znajdziesz w ramce.

IDB – interfejs
Interfejsy i klasy LIZ DB połączenia do bazy
Implementacją tego interfejsu jest klasa
Interfejsy i ich implementacje: MySQLimp, znajduje się ona w katalogu
LIZDB/classes.
• IDB - definiuje 16 metod służących do obsługi transakcji, wykonywaniu instrukcji DDL,
DML, SELECT, definiuje również trzy poziomy logowania zapytań klasą implementują- Dostarcza ona podstawowej funk-
cą ten interfejs jest MySQLimp cjonalności związanej z pracą na bazie.
• IPreparedStatement - definiuje 8 metod służących do obsługi przygotowywanych za- Dzięki niej połączymy się z bazą danych
pytań, służące głównie do ustawiania wartości zapytania klasą implementującą ten i będziemy mogli wykonywać podstawo-
interfejs jest MySQLimpPreparedStatement we operacje na operacje, takie jakie wy-
• IStoredProcedure - definiuje 9 metod służących do obsługi składowanych procedur konujemy dziesiątki tysięcy dziennie.
i funkcji, interfejs ten definiuje także trzy typu kierunków parametrów: IN, INOUT oraz Ale od początku jak wygląda kod
OUT jak również typy: STORED _ PROCEDURE (dla procedur) STORED _ FUNCTION (dla PHP5 co musimy włączyć do nasze-
funkcji) klasą implementującą ten interfejs jest MySQLimpStoredProcedure
go skryptu aby móc rozpocząć pracę
z LIZ DB.

PHP Solutions Nr 1/2007 www.phpsolmag.org 45


Narzędzia LIZ DB

Przede wszystkim pobrać najnow- ci wyjątek z komunikatem, informującym dów które uległy zmianie, dla zapytań
szą wersję z sourceforge.net i rozpako- nas o właściwej metodzie jaką powinni- trupy DDL (CREATE/DROP) RunQuery
wać ją do swojego testowego katalogu. śmy użyć aby prawidłowo wykonać i ob- zwróci: prawdę jeśli operacja się powio-
Możemy od razu podejrzeć przykłady służyć wynik naszego zapytania. dła oraz fałsz jeśli wystąpił problem.
– są one w katalogu examples jest tam A wyniki mogą być różne np. dla za- Dla przykładowej tablicy, jaką mamy
także katalog sql, w którym znajdzie- pytań DML RunQuery zwróci odpowied- pokazaną na Listingu 1, za pomocą LIZ
cie wszystkie potrzebne definicje tabel nio dla: INSERT – ID wstawionego re- DB możemy wykonać podstawowe ope-
(wraz z przykładowymi rekordami) oraz kordu, UPDATE, DELETE – ilości rekor- racje pokazane na Listingu 2.
definicje procedur i funkcji składowa-
nych używanych w przykładach.
Spójrzmy jak powinien wyglądać Listing 1. Przykładowa tabela używana w artykule
skrypt PHP5 korzystający z LIZ DB: CREATE TABLE `lizdb_test_table` (
`id` mediumint(9) NOT NULL
define('LIZDB_PATH', '/home/xh/public_ auto_increment,
html/testy/ `char_column` varchar(255)
NOT NULL default '',
LIZDB');
`int_column` int(11) NOT NULL,
require LIZDB_PATH . '/classes/ `double_column` double NOT NULL,
MySQLimp.inc.php'; PRIMARY KEY (`id`)
// wstaw swoje dane kolejno: serwer, ) ENGINE=InnoDB
login, hasło oraz DEFAULT CHARSET=latin2;

baza danych do której masz prawo


Listing 2. Pokaz podstawowych możliwości LIZ DB - pobieranie zbiorów danych
$db = new MySQLimp
('localhost', 'xh', 'secret', 'test'); define('LIZDB_PATH', '/home/xh/public_html/lizdb/LIZDB');
require LIZDB_PATH . '/classes/MySQLimp.inc.php';
// wstaw swoje dane kolejno: serwer, login, hasło oraz baza danych
Środowisko LIZ DB do pracy potrzebu-
do której masz prawo
je zdefiniowania stałej LIZDB_PATH, $db = new MySQLimp('localhost', 'xh', 'secret', 'test');
nie jest ona bynajmniej użyta przeze $db->Query = 'SELECT * FROM `lizdb_test_table`';
mnie jako elegancki sposób wskazania $records = $db->Select();
ścieżki. Stała ta jest używana przez LIZ // $records jest tabelą, którą możemy przeglądać np. za pomocą instrukcj
i foreach
DB do wczytania wszystkich definicji in-
echo '<ul>';
terfejsów i klas ich implementujących. foreach($records as $r) {
Dzięki temu my, jako programiści, wy- // każdy element jest kolejną asocjacyjną tablicą
konujemy tylko jedno włączenie skryptu // nazwa kolumny jest indeksem w tablicy, możemy więc napisać:
– podajemy ścieżkę do pliku z definicją echo '<li>' . $r['id'] . ', ' . $r['char_column'] . ', ' . $r['int_column'] .
',
klasy MySQLimp.inc.php.
' .$r['double_column'] . '</li>';
Następnie zwyczajnie tworzymy }
obiekt MySQLimp. Zapytania SQL nie echo '</ul>';
będące zapytaniami przygotowanymi // aby pobrać tylko jeden rekord, np. jeśli szukamy po kluczu głównym
czy też procedurami składowanymi są lub kolumnie UNIQUE
// należy użyć poniższej metody -- jest ona zoptymalizowana
definiowane jako publiczne pole Query.
do pobierania 1 wiersza
I tak możemy napisać: $db->Query = 'SELECT * FROM `lizdb_test_table` ORDER BY
id DESC LIMIT 1';
$db->Query = „SELECT * FROM `lizdb_test_ $record = $db->SelectOne();
table`”; echo '<p>Ostatnim rekordem jest: ';
echo $record['id'] . ', ' . $record['char_column'] . ', ' .
$record['int_column'] . ', ' .$record['double_column'];
Lub inne dowolne zapytanie DDL, DML. echo '</p>';
Zapytania pobierające dane – SE- // możemy wybierać zbiory kolumn, używane gdy we
LECT – są wykonywane przy użyciu frazie SELECT występuje jedna kolumna
następujących metod: Select (zbiory $db->Query = 'SELECT `double_column` FROM
`lizdb_test_table` WHERE `double_column` < 0';
rekordów), SelectOne (pojedynczy re-
$negativeDoubles = $db->SelectColumn();
kord), SelectColumn (zbiór kolumn). echo 'ujemne wartości double to:' .
Zapytania DDL lub DML z kolei są wy- implode(',', $negativeDoubles);
konywane przez wywołanie metody // nie musimy zamykać połączenia, twórca LIZ DB
RunQuery. przewidział że część programistów jest leniwa
// wykorzystywany jest mechanizm destructorów
LIZ DB rozpozna czy przypadkiem
PHP5, metoda __destruct wołana przy
nie chcemy wykonać RunQuery na za- // niszczeniu obiektu MySQLimp
pytaniu SELECT lub też czy nie próbu- rozłącza się automatycznie z bazą danych
jemy utworzyć tabeli za pomocą metody $db->CloseConnection();
SelectColumn – wówczas LIZ DB wyrzu-

46 www.phpsolmag.org PHP Solutions Nr 1/2007


LIZ DB Narzędzia

Przykład wykorzystania LIZ DB do


Listing 3. Pokaz podstawowych możliwości LIZ DB - obsługa i wykonywanie zapytań DDL oraz DML pokazany jest na
zapytań DDL oraz DML
Listingu 3.
// mając już połączenie z bazą, chcę wykonać operacje typu INSERT
$chars = "some text"; IPreparedStatement
$int = mt_rand(); – interfejs
$double = mt_rand() / mt_getrandmax();
// standardowy sposób bez wykorzystania
przygotowywanych
przygotowywanych zapytań zapytań
$db->Query = "INSERT INTO `lizdb_test_table` Przygotowywane zapytania to zapytania,
VALUES (NULL, '{$chars}', {$int}, {$double})"; których szablony są przechowywane na
$id = $db->RunQuery(); serwerze, a dane wysyłane oddzielnie,
echo '<p>Nowy rekord w systemie
w dodatku serwer bazodanowy przejmu-
posiada ID: ' . $id . '</p>';
$db->Query = "UPDATE `lizdb_test_table` SET ` je na siebie odpowiedzialność związaną
double_column` = 0.0 WHERE `id` = '{$id}'"; ze zneutralizowaniem potencjalnie nie-
$updatedRows = $db->RunQuery(); bezpiecznych znaków i sekwencji SQL
echo '<p>Ilość zaktualizowanych wierszy: ' . – dzięki temu zwiększamy bezpieczeń-
$updatedRows . '</p>';
stwo i minimalizujemy praktycznie do ze-
$db->Query = "DELETE FROM `
lizdb_test_table` WHERE `id` = '{$id}'"; ra ewentualne problemy z atakami typu
$deletedRows = $db->RunQuery(); SQL Injections.
echo '<p>Ilość usuniętych wierszy: ' . Jeśli nie korzystałeś do tej pory z
$deletedRows . '</p>'; przygotowywanych zapytań to może po-
// możemy również Tworzyć tabele,
ra się przerzucić? Zobaczmy jakie to pro-
indeksy, klucze obce etc.
$db->Query = "CREATE TABLE `t` (`f` int)"; ste z LIZ DB.
if ($db->RunQuery()) { Przygotowane zapytania tworzymy za
echo '<p>Nowa tabela stworzona!</p>'; pomocą metody PrepareStatement zdefi-
} niowanej w interfejsie IDB. Argumentem
$db->Query = "DROP TABLE IF EXISTS `t`";
metody PrepareStatement jest szablon
if ($db->RunQuery()) {
echo '<p>Tabela została usunięta!</p>'; zapytania, natomiast zwracany jest obiekt
} implementujący interfejs IPreparedState-
ment w naszym przypadku tym obiektem
Listing 4. Wykonywanie przygotowywanych zapytań w obiektowym MySQLi będzie MySQLimpPreparedStatement.
// ponownie ustawiamy nasze dane Napiszemy więc tak:
$mysqli = new mysqli('localhost', 'xh', 'secret', 'test');
// przygotowujemy szablon zapytania $stmt = $db->PrepareStatement
$stmt = $mysqli->prepare('SELECT `id`, `char_column`, („INSERT INTO `lizdb_test_table
`int_column` FROM `lizdb_test_table` WHERE
` VALUES (NULL, ?, ?, ?)”);
`char_column` LIKE ? AND `int_column` > ?');
// jeśli szablon jest poprawny wypełnimy go danymi
if ($stmt) { Patrząc na Listing 1 (definicja bazy da-
$string = '%record%'; nych) wiemy, że pod pierwszym marke-
$int = 0; rem (znak zapytania „?”) jest kolumna
// pierwszym parametrem jest ciąg znaków reprezentujący
typu VARCHAR, drugim INT a w ostat-
typy kolejnych parametrów
// s -- łańcuchy znaków, i - int, d - double, b - blob niej kolumnie przechowywane są warto-
// UWAGA! -- użytkownicy wcześniejszych ści DOUBLE.
wersji PHP5 pod Windowsami Wypełniamy nasz szablon danymi, ro-
// -- możecie dostać komunikat mówiący o bimy to w stylu Java'y i JDBC:
nieprawdiłowej ilości parametrów
$stmt->bind_param('si', $string, $int);
// wypełnione zapytanie można wykonać $stmt->SetString(1, “przykładowy tekst ze
$stmt->execute(); znakami:
// aby pobrać wyniki musimy skorzystać z dość ' or 1 LIKE %1% ? !@#”);
niewygodnego mechanizmu wiązania $stmt->SetInt(2, mt_rand());
// rezultatów do zmiennych PHP
$stmt->SetDouble(3, mt_rand() /
$stmt->bind_result($id, $string, $int);
// następnie w pętli pobieramy dane do związanych mt_getrandmax());
zmiennych i wyświetlamy zawartość
while ($stmt->fetch()) { Tak przygotowane i wypełnione zapyta-
printf ("%d: %s, %d\n", $id, $string, $int); nie SQL możemy uruchomić na serwerze
}
SQL, robimy to następująco:
}
$mysqli->close();
$result = $db->Execute($stmt);

PHP Solutions Nr 1/2007 www.phpsolmag.org 47


Narzędzia LIZ DB

I to wszystko, prawda, że proste? Dodat- sty, który w swoim kodzie będzie wykony- i później modyfikować funkcjonalność biz-
kowo przygotowanym zapytaniem mo- wał tylko jedną instrukcję SQL. nesową tylko w jednym miejscu – bazie
że być SELECT, wówczas $result będzie Kolejnym przykładem może być przy- danych.
zawierało zbiór tablic asocjacyjnych z re- kład dużej firmy – zakładu ubezpieczeń, Wszechwładny i okazać by się mogło
kordami. Wszystko jest automatycznie może firmy telekomunikacyjnej. Mamy wszystko posiadający phpMyAdmin nie
rozpoznawane i odpowiednio wykonywa- setki oddziałów, może miliony klientów. potrafi rozpoznawać i wykonywać proce-
ne przez LIZ DB – w przeciwieństwie do Działamy też w środowisku w którym bar- dur składowanych, my za pomocą LIZ DB
ręcznego wykonywania w PHP przedsta- dzo często zmienia się prawo czy profil będziemy w stanie wywołać każdą funkcję
wionego na listingu 4. usług. Każda zmiana przepisów wymu- czy procedurę składowaną, nawet jeśli do-
sza na nas pewne zmiany czy to w struk- piero zaczynamy naszą przygodę z PHP.
IStoredProcedure turze bazy danych czy też w samych za- Spójrzmy na przykładową funkcję
– interfejs do pytaniach. Musielibyśmy w takim razie składowaną i procedurę o wszystkich
wywoływania procedur i wykonywać co miesiąc setki (miliony?) możliwych kierunkach parametrów: IN,
funkcji składowanych aktualizacji oprogramowania użytkowni- INOUT, OUT – listing 5.
Jest to najważniejsza i najpotężniejsza ków końcowych – znacznie prościej zde- Nie jesteśmy pismem dla admini-
część całej biblioteki LIZ DB. Ale najpierw finiować interfejs procedury czy funkcji stratorów baz danych, ale dla porządku
odpowiedzmy sobie na pytania – co to są
tak na prawdę te procedury i gdzie znaj-
dują one swoje zastosowanie. Procedu- Listing 5. Definicje przykładowych procedur i funkcji składowanych
ry składowane są to fragmenty najczę- drop procedure if exists sayMyName;
ściej sparametryzowane i często używa- delimiter //
ne instrukcje SQL, które mogą wykony- CREATE PROCEDURE sayMyName
wać operacje aktualizacji lub tylko pobie- (OUT param1 INT, INOUT param2 CHAR(200),
IN param3 CHAR(100))
rania danych. Fragmenty procedur może-
BEGIN
my opakować np. w transakcje. SELECT COUNT(*) INTO param1 FROM
Procedury mogą przysłaniać przed `lizdb_test_table`;
końcowym użytkownikiem cały mecha- SET param2 = concat(param2, param3);
nizm swoich operacji, np. procedura, któ- END;
//
ra podaje średnie koszty, przychody ze
delimiter ;
sprzedaży, ukrywa w swoim wnętrzu ta- drop function if exists hello;
bele, z których pobiera dane, co więcej CREATE FUNCTION hello (s CHAR(20))
użytkownik wykonujący tę procedurę mo- RETURNS CHAR(50)
że nie mieć dostępu do pewnych zaso- RETURN CONCAT('Hello, ',s,'!');

bów, ale dzięki zastosowaniu mechani-


zmu jaki ofertu MySQL5, procedura mo-
że zostać wykonana w kontekście praw Charakterystyki MySQL
użytkownika, który ją utworzył a nie któ-
• DEFINER - użytkownik, który stworzył procedurę, jeśli posiadamy prawo SUPER może-
ry ją wykonuje.
my stworzyć procedurę na konkretne konto, związane to może być np. z sytuacją, w
Projektując bazę dla szpitala może-
której nie chcemy aby procedura posiadała prawa bieżącego użytkownika (np. admini-
my stworzyć np. procedurę dodajPacjen-
stratora bazy)
ta (z odpowiednimi parametrami) – może- • LANGUAGE SQL - język w jakim napisana została procedura, nie musimy tego definio-
my sprawdzić w niej czy podany adres ist- wać, MySQL5 na razie obsługuje tylko i wyłącznie procedury w języku SQL i taką ma
nieje już w bazie danych (np. ktoś z rodzi- wartość domyślną ta charakterystyka
ny już jest zapisany) – jeśli tak to pobiera- • DETERMINISTIC | NOT DETERMINISTIC - zachowanie procedury, domyślnie MySQL
my ID adresu (z tabeli adresów), jeśli nie, używa NOT DETERMINISTIC, charakterystyka ta pomaga określić MySQL czy pro-
dodajemy nowy rekord, później możemy cedura jest bezpieczna podczas replikacji (ang. replication-safe), deterministyczna
wstawić dane pacjenta, dane takie jak: znaczy tyle, że zawsze dla pewnego zestawu parametrów wejściowych wynik proce-
imię, nazwisko, PESEL wstawiamy do ta- dury będzie taki sam
• SQL SECURITY INVOKER | SQL SECURITY DEFINER - poziom bezpieczeństwa proce-
beli osoby (jeśli w systemie przechowuje-
dury, definiuje czy procedura ma być wykonywana z prawami użytkownika wywołują-
my też pracowników możemy wyodręb-
cego procedurę czy użytkownika, który ją utworzył, domyślna wartość: SQL SECU-
nić tabelę nadrzędną) a dane specyficz-
RITY DEFINER
ne dla pacjenta wstawiamy do tablicy pa- • CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA - tryb pracy
cjenci – w naszej procedurze oczywiście procedury, zacznę przekornie: obecnie MySQL nie bierze pod uwagę tej charaktery-
zachowujemy pełną kontrolę nad klucza- styki dla np. ograniczeń bezpieczeństwa, domyślną wartością jest CONTAINS SQL,
mi obcymi, możemy tu także wykorzystać który oznacza tyle, że procedura nie czyta ani nie pisze nic, NO SQL, że nie zawiera
mechanizm transakcji. Dzięki zastosowa- w ogóle instrukcji SQL, READ SQL DATA - odczytuje dane z bazy, MODIFIES SQL
niu procedury znacznie uprościliśmy ca- DATA - może (nie musi) modyfikować zawartość danych
ły mechanizm procesu dodawania nowe- • COMMENT 'zawartość komentarza' - dodanie komentarza.

go pacjenta z punktu widzenia programi-

48 www.phpsolmag.org PHP Solutions Nr 1/2007


LIZ DB Narzędzia

w ramce 3 przedstawiam pełną składnię


polecenia tworzenia procedur, omawiam
tam także charakterystyki i aspekty zwią-
zane z bezpieczeństwem.
Każda procedura może mieć zdefi-
niowane pewne charakterystyki, które
są, mogą lub w przypadku niektórych
będą w przyszłości brane pod uwagę
przez MySQL podczas np. replikacji,
optymalizacji czy sprawdzania ograni-
czeń bezpieczeństwa.
Załóżmy, że chcielibyśmy jako użyt-
kownik lizdb_user, którego utworzyliśmy
dodać procedurę, i nadać inne niż do-
myślne charakterystyki:

Rysunek 1. Ręczne wykonanie procedur składowanych i funkcji w MySQL CREATE DEFINER = 'xh'@'%' PROCEDURE
simpleproc (OUT param1 INT) LANGUAGE SQL
DETERMINISTIC SQL SECURITY INVOKER
Listing 6. Wywoływanie składowanych funkcji i metod za pomocą biblioteki
NO SQL COMMENT 'ot taki komentarz'
LIZ DB
BEGIN
$call = $db->PrepareCall('sayMyName (?, ?, ?)', SELECT 123 INTO param1;
IStoredProcedure::STORED_PROCEDURE); END;
$parameter = array();
// przykład parametru INOUT
Nie uda się – jak napisaliśmy wcześniej
$parameter['type'] = IstoredProcedure:
:INOUT_PARAMETER; aby utworzyć procedurę z wartością
$parameter['value'] = 'testujemy parametry DEFINER inną niż bieżący użytkownik
wejściowe i wyjściowe'; – lizdb_user powinien posiadać przywi-
// możemy definiować parametry w dowolnej
lej SUPER.
kolejności, powyższy jest drugim parametrem
Zmodyfikujmy więc powyższy kod
$call->SetParameter(2, $parameter);
// parametr OUT wyjściowy i napiszmy tak:
$parameter['value'] = 'ta wartość jest nie istotna i tak
zostanie nadpisana'; CREATE DEFINER = CURRENT_USER
$parameter['type'] = IstoredProcedure:
PROCEDURE simpleproc (OUT param1 INT)
:OUT_PARAMETER;
LANGUAGE SQL DETERMINISTIC SQL
// to jest pierwszy paramter
$call->SetParameter(1, $parameter); SECURITY INVOKER NO SQL COMMENT
// standardowy typ IN 'ot taki komentarz'
$parameter['value'] = 'przyklej mnie do BEGIN
drugiego parametru!';
SELECT 123 INTO param1;
$parameter['type'] = IstoredProcedure:
END;
:IN_PARAMETER;
// ustaw jako trzeci parametr Lub w ogóle omijamy DEFINER = CURRENT_
$call->SetParameter(3, $parameter); USER
$db->ExecuteCall($call); ponieważ jest to domyślne zachowanie
$parameters = $call->GetParameters();
MySQL.
echo '<p>INOUT parametr (#2) ma wartość:
' . $parameters[2]['value'] . '</p>';
echo '<p>OUT parametr (#1) przypisano nową wartość: Jak w ogóle wykonać nasze procedury i
' . $parameters[1]['value'] . '</p>'; funkcje w MySQL? Utwórzmy procedury
// teraz wykonajmy funkcję składowaną i zalogujmy się do MySQL. Zakładamy,
// pierwszym argumentem jest ponownie szablon,
że pracujemy na bazie test:
drugim jest typ STORED_FUNCTION
$call = $db->PrepareCall('hello (?)', IstoredProcedure:
:STORED_FUNCTION); $ mysql -u root -p -D test < examples/
$parameter = array(); stored_
$parameter['type'] = IstoredProcedure: procedures.sql
:IN_PARAMETER;
$parameter['value'] = 'Łukaszu';
Zauważmy, że podałem tutaj parametr
$call->SetParameter(1, $parameter);
$result = $db->ExecuteCall($call); informujący do jakiej chcę się połączyć
echo '<p>Wynikiem wykonania funkcji bazy danych (-D test) – jest to ważne
hello(?) jest: ' . $result . '</p>'; ponieważ procedury utworzone w bazie
test będą widoczne tylko i wyłącznie w

PHP Solutions Nr 1/2007 www.phpsolmag.org 49


Narzędzia LIZ DB

obrębie tej bazy. Nie możemy utworzyć Spójrzmy na problemy z jakimi spo- $call = $db->PrepareCall
procedury globalnej, która będzie dzia- tkalibyśmy się gdybyśmy wykonywa- ('hello (?)',
łała we wszystkich bazach – procedury li wszystko ręcznie w PHP. Przede IstoredProcedure:
działają na konkretnych tabelach, w jed- wszystkim wiele problemów nastarczyło :STORED_FUNCTION);
nej konkretnej bazie. by nam samo oprogramowanie parame-
Następnie połączmy się do bazy i trów o kierunkach OUT czy INOUT. Mu- Markery ustawiamy analogicznie jak
utwórzmy użytkownika z takimi prawami: sielibyśmy wykonywać zawsze ustawie- w przypadku przygotowywanych zapytań:
nie zmiennych, potem musielibyśmy wy-
CREATE USER lizdb_user@localhost wołać procedurę i jeszcze raz zapytać $call->SetParameter
IDENTIFIED BY 'lizdb'; się o zmienne. W dodatku musielibyśmy (1, $parameter);
GRANT tak robić dla każdej naszej procedury co
SELECT, INSERT, UPDATE, DELETE, może być męczące. Z jedną różnica $parameter nie jest tutaj
CREATE, DROP, INDEX, ALTER, LIZ DB automatyzuje cały ten proces, zmienną skalarną reprezentującą kon-
CREATE ROUTINE, ALTER ROUTINE ci z was, którzy programowali w .NET za- kretną wartość a tablicą asocjacyjną,
EXECUTE uważą pewne analogie. Ale od początku która posiada dwa ważne pola:
ON `test`. * TO lizdb_user@localhost jak wykonujemy takie rzeczy w LIZ DB?
IDENTIFIED BY 'lizdb'; Mając już obiekt $db tworzymy obiekt im- $parameter['value'] =
plementują interfejs IStoredProcedure: 'tutaj podajemy wartość
Zauważymy od razu nowe opcje, które parametru';
nie są dostępne w MySQL4 (podałem je $call = $db->PrepareCal $parameter['type'] = IstoredProcedure:
w osobnej linii) są to: CREATE ROUTINE, l('sayMyName (?, ?, ?)', :IN_PARAMETER;
ALTER ROUTINE, EXECUTE – służące ko- IstoredProcedure:
lejno: do tworzenia, zmieniania oraz wy- :STORED_PROCEDURE); Typ decyduje o tym jak zostanie obsłużo-
konywania procedur i funkcji składowa- ny nasz parametr. Nie musimy ustawiać
nych. ROUTINE jest tu użyte jako słowo Pierwszym argumentem jest szablon na- wartości dla parametru typu OUT_PA-
klucz i zostało wprowadzone – aby nie szej procedury składowanej, drugim pa- RAMETER ponieważ cokolwiek podamy
nadawać osobno praw typu: CREATE rametrem jest typ – jak już wiemy inaczej zostanie i tak nadpisane. Jeśli ustawimy
PROCEDURE, CREATE FUNCTION. woła się funkcje a inaczej procedury. W już wszystkie pola naszej procedury wy-
Prze logujmy się na nowego użytkow- przypadku funkcji hello napisalibyśmy tak: konujemy ją bardzo prosto:
nika (do bazy test), którego przed chwilką
utworzyliśmy. Wywołanie funkcji wykonu- Listing 7. Najkrótsza i najprostsza wersja wywołania procedury getRecords()
je się w połączeniu z frazą SELECT – po- w MySQLi
nieważ chcemy „coś” pobrać – tu wynik
$mysqli = new mysqli('localhost', 'xh', 'secret', 'test');
działania funkcji. Piszemy następująco:
// musimy wykonać jako zapytanie typu MULTI
aby MySQL nie zerwał połączenia
mysql> SELECT hello ('Łukaszu'); // jeśli zajrzymy w kod LIZ DB zobaczymy, że tam
nie ma takich wybiegów,
Aby wywołać procedurę użyjemy in- // dodatkowo LIZ DB do wywołań procedur używa
wewnętrznie przygotowywanych zapytań
strukcji CALL, dodatkowo zauważmy,
// zauważmy, że gdybyśmy chcieli oprogramować
że gdy chcemy dostać odpowiedź od
samemu markery i przygotowywane zapytania
MySQL przez parametr nie możemy // jak w poprzednich przykładach,
podać wartości a zmienną! To się ty- najprawdopodobniej dodalibyśmy tu jeszcze kilka
czy jedynie parametrów o kierunkach // lini kodu obsługi do każdego takiego parametru
$mysqli->multi_query('CALL getRecords()');
OUT oraz INOUT. Dodatkowo parame-
// pobieramy rezulat
try INOUT jak widzimy posiadają war-
$result = $mysqli->store_result();
tość, którą wprowadzamy do procedu- // iterujemy po wynikach
ry a która jest wewnątrz modyfikowa- while ($row = $result->fetch_row()) {
na. Musimy więc do takiej zmiennej naj- // musimy znać ilość pól, ich nazwy
// LIZ DB automatycznie za nas to zrobi na
pierw przypisać wartość. Piszemy więc
podstawie meta danych
w konsoli MySQL:
$values['id'] = $row[0];
$values['char_column'] = $row[1];
mysql> set @zmienna = 'Do tego łańcucha $values['int_column'] = $row[2];
dokleję coś w procedurze...'; $values['double_column'] = $row[3];
$records[] = $values;
mysql> CALL sayMyName(@ileRekordow,
}
@zmienna, ' np. to dokleje ;)');
$result->close();
mysql> SELECT @zmienna, @ileRekordow; // końcowa odpowiedź
var_dump($records);
Wynik powyższych sekwencji instrukcji $mysqli->close();
SQL możemy zobaczyć na Rysunku 1.

50 www.phpsolmag.org PHP Solutions Nr 1/2007


LIZ DB Narzędzia

$db->ExecuteCall($call); wartości na kolumny – LIZ DB na podsta-


wie meta danych potrafi odtworzyć struk-
Metoda ExecuteCall pobiera przez referen- turę zbioru wynikowego.
cje obiekt $call, wykonuje procedurę i wpisu- Nadmienię tylko, że przy takich pro-
je do niej nowe wartości (w przypadku para- cedurach składowanych wykonywanych
metrów OUT bądź INOUT). Aby później po- z poziomu PHP, standardowymi metoda-
brać nowe wartości musimy napisać: mi, MySQL zrywa połączenia. Procedu-
ra zwracająca zbiór jest nietypowa – My-
$parameters = $call->GetParameters(); SQL obsługuje wywołanie, zwraca stero-
wanie do klienta, ale też alokuje bufory z
$parameters jest teraz tablicą parametrów wynikiem i czeka na ich pobranie. Jeśli
– wszystkich, które ustawiliśmy przed wy- ich nie odbierzemy i później nie zwolnimy
wołaniem metody (włącznie z parametrami tych zasobów MySQL uważa to za błąd i
IN). Pod indeksem 1 znajduje się pierwszy przy próbie wykonania nowego zapytania
parametr itd. Parametry mają dokładnie tę rozłącza połączenie.
samą strukturę, pod kluczem vale znajdzie-
my nową wartość parametru. Na listingu 6 Podsumowanie
możemy zobacz pełny przykład wykona- LIZ DB to potężne środowisko znakomi-
nia składowanej funkcji i procedury za po- cie ułatwiające prace programistom. Nie
mocą LIZ DB. zdążyłem nawet omówić części LIZ DB
Aby uzmysłowić sobie ile pracy jest wy- związanej z logowaniem wykonywanych
konywanych za nas pokażę ostatni bardzo zapytań, w całości pominąłem wsparcie
wykorzystywany przy procedurach składo- dla zaawansowanych transakcji – takich
wanych mechanizm – mechanizm pobiera- jak obsługa savepointów, cofanie zmian
nia zbiorów danych. Jeśli nasza procedu- do wcześniejszych stanów bazy danych,
ra nie posiada żadnych parametrów kod odwoływania całych transakcji, opcje Au-
upraszczamy drastycznie z użyciem LIZ toCommit (każde zapytanie jest automa-
DB, napiszemy tylko dwie linie kodu: tycznie zatwierdzane) czy CommitOnClo-
se (wszystkie zmiany są utrwalane w ba-
$call = $db->PrepareCall('getRecords()', zie dopiero przy zamykaniu połączenia).
IStoredProcedure::STORED_PROCEDURE); Autor projektu jest otwarty na współ-
$records = $db->ExecuteCall($call); pracę i współudział w rozwijaniu tej biblio-
teki (nie tylko dla bazy MySQL), najbliż-
LIZ DB tworzy odpowiedź w jak najbar- sze plany zakładają wbudowanie systemu
dziej wygodnej dla nas postaci. W powyż- cache, obecnie w repozytorium projektu
szym kawałku kodu $records jest tablicą znajdują się już interfejsy i przykładowa
tablic asocjacyjnych, których indeksy są implementacja cache – wykorzystująca
nazwami kolumn. PECL APC. W najbliższej przyszłości zo-
Ręczna obsługa procedury getRecords stanie także wypuszczona wersja oferują-
zamieszczona jest na listingu 7. Wywołanie ca tworzenie obiektów poprzez wzorzec
tej procedury wybrałem na przykład stan- projektowy singleton oraz mechanizm
dardowego kodu PHP5 i MySQLi ponieważ tworzenia połączeń persystentnych.
jest ona najkrótsza. Zauważmy, że nie uży- Jeśli przekonałem Ciebie do LIZ
liśmy tutaj żadnego parametru – kod PHP, DB – nie czekaj tylko pobierz najnow-
który nie korzystałby z LIZ DB a który pró- sze wersje źródeł i przykładów z http://
buje wykonać procedury składowane z róż- sourceforge.net/projects/lizdb lub http://
nymi parametrami miałby co najmniej kilka- www.komputery-internet.net/php/. n
naście linii kodu więcej. Dodatkowo kod nie
należy do ponownie-używalnych, będzie
działał tylko i wyłącznie dla tej jednej pro- O autorze
cedury. Mógłbym próbować zwiększyć je-
go reużywalność, ale chciałem za wszelką Łukasz Budnik jest studentem V roku
cenę zmniejszyć ilość kodu tak aby zbliżyć Informatyki na Politechnice Gdańskiej,
uczestniczy w projektach nad rozwija-
się do 2 linii jakie musieliśmy napisać uży- niem systemów zbierania i analizy danych
wając biblioteki LIZ DB. w postaci XML, jest również administrato-
Używając LIZ DB nie musimy się za- rem serwisu www.komputery-internet.net.
głębiać w definicje procedur, nie musimy
Kontakt z autorem:
znać nazw kolumn zwracanych przez nią, lukasz.budnik@komputery-internet.net
nie musimy tworzyć żadnych mapowań

PHP Solutions Nr 1/2007 www.phpsolmag.org 51


Narzędzia

Wielojęzyczna konfiguracja
stron z użyciem eZ publish
Stopień trudności: lll
Łukasz Serwatka

Tworzenie stron webowych z zawartością


w wielu językach może być zajęciem trudnym
i czasochłonnym. Wraz z wprowadzeniem tech-
nologii skryptowych po stronie serwera, jak
PHP i systemów opartych na PHP, takich jak
eZ publish Content Management System, czas
potrzebny na stworzenie i utrzymywanie wieloję-
zycznych stron można skrócić.

T
en artykuł opisuje, jak konfiguro- zainstalowanej jako moduł Apache'a
wać wielojęzyczne strony z uży- (mod_php). (Zwracamy uwagę, że eZ
ciem eZ publish, udostępniając publish nie działa z PHP w wersji 5).
stronę webową międzynarodowej grupie PHP musi mieć wbudowaną obsługę al-
użytkowników. eZ publish w wersji 3.8 bo MySQL 4.1 lub nowszego, albo Post-
zawiera wiele ulepszeń do swojego mo- greSQL 7.3 lub nowszego.
delu wielojęzycznej zawartości strony.
Te ulepszenia są opisane w specyfikacji
wielojęzycznej (http://ez.no/community/
Co obiecujemy:
Po przeczytaniu tego artykułu czytelnik
developer/specs/improved_multi_langu- będzie umiał zainstalować eZ publish z
age_in_ez_publish_rev_2). obsługą kilku języków, zmieniać usta-
Ten samouczek przedstawi, jak wienia i konfigurację systemu pod ką-
tem obsługi wielu języków. Tworzyć wła-
tworzyć wielojęzyczne strony webo-
sne rozszerzenia językowe dla eZ pu-
we z użyciem eZ publish, dodawać blish. Dodawać nowe języki do istnieją-
nowe języki do istniejących instalacji cej już instalacji.
i tłumaczyć zawartość strony na róż- Tłumaczyć i tworzyć treść w dostęp-
nych w eZ publish językach.
ne języki.
Co powinieneś wiedzieć:
Wymagania Artykuł jest adresowany do osób, któ-
re mają niewielkie doświadczenie lub
eZ publish pracuje na serwerze webo-
dopiero zaczynają swoją przygodę
wym Apache. Zaleca się używać ostat- z eZ publish, potrzebna jednak będzie
niej wersji z gałęzi 1.3. Upewnij się, że podstawowa wiedza z zakresu tworze-
używasz wersji 4.4 PHP. Zalecamy rów- nia witryn internetowych.
nież używać ostatniej wersji z gałęzi 4.4

52 www.phpsolmag.org PHP Solutions Nr 1/2007


Wielojęzyczna konfiguracja Narzędzia

Kreator ustawień Wybierz „English (United Kingdom)”


W wersji 3.8 eZ publish, można włączyć jako język podstawowy oraz „French
unikod podczas instalacji. Kreator usta- (France)” i „German” jako języki dodat-
wień eZ publish włączy unikod (UTF-8) kowe. Po zapytaniu o „site type”, wy-
dla wewnętrznego kodowania i konwer- bierz „new site”.
Rysunek 1. Tworzenie bazy
sji strony kodowej. To ustawienie jest za-
pisane w pliku: Konfiguracja
Instalacja po instalacyjna
Ten rozdział opisuje aspekty procesu in- settings/override/i18n.ini.append.php. Po zainstalowaniu eZ publish i uzy-
stalacji eZ publish, które wpływają na <?php /* #?ini charset="iso-8859-1"? skaniu dostępu do interfejsów publicz-
wielojęzyczną konfigurację. (Kompletny [CharacterSettings] nych i administracyjnych, należy zmie-
proces instalacji jest opisany szczegóło- Charset=utf-8 nić konfigurację, by udostępnić stro-
wo w dokumentacji online na http://ez.no/ */ ?> nę w wielu językach. Domyślnie kre-
doc/ez_publish/technical_manual/3_8/ ator ustawień tworzy dwa „siteaccess-y”
installation.) Poniższy zrzut ekranu pokazuje opcje wy- (zestawy plików konfiguracyjnych, któ-
szczególnione w kreatorze ustawień: re przesłaniają ustawienia domyślne):
Baza danych
Aby udostępnić obsługę wszystkich Listing 1. Struktura katalogów i umiejscowienie plików konfiguracyjnych
zestawów znaków, skonfigurujemy ko-
dowanie UTF-8 (unikod). Aby używać settings/override/ globalne ustawienia dla wszystkich siteaccesses
settings/siteaccess/gb pliki konfiguracyjne dla angielskich siteaccess
UTF-8, baza danych musi mieć ob-
settings/siteaccess/de pliki konfiguracyjne dla niemieckich siteaccess
sługę unikodu. PostgreSQL i MySQL settings/siteaccess/fr pliki konfiguracyjne dla francuskich siteaccess
(wersja 4.1 lub nowsza) w pełni obsłu- settings/siteaccess/site_admin pliki konfiguracyjne dla siteaccess
gują unikod. (Rysunek 1). Skonfiguru- administratorskich
jemy zatem stronę, aby pokazywała
zawartość w trzech językach: angiel-
skim, francuskim i niemieckim. Ponie-
waż jednak używamy kodowania UTF-
8, możemy też używać języków, które
używają nie łacińskich liter (chiński, ja-
poński itd.).
Następujące przykłady pokazują, jak
tworzyć nazwę danych z obsługą unikodu.
Dla MySQL należy wykonać:

CREATE DATABASE `mydb` DEFAULT


CHARACTER SET utf8
COLLATE utf8 _ general _ ci;

W miejsce „mydb” należy wstawić nazwę


swojej bazy.
Dla PostgreSQL należy wykonać na-
stępującą komendę z poziomu powłoki:

$ createdb -E Unicode mydb

W miejsce „mydb” należy wstawić nazwę


swojej bazy.
Można też użyć narzędzi graficz-
nych, jak phpMyAdmin (MySQL) [link]
lub phpPgAdmin (PostgreSQL) [link] do
utworzenia bazy danych. Na przykład,
by utworzyć bazę o nazwie „mydb”
używając phpMyAdmin, należy wy-
brać „utf8_general_ci” z listy rozwijanej
„collation”, jak pokazano poniżej (Ry-
sunek 2). Rysunek 2. Opcje wyszczególnione w kreatorze ustawień

PHP Solutions Nr 1/2007 www.phpsolmag.org 53


Narzędzia Wielojęzyczna konfiguracja

jeden do użytku publicznego („news_si-


te”) i jeden do administracji („news_site_ Listing 2. Globalny plik konfiguracyjny
admin”). Użyjemy tych plików konfigura- settings/override/site.ini.
cyjnych utworzonych przez kreator usta- append.php
wień jako wzór dla innych konfiguracji <?php /*
dostępu do stron (siteaccess). Zmień na- [...]
[SiteSettings]
zwę katalogu news_site na „gb”. Utwórz
DefaultAccess=gb
nowe katalogi „de” i „fr” pod „settings/ SiteList[]
siteaccesses”, a potem zmień nazwę SiteList[]=gb
katalogu „news_site_admin” na „site_ SiteList[]=de
admin”. Skopiuj pliki konfiguracyjne SiteList[]=fr
[SiteAccessSettings]
INI z folderu „settings/siteaccesses/gb”
CheckValidity=false
do „settings/siteaccesses/de” i „settintgs/ AvailableSiteAccessList[]
siteaccesses/fr ”. Nie zmieniaj plików kon- AvailableSiteAccessList[]=gb
figuracyjnych w site_admin. Teraz mamy AvailableSiteAccessList[]=de
mniej więcej taką strukturę (Listing 1). AvailableSiteAccessList[]=fr
AvailableSiteAccessList[]=
Stworzyliśmy zatem po jednym si-
site_admin
teaccess dla języka. eZ publish będzie RelatedSiteAccessList[]
przeglądać pliki konfiguracyjne zapi- RelatedSiteAccessList[]=gb
sane w tych ostatnich katalogach, gdy RelatedSiteAccessList[]=de
użytkownik zażąda URL-a z końców- RelatedSiteAccessList[]=fr
RelatedSiteAccessList[]=
ką języka:
site_admin
[...]
www.example.com/gb > settings/siteaccess/gb */ ?>
www.example.com/de > settings/siteaccess/de
Listing 3. Główny plik konfiguracyjny
Globalny plik konfiguracyjny settings/
<?php /*
override/site.ini.append.php zawiera in- [...]
formacje o dostępnych siteaccess-ach [RegionalSettings]
(Listing 2). Locale=eng-GB
Te ustawienia informują eZ publish, ContentObjectLocale=eng-GB
SiteLanguageList[]=eng-GB
że nasz domyślny siteaccess (Default-
SiteLanguageList[]=fre-FR
Access) jest „gb” (angielski). Gdy użytkow- SiteLanguageList[]=ger-DE
nik łączy się z naszą stroną nie specyfiku- TextTranslation=disabled
jąc siteaccess-u (np. przez www.exam- [FileSettings]
ple.com albo www.example.com/site), VarDir=var/news_site
[...]
otrzyma domyślną angielską stronę. Na-
*/ ?>
stępnie określamy listę naszych publicz-
nych siteaccess-ów (SiteList) i informuje-
my eZ publish o wszystkich dostępnych
siteaccess-ach (AvailableSiteAccessList),
w tym administracyjne. RelatedSiteAccess-
List jest używane przez mechanizm
buforujący. Bufor widoku będzie opróż-
niony dla skonfigurowanego siteaccess-
a, gdy na tej stronie zostanie opublikowa-
ny nowy artykuł.
Konfiguracja dla naszych publicz-
nych siteaccess-ów jest związana
z ustawieniami regionalnymi. Główny
plik konfiguracyjny (settings/siteaccess/
gb/site.ini.append.php) będzie zawierał
(Listing 3).
Tłumaczenia etykietę GUI w eZ pu-
blish są zapisane w plikach XML (zloka-
lizowanych w share/translations) dla każ-
dego języka. Gdy TranslationCache zo-
stanie ustawione na „enabled”, system
sparsuje plik XML z tłumaczeniem (trans- Rysunek 3. Domyślne siteaccess-y kreatora ustawień

54 www.phpsolmag.org PHP Solutions Nr 1/2007


Wielojęzyczna konfiguracja Narzędzia

lation.ts) i skompiluje do natywnych pli- etykiety są po angielsku, więc nie ma


Listing 4. Części plików konfiguracji ków PHP dla szybszego uruchamiania. potrzeby dokonywać tłumaczenia.
niemieckiej i francuskiej To znacznie zmniejszy czas ładowania Z przyczyn wydajnościowych, waż-
settings/siteaccess/de/ i powinno być zawsze używane. Bufor ne jest, by włączyć TranslationCache
site.ini.append.php translacji jest zapisany w systemie pliku razem z TextTranslation dla stron wie-
<?php /* pod katalogiem var w katalogu tłumaczeń lojęzycznych.
[...] (var/(site)/cache/translation). Ponieważ w naszej wielojęzycznej
[RegionalSettings]
Dla angielskich stron (eng-GB) konfiguracji użyjemy jednego z admini-
Locale=ger-DE
ContentObjectLocale=ger-DE TextTranslation i TranslationCache są stracyjnych siteaccess-ów dla zarządza-
SiteLanguageList[]=ger-DE domyślnie wyłączone, gdyż domyślne nia zawartością wszystkich stron, ważne
SiteLanguageList[]=eng-GB
SiteLanguageList[]=fre-FR
TextTranslation=enabled Listing 6. Konfiguracja dla rozszerzenia tłumaczeń
[FileSettings]
<?php /*
VarDir=var/news_site
[RegionalSettings]
[...]
TranslationExtensions[]=
*/ ?>
mytranslationext
settings/siteaccess/fr
*/ ?>
/site.ini.append.php
<?php /*
[...]
Listing 7. Źródło:
[RegionalSettings]
extension/mytranslationext/
Locale=fre-FR
translations/untranslated
ContentObjectLocale=fre-FR
/translation.ts
SiteLanguageList[]=fre-FR
<!DOCTYPE TS><TS>
SiteLanguageList[]=eng-GB
<context>
SiteLanguageList[]=ger-DE
<name>extension/
TextTranslation=enabled
mytranslationext</name>
[FileSettings]
<message>
VarDir=var/news_site
<source>Example label
[...]
</source>
*/ ?>
<comment>Example
comment</comment>
Listing 5. Ustawienia Path Prefix <translation type=
"unfinished"></translation>
settings/siteaccess/de/site.
</message>
ini.append.php:
<message>
PathPrefix=german
<source>More examples
settings/siteaccess/gb/site.
</source>
ini.append.php:
<translation type=
PathPrefix=english
"unfinished"></translation>
settings/siteaccess/fr/site.
</message>
ini.append.php:
</context>
PathPrefix=french
</TS>

Rysunek 4. Wybór kilku opcji


jednocześnie przy użyciu Contral Rysunek 5. Ustawienia polityki po wybraniu siteaccess-ów

PHP Solutions Nr 1/2007 www.phpsolmag.org 55


Narzędzia Wielojęzyczna konfiguracja

jest, by zarówno publiczny siteaccess, jak [FileSettings] fr, de). W eZ publish możemy ograni-
i siteaccess Interfejsu Administracyjnego VarDir=var/news _ site czyć prawa użytkowników tylko do wy-
używały tego samego katalogu (umiesz- branych siteaccess-ów. To oznacza, że
czonego poniżej katalogu var). W przeciw- Katalog 'var' zawiera pliki buforowe (ca- użytkownicy mogą się zalogować tyl-
nym razie niektóre składniki strony (jak pli- che files) i logi. Zawiera również części, ko na strony, na których mają gwaranto-
ki) przerzucone przez interfejs administra- które nie będą przechowywane w bazie wane prawa dostępu przez administrato-
cyjny będą niedostępne publicznie, bo nie (obrazki i pliki) (Listing4). ra. Ponieważ zmieniliśmy istniejącą kon-
będą mieć dostępu do katalogu 'var' site- I konfiguracja jest gotowa. Następny figurację, musimy przekazać eZ publish,
access-u administracyjnego. Należy się krok to ustawienie odpowiednich praw które siteaccess-y są teraz dostępne pu-
też upewnić, że Apache ma wystarczają- dla użytkownika anonimowego do okre- blicznie.
ce prawa do utworzonych katalogów: ślonych publicznych siteaccess-ów (gb, Zaloguj się jako administrator do In-
terfejsu Administracyjnego za pomocą
Listing 8. Łącza tekstowe użytkownika i hasła skonfigurowanego
przez kreator ustawień. Nowy URL do
{def $locales=fetch( 'content', Interfejsu Administracyjnego będzie po-
'translation_list' )}
dobny do www.example.com/site_admin
{foreach $locales as $locale}
<a href={concat( "index.php/"
lub www.example.com/index.php/site_
, $locale.country_code|downcase(), admin, zależnie od nowych ustawień
"/", $DesignKeys:used.url_alias ) konfiguracyjnych i od tego, czy używasz
|ezroot}> metody Virtual Host dla URL-a. Po zalo-
{$locale.country_code }
gowaniu się, przejdź do zakładki Setup
</a>
{delimiter}
i kliknij „Roles and policies”. W liście ról,
| kliknij rolę „Anonymous” i przycisk „Edit”.
{/delimiter} W liście bieżących polityk znajdź nastę-
{/foreach} pujący wiersz:
Module: user, Function: login,
Listing 9. Łącza z obrazkiem flagi
Limitations: SiteAccess()
{def $locales=fetch( 'content', Kliknij ikonę „Edit” (symbol pióra po
'translation_list' )} prawej) i wybierz siteaccess-y „gb”, „de”
{foreach $locales as $locale} i „fr”. Możesz wybrać wiele opcji jedno-
<a href={concat
cześnie, przytrzymując klawisz Control.
( "index.php/",
$locale.country_code| (Rysunek4)
downcase(), "/" Po wybraniu siteaccess-ów, kliknij
, $DesignKeys:used. „OK”. eZ publish zapisze ustawienia poli-
url_alias )|ezroot}> tyki (Rysunek 5).
<img src={concat
Module: user, Function: login, Limita-
( "share/icons/flags/",
$locale.locale_code, ". tions: SiteAccess( gb , fr , de ).
gif" )|ezroot()} alt= Wyjdź z trybu edycji ról klikając
"" border="0" /> „OK”. Zakończyliśmy zatem aktuali-
</a> zację praw eZ publish, a teraz należy
{/foreach}
sprawdzić, czy nasze siteaccess-y są
dostępne publicznie dla użytkowników

Rysunek 6. Logowanie do interfejsu Administracyjnego Rysunek 7. Wybór języka z listy

56 www.phpsolmag.org PHP Solutions Nr 1/2007


Wielojęzyczna konfiguracja Narzędzia

anonimowych. Możesz to sprawdzić,


wklejając poniższe URL-e do przeglą-
darki:

• www.example.com/gb (or www.exam-


ple.com/index.php/gb);
• www.example.com/fr (or www.exam-
ple.com/index.php/fr);
• www.example.com/de (or www.exam-
ple.com/index.php/de).

Tłumaczenia
Proces konfiguracji jest zakończony.
Teraz możemy zająć się tłumaczeniem
naszej zawartości z użyciem Interfejsu
Administracyjnego eZ publish. Aby prze-
tłumaczyć zawartość na jeden z dostęp-
nych języków.
Zaloguj się do Interfejsu Administra-
Rysunek 8. Definiowanie języków dodatkowych podczas instalacji
cyjnego. Pamiętaj, że nowy URL do In-
terfejsu Administracyjnego będzie po-
dobny do www.example.com/site_admin
lub www.example.com/index.php/site_
admin. (Rysunek 6).
W widoku „Content structure” wy-
bierz obiekt, który chcesz przetłuma-
czyć. Następnie, z listy rozwijanej wy-
bierz „Another language” i kliknij przy-
cisk „Edit”. (Rysunek 7).
W następnym widoku, eZ publish za-
pyta o nowy język do tłumaczenia i o ję-
zyk, z którego będzie tekst tłumaczony.
Wybierz „French” dla tłumaczenia i „En-
glish (United Kingdom)” jako język ba-
zowy i kliknij przycisk „Edit”. Zauważ,
że ten krok zostanie pominięty, jeśli tylko
jeden język dodatkowy zoastał zdefinio-
wany podczas instalacji. (Rysunek 8).
W następnym kroku, eZ publish poka-
że widok edycji dla nowego tłumaczenia.
Na szczycie każdego pola edycji będzie
pokazany tekst w oryginalnym, bazowym
Rysunek 9. Widok edycji dla nowego tłumaczenia języku. Po zakończeniu tłumaczenia klik-
nij „Send for publishing”. (Rysunek 9).
Lista dostępnych tłumaczeń dla bie-
żącego obiektu jest pokazana, gdy ak-
tywna jest zakładka „Translations”. To
również daje dostęp do dodatkowych
opcji. (Rysunek 10).

Jeden Interfejs
Administracyjny, trzy
niezależne strony
wielojęzyczne
Nowa wielojęzyczna funkcjonalność w
eZ publish w wersji 3.8 daje możliwość
tworzenia obiektów niezależnie w wie-
lu językach i używania aliasów URL do
Rysunek 10. Lista dostępnych tłumaczeń dla bieżącego obiektu

PHP Solutions Nr 1/2007 www.phpsolmag.org 57


Narzędzia Wielojęzyczna konfiguracja

dostępu do zawartości w różnych języ- ini.append.php dla publicznego site- Więcej informacji na temat i18n we
kach. Powiedzmy, że chcemy mieć nie- access-u (gb, fr, de), które odetnie na- wzorcach znajdziesz na stronie dokumen-
zależne tłumaczenia, zatem zawartość zwę folderu języka z każdego URL-a. tacji: http://ez.no/doc/ez_publish/technical
dla czytelnika angielskojęzycznego bę- W przeciwnym razie eZ publish bę- _ manua l / 3 _ 8 / r efer enc e / tem p late _
dzie inna, niż zawartość dla czytelnika dzie używał ścieżek np.: http://localhost/ operators /formatting _and_internatio-
francuskojęzycznego. W naszej konfigu- ezpublish/index.php/gb/english, gdzie „gb” nalization/i18n
racji mamy trzy języki, więc powinniśmy jest nazwą siteaccess-u, a „english” na-
stworzyć trzy foldery (po jednym dla zwą katalogu języka pod drzewem głów- Przełącznik języków
każdego języka) w drzewie zawartości. nym eZ publish. Używając ustawienia Pa- Mechanizm przełączania języków zale-
Te foldery będą przechowywały zawar- thPrefix możemy nakazać eZ publish uży- ży od liczby języków skonfigurowanych
tości stron specyficzne dla języka. wanie domyślnie katalogu „English”, ale dla strony. Mając tylko trzy języki, może-
Zaloguj się do Interfejsu Administra- nie używać go w URL-u. W ten sposób my wyświetlać łącza tekstowe, które po-
cyjnego i stwórz trzy foldery w głównym nasza ścieżka będzie wyglądać jak http:// zwalają użytkownikowi na zmianę języ-
drzewie katalogów, po jednym dla każde- localhost/ezpublish/index.php/gb. ka. Jednak jeśli mamy dużo języków, za
go języka: „English”, „French” i „German”. Dodaj następujące ustawienia do dużo miejsca byłoby potrzebne na poka-
(Rysunek 11). publicznych siteaccess-ów (gb, de, fr) zanie wszystkich łączy, zatem zamiast
To wszystko. Teraz mamy zdefinio- w bloku [ SiteAccessSettings]: łączy pokażemy wybór języka poprzez
wane katalogi główne dla zawartości wie- Tak samo, jeśli użytkownik wybierze listę rozwijalną. Przedstawione przykła-
lojezycznej. Zawartość angielska będzie angielski siteaccess, eZ publish będzie dy kodu mogą zostać użyte albo w pa-
przechowywana w folderze „English”, używał folderu „English” jako folder głów- gelayout.tpl (główny wzorzec eZ pu-
francuska w „French” itd. To pozwala na ny angielskiej zawartości. blish), albo we wzorcach węzłów.
segregację zawartości w różnych języ- Oto przykład przełącznika języków,
kach i dostarczania zawartości w okre- Własne tłumaczenia który wyświetla tekst lub łącza obrazkowe
ślonym języku podanym w aliasie URL-a. Podczas tworzenia wielojęzycznych dla każdego języka:
Następnym krokiem jest dodanie usta- stron, czasem potrzebujemy przetłuma- Jeśli używasz ustawień Virtual Host
wień konfiguracyjnych do każdego site. czyć jakieś własne etykiety, które nie są na swojej stronie, usuń „index.php” z
dostępne w domyślnym pliku tłumaczeń URL-a w przykładowym kodzie. Ten
eZ publish. Możemy zaimplementować przykład będzie działał z metodą dostępu
tłumaczenie tych własnych etykiet jako URI. Dla metody dostępu HOST kod bę-
rozszerzenie eZ publish (Rysunek 12). dzie podobny. Załóżmy, że mamy skonfi-
W pliku extension/mytranslationext/ gurowane hosty jak następuje:
settings/site.ini.append.php, potrzebujemy
przekazać eZ publish, że jest dostępne roz- Podsumowanie
szerzenie tłumaczeń. Ten plik domyślnie W tym artykule objaśniliśmy, jak skonfi-
nie jest zakładany – należy go stworzyć. gurować wielojęzyczną stronę za pomo-
eZ publish zapisuje tłumaczenia ja- cą eZ publish, używając cech dostęp-
ko XML w plikach o nazwie translation.ts. nych w wersji 3.8. Przedstawiliśmy prak-
Poniższy zrzut ekranu pokazuje program tyczny przykład, który objaśnił ustawie-
QT Linguist użyty do tłumaczenia zawar- nia konfiguracyjne strony i pokazał jak
tości w pliku XML. To jest plik źródłowy tworzyć nowe tłumaczenia dla obiek-
dla innych tłumaczeń użytych jako roz- tów strony. Strona wynikowa posiada
szerzenie. trzy niezależne językowe siteaccess-
y, wszystkie uruchamiane z jednego In-
Plik translation.ts terfejsu Administracyjnego. Z nowymi
Rysunek 11. Drzewo zawartości
to zwykły plik tekstowy cechami eZ publish 3.8 można dotrzeć
w formacie XML do międzynarodowej publiczności przez
We wzorcach, operator wzorca i18n ozna- dodanie języków do twojej strony. n
cza napis do przetłumaczenia:

{'Example'|i18n( 'extension O autorze


mytranslationext' )}

Łukasz Serwatka jest developerem sys-


Operator pobiera trzy opcjonalne pa- temu w EzSystems. W swojej pracy sku-
rametry: „context”, „comment” i „argi- pia się głównie na rozwoju kontaktów ze-
ments”. Parametr „context” może być uży- wnętrznych. Jest autorem wielu aplikacji
ty do określenia grupy, do której powi- i suplementów. Współtwórca największej
strony o PHP w Polsce www.php.pl.
nien być zaliczony parametr wejściowy.
Rysunek 12. Struktura katalogów W naszym przykładzie jest to „extension/ Kontakt z autorem: ls@ez.no
rozszerzenia tłumaczeń mytranslationext”

58 www.phpsolmag.org PHP Solutions Nr 1/2007


Testy

Jarek Litwa
Telewizja Internetowa TVNET
tArt w serwisie nazwa.pl. Przejrzysty inter- czyłby sobie tego każdy nieco zagubio-
fejs i wszystkie podstawowe opcje do za- ny klient. Zarówno przestrzeń dyskowa,
rządzania serwerem (podział powierzchni wielkość transferu, jak i możliwość swo-
pomiędzy dowolnymi usługami, zakłada- bodnego podziału przestrzeni są dosko-
nie nowych baz danych, zakładanie kont nałym rozwiązaniem dla firm takich, jak
e-mail) bardzo mi się spodobały ze wzglę- moja gdzie na jednym serwerze prowadzi
du na ogromną prostotę działania. się kilka niezależnych serwisów interneto-
Po wstępnej selekcji rozpoczęliśmy wych, oceniamy na plus.
analizę ofert dwóch firm – NetArt i Ho- Dzisiaj prócz serwisu Telewizji Inter-
me. Obie należą do czołówki dostawców netowej www.TVNET.com.pl na serwe-
usług internetowych i pozostawiły konku- rze są jeszcze dwie nasze domeny. Dlate-
rencję w tyle. Przy porównaniu cen NetArt go szukając firmy, w której postawimy ser-
wypadł lepiej zarówno przy domenach, jak wer dystrybucyjny braliśmy również Net-
i serwerach WWW, dodatkowo zapewnia- Art pod uwagę, ale rozwiązania informa-

D wa lata temu Telewizja Interneto-


wa TVNET, szukała providera, który
sprzeda i utrzyma odpowiednią domenę,
jąc większy serwer i większy limit roczny
transferu. Jednak nie to przesądziło o wy-
borze NetArtu. Poprosiliśmy o opinię zna-
tyczne, niezbędne do prowadzenia naszej
działalności przemawiały za firmą AirBi-
tes Polska, która dostarcza nam łącze in-
umożliwi zakładanie i administrację konta- jomych, korzystających z usług obu firm ternetowe. Wiąże się to z tym, że pomimo
mi pocztowymi oraz wymianę dużych pli- – więcej osób radziło nam NetArt. Ja- dużego transferu serwer Active nie jest
ków przez ftp. Najważniejszy jednak był ko minus ich usług można wymienić brak serwerem przeznaczonym do nadawania
dla nas szybki dostęp do materiałów zgro- możliwości definiowania użytkowników programów TV. A posiadając łącze u jed-
madzonych na serwerze przez wiele tysię- kont ftp, tak by każdy mógł mieć dostęp nego dostawcy bez dodatkowych proble-
cy osób w jednym czasie. Nie mniej ważne tylko do przydzielonych im plików. Nato- mów umieściliśmy tam serwer dystrybu-
było to, żeby serwerem można łatwo admi- miast na plus oceniam kontakty z Biurem ujący strumień wideo – było to bardziej
nistrować za pośrednictwem jakiegoś pro- Obsługi Klienta. Działa w dogodnych go- dogodne rozwiązanie pod względem or-
stego programu internetowego. Takim pro- dzinach, pracownicy zawsze cierpliwie ganizacyjnym i formalnym. Dziś dokona-
gramem jest Active.admin – obsługujący odpowiadają na nawet najbardziej zawi- libyśmy tego samego wyboru.
usługę hostingową dostępną w firmie Ne- łe i skomplikowane pytania – tak jak ży- Ocena: 4.5/5

Jacek Kmiecik
www.kmiecik.com.pl

P rowadząc firmę, której jednym z dzia-


łów są usługi dotyczące multime-
diów oraz usługi wykorzystujące możli-
min i Active.mail nie stanowi to większe-
go problemu. Twórcy tych aplikacji posta-
wili na intuicyjną obsługę, a ponadto za-
ne są niezwykle sprawnie, poza ,,godzina-
mi szczytu”. Pozytywnie należy też oce-
nić serwery pod względem parametrów
wości współczesnego internetu – poszuki- wsze mamy do dyspozycji obszerny sys- technicznych: spora przestrzeń dyskowa,
wałem na rynku możliwie najlepszego do- tem pomocy on-line, kontakt e-mailowy duży (choć jednak ograniczony) transfer,
stawcy usług hostingowych. Spośród kilku z firmą lub kontakt telefoniczny z konsul- możliwość posiadania nielimitowanej licz-
dostawców tych usług, jakie miałem moż- tantem technicznym czy dyżurnym admi- by domen, nielimitowana liczba kont e-
liwość przetestować w okresie ostatnich nistratorem systemu. mail wraz z wysoce wydajną i sprawną
kilku lat, firmę ,,NetArt'' oceniam najwy- Kwestia bezawaryjności to kolejna klu- ochroną przed spamem i wirusami, dodat-
żej, i tę polecam wszystkim moim zlece- czowa kwestia – strona internetowa jest kowe konto FTP – to kolejne atuty oferty
niodawcom. niekiedy jedynym sposobem komunikacji z „NetArt”. Należy dodać, że stosunek tych
Przy wyborze dostawcy hostingu, klientami, którzy mogą zechcieć odwiedzić parametrów do ceny należy do bardzo
istotnym dla klienta czynnikiem jest oczy- strony niezależnie od pory dnia (i nocy!) Nie atrakcyjnych. Dotychczasowe kontakty z
wiście cena – tu firma NetArt wychodzi można pozwolić sobie na częste awarie, Biurem Obsługi Klienta były bez zarzu-
naprzeciw oczekiwaniom nowych klien- bo przypomina to niegdysiejsze wywieszki tu – bardzo miła i kompetentna obsługa,
tów, proponując bardzo atrakcyjne ceno- na drzwiach sklepu ,,przyjęcie towaru” al- a otrzymane informacje rzeczowe i wy-
wo promocje. W moim przypadku nie to bo ,,remanent” – co dla wielu firm oznacza czerpujące. Podobnie kilkakrotne kontak-
było głównym kryterium wyboru właśnie to wymierne straty finansowe. Posiadam ty e-mail z administratorami spotkały się
tej firmy – czynnikiem, który ułatwił mi serwer w nazwa.pl od ponad dwóch lat z szybka reakcją – udzielone odpowiedzi
podjęcie decyzji było bezpieczeństwo da- – i do tej pory nie wystąpiły żadne po- pozwalały rozwiać wątpliwości związane
nych, obsługi i łatwość administrowania ważne problemy z jego funkcjonowaniem. z konfiguracją serwerów i sprawnie popra-
serwerem. Dzięki programom Active.ad- Wszelkie prace konserwacyjne wykonywa- wić działanie aplikacji.

60 www.phpsolmag.org PHP Solutions Nr 1/2007


Testy konsumenckie Testy

Sebastian Zawali
ret.pl
nowych wersji MySQL. Wbrew pozo- to z tego, iż jest to usługa hostingowa,
rom jest to ważne, bo świadczy o tym, a nie serwer wirtualny i stąd te ograni-
że firma rozwija swoją infrastrukturę. czenia.
Spośród wszystkich innych ofert Podsumowując chwale sobie sta-
pod uwagę brałem tylko rozwiąza- bilność serwera – praktycznie, od kie-
nia głównego konkurenta nazwa.pl – dy korzystam z serwerów w nazwa.pl
home.pl, ale niestety ich interfejsy do nie miałem żadnych przerw w wyświe-
obsługi poczty przez WWW nie po- tlaniu stron co zdarzało się u mojego
siadają wersji niemieckiej (posiada poprzedniego dostawcy, aktualizację
tylko polską i angielską). Oprócz te- php'a i MySQL'a, program partnerski,
go jakość samego programu do admi- infolinie 0801, szybkość przypisywania
nistracji serwerem oraz obsługi pocz- domen do serwera, pomoc techniczną
ty przez WWW, jest znacznie wyższa oraz przejrzystość panelu administra-
w nazwa.pl – choć jest to zupełnie su- cyjnego zarówno serwera jak i poczty.

J ednym z głównych źródeł docho-


dów mojej firmy jest tworzenie
stron WWW opartych o systemy za-
biektywne odczucie i nie każdy się z
nim zgadza. Także stosunek ceny do
oferowanego produktu wypada na ko-
Gdybym miał ponownie podjąć de-
cyzję o zakupie usługi hostingowej by-
łaby ona taka sama.
rządzania treścią (CMS). Dostarczam rzyść nazwa.pl. No i pozostaje kwestia O nazwa.pl dowiedziałem się z re-
rozwiązań zarówno dla klientów z Pol- korzystania z programu partnerskiego klam internetowych i prasowych. Tylko
ski, jak i zagranicy, którzy nie zawsze – choć niestety żadna poważna firma nazwa.pl i home.pl to firmy hostingo-
chcą i potrafią administrować swoimi nie oferuje pieniędzy za poleconych we prowadzące działania marketingo-
serwisami internetowymi. Wymagają klientów, to nazwa.pl ma znacznie bo- we na wysokim poziomie. Wbrew po-
natomiast ode mnie, żebym umieścił gatszy i bardziej rozwinięty taki pro- zorom jest to ważne, bo swoim klien-
gdzieś ich witryny – dla nich oczywi- gram. Dla mnie udział w nim to czysty tom oferuję usługi znanych firm – prak-
stym jest, że strony będą widoczne w zysk, gdyż, jeśli polecę jednemu klien- tycznie każdy mój klient kiedyś spotkał
sieci bez przerw, a z poczty będą mo- towi zakup serwera to praktycznie dru- się z reklamami nazwa.pl i to daje po-
gli korzystać także przez przyjazny in- gi serwer mam gratis i mogę go wyko- czucie bezpieczeństwa oraz pośrednio
terfejs WWW. rzystywać do własnych potrzeb – np. wpływa na mój wizerunek. Skoro w ra-
Poszukiwałem usług wydajnych, umieszczać na nim serwisy WWW in- mach stworzenia serwisu WWW doda-
niezawodnych o przyzwoitej cenie oraz nych moich klientów. Gdzie indziej nie ję jego umieszczenie u znanego ope-
wielojęzycznych interfejsach do odczy- ma takiego przelicznika, że jeden pole- ratora, to znaczy, że traktuję klientów
tu poczty przez strony WWW. Bardzo cony serwer daje mi serwer gratis a w poważnie i nie szukam oszczędności
mi zależało, aby program do obsługi nazwa.pl tak – to był jeden z argumen- kosztem jakości usług oraz mogę gwa-
poczty przez WWW był maksymalnie tów, który przemawiały za nazwa.pl. rantować jakość tych usług.
prosty w obsłudze. Te cechy połączy- Ogólnie rzecz biorąc jestem zado- Uważam, że usługę, z której korzy-
ły usługi nazwa.pl, dodatkowo w obsłu- wolony z usług nazwa.pl, choć braku- stam mogę bez wahania ocenić na 4,5
dze poczty traktuję możliwość darmo- je mi możliwości zakładania kont pocz- gwiazdki, 0,5 gwiazdki zabieram wła-
wego otrzymywania smsów z powia- towych o takiej samej nazwie na jed- śnie za względu na brak możliwości
domieniami o przychodzącej poczcie. nym serwerze dla różnych domen, np. zakładania kont pocztowych o takiej
Duże znaczenie miała także elastycz- biuro@ret.pl oraz biuro@costam.pl. samej nazwie na jednym serwerze dla
ność serwera, czyli możliwość dowol- Jednak mam świadomość, że wynika różnych domen.
nego podziału zakupionej przestrzeni
na usługi WWW, bazy danych i pocztę
elektroniczną oraz rozliczanie transfe-
ru w skali roku, a nie miesięcznej.
Serwisy mniej wymagających klien-
tów utrzymuję na swoim serwerze, dla-
tego też szukałem hostingu pozwalają-
cego na utrzymywanie wielu domen na
jednym serwerze – dzięki temu minima-
lizuję koszty, a mam możliwość dostar-
czenia klientom usług komplementar-
nych. Ponadto zależało mi na tym, aby
serwery posiadały PHP 5.0 – sam piszę
pod tą wersję oraz dbały o wdrażanie

PHP Solutions Nr 1/2007 www.phpsolmag.org 61


Testy Testy konsumenckie

Justyna Zajączkowska
Specjalista ds. Public Relations w NetArt

N asza firma istnieje już od prawie 10


lat. Koncentrujemy się na dostar-
czaniu usług serwerów małym i średnim
wać zespół, który sprawnie wdraża no-
we pomysły i działa według określonych
standardów. Tego nie da się wypraco-
firmom. Ostatnio szeregi naszych klien- wać w rok czy dwa.
tów powiększają się stopniowo także o Nasze Data Center znajduje się w
użytkowników indywidualnych. Rosną- Polsce, co znacznie skraca czas reak- widoczne i doceniane. To pozytywny im-
ca liczba klientów nie jest tylko wynikiem cji na ewentualne problemy. Nie mu- puls do tego, aby jeszcze intensywniej
atrakcyjnej ceny, chociaż ta faktycznie w simy korzystać z łańcucha pośredni- pracować.
przeciągu kilku ostatnich lat bardzo się ków, aby móc wyjaśnić każdy, nawet Cieszymy się także, że coraz więk-
zmniejszyła. Obniżenie progu cenowe- najmniejszy problem w działaniu usłu- sze uznanie zyskuje nasze Biuro Ob-
go kupna serwera do 50 zł netto sprawi- gi konkretnego klienta. Doświadcze- sługi Klienta – od kilku lat intensyw-
ło, że w potocznym mniemaniu przestał nie w diagnozowaniu problemów, z ja- nie je powiększamy i wdrażamy kolej-
on być uważany za usługę drogą, bę- kimi zgłaszają się do nas użytkownicy ne standardy obsługi klienta. Chcemy
dącą poza zasięgiem małego przedsię- internetu i dogłębna wiedza na temat zapewnić bezproblemowy kontakt z
biorcy, a tym bardziej osoby prywatnej. serwerów to natomiast kapitał, który naszymi konsultantami i fachową ob-
Oferta NetArt przyciągnęła rzesze klien- zbieraliśmy przez wszystkie lata na- sługę bez długiego okresu oczekiwa-
tów, którzy mogli dzięki temu przekonać szej działalności. nia na połączenie telefoniczne. Zdaje-
się o korzyściach wynikających z posia- Na każdą z naszych usług patrzy- my sobie sprawę, że dla części klien-
dania serwera WWW. my przez pryzmat naszego klienta. tów administrowanie serwerem może
Widać, że nasi klienci doceniają ja- Wiemy, że jest grupa klientów bardzo czasem generować problemy – dlate-
kość naszych usług i ich sprawne funk- zaawansowanych, którzy w pełni wy- go też kilkudziesięciu konsultantów po-
cjonowanie. Trzeba zdawać sobie jed- korzystają serwery. Jednak dla dużej maga uporać się nie tylko z kwestiami
nak sprawę, iż jest ono efektem wielu lat części klientów jest to pierwszy kon- technicznymi, ale także administracyj-
doświadczenia w dostarczaniu hostingu takt z serwerem WWW. Dlatego bar- nymi.
oraz bardziej zaawansowanych usług dzo istotne było dla nas opracowanie Nasi klienci zgłaszają oczywiście
serwerów. To niezbędny czas, by osią- aplikacji, które umożliwią administro- drobne zastrzeżenia – takie jak limit
gnąć wysoki poziom usług, opracować wanie serwerem i zarządzanie pocz- transferu czy brak kont FTP zdefinio-
funkcjonalne oprogramowanie, zbudo- tą w jak najprostszy sposób. Efektem wanych dla każdego użytkownika. Fak-
naszej pracy są programy Active.ad- tycznie można uznać to za pewne nie-
min i Active.mail, które wciąż są udo- dogodności, ale pamiętajmy, że roz-
skonalane i modyfikowane. Ich intu- mawiamy tutaj o hostingu. Jest to usłu-
icyjność to czynnik często podkreślany ga podstawowa, która z definicji pew-
przez naszych klientów. Dzięki ich pro- ne parametry musi mieć ograniczone.
stocie i funkcjonalności klienci nie boja Osoby pragnące posiadać nieograni-
się sami administrować swoimi usługa- czony transfer czy więcej kont FTP de-
mi, nie nastręcza to bowiem żadnych cydują się na usługi bardziej zaawan-
problemów. sowane, takie jak serwer wirtualny czy
Stabilność działania i systematycz- dedykowany.
ny rozwój to czynniki, które umożliwia- Wiemy, że potrzeby i wymagania
ją nam inwestowanie w infrastrukturę. naszych klientów nieustannie rosną,
Na bieżąco staramy się aktualizować tak samo jak zwiększa się zakres ich
nasze oprogramowanie, dbamy także działalności. Dlatego staramy się tak
o najwyższą jakość rozwiązań hardwa- konstruować nasze usługi, aby każ-
rowych. dy klient mógł znaleźć coś dla siebie.
Najlepszą dla nas nagrodą jest za- Użytkownicy, którzy potrzebują rozbu-
dowolenie naszych klientów. Cieszą sło- dowanych możliwości zarządzania, al-
wa Panów, którzy odpowiedzieli na py- bo których serwery generują bardzo
tania redakcji PHP Solution. Widać tu- duży ruch mogą skorzystać z nasze-
taj, że nasze serwery spełniają wyma- go serwisu – serwery.pl, gdzie zakupić
gania nawet najbardziej wymagających można bardziej zaawansowane usługi,
klientów. Służą nie tylko do budowania takie jak serwer dedykowany, serwer
najprostszych serwisów, ale pozwalają wirtualny czy kolokację. Wierzymy, że
także na budowanie zaawansowanych szeroka gama usług, ich wysoka ja-
serwisów multimedialnych. Cieszymy kość oraz przystępna cena sprawiają,
się, że wysiłki zmierzające ku zapewnie- że grono naszych klientów tak szybko
niu klientom najwyższej jakości usług są się powiększa.

62 www.phpsolmag.org PHP Solutions Nr 1/2007


Testy konsumenckie Testy

Maksymilian Drążek
Grupa 505

W łasna domena, szata graficzna


oraz funkcjonalność strony inter-
netowej jest dziś istotnym elementem



pojemność konta,
transfer,
cena,
szych operuje całodobową pomoc tech-
niczną administratora. Otóż prawda czę-
sto bywa zupełnie inna. Administrator jest
polityki marketingowej firmy. Bez niej • ilość obsługiwanych domen/ ale w ograniczonym czasie.
firma w oczach Klientów z pewnością subdomen, Moim zdaniem, kluczowym elemen-
jest mniej wiarygodna. Działania pro- • ochrona antywirusowa, tem atrakcyjności danej oferty prócz ce-
mocyjne i reklamowe skupiające się na • pomoc techniczna 24h, ny i parametrów konta jest właśnie bardzo
wizerunku firmy i jej obecności na rynku • panel administracyjny konta. dobry kontakt z administratorami serwera.
z pewnością odnoszą znacznie większy Sposób dowolny (przez formularz kontak-
skutek gdy firma podaje własny adres Uwagę zwróciła oferta Miracle Systems towy, telefon czy po prostu zwykły e-ma-
internetowy związany z jej działalno- Cybermedia (Miracle.pl). il). Wiele prac związanych z funkcjono-
ścią lub nazwą. Serwer o wystarczającej pojemności waniem danej witryny internetowej, doko-
Wdrażając w życie kolejny serwis 1 GB z miesięcznym pakietem ruchu z/do nuje się w godzinach wieczorno nocnych,
internetowy, potrzebowaliśmy stosun- sieci Internet 10GB, nieograniczoną ilo- gdzie ruch w sieci internet jest stosunko-
kowo taniej, a dobrej oferty serwera ścią subdomen, nielimitowana ilość kont wo mniejszy i niekiedy są to operacje wy-
wirtualnego. pocztowych, ochrona m antywirusowa, magające kontaktu z administratorem.
Funkcjonując w sieci od 2001 roku, całodobowa pomoc techniczna, panel itp. W przypadku testowanego konta w
mając dosyć dobre rozeznanie w ofer- Całość w cenie 99 zł. ofercie hostingowej Miracle.pl wszystkie
cie usług hostingowych na rynku polskim Przyszedł czas na sprawdzenie funk- parametry jak obsługa techniczna wypa-
(aktualnie korzystamy z 11 serwerów wir- cjonalności oferty czyli wykorzystanie 7 dły bardzo dobrze i zapadła decyzja o za-
tualnych różnych dostawców), przy za- dniowego okresu testowego. kupie.
chowaniu pewnych kryteriów wynikają- Sprawdzaliśmy bardzo podstawową Aktualnie blisko pół roku korzy-
cych z dotychczasowych doświadczeń, funkcjonalność konta jak: szybkość łado- stamy z zakupionego konta na serwe-
kwestią czasu było odnalezienie produk- wania się średniej wielkości strony, ochro- rze. Wszystkie zadeklarowane w ofer-
tu odpowiadającego naszym wymaga- nę antywirusową, „uptime” serwera, prze- cie, sprawdzone w okresie testowym pa-
niom. Przy wyszukiwaniu ofert nie suge- sył danych pomiędzy komputerem a ser- rametry jaki i kontakty z administratorem
rowaliśmy się reklamami, ale sprawdzali- werem czy praca obszerniejszej bazy da- sprawdzają się w 100%. Nasza współpra-
śmy firmy hostingowe z czołowych pozy- nych, co przy rozwoju serwisu i wzrostu ca z pewnością będzie kontynuowana.
cji w wyszukiwarkach. Pod uwagę brane liczby użytkowników ma znaczenie. Wie- Gdybym miał możliwość ocenienia
były parametry: le firm hostingowych mniejszych, więk- użytkowanego konta w skali 1 do 5 ocenił
bym to 5 przysłowiowych gwiazdek.

PHP Solutions Nr 1/2007 www.phpsolmag.org 63


Testy Testy konsumenckie

Grzegorz Tarnowski Łukasz Górski


www.4hotele.pl Specjalista od Reklamy i Marketingu Cybermedia.pl

W ybraliśmy hosting Firmy Miracle ze


względu na bardzo dobre Parame-
try. Szukaliśmy hostingu i przetestowali-
śmy kilkunastu hostingowdawców, którzy
nie spełnili naszych oczekiwań. W zasto-
sowaniach businessowych korzystamy z
usług home.pl i jesteśmy przyzwyczajeni
do ich standardów. Niestety W niektórych
przypadkach nie można korzystać z ich
usług gdyż wymóg skali pociąga za so-
bą małą elastyczność rozwiązań. Szuka-
liśmy więc hostingu na którym w sposób
bezpieczny przy minimalnych zmianach
będzie dział kod hostowany również na
home.pl. Jak się przekonaliśmy nie jest to
prosta sprawa. Użwamy wielu technologii
N a wstępie dziękuję „Phpsolmag”za
zainteresowanie się Miracle.pl i jego
ofertą.
dynamicznie rozwijany, co będzie wiąza-
ło się z dokupywaniem nowych serwerów
na różnych klasach IP.
PHP proces konfiguracji hostingu i dosto- Dziękuję także klientom za wyrażenie Nasza firma zajmuje się usługami in-
sowania kodu zajął nam kilka dni. opinii na łamach magazynu, cieszę się ternetowymi od 1997 roku, posiada kil-
Oprócz home.pl korzystamy jeszcze że usługi które Wam świadczymy spoty- ka serwisów internetowych na Polskim
z usług pair.com i xon.pl każdy z provie- kają się z pozytywnym odbiorem z Wa- rynku co pozwala nam dotrzeć do bar-
derów posiada specyfikę i jest przez nas szej strony. dzo szerokiego grona odbiorców, na-
wykorzystywany w różnych zastosowa- Nie poprzestajemy jednak „na laurach” sze usługi oferujemy także w sprzedaży
niach. ciągle staramy się ulepszać jakość usług bezpośredniej (projektowanie stron, kon-
Zalety miracle.pl to: szybkie transfe- (jako że zadowolenie klientów jest naj- figuracja serwerów). W związku z szyb-
ry, bezpieczeństwo zdecydowanie ponad ważniejsze i bardzo motywujące) przy- kim rozwojem Internetu i wzrostem kon-
standard, dobra obsługa, elastyczność kładowo kilka dni temu wprowadziliśmy kurencji na rynku w 2006 roku podjęli-
i dobra cena. nowy, bardzo funkcjonalny i prawdopo- śmy decyzję o stworzeniu serwisu Mirac-
Wadą jest brak wielu klas IP C ta ce- dobnie najlepszy na świecie panel użyt- le.pl. Serwis ten oferuje wysoką jakość
cha była przez nas szczególnie pożądana kownika – Cpanel, a od 1 grudnia zo- usług w dobrych cenach, oferta skiero-
średni czas reakcji może być akceptowal- stała wprowadzona promocja miesięcz- wana jest głównie do małych i średnich
ny i jest to zwykle kilka godzin. na związana ze świętami co ma zachę- firm, oraz klientów indywidualnych. Sta-
Pierwszy hosting zakupiliśmy w ma- cić Państwa do skorzystania z oferty Mi- ramy się kłaść nacisk na jakość ofero-
ju 2006 w październiku kolejny jeśli firma racle.pl. wanych usług, oraz dobre i indywidual-
Miracle.pl będzie się rozwijała planować Średni czas reakcji w ostatnim cza- ne podejście do klienta, bo to klient jest
będziemy osadzanie kolejnych projektów. sie został bardzo skrócony w związku najważniejszy, a Jego zadowolenie gwa-
Polecamy usługi Miracle dla średnio z wprowadzeniem telefonicznej pomocy rantuje sukces każdej firmy. Zapraszam
wymagającego klienta przy niektórych technicznej - pod numerem tel. 600 61 00 do zapoznania się z naszą ofertą i aktu-
lub dla dodatkowych zastosowań dla wy- 51 mogą Państwo uzyskać wszelką po- alnymi promocjami.
magającego klienta. moc.
W skali 1-5 oceniamy usługi Miracle.pl Odnośnie klas IP, to są one nieroz-
na 4 gdyby z naszych doświadczeń wyklu- łącznie związane z nowymi serwerami,
czyć te związane z home.pl byłaby to 5. w chwili obecnej serwis miracle.pl jest

64 www.phpsolmag.org PHP Solutions Nr 1/2007


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) 887 10 11 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) 887 14 44

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
6 135

Hakin9, jak się obronić (1 płyta CD)


Miesięcznik o bezpieczeństwie i hakingu
12 1991/219

.psd (1 płyta CD + film instruktażowy)


Dwumiesięcznik użytkowników programu Adobe Photoshop
6 140

.psd numery specjalne


(.psd Extra + .psd Starter Kit)
6 140

Aurox Linux (4 płyty CD + 1 płyta DVD)


Magazyn z najpopularniejszym polskim Linuksem
4 1193

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
Narzędzia triki w php

Znaki specjalne
Pisząc skrypty w PHP często zdarza dzie PHP. Jest to spowodowane tym iż nie Listing 1. Skrypt PHP bez zastoso-
się, że należy zajrzeć do źródła wyge- ma znaków nowej linii. wania znaków nowej linii
nerowanej strony aby sprawdzić czy W celu uniknięcia takiego problemu
wszystkie elementy zostały wydruko- możemy zastosować znaki nowej linii na <?php
echo 'Ala ma kota';
wane poprawnie. Niestety jeżeli skrypt zakończeniu każdego wiersza.
echo '<br />';
jest w całości napisany za pomocą ję- W tym przypadku źródło strony bę- echo 'Kot ma Ale';
zyka PHP i nie ma w nim miejsc, w któ- dzie podzielone na osobne linie w których ?>
rych zastosowany jest czysty HTML zo- umieściliśmy tekst. Nowe linie powstały w
rientowanie się w źródle programu bę- miejscu gdzie umieściliśmy znak \n. Listing 2. Formatowanie strony z
dzie bardzo ciężkie ze względu na brak Przekształcanie zmiennych wysłanych użyciem znaku nowej linii
nowych linii. Całość strony WWW zosta- za pomocą metody GET i POST w zwykłe <?php
nie wypisana linia za linią bez znaków zmienne echo "Ala ma kota\n";
nowego wiersza. Można tego uniknąć W PHP możesz także przetworzyć echo "<br />\n";
stosując specjalne znaki, które pomo- zmienne z tablicy w zwykłe zmienne. echo "Kot ma Ale\n";
?>
gą w nadaniu dla źródła strony WWW Musisz tylko wybrać, którą tablicę masz
odpowiedniego formatowania. Znakiem zamiar przetwarzać. Jest to zwłasz- Listing 3. Skrypt przetwarzający
specjalnym jest między innymi \n - czyli cza przydatne, kiedy funkcja register_ zmienne z tablicy $_GET
znak oznaczający nową linię. globals jest wyłączona. Funkcję
<?php
Po zajrzeniu do źródła takiej strony zo- register_globals wyłącza się specjal-
if( is_array($_GET) )
baczymy całość tekstu w jednej linii mimo nie w celu uczynienia skryptów bardziej {
iż wypisywaliśmy ja w kilku linijkach w ko- bezpiecznych pod względem użytkowa- while( list($k, $v) =
each($_GET) )
{
if( is_array($_GET[$k]) )
{
while( list($k2, $v2) =
each($_GET[$k]) )
{
$$k[$k2] = $v2;
}
reset($_GET[$k]);
}
else
{
$$k = $v;
}
}
reset($_GET);
}
?>

Rysunek 1. Wygląd źródła strony bez zastosowania znaków formatujących


nia. Jeżeli będziesz stosował przedsta-
wioną metodę musisz bardzo dokładnie
sprawdzać zmienne które otrzymałeś od
użytkownika.
Skrypt ten przetwarza wszyst-
kie zmienne z tablicy $_GET na zmien-
ne globalne. Bierze on po kolei każdy
element i wpisuje go do zmiennej takiej
samej, jaką ma indeks tablicy. Dzię-
ki temu możesz korzystać od razu ze
zmiennych nie odwołując się do okre-
ślonej tablicy.
W taki sam sposób można dokonać
przekształcenia tablicy $_POST i każdej
innej. Pamiętaj jednak o tym iż jest to
trochę niebezpieczne. Najlepiej jest to
stosować na stronach w intranecie gdy
Rysunek 2. Wygląd źródła strony z zastosowaniem znaków formatujących wiemy kto z nich korzysta.

68 www.phpsolmag.org PHP Solutions Nr 1/2007


triki w php Narzędzia

Przekierowanie w zależności od przeglądarki


PHP przychodzi z pomocą w przypad- warta wówczas za pomocą polece-
ku, gdy mamy potrzebę przekierowa- nia header przekierowujemy użytkow- Listing 4. Przekierowanie użytkow-
nika na odpowiednią stronę w zależ-
nia użytkownika w zależności od uży- nika na odpowiednią stronę WWW.
ności od przeglądarki której używa
wanej przeglądarki internetowej. Wy- W przypadku gdyby była to inna prze-
starczy wówczas sprawdzić jakiej glądarka, wówczas możemy użytkow- <?php
przeglądarki używa osoba odwiedza- nika przekierować pod inny adres. if ($name = strstr ($_SERVER
['HTTP_USER_AGENT'], "MSIE"))
jący naszą stronę WWW, a następnie Bardzo ważne jest aby skrypt zna-
{
za pomocą polecenia header przekie- lazł się zanim cokolwiek wydrukujesz Header ("Location:
rować ją pod odpowiedni adres w sie- do przeglądarki. Oznacza to, iż mu- http://www.stronadomowa.pl/");
ci Web. si on znaleźć się na samym począt- }
W skrypcie za pomocą funk- ku pliku zanim cokolwiek wyjdzie ze else
{
cji strstr sprawdzamy, czy w zmien- skryptu gdyż wtedy nagłówek już zo-
Header ("Location:
nej $ _ SERVER['HTTP_USER_AGENT'] , stanie wysłany i nie będziesz mógł już http://www.innastrona.pl/");
jest zawarta nazwa przeglądarki, o nic zrobić. }
którą nam chodziło. Jeżeli jest za- ?>

Walidacja adresu e-mail Sprawdzenie hosta Odświeżania strony


W momencie, gdy jakaś osoba będzie z adresu e-mail W PHP możesz także dokonać odświe-
się rejestrowała na twojej stronie WWW Oprócz sprawdzenia czy adres e-mail jest żenia strony. Jest to także często stoso-
będziesz miał możliwość walidacji czy- poprawy czyli zawiera przynajmniej znak wana instrukcja w kodzie HTML. Jed-
li sprawdzenia poprawności jej adresu małpy „@” i jedną kropkę możemy jesz- nak dzięki zastosowaniu w tym przypad-
e-mail. Użyjemy do tego wyrażenia re- cze stwierdzić czy host danego adresu ku kodu PHP nikt nie będzie mógł takiej
gularnego i za pomocą odpowiedniej istnieje. Zrobimy to poprzez sprawdzenie instrukcji usunąć jak byłoby to możliwe w
funkcji ereg sprawdzimy, czy e-ma- rekordu MX danego serwera. Oczywiście kodzie HTML.
il został wprowadzony prawidłowo. Ad- możemy to zrobić jedynie wtedy, gdy host Skrypt ten spowoduje odświeżenie
res będzie przechowywany w zmiennej serwera obsługuje port 25. się strony za 3 sekundy, które podajemy
$email którą poddamy sprawdzeniu. W ten sposób możemy od razu do- w parametrze. Po słowie url podajemy
W tym momencie musimy jeszcze wiedzieć się czy adres który podano w adres URL do którego strona ma przejść
dokonać odpowiedniej czynności, gdy formularzu jest poprawny pod względem po odświeżeniu. W tym wypadku strona
sprawdziliśmy już, czy adres e-mail zo- faktu, iż serwer na którym się on znajdu- przeładuje się i wrócisz automatycznie
stał zweryfikowany. Najlepiej jest doko- je istnieje. na stronę główną.
nać tego za pomocą polecenia if. Możesz także skonstruować ele-
ment przekierowujący użytkownika na
Listing 5. Wyrażenie regularne do Listing 7. Program sprawdzający inną stronę. Ten skrypt jest trochę inny
sprawdzenia, czy tekst jest popraw- dostępność hosta od użycia parametru location. W przy-
nym adresem e-mail padku location strona nie pojawiała się
<?php w przeglądarce tylko automatycznie się
<?php list($Username, $Domain) =
przeładowywała. W tym przypadku stro-
preg_match( "|^[-_\.a-z0-9]+ split("@",$email);
@[-_a-z0-9\.\+]+\.[a-z0-9] if(getmxrr($Domain, $MXHost)) na zostanie wyświetlona w przeglądar-
{2,4}$|i", trim($email)); { ce, a następnie się przeładuje.
?> echo 'adres e-mail jest
poprawny';
Listing 6. Kod do sprawdzenia ad- } Listing 8. Automatyczne odświeże-
resu e-mail else nie strony
{
<?php if(fsockopen($Domain, 25, <?php
if(!preg_match( "|^[-_\.a-z0-9]+ $errno, $errstr, 30)) header( 'refresh: 3; url=/' );
@[-_a-z0-9\.\+]+\.[a-z0-9]{2,4}$|i" { echo '<h1>Zostaniesz
, trim($email))) echo 'adres e-mail jest poprawny'; przeniesiony za 3 sekundy...</h1>';
{ ?>
echo 'e-mail nie jest poprawny'; }
} else Listing 9. Przekierowanie na stronę
else {
{ echo 'adres e-mail NIE jest <?php
echo 'e-mail jest poprawny'; poprawny'; header('refresh: 0; url
} } =http://www.google.pl');
?> } ?>
?>

PHP Solutions Nr 1/2007 www.phpsolmag.org 69


Narzędzia triki w php

Czas generowania strony Dodawanie slashy do zawartości zmiennych


Pewnie zauważyłeś wielokrotnie na stro- Funkcje te pozwalają na dodawanie do Można także skorzystać ze spe-
nie jest pokazany czas jej generowa- ciągów znaków, które otrzymujemy od cjalnej funkcji gdy mamy zamiar dodać
nia. Jest to bardzo proste do wykonania i użytkowników z różnych formularzy czy wprowadzone dane do bazy MySQL.
umożliwi ci wzbogacenie swojej strony o tez adresów URL specjalnych znaków, Funkcja mysql_real_escape_string okre-
dodatkowy element. które zabezpieczają takie ciągi przed śli aktualnie używany w połączeniu ze-
Pierwszą rzeczą, której będziemy po- wprowadzeniem do bazy danych wraz ze staw znaków i zabezpieczy wszystkie
trzebować to pobranie wartości z funkcji znakami które mogą spowodować błąd. znaki uznane za niebezpieczne.
microtime i rozdzielenie jej na dwie części. Dzięki tym funkcjom unikniemy ataków
Następnie dodamy te części do siebie aby „SQL injection”. Ataki te polegają na odpo- Listing 14. Zabezpieczanie zmien-
uzyskać pełny czas. Następnie na samym wiednim spreparowaniu zapytań do baz nych
końcu strony wykonujemy ponownie po- danych, dzięki czemu można uzyskać róż-
branie czasu z funkcji microtime, rozdzie- ne dane nie przeznaczone dla użytkowni- <?php
if(!get_magic_quotes_gpc())
lenie jej na dwie części za pomocą pole- ka. Dzięki zastosowaniu tej funkcji nie bę-
{
cenia explode i dodania do siebie czasów. dziesz musiał za każdym razem używać $_GET = array_map
Deklarujemy także zmienną która pozwoli funkcji addslashes() dla każdej zmiennej ('addslashes', $_GET);
nam na zaokrąglenie czasu do odpowied- pobranej z adresu URL lub formularza. $_POST = array_map
niego miejsca po przecinku. Ten fragment kodu sprawdza czy ('addslashes', $_POST);
$_COOKIE = array_map
W celu uzyskania czasu ładowania się funkcja automatycznego dodawania sla-
('addslashes', $_COOKIE);
strony należy odjąć od czasu końcowego shy jest włączona, jeżeli nie jest włączo- $_REQUEST = array_map
czas początkowy, który pobraliśmy na po- na używane są funkcje do automatycz- ('addslashes', $_REQUEST);
czątku ładowania się strony. nego zabezpieczenia danych. Pamiętaj }
W następnym kroku wystarczy różnicę jednak iż jeżeli będziesz chciał użyć war- ?>

czasu już tylko wyświetlić zaokrągloną do tości tych zmiennych w formularzach ge-
Listing 15. Specjalna funkcja do za-
odpowiedniej ilości miejsc po przecinku. nerowanych za pomocą PHP będziesz bezpieczania danych przed wprowa-
musiał dane poddać obróbce polece- dzeniem ich do bazy danych
Listing 10. Pobranie czasu począt- niem stripslashes. Jest to spowodowane
kowego faktem iż jeżeli użytkownik wstawi jakiś <?php
$zdanie = "Mark's laptop";
tekst do formularza zostanie on automa-
<?php $zabezpieczone_zdanie =
tyczne oznaczony znakami slash. Więc mysql_real_escape_string($zdanie);
$m_time = explode
(" ",microtime()); przed użyciem polecenia echo, print lub print($zabezpieczone_zdanie);
$m_time = $m_time[0] + podobnego będziesz musiał usunąć sla- ?>
$m_time[1]; she z wartości tych zmiennych.
$starttime = $m_time;
?>

Listing 11. Pobranie czasu koco-


Sprawdzanie adresu URL
wego W przypadku gdy użytkownik Interne- kund jaką ma czekać skrypt zanim
tu podaje link do swojej strony WWW przestanie próbować połączyć się z
<?php
możesz od razu sprawdzić czy taka serwerem.
$round = 3;
$m_time = explode(" ",microtime());
strona istnieje. Zrobisz to za pomocą
$m_time = $m_time[0] + funkcji fsockopen, która da ci informa- Listing 16. Sprawdzanie dostępno-
$m_time[1]; cję, czy wskazany przez ciebie host ści adresu URL
$endtime = $m_time; znajduje się w sieci, czy tez nie.
?> <?php
Funkcja fsockopen próbuje połą-
$up = @fsockopen('www.google.pl',
Listing 12. Odjęcie czasu końcowe- czyć się z serwerem, który podasz
80, $errno, $errstr, 30);
go i początkowego mu w pierwszym parametrze. Pamię- if($up)
taj, aby adres strony podać bez http:// {
<?php z przodu ponieważ funkcja nie zadzia- echo '<a href=
$totaltime = ($endtime "http://www.google.pl"
ła w takim przypadku.
- $starttime); >Google.pl</a>';
?> Drugi parametr to port którego uży-
}
wa skrypt do połączenia się ze wska- else
Listing 13. Wyświetlanie czasu ła- zana stroną. Domyślnym portem dla {
dowania strony strony WWW jest port 80 więc tego echo '<a href=
parametru nie powinieneś zmieniać. "http://www.google.pl"
<?php >Google.pl nie działa</a>';
echo 'Strona ładowała się: '. round Następne dwa parametry są standar-
}
($totaltime,$round) . ' sekund'; dowymi błędami PHP które są wypi- ?>
?> sywane do tych zmiennych. Ostatnim
z argumentów czyli 30 jest ilością se-

70 www.phpsolmag.org PHP Solutions Nr 1/2007


triki w php Narzędzia

Kompresja strony za pomocą zlib


Kompresja pozwala na znaczne przy- naleźć fragment opatrzony etykietą zlib. lepiej w takim przypadku zrobić detekcje
spieszenie się ładowania strony na na- Jeżeli znajduje się tam obok napisu ZLib przeglądarki internetowej i dla odpowied-
szym komputerze dzięki temu iż jest ona Support napis enabled oznacza to, iż bi- niej zastosować kompresję.
skompresowana i znacznie mniej czasu blioteka jest włączona.
zajmuje jej przesłanie. Dla serwera jest Następnie wystarczy dodać mały frag- Listing 17. Skrypt pokazujący infor-
to jednak obciążenie gdyż oprócz wyge- ment skryptu do naszej strony WWW. Pa- macje o PHP
nerowania strony musi ją także skompre- miętaj, iż musi się on znaleźć zanim co-
<?php
sować. kolwiek wyślesz do przeglądarki. W takim
phpinfo();
W celu rozpoczęcia kompresji strony przypadku spowoduje to błąd. Skrypt mu- ?>
należy sprawdzić czy na naszym serwe- si znaleźć się na samej górze strony
rze jest zainstalowana biblioteka zlib i czy W niektórych przeglądarkach takich Listing 18. Strona WWW z włączo-
jest ona włączona. jak na przykład Internet Explorer 6 kom- ną kompresją
Skrypt pozwoli nam na sprawdzenie, presowanie strony niestety nie działa. <?php
czy biblioteka została włączona do inter- Przeglądarka najczęściej zawiesza się ob_start('ob_gzhandler');
pretera PHP na serwerze. Wystarczy od- przy próbie przeczytania takiej strony. Naj- ?>
<html>
<head>
</head>
<body>
<p>Ta strona została
SKOMPRESOWANA!</p>
</body>
</html>
Rysunek 3. Informacje na temat biblioteki zlib

Przekierowanie w PHP
Jeżeli będziesz musiał przekierować użyt- Skrypt ten przekieruje użytkownika czątku pliku. Jeżeli wypiszesz już coś do
kownika do innej strony i będziesz chciał na stronę http://www.google.pl bez poka- przeglądarki wówczas generowanie stro-
zrobić to za pomocą PHP z pomocą przyj- zywania mu jakichkolwiek komunikatów. ny zakończy się błędem.
dzie w tym momencie polecenie header. W celu zmiany adresu URL wystarczy, iż
Pozwala ono na przeniesienie użytkowni- w skrypcie zmienisz tylko adres który jest
Listing 19. Automatyczne przekie-
ka na inną stronę bez jego wiedzy o tym tam obecnie. Funkcja header której uży- rowanie użytkownika
fakcie. Możesz na przykład za pomocą te- łem w tym skrypcie służy do wysyłania
go polecenia zrobić system zliczania ilości nagłówka dokumentu. Jest w niej użyty <?php
header('location:
pobierania pliku. Najpierw tworzysz stronę parametr location co oznacza, iż serwer
http://www.google.pl/');
na której dodajesz jeden do licznika po- ma przejść na odpowiednią stronę WWW.
?>
brań programu, a potem przekierowujesz Funkcja ta zadziała tylko wówczas gdy
użytkownika do pliku który chciał pobrać. zostanie ona wywołana na samym po-

Rozszerzenie plików
Bardzo często podczas przenoszenia pli- będziemy chcieli używać funkcji include()
ków na inny serwer możemy natknąć się należy zaimportować wcześniej przygoto- Listing 20. Plik z rozszerzeniem pli-
na błąd w ich rozszerzeniu. W większości wany kod. Później podczas włączania kodu ków PHP
serwerów jako pliki zawierające skrypty PHP z innych plików wystarczy tylko wyko- <?php
w języku PHP uznawane są pliki posia- rzystać zmienną $RozszerzeniePHP, która $RozszerzeniePHP = 'php';
dające rozszerzenia: .phtml, .php3, .php zawiera rozszerzenie obsługiwane na na- ?>
i .php5. Jeżeli będziemy budować stronę szym serwerze.
Listing 21. Włączanie pliku z roz-
najlepiej jest sobie zapisać rozszerzenie W ten sposób będziemy mogli przeno-
szerzeniem zawartym w zmiennej
plików w osobnym pliku, który będzie je sić nasze skrypty na dowolny serwer, na
przechowywał, gdyż na różnych serwe- którym rozszerzenie plików zawierających <?php
rach są obsługiwane różne rozszerzenia skrypt PHP jest zupełnie inne od zazwy- include('rozszerzenie.inc');
i pomoże to nam uniknąć błędu. Dla prze- czaj stosowanych. Wówczas wystarczy tyl- include('plik. '.$RozszerzeniePHP);
?>
chowywania rozszerzenia stwórz plik roz- ko pozmieniać rozszerzenia plików i war-
szerzenie.inc, w którym zapisz je w dowol- tość zmiennej w pliku rozszerzenie.inc, a
nej zmiennej. Następnie w pliku, w którym cały nasz skrypt będzie działał bez błędów.

PHP Solutions Nr 1/2007 www.phpsolmag.org 71


Narzędzia triki w php

Własne ustawienia w Arkusz styli CSS zależny od przeglądarki


pliku php.ini Różne przeglądarki różnie interpretują sty- nej $_SERVER['HTTP_USER_AGENT'] znaj-
Niewiele osób wie o fakcie iż mogą zmie- le CSS dołączone do naszych plików stron duje się odpowiedni opis przeglądarki.
niać ustawienia interpretera PHP bez po- sieci Web. Style CSS służą formatowaniu W zależności od tego jaka jest to prze-
trzeby uzyskiwania dostępu do panelu kon- stron WWW więc dobrze byłoby dobrać glądarka skrypt drukuje załączenie od-
figuracyjnego samego interpretera. W ten odpowiedni arkusz CSS dla odpowiedniej powiedniego arkusza styli. W przypadku,
sposób możesz sam ustawić sobie funkcje przeglądarki internetowej. gdyby przeglądarka nie została rozpozna-
z których chcesz korzystać. Opcje które W skrypcie tym PHP za pomocą funk- na wówczas wydrukuje domyślny arkusz
możesz ustawić za pomocą funkcji ini_ cji strstr sprawdzane jest, czy w zmien- styli dla strony.
set() są zdefiniowane na stronie: http://
pl2.php.net/manual/pl/ini.php#ini.list. Funk- Listing 25. Włączenie odpowiedniego arkusza w zależności od przeglądarki
cja ta zmieni ustawienia tylko lokalnie dla
<?php
danego skryptu. Natomiast cała reszta ele-
mentów na serwerze pozostanie przy stan- if ($name = strstr
dardowych ustawieniach. W przykładzie ($_SERVER['HTTP_USER_AGENT']
opcja magic_quotes_gpc została włączona. , 'Opera'))
Możesz także wyłączyć tą opcję przy uży- {

ciu składni, w której jako parametr podasz


?>
cyfrę 0. Tak samo możesz czynić z innymi
opcjami PHP, w pierwszym parametrze po- <link rel="stylesheet" href=
dajesz nazwę wartości którą chcesz zmie- "opera_stylesheet.css">
nić, natomiast w drugim parametrze poda-
<?php
jesz jej nową wartość. Ustawianie wartości
w php.ini za pomocą serwera Apache. }
W przypadku korzystania z serwe- elseif ($name = strstr
ra Apache możesz także ustawiać własne ($_SERVER['HTTP_USER_AGENT'],
wartości zmiennych konfiguracyjnych PHP. 'Firefox'))
{
Zrobisz to za pomocą pliku .htaccess. W pli-
ku tym deklarujesz miejsce gdzie chcesz ?>
zmienić zmienną. W naszym przypadku bę-
dzie to fragment konfiguracji pliku php.ini. <link rel="stylesheet" href=
Do tego celu używamy wartości php_value. "firefox_stylesheet.css">

Następnie po niej deklarujemy opcję któ-


<?php
rą mamy zamiar ustawić oraz podajemy
jej wartość. Niestety możliwość ustawia- }
nia opcji konfiguracyjnych występuje tylko elseif ($name = strstr ($_SERVER
na niektórych serwerach. Najczęściej są to ['HTTP_USER_AGENT'], 'MSIE'))
{
serwery płatne. Dlatego przed tworzeniem
pliku .htaccess należy napisać do nasze- ?>
go dostawcy usług czy możliwa jest zmiana
ustawień PHP właśnie w tym pliku. <link rel="stylesheet" href=
"ie_stylesheet.css">

Listing 22. Zmiana ustawień PHP <?php


<?php
ini_set('magic_quotes_gpc', '1'); }
?> else

Listing 23. Wyłączenie opcji w {


ustawieniach PHP
?>
<?php
ini_set('magic_quotes_gpc', '0'); <link rel="stylesheet" href=
?> "o_stylesheet.css">

Listing 24. Zmiana opcji konfigura- <?php


cyjnych za pomocą piku .htaccess
}
php_value
magic_quotes_gpc 1 ?>

72 www.phpsolmag.org PHP Solutions Nr 1/2007


Ciao GmbH
Ciao GmbH jest właścicielem wiodącego porta-

Prenumerata PRO
lu konsumenckiego w Europie – Ciao.com. Do
nowo powstałego centrum rozwoju oprogramo-
wania we Wrocławiu poszukujemy doświadczo-
nych programistów PHP. Chcesz dobrze zara-
biać, pracować w międzynarodowym środowi-
sku i w przyjaznej atmosferze – dołącz do nas.
www.ciao-group.com/careers_wroclaw.php

Agencja Interaktywna
– br-design.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-
Więcej informacji: patrycja.wadolowska@software.com.pl tel.: 022 887-13-45

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

protHOST
Rewelacyjny hosting o12 już od 49 zł netto/rok
(w tym cPanel PL). Rejestracja domen od 1 zł
netto. Webdesign i pozycjonowanie. Wszystko
czego potrzebujesz.
http://o12.pl

Hosting
Elastyczny dobór pakietów, pakiet POCZTA – 40
zł, pakiet START (www, email, 10 domen, php
5, mysql, pgsql) – 150 zł, pakiety KOMFORT,
PROFIT, PROFITSSL, zarządzanie przez cPanel.
Rejestracja domen globalnych, krajowych, funk-
cjonalnych i regionalnych. Ceny od 50 zł.
www: http://www.lubman.pl,
e-mail: biuro@lubman.pl,

Agnat Sp. z o.o.


Dostarcza pełen wachlarz usług związanych ze
stronami WWW. Serwis www.agnat.eu obsłu-
guje kilkanaście tysięcy Klientów z całej Polski
oraz Unii Europejskiej, wyposażając je w do-
meny internetowe, hosting, pozycjonowanie,
kreację stron WWW, kampanie reklamowo-pro-
mocyjne, oprogramowanie i aplikacje niezbędne
do prowadzenia biznesu w sieci.
Wywiad

Wywiad z Rafałem Mrzygłockim


– twórcą i pomysłodawcą
serwisu ILOGGO

Logotypy łatwo się kojarzy, otaczają nas


wszędzie dookoła, nie tylko w internecie.
Rafał wykorzystał to do stworzenia bramki,
która pozwala każdemu internaucie szybko
dotrzeć do tych miejsc w sieci, które odwiedza
najczęściej.
Rafał Mrzygłocki

Patrycja Wądołowska: Dlaczego zde- dowała o tym jakaś wyszukiwarka, która śmy ten serwis. Pracujemy już nad nowy-
cydował się Pan stworzyć taki serwis? zbiera po drodze wszystkie możliwe lin- mi funkcjami, które zapewnią użytkowni-
Rafał Mrzygłocki: Wszystko zaczę- ki. Po przeanalizowaniu wpadłem na po- kom jeszcze większą wygodę i usprawnią
ło się od mojej prywatnej strony starto- mysł, co pozwoli użytkownikom szyb- korzystanie z sieci.
wej, Zawsze miałem niesamowity bała- ko i łatwo dojść do wartościowych stron. PW: Jakich technologii użyto do stwo-
gan w bookmarkach. Dodawałem bardzo Dlatego oprócz siatki logotypów, powsta- rzenia serwisu? Zakładając, że będzie miał
dużo stron, próbowałem porządkować je ła także wyszukiwarka działająca wśród wielu użytkowników, musi działać bardzo
i grupować w katalogach, ale i tak znale- sprawdzonych i wartościowych stron użyt- wydajnie. Jakie zastosowano rozwiązania?
zienie później jakiejś informacji zajmowało kowników. Według mnie Internet to użyt- RM: U podstaw konstrukcji serwisu le-
mi sporo czasu. Żaden istniejący portal nie kownicy, to oni go tworzą i są najlepszym żały idee elastyczności i skalowalności.
oferował mi satysfakcjonującego rozwiąza- wyznacznikiem, które portale są warto- Poprzez te pojęcia rozumiemy możliwość
nia, dlatego pomyślałem o stworzeniu wła- ściowe i godne polecenia. szybkiej reakcji na zmieniające się potrze-
snej strony. Nie jestem programistą, ko- PW: Jaki jest dzienny przyrost użyt- by naszych użytkowników i klientów, w tym
rzystam jedynie z podstawowych aplikacji, kowników serwisu? często trudny do przewidzenia wzrost ich
dlatego zrobiłem prostą siatkę w HTML-u, RM: Po zaledwie kilku dniach od ofi- liczby. Zdecydowaliśmy się na rozwiązania
na której umieściłem logotypy ulubionych cjalnego startu każdego dnia w iloggo re- open-source nie tylko ze względów ekono-
stron. Z czasem pomysł podchwycili moi jestruje się około 100 nowych użytkowni- micznych, ale w dużej mierze ze względu
znajomi-coraz więcej osób prosiło mnie o ków. To dla nas informacja, że Internau- na możliwość kontroli ich działania. Uwa-
dodawanie kolejnych logotypów i ustawiało tom spodobała się idea serwisu. Najwięk- żamy ponadto, że w tej chwili naszą praw-
sobie siatkę jako stronę startową. szym zaskoczeniem jest dla nas szyb- dziwą siłą jest nie tylko sam publicznie do-
Podsunęło mi to pomysł na stworze- kość, z jaką rośnie katalog iloggo – każda stępny serwis, ale przede wszystkim zbiór
nie ogólnodostępnej siatki, którą każdy minuta to kilkanaście dodanych stron. sprawdzonych narzędzi i procesów, wspo-
użytkownik zdefiniuje, w sposób odpo- Chcemy, żeby iloggo rozwijało się i magających wytwarzanie oprogramowa-
wiadający jego potrzebom. Zainteresowa- zmieniało, dotrzymując kroku użytkowni- nia. Dzięki temu możemy nie koncentro-
ło mnie także to, że niektóre strony miały kom. W każdym miejscu i w każdej chwili wać się wyłącznie na problemach techno-
ogromną ilość użytkowników i odwiedzin, ma spełniać ich wymagania i odpowiadać logicznych, ale skutecznie rozwiązywać
a inne w ogóle. Wiedziałem, że nie decy- na ich potrzeby – po to właśnie stworzyli- nowe biznesowe wyzwania.

74 www.phpsolmag.org PHP Solutions Nr 1/2007


Wywiad

PW: Czy są prowadzone jakieś zabie-


gi marketingowe w celu zwiększenia po-
pularności serwisu? Jak to wygląda?
RM: Planujemy i realizujemy szereg
działań, które mają na celu spopularyzo-
wanie naszego serwisu i jego idei. Chce-
my pokazać jakie są zalety iloggo, dlacze-
go warto ustawić go jako stronę startową,
jak bardzo ułatwia korzystanie z ogrom-
nych zasobów Internetu. Szykujemy też
dla użytkowników niespodziankę…
PW: Google stworzyło podobny pro-
jekt do serwisu iloggo, tzw. Google Note-
book, czym iloggo różni się od tego pro-
jektu. Konkurencji jest cała masa. Być mo-
że jest jakiś pomysł, żeby iloggo przodo-
wało w tego typu projektach?
RM: Nie postrzegamy Google Note-
book jako bezpośredniej konkurencji, bo
jest to zupełnie inna usługa. To prawda, że
nie jesteśmy jedynym serwisem oferują-
cym możliwość stworzenia spersonalizowa-
nej strony startowej, ale to co nas odróżnia
to fakt, że użytkownik nie jest dla nas tylko
liczbą w statystykach ale osobą, która mo-
że współdecydować o kształcie serwisu. My
nie narzucamy żadnych rozwiązań uważa-
jąc, że wiemy czego potrzebują użytkowni-
cy. Szczegółowo analizujemy wszystkie na-
pływające do nas głosy, to one wyznaczają
linię rozwoju iloggo.
Myślę, że to jest naszą największą siłą.
PW: Jakie są plany, co do dalszego
rozwoju serwisu? Wspominał Pan, że ja-
kieś pomysły leżą gdzieś w szufladzie...
RM: Oczywiście pomysłów jest ca-
łe mnóstwo, jednak przed ich wprowa-
dzeniem chcemy je poselekcjonować, a
wcześniej usłyszeć, jakie propozycje ma-
ją użytkownicy. To oni najlepiej będą wie-
dzieli, czego im brakuje a jaką funkcjonal-
ność uważają za zbędną. Chcemy, aby
bezpośrednim motorem zmian w serwisie
były potrzeby użytkowników.
PW: Co może zachęcić internautów
do korzystania z serwisu iloggo?
RM: Iloggo to szybkość, łatwość i intu-
icyjność. To możliwość gromadzenia swo-
ich ulubionych stron, dzielenia się nimi ze
znajomymi, pozyskiwania nowych cieka-
wych informacji. Nasz serwis jest odpo-
wiedzią na realne potrzeby Internautów,
niezależnie od ich wieku czy stopnia zna-
jomości Internetu i obsługi komputera.
Jest odpowiedzią, na którą czekali bardzo
długo, zbyt długo.
PW: Dziękuję za rozmowę.

PHP Solutions Nr 1/2007 www.phpsolmag.org 75


Recenzje

PHP i MySQL. Tworzenie aplikacji WWW «««««


Autor: Marc Wandschneider

Jak sam autor pisze, książka oparta jest na jego doświadczeniach a do rozpoczęcia lektury potrzeba nam jest podstawowa zna-
jomość HTML’a. Programowania w PHP (w książce wykorzystano wersję 5 tego języka i nowe możliwości, jakie ze sobą niesie)
autor uczy nas od podstaw, więc nawet, jeśli PHP to nasz pierwszy język programowania to na pewno damy rade ogarnąć wie-
dzę wiedzę zawartą w podręczniku łącznie z technikami obiektowymi. Podobnie sytuacja ma się z bazami danych autor powie
nam wszystko, co powinniśmy wiedzieć o bazach danych i pokaże przykłady dla MySQL. Unikalną cechą tej książki jest cześć
poświęcona planowaniu aplikacji webowych dzięki temu początkujący deweloperzy nauczą się właściwego toku produkcji opro-
gramowania. Oczywiście przy okazji projektowania dowiemy się, czym jest logiczny podział aplikacji i jak go wykorzystać we wła-
snych projektach. Razem z rozdziałami o testowaniu (testy jednostkowe na przykładzie SimpleTest) i wdrażaniu aplikacji, kontroli
wersji (CVS) poznajemy tajniki tworzenia aplikacji na wysokim poziomie.
Znaczna część książki przeznaczona jest raczej dla początkujących. W związku z powyższym podczas omawiania SSL
dowiemy się o podstawowych zasadach działania internetu a nim przystąpimy do „zabawy” z dokumentami XML przy po-
mocy modelu DOM dowiemy się więcej o języku XML. Bardziej zaawansowanych i tych początkujących po lekturze
pierwszych rozdziałów książki na pewno zainteresuje opis debugowania i obsługi błędów a także dość dobrze opi-
sane aspekty tworzenia witryn międzynarodowych. Autor postanowił również opisać wyrażenia regularne, ale szko-
da, że ograniczył się jedynie do tych zgodnych ze standardem. Niemal każde zagadnienie jest połączone z pro-
stym, ale przydatnym przykładem i tak podczas omawiania Web Serwisów (Web Services) zbudujemy wyszukiwar-
kę używając Google API a zasady działania PEAR poznamy wykorzystując pakiet Date. Omówione zostały także
aspekty bezpieczeństwa dotyczące nie tylko samego kodu PHP, ale również całego środowiska działania aplikacji.
Co więcej autor wraca do tych kwestii przy okazji omawiania innych zagadnień - nie daje to zapomnieć o bezpie-
czeństwie. Całość wiedzy zawartej w książce można przećwiczyć na trzech kompletnych projektach – Blog, system
zarządzania terminami i sklep internetowy. Nie musimy tez martwić się, że książka szybko się rozleci, ponieważ po-
siada ona twarda oprawę a jej strony są zszywane.
Łukasz Witczak

PHP ALMANACH «««««


Autor: Paul Hudson

„Almanach PHP” to efekt kolejnej próby napisania podręcznika, w którym zawarte byłyby wszelkie aspekty programowania w
PHP – począwszy od historii języka i instalacji interpretera w różnych środowiskach, poprzez podstawy, po obiektowość PHP 5
oraz problemy związane z wydajnością skryptów i debugowaniem. Czy autorowi udało się zmieścić to wszystko na 382 stro-
nach? Zobaczmy. Lekturę każdej nowej pozycji związanej z technologiami webowymi zaczynam zwykle od sprawdzenia da-
ty jej wydania. W tej branży informacje szybko stają się nieaktualne, zatem szkoda mi czasu na lekturę książek „historycz-
nych”. Pierwsza edycja „Almanachu PHP” została wydana w oryginale (po angielsku) w roku 2005, zatem pierwsze kryte-
rium oceny książki można uznać za zaliczone.
Czas na ocenę treści. Książka napisana jest bardzo przystępnym językiem, którego zrozumienie nie powinno przyspo-
rzyć nikomu żadnych problemów. Wszystkie zagadnienia poparte są sensownymi przykładami. Co ważne, kod w przykła-
dach nie zawiera błędów, co nie jest niestety standardem w podręcznikach z dziedziny informatyki. W książce nie znajdzie-
my przykładów zaawansowanych rozwiązań, ani przepisu na budowę portalu – jest ona raczej przewodnikiem po
języku. Dodajmy, że przewodnikiem dość dokładnym, w którym nie pominięto takich zagadnień jak programowanie
zorientowane obiektowo, transformacje XML, czy obsługa wyjątków (jedna z nowości PHP 5). Zakres zagadnień
jest bardzo szeroki, niestety, ze względu na ograniczoną objętość książki, wiele z nich jest tylko zasygnalizowana i
wymaga dodatkowego przestudiowania w innych źródłach (chociażby w manualu: http://pl2.php.net/manual/pl/).
„Almanach PHP” z całą pewnością mogę polecić początkującym i średnio zaawansowanym miłośnikom języka
PHP. Ci pierwsi będą mogli zacząć swoją przygodę z językiem od nabycia dobrych nawyków programistycznych,
drudzy – zapoznać się ze zmianami i nowymi możliwościami wprowadzonymi w ostatnich wersjach PHP. Ważne,
by Almanach nie był jedyną pozycją w podręcznej biblioteczce. Opisuje on bardzo wiele zagadnień, ale też wiele z
nich jest opisana bardzo pobieżnie i wymaga samodzielnego zgłębienia.
Marcin Stefaniak
Felieton

Własne życie
Aleksander Cynarski

P
ojęcie potęgi informacji w naszych jest to, że tzw. nowoczesne zabawki nie rych możemy pobierać „na żywo” informacje
czasach jest już na tyle banalne są już na tyle drogie, że może sobie na nie – uważam, że może. Wystarczy tylko odro-
i powszechnie używane, że ge- pozwolić tylko mała grupa bogatych szcze- bina samo zaparcia, trochę czasu, no i oczy-
neralnie nie ma sensu o tym wspominać. niaków. Dzięki szybkiemu rozwojowi tech- wiście pomysł. Przecież te wszystkie obraz-
Ale.. no właśnie. Jak rozejrzymy się do- nologii jesteśmy w stanie przenieść do sie- ki, teksty i filmy dostępne on-line za pomocą
okoła najdzie nas myśl – integracja. ci właściwie całe swoje aktualne życie. coraz to bardziej zaawansowanych wyszuki-
Otoczeni komórkami, laptopami, cały Należę do tej grupy ludzi, którzy sie- warek tworzą już wiele nowych przestrzeni,
czas „w sieci” – mnie często aż korci, żeby dzą przed komputerem cały czas – praca, które możemy eksplorować tak samo jak uli-
przenieść tam swoją tożsamość. Wstęp- przyjemność – to jedno i to samo. Chcę jak ce nowo poznanych miast. Idąc dalej w roz-
nie pomysł nieco futurystyczny, ale czy tak największą część swojego realnego życia myślania nad ożywieniem naszego wirtual-
bardzo nie realny? Oczywiście nie mówię przenieść na informacje i publikować, publi- nego ja, możemy zastanowić się nad „per-
tu o wizjach filmowych, ale o czysto „in- kować ile się da. Wracając do przykładu z sonalizacją” nas dla innych. Wiem, że dziw-
formacyjnym przeniesieniu”. Większość z kawiarnią. Wyobraźcie sobie, że wasza ko- nie brzmi, ale już wyjaśniam o co mi cho-
nas posiada blogi, często bawimy się w mórka – a raczej palmofon, który kupiliście dzi. Otóż często spotykamy się z możliwo-
tzw. „social networking” (grono.net czy lin- na jednej z aukcji internetowych ma wbudo- ścią zmiany wyglądu strony, jej rozłożenia.
kedin.com) – piszemy tam o sobie, co ro- wany GPS oraz EDGE lub GPRS. Wysyła- Ale co w przypadku, jeżeli chcemy być dla
bimy, co chcielibyśmy robić. Nasza tożsa- my informację do naszego bloga obsługu- wszystkich „trendi” w realnym życiu nie je-
mość przechodzi ze świata realnego do jącego XMLRPC, w treści której jest nasza steśmy w stanie, ale „tam” możemy. Skoro
wirtualnego bardzo naturalnie. Gramy w aktualna pozycja. Wszystko mamy oczywi- można personalizować pojęcie „jak” to cze-
popularne ostatnio gry MMORPG. Często ście zintegrowane z frappr.com – pokazuje mu nie możemy zrobić tego samego z „co”.
nie zdajemy sobie sprawy, że aby kogoś gdzie jesteśmy. Jeżeli spotkanie jest na ty- Umieśćmy małą sondę przy wejściu na blo-
poznać wystarczy go po prostu poszukać le ciekawe, że nie chcemy aby ktokolwiek ga i już. Niech się pokazują tylko te wpisy
i to w dodatku bez wychodzenia z domu. nam przeszkadzał klikamy „do not disturb” które mogą pasować do proflu osoby oglą-
Współczesne systemy operacyjne, wszech- i już na blogu pokazuje się informacja – „je- dającej. Każdy z nas ogląda filmy science
obecne oprogramowanie publikujące da- stem tu i tu, ale nie radzę przeszkadzać”. fiction – częstym motywem w takowych, któ-
ne on-line, książki adresowe importowane Wszystko to mamy w zasięgu ręki, wystar- re traktują o innych cywilizacjach jest zbioro-
z telefonów i wędrujące gdzieś do baz da- czy ją tylko wyciągnąć. Najlepszą chyba wa świadomość. Umiejętność pewnej gru-
nych. Kalendarze, którymi możemy dzielić rzeczą we współczesnym świecie jest nie- py do swobodnej wymiany informacji. Czy
się ze znajomymi. Ciekaw jestem ilu z Was skończona możliwość tworzenia. Czy aby obecne formy publikowania w sieci, nie są
pozbawionych dostępu do sieci ma wraże- nie warto było by do tego naszego bloga namiastką? Owszem, że do generowania
nie, że czegoś brakuje – ten komputer jest dodać jeszcze informację o kamerach on-li- pełnego obrazu osobowości jeszcze mamy
taki nie pełny. Świat rzeczywisty i ten, w któ- ne znajdujących się najbliżej miejsca w któ- daleko, ale myślę – że to kwestia czasu, no i
rym żywo uczestniczymy w zaciszu własne- rym się znajdujemy, czy też ściągać dyna- oczywiście tego jak się rozwinie technologia,
go biurka są już ze sobą bardzo powiązane. micznie prognozy pogody. Zaś dodając no- w jakim kierunku pójdą producenci sprzętu
Czy można pójść dalej? Czy możemy jesz- we informacje wszystko to automatycznie i dostawcy usług. Ciekawe czy kiedyś du-
cze głębiej zanurzyć się w wirtualne morze trafia do grupy zainteresowanych osób, któ- że firmy ISP wejdą w spółki z firmami pro-
powiązanych informacji? re za pomocą jednego z wielu dostępnych dukującymi hardware i zaczną sprzedawać
Myślę, że tak. Wystarczy odrobina wy- mechanizmów dostają je na swoje małe nie tyle dostęp, co całe zintegrowane plat-
obraźni, łącze do internetu i parę elektro- przenośne zabaweczki w jakiejkolwiek for- formy działające całkowicie on-line. W do-
nicznych zabawek, które zabieramy ze so- mie. Wszystkie te informacje możemy do- mach będziemy mieli gniazda światłowodo-
bą nawet do kawiarni. Po co nasi znajomi, wolnie filtrować, przerabiać i modyfikować we do których będziemy podłączać stacjo-
mają dzwonić i pytać gdzie jesteśmy? Wy- w taki sposób, aby trafiały tam gdzie powin- narne lub przenośne terminale. Zaś całe na-
starczy, że wejdą na naszego bloga i zo- ny. Aktualnie dostępne technologie dyna- sze codzienne i wirtualne życie będzie odby-
baczą gdzie aktualnie spędzamy czas, czy micznej wymiany danych (Publish subscri- wać się jednocześnie. Technologie potrzeb-
mamy ochotę na to by ktoś się przyłączył, be) naprawdę dają wielkie możliwości. ne do wdrażania takich pomysłów już istnie-
czy też nie. Prawie wszystko możemy ak- Dzięki całej masie dynamicznie gene- ją, lecz niestety tak daleka integracja na ra-
tualnie przerobić na bity i wypuścić ich rowanych stron, blogów mogących się in- zie jest tylko fantastyczną wizją, przynajm-
strumień w globalną sieć. A najważniejsze tegrować, portalom tematycznym, z któ- niej jeżeli chodzi o problem skali. n

78 www.phpsolmag.org PHP Solutions Nr 1/2007


d e d s i t e s > > >
Recommen
Jeśli prowadzisz ciekawą stronę internetową
i chcesz abyśmy przedstawili ją w ramach akcji Recommended sites,
skontaktuj się z nami pod adresem redakcja@phpsolmag.org

Serwis poświęcony zagadnieniom związanym z


komputerami klasy PC, choć nie tylko. Prezen-
Dziennik Internautów – czyli gazeta dla użyt- towane są tam informacje związane z Open So-
kowników Internetu, to bogaty i dobrze zapla- urce i światem Internetu.
nowany serwis prezentujący informacje pogru- pcmaniak.pl
Serwis prezentujący prace kobiet, zajmujących powane w działy.
się zawodowo bądź dla własnej przyjemności www.di.com.pl
grafiką, webdesignem, rysunkiem, fotografią,
malarstwem, rzeźbą, itp.
womaninaction.net

Oficjalny serwis magazynu PHP Solutions.


Można stąd pobrać przykładowe artykuły, li-
Obszerny i bogaty w informacje serwis poświę- stingi z artykułów, skorzystać z forum, bądź za-
cony Sieci. Zawiera informacje dotyczące bez- poznać się z aktualnościami.
pieczeństwa, programowania, sieci bezprze- www.phpsolmag.org
Serwis poświęcony aktualnej, piątej wersji ję- wodowych i inne.
zyka PHP. Jego zwięzła i skromna forma nie www.webhat.pl
rozprasza i pozwala szybko odnaleźć szukane
informacje, które zawarto w serwisie.
www.php5.pl

Jeden z ważniejszych polskich portali dla we-


bmasterów i programistów PHP. Istnieje już cał-
Oficjalny serwis czytelników magazynu Softwa- kiem długo, co potwierdza zawartość zarówno
re Developer’s Journal. Często aktualizowany, serwisu jak i forum.
posiada wszystkie informacje przydatne czytel- webcity.pl
Oficjalny serwis magazynu Hakin9. Można nikom magazynu, ale nie tylko.
stąd pobrać darmowe artykuły, zapoznać się z www.software20.org
zawartością aktualnych i archiwalnych nume-
rów lub skorzystać z bogatego forum.
www.haking.pl

ites
Recommended s
Klub techniczny

Zend Platform 2
Rozszerzanie serwerowe
Zend Platform 2 jest cebulą w ofercie firmy Zend.
Każdy kto oglądał film Shrek wie o czym mówię
– chodzi o to, że cebula posiada warstwy. Platfor-
mę można zainstalować i zapomnieć o jej istnie-
niu, a i tak będziemy odczuwać pozytywne efek-
ty jej posiadania. Produkt można wykorzystać przy
samodzielnym tworzeniu i dostrajaniu aplikacji
webowych. Cały trik polega na tym, że bez żadne-
go problemu możemy odrzucić warstwy, które są
nam niepotrzebne do pracy i skupić się jedynie na
tych potrzebnych.
Czym więc jest Zend Platform 2? Oto odpo-
wiedź firmy Zend:
„Zend Platform jest solidnym, produkcyjnym
środowiskiem PHP, w którym aplikacje będą za-
wsze działać bez problemu.
Rozwiązanie dedykowane jest dla zastosowań
informatyczno-biznesowych, które wymagają nie-
zawodnych i stabilnych aplikacji osadzonych w śro-
dowisku klasy produkcyjnej. Zend Platform oferuje
wydajność i skalowalność. Rozwiązanie gwarantu-
je bardzo długi czas sprawności aplikacji oraz jej
niezawodność – wszystko to jest możliwe dzię-
ki zastosowaniu mechanizmów monitorowania
PHP oraz narzędzi wspomagających rozwiązywa-
nie problemów. Wymienione właściwości minima-
lizują ryzyko związane z diagnozowaniem błędów Rysunek 1. Rezultaty testów
i pozwalają uniknąć niedogodności związanych
z tym procesem. Reasumując, przy stosowaniu (bądź serwerach). Spróbujmy przekonać się jak stall.sh. Jeśli rzeczywiście tak jest, to należy wspo-
platformy Zend, zarówno Twój czas jak i zasoby fi- to wszystko jest możliwe. mniany plik uruchomić; można to zrobić komendą:
nansowe będziesz mógł w całości wykorzystać
na tworzenie pięknych aplikacji PHP, nie martwiąc ZACZYNAMY ./install
się problemami związanymi z ich uruchamianiem W momencie przygotowywania niniejszego tekstu
i utrzymywaniem.” opisywany produkt jest dostępny w postaci aplika- Skrypt instalacyjny powinien uruchomić graficz-
Ostatnie zdanie w opisie przedstawionym cji nieokienkowej. Do testowania platformy użyłem nego czarodzieja (ang. Wizard). Teraz wystar-
przez Zend na pierwszy rzut oka wydaje się za- dystrybucji Linux Debian. czy wykonywać po kolei instrukcje pojawiające
latywać napuszonym żargonem marketingowym, Na początku należy pobrać pakiet instalacyjny się na ekranie. Nie będę w tym miejscu zawierał
jednakże tak naprawdę w pełni oddaje istotę pro- Zend Platform 2. Pakiet ten, w postaci próbnej jest szczegółowego opisu całego procesu (złożone-
duktu. Mówiąc prosto, Zend Platform 2 to gru- dostępny za darmo na stronie domowej firmy Zend go z około 20 kroków) – opis taki można znaleźć
pa plików, które siedzą między silnikiem PHP (http://www.zend.com). Przed pobraniem paczki w wymienionym wcześniej przewodniku instala-
a skryptami PHP i powodują przyśpieszenie dzia- instalacyjnej trzeba mieć założone konto. cji. Chciałbym za to zwrócić uwagę na dwa istot-
łania skryptów, potrafią śledzić błędy, wykrywają Po ściągnięciu pakietu na serwer czas brać ne szczegóły:
potencjalne problemy i udostępniają śliczny inter- się za instalowanie produktu. Warto w tym miejscu
fejs webowy, który pozwala użytkownikowi moni- nadmienić, że na stronie Zend umieszczony jest • przy wybieraniu typu serwera wybrałem opcję
torować wszystko co dzieje się na jego serwerze bardzo dobry przewodnik instalacji, gdzie można Cluster Manager/Standalone. Użytkownicy ko-
znaleźć bardzo szczegółowe informacje na temat rzystający z pojedynczego serwera, lub insta-
całego procesu. Ten sam przewodnik jest umiesz- lujący pierwszy serwer w klastrze, muszą rów-
Ian Morse mieszka w Kanadzie – na Wyspie
czony w pobranym archiwum tar. Archiwum to na- nież wybrać tę opcję;
Księcia Edwarda; jest właścicielem i kierow-
nikiem firmy konsultingowej specjalizującej leży rozpakować korzystając z komendy gunzip -c • w trakcie instalacji otrzymujemy pytanie
się w technologiach webowych. Witrynę Iana <package name> | tar –xvf o pewne informacje systemowe; na przykład
można obejrzeć pod adresem: Aby rozpocząć instalację należy przejść do o lokalizację pliku php.ini, lokalizację kontrole-
http://www.geckoware.com katalogu utworzonego w trakcie rozpakowywania ra apache, wersję zainstalowanego silnika PHP
pakietu i sprawdzić czy znajduje się tam plik in- itd. Warto otworzyć przed instalacją dodatko-

80 www.phpsolmag.org PHP Solutions Nr 1/2007


Zend Platform 2 Klub techniczny

we okno terminala, dzięki czemu można póź- dla zabawy stworzyć oraz uruchomić skrypt in- Tabela 1. Zend Platform 2
niej łatwo sprawdzić te informacje. tensywnie korzystający z zasobów pamięciowych PHP: 4.3.9 i wyżej, 4.4.x, 5.0.x, 5.1
i zobaczyć co się stanie. Ja użyłem skryptu poka-
Wersja pro-
Po zakończeniu procesu instalacji użytkownik zanego na Listing 1. 2.1.2
duktu
otrzymuje podsumowanie, na którym widać czy Przedstawiony skrypt uruchomiłem dzie-
Linux/Unix, FreeBSD, Solaris,
wszystkie komponenty platformy zainstalowały sięć razy z włączonymi opcjami Code Accelera- O/S:
Mac OS X
się pomyślnie. Na tym kończy się pierwsza war- tion oraz Dynamic Content Caching, a następnie
stwa cebuli Zend Platform. Średnio zaawansowa- powtórzyłem tę czynność – tyle, że wspomnia- Pakiet darmowy w wersji
próbnej. W przypadku zaist-
ny użytkownik może w tym miejscu zakończyć ne opcje były wyłączone. Co ciekawe, w obydwu
nienia chęci stosowania plat-
interakcję z platformą i zacząć pracować ze swo- przypadkach wydajność była podobna. Może to Cennik:
formy w trybie komercyjnym
imi aplikacjami PHP. Użytkownik taki zauważy, że wydawać się zaskakujące, jednak należy zauwa- należy skontaktować się z fir-
wspomniane aplikacje działają teraz o wiele szyb- żyć, że rozważany skrypt nie jest przeznaczony mą Zend.
ciej i stabilniej – i to mu wystarczy. Bardziej za- do testowania obsługi żądań; został on zaprojek-
Adres w sieci: http://www.zend.com/
awansowani użytkownicy mogą uruchomić prze- towany w taki sposób, aby platforma mogła za-
glądarkę internetową i rozpocząć monitorowanie, reagować na potencjalnie niewłaściwy kod – co z moich Serwerów Pobierających (ang. Down-
testowanie i optymalizację swoich rozwiązań, cie- w rzeczywistości nastąpiło! load Server). Na podstawie zamieszonych tam
sząc się pełną gamą możliwości platformy. Jeśli przejdziemy teraz ponownie do zakład- informacji można się przekonać, że wyniki sta-
ki Zend Central to zauważymy, że zanotowano no- ją się coraz bardziej imponujące, proporcjonal-
ROZBIERANIE CEBULI we zdarzenie. Jeśli uruchomimy odpowiednio du- nie do zwiększania się częstotliwości występo-
Aby uzyskać dostęp do webowego interfejsu Zend żo odmiennych skryptów to zaobserwujemy, że wania równoległych żądań do serwera. Przy sto-
Platform 2 należy wpisać w przeglądarce URL okre- niektóre zdarzenia opisują błędy, zaś inne infor- sowaniu Zend Platform ponad połowa z 45 rów-
ślający miejsce instalacji środowiska. Domyślnie mują nas o tym, że kod wykonywany na skrypcie nolegle przychodzących żądań została obsłużo-
jest to: http://<nazwa serwera>/ZendPlatform jest zbyt wolny. Każdy wpis zawiera informacje na w czasie krótszym niż sekunda. Dla mniejszej
Na początku należy się zalogować (domyślna o czasie wykonania, o serwerze na którym docelo- liczby żądań wzrost wydajności wyraźnie spa-
nazwa użytkownika to Admin, hasło zaś definiuje- wy skrypt był uruchomiony oraz o URL, który wy- da, jednak rezultaty są i tak o wiele lepsze niż
my sami w trakcie procesu instalacji). Po pomyśl- wołał zadany skrypt. Informacje te to prawdziwa ko- w przypadku nie korzystania z platformy.
nym zakończeniu tego krok użytkownik jest powi- palnia złota – szczególnie jeśli mamy do czynienia Pozostałe benchmarki oferują testy wydaj-
tany i na wejściu otrzymuje podstawowe informa- z klastrem serwerów. nościowe, testy kompresji oraz testy skryptów.
cje systemowe. Przy pierwszym logowaniu inter- Po kliknięciu na wybrany wpis otrzymujemy We wszystkich tych przypadkach rezultaty są
fejs może wydawać się dość ubogi, jednak polecam nowe okienko typu pop-up, gdzie można znaleźć podobne: korzystając z Zend Platform otrzymu-
jeszcze bardziej szczegółowe informacje na temat jemy mniej więcej dwukrotną poprawę parame-
Listing 1. Skrypt użyty przy pierwszym logowaniu skryptu. Znajdziemy tu miedzy innymi szczegóło- trów będących przedmiotem testowania. Nale-
we zapisy na temat czasu wystąpienia usterki, dłu- ży pamiętać, iż twórcy platformy zaznaczają bar-
// testowanie przyśpieszenia kodu gości jej trwania oraz informacje o zmiennych prze- dzo mocno, że rezultaty testów będą miarodajne
$test_array1 = array(); kazanych do skryptu, a także o dołączonych przez w przypadku występowania odpowiednio wzmo-
$test_array2 = array(); niego plikach. Ukoronowaniem tych wszystkich żonego ruchu na serwerze webowym – takim,
// zapisywanie czasu początkowego testu udogodnień jest fakt, iż Zend Platform 2 integru- który odzwierciedla typowe obciążenie określo-
$start = time(); je się z Zend Studio dzięki czemu możemy z miej- nej witryny.
// sztuczne obciążenie serwera sca naprawiać błędy w kodzie. Dla użytkowników
for($i = 0; $i < 25000; $i++) { nie posiadających tego ostatniego pakietu przewi- PODSUMOWANIE
$test_array[$i] = rand(); dziano możliwość przeglądania kodu bezpośrednio Zend Platform 2 jest dobrze zaprojektowaną
} z przeglądarki. i wysoce wydajną warstwą serwerową, która po-
for($j = 0; $j < 25000; $j++) { Zend Platform 2 oferuje olbrzymią gamę wła- trafi przyśpieszyć i uczynić bardziej niezawod-
$test_array2[$j] = rand(); ściwości, o których można by pisać oddzielne, ną każdą niemalże aplikację PHP. Wydaje się,
} duże artykuły – warto tu wspomnieć chociażby iż każdy system jest w stanie skorzystać z za-
asort($test_array); mechanizm obsługi klastrów serwerowych oraz let wynikających ze stosowania platformy, jed-
asort($test_array2); pomost integracyjny dla platformy Java (ang. nakże najwięcej korzyści czerpać tu będą nie-
$test_array3 = array_merge($test_array, Java Integration Bridge), który (według zapew- wątpliwie witryny pracujące pod bardzo dużym
$test_array2); nień umieszczonych na witrynie Zend) pozwala obciążeniem. Rozwiązanie jest wręcz nieodzow-
asort($test_array3); firmom inwestującym w serwery aplikacji oparte ne dla podmiotów, które nie mogą inwestować
// zapisywanie czasu końcowego testu na platformie J2EE korzystać z zalet PHP. Oczy- w nową infrastrukturę sprzętową i są zmuszone
$end = time(); wiście wszystkie te stwierdzenia muszą mieć do wyciskania wszystkiego co najlepsze z posia-
// obliczanie różnicy czasów pokrycie w konkretnych benchmarkach. Mnie in- danych zasobów. Zend Platform 2 jest również
$difference = $end - $start; teresują konkretne liczby. Jak dobra jest tak na- bardzo przydatne w sytuacji kiedy monitorowa-
// wyświetlenie wyników prawdę platforma Zend? Łatwo to sprawdzić, ja- nie serwera przy pomocy ogólnodostępnych na-
echo "Start: ".$start; ko że benchmark testujący jest wbudowany bez- rzędzi staje się zbyt uciążliwe. Wzrost wydajno-
echo "<br />End: ".$end; pośrednio w system – można go znaleźć pod za- ści, który pociąga za sobą stosowanie platformy
echo "<br />Difference: ".$difference; kładką Performance. Na Rysunku 1 przedstawi- jest ewidentnie znaczący.
łem rezultaty testów wykonanych dla jednego

PHP Solutions Nr 1/2007 www.phpsolmag.org 81


W następnym numerze PHP Solutions 2/2007 (19)

W sprzedaży od lutego

ROZWIĄZANIA
UWAGA KOLEJNY TEST KONSUMENCKI
n Prototype z PHP
Pokażemy, jak budować nowatorskie systemy
n Relokacje serwerów
rankingowe w oparciu o bibliotekę script.aculo.us

n PHP-GTK2 w praktyce NOWE ARTYKUŁY W DZIAŁACH:


stworzymy GUI bazy danych dla naszych klientów wykorzystując
nowe możliwości PHP-GTK2 n dla początkujących

n dla zaawansowanych
NARZĘDZIA
n narzędzia
n eZ publish jako Mulisite CMS
jedna instalacja wiele stron.

n Konfiguracja eZ publish, Apache, etc.

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

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

You might also like