PHP Solutions 01 2007 PL

84

description

* Tworzymy aplikacje okienkowe z PHP-Qt* PunBB-nowoczesne forum dyskusyjne* Xajax – łatwy AJAX* Budowanie obiektów z requestu przy pomocy Reflection API* Warstwowy model aplikacji* LIZ DB – zaawansowane możliwości bazy MySQL5* Wielojęzyczna konfiguracja stron z użyciem eZ publish* Testy konsumenckie firm hostingowych* TRIKI W PHP* Rozmowa z Rafałem Mrzygłockim – twórcą i pomysłodawcą serwisu ILOGGO.* Zend Platform 2

Transcript of PHP Solutions 01 2007 PL

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

Spis treści

www.phpsolmag.org4 PHP Solutions Nr 1/2007

Spis treści

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

AKTUALNOŚCI 6

Krzysztof Trynkiewicz

OPIS CD 10

Patrycja Wądołowska

DLA POCZĄTKUJĄCYCHTworzymy aplikacje okienkowez PHP-Qt 12

Thomas Moenicke

Thomas wskazuje jak pisać w PHP programy ko-rzystając z Qt na przykładzie kalkulatora. Obja-śnia również podstawowe zagadnienia związane z Qt-kolejnym standardem GUI, na którym opie-ra się m.in. KDE

PROJEKTY

PunBB-nowoczesne forum dyskusyjne 18

Piotr Maliński

Piotr uczy sztuki integrowania punBB z ze-wnetrznymi skryptami. Obrazuje również migra-cje danych z innych skryptów forum.

DLA ZAAWANSOWANYCHXajax – łatwy AJAX 24

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.

Budowanie obiektów z requestu przy pomocy Reflection API 34

Piotr Szarwas

Reflection API to zestaw klas i funkcji, przy po-mocy których programista może zdobyć infor-mację o budowie dowolnej klasy, obiektu lub 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.

francuskimpolskim

Nasz magazyn ukazuje się w dwóch językach!

Jeśli jesteś zainteresowany zakupem licencji na wydawanie naszych pism prosimy o kontakt:Monika Godlewska [email protected] tel.: 48 22 887 12 66, fax: 48 22 887 10 11

Patrycja Wądoł[email protected]

Redakcja 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-ry Extra o Xoops, eZpublish, Typo3 i Mambo!

Chcielibyśmy również, abyście Drodzy Czytelnicy mieli jeszcze większy udział w tworzeniu pisma, które jest dla Was. Planujemy jesz-cze więcej testów konsumenckich. Na pewno bedziemy zwracać się do Was z prośbą o opinię jako konsumentów. W nastepnym numerze po-dejmiemy temat relokacji serwerów. Piszcie do nas!

Możliwe, że w huku strzelających fajerwerków przyjdą Wam do gło-wy pomysły na felietony, bądź też wśród noworcznych postanowień 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ć!

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 jako betatesterzy!

Wreszcie, jeśli pragniecie, aby na twarzy bliskiej Wam osoby uśmiech gościł nie tylko w czasie otwierania prezentu gwiazdkowe-go, ale przez cały rok, zprezentujcie jej prenumeratę roczną magazy-nu PHP Solutions, a my dołożymy wszelkich starań, żeby każdy numer 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-le pomyślności oraz radości z każdego numeru magazynu PHP Solu-tions.

Będziemy z Wami przez cały rok!

Page 5: PHP Solutions 01 2007 PL

Spis treści

www.phpsolmag.org4 PHP Solutions Nr 1/2007

Spis treści

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

NARZĘDZIALIZ DB – zaawansowane możliwości bazy MySQL5 44

Łukasz Budnik

Łukasz wskzuje jak sprawnie pisać programy bazodanowe począwszy od prostych zapytań a skończywszy na wywołaniach procedur składo-wanych dzięki LIZ DB, które jest narzędziem na-pisanym w PHP5.

Wielojęzyczna konfiguracja stronz użyciem eZ publish 52

Łukasz Serwatka

Łukasz ilustruje jak zainstalować eZ publish z obsługa kilku języków, zmieniać ustawienia i konfigurację systemu pod kątemj wielujezyków. Opisuje też tworzenie własnych rozszerzeń ję-zykowych dla eZ publish.

TESTY KONSUMENCKIETesty konsumenckie firm hostingowych 60

Opinie klientów firm NetArt i Miracle Systems.

TRIKI W PHP 68

Łukasz Sosna

WYWIAD 74

Patrycja Wądołowska

Rozmowa z Rafałem Mrzygłockim – twórcą i po-mysłodawcą serwisu ILOGGO.

RECENZJE 76

Łukasz Witczak, Marcin Stefaniak

FELIETON Własne życie 78

Aleksander Cynarski

KLUB TECHNICZNYZend Platform 2 80

Ian Morse

Ian przedstawia Zend Platform 2 – dobrze za-projektowaną i wysoce wydajną warstwę ser-werową.

ZAPOWIEDZI 82

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

Listingi wszystkich opisywanych programów zostały zamieszczone na naszej stronieinternetowej www.phpsolmag.org/pl.

Pytania dotycząceprenumeratytel. (22) 887 14 44e-mail: [email protected] Wydawnictwo Sp. z o.o.dział prenumeratyul. Bokserska 102-682 Warszawa

CDtel. (22) 887 14 44e-mail: [email protected] Wydawnictwo Sp. z o.o.Defekty CD/DVDul. Bokserska 102-682 Warszawa

Zamówienia /Numery archiwalnetel. (22) 887 14 44e-mail: [email protected] on-line: www.shop.software.com.pl

Kontakt z redakcjąe-mail: [email protected] Wydawnictwo Sp. z o.o.Redakcja PHP Solutionsul. Bokserska 102-682 Warszawa

Strona WWW/Forumstrona www: www.phpsolmag.orgTu znajdą Państwo informacjedotyczące aktualnych i przyszłychnumerów magazynu PHP Solutions.

Forum: www.phpsolmag.org/newforumZachęcamy do dyskusji na naszymforum. Czekamy na propozycjetematów, które chcieliby Państwoznaleźć w najbliższym numerze pisma. Zapraszamy także do wymianypoglądów z innymi fanami PHP.

Cena Prenumerata: 135 złPrzelew na konto nr:46 1440 1299 0000 0000 0391 8238 Nordea Bank Polska S.A.II Oddział w Warszawie

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

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

Kierownik produkcji: Marta Kurpiewska [email protected] okładki: Agnieszka MarchockaSkład i łamanie: Sławomir Zadrożny [email protected]

Stali współpracownicy: Krzysztof Trynkiewicz [email protected]

Dział reklamy: [email protected]: Marzena Dmowska [email protected]ład: 6 000 egz.

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

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

Redakcja dokłada wszelkich starań, by publikowane w piśmie i na towarzyszących mu nośnikach informacjei programy były poprawne, jednakże nie bierze odpowiedzialności za efekty wykorzystania ich; nie gwarantujetakże poprawnego działania programów shareware, freeware i public domain.Uszkodzone podczas wysyłki płyty wymienia redakcja.Wszystkie znaki firmowe zawarte w piśmie są własnością odpowiednich firmi zostały użyte wyłącznie w celach informacyjnych.

Redakcja używa systemu automatycznego składu Do tworzenia wykresów i diagramów wykorzystano program firmy

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

Druk: ArtDruk

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

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

Page 6: PHP Solutions 01 2007 PL

Aktualności

PHP Solutions Nr 1/2007www.phpsolmag.org6

Konferencja phptech 2007Wielkimi krokami zbliża się jedna z największych 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-nad 35 prezentacji. Wstęp na konferencję kosz-tuje wprawdzie aż 700 USD, jednak z pewno-ścią warto poświęcić trochę pieniędzy choć raz w roku, by otrzymać świeżą porcję nowinek ze świata PHP prosto od największych wybitności z nim związanych. Bilety na poprzednią edycję zostały w pełni wyprzedane już na miesiąc przed konferencją, toteż rejestrować się na obecną można już teraz. Organizatorzy zapowiadają du-żą ilość prezentacji typu BYOL (ang. Bring Your Own Laptop), podczas których widownia będzie mogła pisać kod wraz z prelegentem i testować go na udostępnionym, oficjalnym serwerze kon-ferencyjnym. Materiały prezentacyjne zostaną opublikowane na stronie konferencji, jeśli więc nie mamy czasu lub pieniędzy, wciąż możemy poznać szczegółową treść wykładów.http://hades.phparch.com/ceres/public/tek

Konferencja PHP w VancouverMniejsza konferencja będzie natomiast mia-ła miejsce w Vancouver między 12, a 14 lu-tego 2007. Organizatorzy zapowiadają wie-le wybitności, które zaprezentują wczesne wer-sje wykładów przygotowanych na konferen-cję php|tech. Cena wstępu nie została jeszcze ustalona, jednak powinna być dużo niższa, niż w poprzednim przypadku. Szczegóły na temat tej konferencji są podawane na bieżąco na stro-nie jej organizatorów.http://vancouver.php.net

Kobiety w PHP? Jak najbardziej!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-nej głównie dla płci pięknej, deweloperzy PHP ze zdumieniem odkryli, że kobiet w tym świat-ku nie brakuje. Autorki projektu zostały podda-ne wywiadowi, który teraz możemy przeczytać na stronie głównej projektu. Jeśli interesuje nas trochę świeższe podejście do programowania i mamy ochotę przeczytać ciekawy wywiad, warto odwiedzić adres http://www.phpwomen.org/wordpress/2006/10/22/interview-with-founding-women/, jednak główną siłą organizacji pozostaje forum, dostępne pod adresem http://www.phpwomen.org/forum/http://www.phpwomen.org

Horda naciera na PHPNa popularności zyskuje ostatnio projekt o intry-gującej nazwie Horde. Jego podstawą jest fra-mework o takiej samej nazwie, natomiast ilość modułów na nim zbudowanych jest godna po-dziwu. Mamy więc do wyboru książki adresowe, notatnik, harmonogram, menedżer plików oraz klasy np. do sprawdzania i filtrowania e-ma-ili, generujące kod oparty o technologię AJAX. Projekt rozwija się dość prężnie, średnio co miesiąc publikowana jest nowa wersja frame-worka, wnosząca istotne modyfikacje. Całość udostępniana jest na licencji GNU LGPL.http://www.horde.org

Łączymy PHP i ColdFusionFusebox to framework oparty o architekturę MVC, mający na celu połączenie aplikacji PHPi ColdFusion. Jak zachwalają autorzy, jego głównym atutem jest szybkość wykonywania kodu. Framework jest udostępniany na darmo-wej licencji i z pewnością przypadnie do gustu deweloperom, którzy znają już ColdFusion, lecz potrzebują możliwości oferowanych przez PHP.http://www.fusebox.org

Recepty dla deweloperów PHP-GTK2

W poprzednim numerze informo-waliśmy o zbliżeniu się poziomu

ukończenia dokumentacji PHP-GTK2 do 50%. Już teraz jednak można w In-ternecie znaleźć zapiski wielu osób na temat tworzenia aplikacji tym narzę-dziem. Wyzwaniem jest jednak, by na-pisać aplikację w pełni wykorzystują-cą nie do końca jeszcze opisane funk-cje. Przed podobnym problemem sta-nął autor php-gtk2 CookBook. Sam do-szedł do wielu istotnych wniosków, ze-brał wiadomości z wielu blogów, wyse-lekcjonował i skatalogował.

Rezultatem jest zbiór ponad 100 prak-tycznych porad, przydatnych przy two-rzeniu aplikacji w PHP-GTK2. Wszystkieodpowiedzi na najczęściej zadawanepytania są opatrzone zrzutami ekranów, a przeglądać je możemy używając wy-szukiwarki (strona jest świetnie zindek-sowana przez Google), według tematyki, lub określonego widgetu. Początkujący programiści znajdą tu informacje pomoc-

ne przy instalacji PHP-GTK2 na systemie Linux oraz Windows, a także linki do list dyskusyjnych, for, i blogów ludzi związa-nych z tym rozszerzeniem PHP. Na witry-nie projektu znajdziemy ponadto przykła-dowe aplikacje, manual i turoriale. Strona ta stanowi repozytorium najważniejszych informacji o PHP-GTK2, jest to pierwszy przystanek dla wszystkich wielbicieli tego typu aplikacji okienkowych.

http://www.kksou.com

HotScripts – największa skryptoteka PHP

Większość deweloperów PHP jeśli nie odwiedziła, to przynajmniej sły-

szała o HotScripts. Praktycznie każda apli-kacja napisana w tym języku (chociaż nie tylko – HotScripts kataloguje także aplika-cje Flash, ASP i wiele innych) trafia do te-go repozytorium. Tym samym, na witrynie http://hotscripts.com znajdziemy ponad 11 000 skatalogowanych aplikacji PHP. Każ-da z nich opatrzona jest opisem, przydzie-lona do odpowiednich kategorii. Podana jest także jej licencja (oraz, ewentualnie, cena) wraz z odnośnikiem do strony pro-jektu. Ogrom tych informacji pozwala na sprawne wyszukanie żądanego skryptu w jednej z wielu kategorii: systemy blogowe, CMSy, chaty, organizery plików muzycz-nych, fora, ankiety, liczniki, galerie... Łącz-

nie mamy do wyboru blisko 100 kategorii! Na tym jednak potęga HotScripts się nie kończy. Serwis ten oferuje także recenzje oraz download ponad 50 książek i 45 arty-kułów związanych z PHP, linkuje do ponad 100 stron skupiających społeczność PHP, zawiera informacje o 150 programach po-mocnych przy pisaniu kodu, popartych po-nad tysiącem tutoriali, listą 35 agencji fre-elancingowych, a wreszcie: linkami do 450 innych stron związanych z PHP. Na-leży więc pamiętać, że skryptorium, to je-dynie mała część serwisu HotScripts. Od-wiedzając witrynę, pamiętajmy, by i nasze dzieło umieścić w największym repozyto-rium skryptowym świata!

http://hotscripts.com

Page 7: PHP Solutions 01 2007 PL

Aktualności

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

PHP od podstawNiektórzy z nas na pewno dopiero zaczyna-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://www.w3schools.com), specjalizujące się w pisaniu elektronicznych podręczników na te-maty związane z Internetem, udostępniło bar-dzo dobry projekt, skierowany na początkują-cych użytkowników, a traktujący o PHP. Pod-ręcznik ten można traktować jak poszerzenie manuala PHP. Znajdziemy tu więc opisy pę-tli i instrukcji warunkowych, ale też przykłady tworzenia systemu uploadu plików na serwer, objaśnienia na temat połączeń PHP z różny-mi typami baz danych, czy parsowania plików XML. Całość napisana jest przystępnym języ-kiem. Dodatkowo, na stronie W3Schools znaj-dziemy kilka innych ciekawych pozycji pod-ręcznikowych oraz propozycje hostingów, po-rady na temat tworzenia stron i różnego ty-pu statystyki.http://www.w3schools.com/php/default.asp

Szukamy gotowców, czyli skryptoria PHPKażdy deweloper PHP musi czasami się-gnąć po kawałki cudzego kodu. Czy to w ce-lach edukacyjnych, by oszczędzić czas, lub z braku pomysłu, szukamy gotowych rozwią-zań często pojawiających się problemów. Do-tychczas, w kategorii skryptoriów, niewzrusze-nie królował serwis HotScripts (http://www.hot-scripts.com), mający w swoim repozytorium ponad 10 000 skatalogowanych aplikacji PHP. Na rynek profesjonalnych repozytoriów wkro-czył jednak konkurent – ScriptSearch. W swo-ich zasobach posiada on już ponad 2 000 aplikacji, a dodatkowo na witrynie projektu znajdziemy zbiór artykułów, tutoriali i linków związanych z PHP.http://www.scriptsearch.com/PHP

php directoryPHP Directory to projekt, w założeniu które-go jest skatalogowanie najistotniejszych linków powiązanych z tym językiem. W tym repozyto-rium znajdziemy informacje o grupach dysku-syjnych, artykułach, pismach, newsach, aplika-cjach IDE, konferencjach, publikacjach i wie-lu innych zagadnieniach kluczowych dla dewe-loperów PHP. Stąd trafimy też na blogi wybit-ności ze światka PHP. Chociaż PHP Directo-ry dopiero się rozwija, już teraz stanowi dosko-nały zbiór linków dla głodnego informacji pro-gramisty.http://www.phpdirectory.com

Miniaturki w PHP z phpThumb()phpThumb() to rozwinięty skrypt, generujący miniaturki. Wynikowy obrazek może być więk-szy lub mniejszy od oryginału. Obróbce może zostać poddana całość grafiki lub jej fragment. Dodane mogą zostać tło i obramowanie. Źró-dłowy plik może być na serwerze zdalnym, lo-kalnym, lub w bazie danych. Tworzenie obra-zów GIF jest możliwe z lub bez biblioteki GD. Podobnie sprawa ma się z formatem BMP i bi-blioteką ImageMagick. W przypadku posiadania zainstalowanej wersji tej ostatniej, możliwa jest generacja obrazu w każdym przez nią obsłu-giwanym formacie. Poza tymi formatami, ma-my do wyboru PNG, JPEG i ICO. Dodatkowo, autor udostępnił wiele przydatnych filtrów (roz-mycie, cień, zaokrąglanie krawędzi, wyostrza-nie, poziom kontrastu, sephia, negatyw itd.) oraz funkcję cachingu. Wygenerowane obrazy, zgodne ze standardem EXIF, mogą być zapisy-wane, eksportowane, bądź użyte bezpośrednio w innych aplikacjach.http://freshmeat.net/projects/phpthumb

Gdzie szukać pomocy?

Już kilka numerów temu wspomi-naliśmy o forum SitePoint (http://

sitepoint.com), jako doskonałym miejscu na poznanie ciekawych ludzi, ich pomy-słów, a nade wszystko: znalezieniu solu-cji na dręczące nas problemy związane z PHP. Forum to, choć ma aż 141 tysięcy użytkowników, traktuje o wielu aspektach Internetu, tworzenia stron i ich marketin-gu. Jeśli trudno nam znaleźć tam rozwią-zanie naszego problemu, możemy spró-bować na forach ukierunkowanych ści-ślej na PHP. Naszym pierwszym przy-stankiem może być forum PHP Editors (http://www.php-editors.com), mające bli-sko 10 tysięcy zarejestrowanych progra-mistów PHP. Jeśli nie powiedzie nam się i tam, lub zależy nam na czasie, warto tak-że zadać pytanie na PHP Developers Ne-twork (http://forums.devnetwork.net) mają-cym 25 000 użytkowników oraz na Coding Forums (http://www.codingforums.com) z bazą blisko 50 000 użytkowników. W przy-padku, gdy niezbędna jest natychmiasto-wa pomoc, powinniśmy skierować się na jeden z serwerów sieci IRC, np. EFNet, odwiedzając kanał #php. W każdym z po-wyższych przypadków, przyda się tzw. pa-

ste-bin, czyli miejsce, w które możemy wkleić nasz kod PHP, nie narażając się na oskarżenia o zapychanie kanału bądź wąt-ku na forum. Dodatkowo, wklejając kod do takiego systemu, umożliwiamy innym jego edycję, a składnia jest odpowiednio wcię-ta i pokolorowana, my zaś otrzymujemy łatwy do rozpowszechnienia link z kodem źródłowym. W Internecie znajdziemy wie-le skryptów typu paste-bin, my polecamy ten z http://www.phpriot.com/resources/phpaste/.

http://www.phpriot.com/resources/phpaste/http://www.sitepoint.com/forumshttp://www.php-editors.com/forumshttp://forums.devnetwork.nethttp://www.codingforums.com

php Interactive

Czy nie często spotykamy się z pro-stymi problemami, których rozwiąza-

nia nie jesteśmy całkowicie pewni, mimo, że zawiera ono ledwie kilkanaście linijek kodu? Napisanie tego kodu nie stano-wi problemu, ale czas potrzebny na po-łączenie się z serwerem, upload plików i ich egzekucja w przeglądarce to zbęd-ne sekundy, które odrywają nas od głów-nego toku myślenia przy programowaniu większej aplikacji. Z pomocą przychodzi php Interactive, umożliwiający wykonanie kodu PHP bezpośrednio z poziomu prze-glądarki. Po instalacji pakietu, wystarczy wejść na nasz ustalony adres, by ujrzeć stronę, na którą możemy wkleić nasz kod PHP. Rezultat jego działania otrzy-mamy po naciśnięciu jednego przycisku. Ponieważ często zdarza się, że kod PHP zwraca tekst zamknięty w znaczniki, de-weloperzy projektu php Interactive udo-stępnili dwie możliwości podejrzenia wy-ników wykonania kodu (ang. output): czy-sty tekst (RAW), lub tekst sformatowany (HTML). Dodatkowo, do naszej dyspo-zycji zostały oddane specjalne zakładki (ang. tabs), każda z nich działa jak osob-

no wywołana sesja skryptu. Dzięki takie-mu rozwiązaniu, w jednym oknie prze-glądarki możemy sprawdzić kilka warian-tów naszego kodu. Każdej zakładce mo-żemy nadać unikalną nazwę. Interfejs php Interactive zawiera także podręczną wyszukiwarkę, podobną do tej z http://php.net, która niejednokrotnie przyda się w razie otrzymywania nieoczekiwanych wyników. Skrypt do działania nie wyma-ga żadnego dodatkowego oprogramo-wania (np. bazy danych), chociaż kata-log z nim warto zabezpieczyć przed pu-blicznym dostępem. Projekt jest udostęp-niany na zasadach określonych w licen-cji GNU GPL.

Licencja: GNU GPL.http://www.hping.org/phpinteractive

Page 8: PHP Solutions 01 2007 PL

Aktualności

PHP Solutions Nr 1/2007www.phpsolmag.org8

Alternatywa dla Planet PHPW poprzednim numerze pisaliśmy o centrum aktualności ze świata PHP, jakim jest Planet PHP (http://www.planet-php.org/). PHP Develo-per to podobny projekt, agregujący informacje z wielu źródeł (także blogów). Jego przewagą jest niewątpliwie popularny tag-cloud, który ob-razuje i ułatwia wyszukiwanie najciekawszych wiadomości. Dodatkowo, na stronie PHP Deve-loper znajdziemy odnośniki do ciekawych arty-kułów o PHP, tutoriali oraz informacje o nadcho-dzących wydarzeniach i konferencjach.Licencja: BSD.http://www.phpdeveloper.org

Generator wątków RSSRSS Writer Class to skrypt, umożliwiający pro-stą generację plików XML w standardzie RSS 0.9, 0.91, 1.0 i 2.0. Pozwala na dodawanie opcjonalnych znaczników graficznych, zaś udo-stępniany jest na licencji BSD. Dodatkowo, do pakietu dołączony został szablon XSL, by uła-twić podglądanie wyników jako stron HTML w przeglądarkach obsługujących XML.http://freshmeat.net/projects/rsswriterclass

Świetny generator plików PDFCPDFWriter to klasa napisana w PHP5, służą-ca do generacji plików PDF, a oparta na projek-tach TCPDF i FPDF. Do zasobów możemy do-dać grafiki (GIF, JPG, PNG), elipsy, efekty prze-zroczystości, wypełnienia (także graficzne-go i gradientowego) i wiele innych, dzięki cze-mu tworzone arkusze wyglądają na prawdę im-ponująco. Kolejną zaletą klasy jest jej licencja – GNU LGPL.http://freshmeat.net/projects/cpdfwriterhttp://www.palos.ro/index.php?page=opensource_active

Manipulacja archiwaliów z poziomu PHPAutor powyższego projektu stworzył także roz-szerzenie do PHP5, ułatwiające edycję archi-waliów ZIP, TAR, GZ, BZ2, BZ, TGZ, TBZ. Mo-ż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-ści może odbywać się na dysku lokalnym lub w pamięci. Dodatkowo, dla bardzo szybkiej kom-presji, do pakietu włączono funkcje kompresji i dekompresji algorytmu LZF, które działają w pa-mięci operacyjnej komputera. psArchive zawie-ra także obszerną dokumentację.http://www.palos.ro/index.php?page=opensource_active

Nowa biblioteka Flashowa SDK dla PHPFreeMovie to projekt mający być alternatywą dla SDK Macromedii, oferujący potężne API dla operacji na plikach SWF. Głównymi atutami bi-blioteki są: konwersja czcionek TrueType do fil-mów Flash, obsługa wielu formatów graficznych oraz zaawansowane funkcje do rysowania, operowania na dźwięku oraz animacjach. Pa-kiet jest rozpowszechniany na licencji XFree86, która pozwala na używanie go za darmo nawet w komercyjnych projektach.http://freemovie.sourceforge.net

PHP Shell TerminalJeśli nie odpowiada nam aplikacja PHP Shell, szerzej opisywana w tym wydaniu aktualności, ale podoba nam się sama idea, możemy się-gnąć po konkurencję. PHP Shell Terminal swo-im wyglądem ma na celu upodobnienie się do KDE, zaś jego funkcjonalność jest zbliżona do wspomnianego wcześniej skryptu.Licencja: GPL.http://sourceforge.net/projects/phpterm

Shell w PHP

Wszyscy znamy procedury instalacji większości nowych skryptów PHP:

autorzy radzą nam pobrać archiwa za po-mocą aplikacji wget, rozpakować je i roz-począć instalację i konfigurację z poziomu przeglądarki. Pierwsze dwa zadania wy-konujemy zazwyczaj przez shell (opcjo-nalnie ftp), jednak nie zawsze przecież mamy czas i sposobność, by z niego sko-rzystać (choćby z powodu blokady odpo-wiednich portów). Z pomocą przychodzi PHP Shell – skrypt, umożliwiający wy-konywanie poleceń przez interfejs www, a skierowanych bezpośrednio do powło-ki systemu operacyjnego, na którym pra-cuje serwer http. Sam autor określa go ja-ko odpowiednik połączenia telnet z lek-ką dawką SSH. By uruchomić aplikację, wystarczy wgrać pliki na serwer (nie za-pominając o zmianie loginu oraz hasła!) i przejść pod odpowiedni adres. Powita nas raczej skromne okienko, do którego możemy wpisać różne przydatne komen-dy, np. ls, free, df, du i wiele innych. PHP Shell ma jednak pewne ograniczenia: nie uda nam się uruchomić w nim żadnej apli-kacji graficznej, ani wprowadzić treści do tych już uruchomionych.

Kod skryptu został napisany pod PHP4 i działa jedynie z wyłączonym try-bem Safe Mode. W przypadku próby uru-

chomienia skryptu pod PHP5, mogą wy-stąpić problemy z autentykacją – kilka so-lucji tego problemu można znaleźć w In-ternecie. PHP Shell doskonale sprawdza się w manipulacji dużymi zbiorami plików i szybkiego rozpakowywania archiwaliów. Efekty wykonywanych poleceń zostają zwracane do naszego okienka – dotyczy to także błędów. PHP Shell, odpowied-nio zabezpieczony, potrafi skrócić czas w przypadku potrzeby instalacji i testowania wielu skryptów w krótkim czasie, a w po-łączeniu z aplikacjami wcześniej zapro-jektowanymi, a pozostającymi po stronie serwera, może stanowić doskonały po-most z naszym zdalnym serwerem na porcie serwera http.

Licencja: GNU GPL.http://mgeisler.net/php-shellhttp://freshmeat.net/projects/phpshell

Tiki CMS

Tiki CMS to szybko rozwijający się system zarządzania treścią o otwar-

tym kodzie. Autorzy zachwalają, że na-daje się tak do aplikacji portalowych, jak na prywatne strony. Kod rozwija 256 pro-gramistów, zaś społeczność reprezentu-je ponad 10 000 zarejestrowanych użyt-kowników. Tiki CMS korzysta z systemu szablonów Smarty i oferuje między inny-mi moduły artykułów, newsów, for dys-kusyjnych, newsletterów, blogów, galerie graficzne, trackery, ankiety, quizy, system wymiany bannerów, chat, webmail, kalen-darz, mapy, statystyki, strony WAP, wątki RSS, systemy kategorii, shoutbox, skórki, live support, wikipedię, i wiele innych. Na stronie projektu znajdziemy wiele przydat-nych materiałów: artykuły, fora dyskusyj-neitp. oraz filmy demonstracyjne. CMS dostępny jest w wielu wersjach języko-wych: angielskiej, polskiej, czeskiej, duń-skiej, niemieckiej, francuskiej, holender-skiej, włoskiej, japońskiej, portugalskiej, słowackiej, hiszpańskiej i szwedzkiej. Do-

datkowo, na stronie http://doc.tikiwiki.org/tiki-index.php?page=Features dowiemy się,czy Tiki to CMS dla nas – każdy z modu-łów ma przypisaną ocenę odnoszącą się do prostoty instalacji, administracji, stabil-ności i jakości. Dzięki temu możemy jesz-cze przed pobraniem pakietu dowiedzieć się, ile pracy będziemy musieli włożyć, by dostosować system do naszych potrzeb.

Licencja: GNU LGPL.http://tikiwiki.orghttp://freshmeat.net/projects/tiki

Page 9: PHP Solutions 01 2007 PL
Page 10: PHP Solutions 01 2007 PL

www.phpsolmag.org10

Opis CD

PHP Solutions Nr 1/2007

MySQL Serwer 5.0

Tutorial 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

Tematy 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łowskiKontakt: [email protected]

Page 11: PHP Solutions 01 2007 PL

Na CDNa CD

HITYPełna wersja kursu HTML- MySQL Serwer 5- XAJAX: Łatwy AJAX dla programistów PHP

Wsz

ystk

ie lis

tingi

z a

rtyku

łów

zos

tały

zam

iesz

czon

ena

nas

zej s

troni

e in

tern

etow

ej p

od a

dres

em www.phpsolmag.org/pl

Wsz

ystk

ie lis

tingi

z a

rtyku

łów

zos

tały

zam

iesz

czon

ena

nas

zej s

troni

e in

tern

etow

ej p

od a

dres

em www.phpsolmag.org/pl

Przetestuj dowolne skryptybez instalacji!

E-BOOKS- Built Your Own Database Driven Website Using PHP and MySQL - PostgrSQL 8.1.4 Documentation- MySQL 5.1 Reference Manual

Page 12: PHP Solutions 01 2007 PL

www.phpsolmag.org12 PHP Solutions Nr 1/2007

Dla początkujących

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

PHP-Qt Dla początkujących

Choć PHP-Qt znajduje się we wczesnej fazie rozwoju, zaim-plementowano w nim już naj-

ważniejsze technologie, co umożliwia tworzenie prostych aplikacji. Pokażemy później, jak pisać w PHP programy ko-rzystające z Qt na przykładzie kalkulato-ra. Zacznijmy jednak od ogólnego omó-wienia Qt.

Qt zawiera bibliotekę klas, a także narzędzia ułatwiające tworzenie aplika-cji oraz internacjonalizację. W tej pierw-szej znajduje się ponad 400 klas odpo-wiedzialnych za tworzenie graficznych interfejsów użytkownika (GUI, ang. Gra-phical User Interface), wygląd aplikacji okienkowych (layout), obsługę SQL-a, sieci, XML-a, internacjonalizację, współ-pracę z OpenGL i wiele innych. Qt4.1 i 4.2 zawierają również silnik obsługi PDF-ów, wsparcie dla tworzenia grafiki SVG, frameworki: Graphics-View oraz undo (cofanie operacji), arkusze sty-lów dla widgetów (kontrolek) czy wspar-

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...

cie dla standardu D-BUS pod Linuk-sem i Uniksem. Wspomniane wersje Qt umożliwiają również integrację aplikacji z konkurencyjnym wobec KDE środowi-skiem GNOME.

W najnowszej wersji PHP-Qt zosta-ło zaimplementowanych 75 należących do Qt klas. Następne wydanie, nad któ-rym trwają prace, ma zawierać prawie wszystkie spośród wspomnianych 400 klas. Biblioteka Qt ma rozwinięty, doj-

Tworzymy aplikacje okienkowe z PHP-QtThomas Möenicke

W SIECI

1. http://php-qt.berlios.de– strona domowa PHP-Qt

2. http://docs.trolltech.com/4.1 – dokumentacja Qt

3. http://www.trolltech.no– strona główna firmy Trolltech

4. http://www.trolltech.com/products/qt/learnmore/classchart – klasa Qt 4.1

Stopień trudności: lll

Co powinieneś wiedzieć:Powinieneś znać podstawy programo-wania obiektowego. Przydatna będzie również znajomość ogólnych zasad tworzenia interfejsów graficznych (GUI) w Qt lub innych systemach widgetów (np. wxWidgets czy GTK).

Co obiecujemy:Pokażemy, jak korzystając z PHP-Qt utworzyć w PHP aplikację korzystającą z Qt (kalkulator) i objaśnimy podstawo-we zagadnienia związane z Qt.

Page 13: PHP Solutions 01 2007 PL

www.phpsolmag.org12 PHP Solutions Nr 1/2007

Dla początkujących

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

PHP-Qt Dla początkujących

rzały model obiektowy, a jej API jest ele-ganckie i przejrzyste, co ułatwia two-rzenie aplikacji i czyni je przyjemniej-szym. Firma Trolltech (twórca Qt) roz-powszechnia Qt4 na podwójnej licen-cji (komercyjnej lub GNU GPL) dla plat-form X11 (X-Window), MacOS X i MS Windows.

Przejdźmy teraz do naszego kal-kulatora (zob. Rysunek 1), na podsta-wie którego pokażemy, jak stosować główne koncepcje Qt, takie jak sygnały (ang. signals), sloty (ang. slots), dzie-dziczenie, definiowanie wyglądu (lay-out), łańcuchy, przeciążenie metod (overloading) oraz zmiana typów (ang.

type casting). Kalkulator będzie umoż-liwiał wykonywanie podstawowych ope-racji arytmetycznych. Będzie miał pa-mięć do przechowywania liczb, wyświe-tlacz, klawiaturę numeryczną oraz przy-ciski służące do kasowania pojedyn-czych cyfr lub całych wpisanych warto-ści oraz wykonywania obliczeń.

Aplikacje wPHP-Qt: zaczynamyZanim jednak przejdziemy do kalkulato-ra, musimy wiedzieć, jak utworzyć okno główne aplikacji. W tym celu przyjrzyj-my się prostszemu przykładowi z Li-stingu 1.

Zaczynamy od utworzenia nowej in-stancji $app klasy QApplication. Dziedzi-czy ona z QCoreApplication i jest głów-ną klasą Qt, zarządzającą ustawieniami oraz interakcją z użytkownikiem (control flow). Możemy przekazać parametry $ar-gc i $argv do jego konstruktora.

Następnie tworzymy obiekt $window klasy QWidget, która z kolei jest klasą ba-zową dla wszystkich widgetów (kontro-lek). Jej zadaniem jest ich prezentacja na ekranie oraz odbieranie zdarzeń. Z jej pól, slotów i metod mogą korzystać wszystkie obiekty, które z niej dziedziczą. Obiekt $window będzie głównym oknem naszej aplikacji. Ustawimy jego rozmiar metodą resize() na 200 (szerokość) i 120 pikse-li (wysokość).

Kolejnym obiektem, który utworzy-my, będzie przycisk (ang. button) $quit klasy QPushbutton. Przypiszemy mu na-pis Quit, który się na nim ukaże i za-gnieździmy go w oknie $window: w taki właśnie sposób umieszczamy kontrolki w oknach. Następnie ustawimy współ-rzędne przycisku $quit (kolumna, wers, szerokość, wysokość) używając jego metody setGeometry(). Ostatnią rze-czą, którą zrobimy z naszym przyci-skiem, bedzie przypisanie mu sygna-łu clicked() odpowiadającego za je-go kliknięcie myszką oraz slotu quit(): w ten sposób kliknięcie tego przycisku będzie powodowało zakończenie dzia-łania aplikacji . Dodajmy, że slot quit() jest wbudowaną metodą klasy QAppli-cation. Przypisując nazwę obiektu $app określamy też przynależność przycisku $quit do naszej aplikacji.

Teraz pozostało wyświetlenie okna na ekranie ($window->show() oraz uru-chomienie głównej pętli naszej aplika-

Instalacja i szybki startObecna wersja PHP-Qt pracuje wyłącznie pod Linuksem; planowane wydanie (port) dla Windows nie zostało jeszcze ukończone.

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-instalować PHP-Qt na swoim komputerze, musisz pobrać źródła najnowszego wydania tej biblioteki pod adresem http://php-qt.berlios.de i rozpakować je na twardym dysku.. Opiszemy instalację wersji 0.0.3. Poza samym PHP-Qt potrzebne będą:

� źródła parsera PHP5.1 (lub nowszego),� źródła PHP-Qt,� pliki nagłówkowe Qt 4.1 i skompilowana biblioteka Qt.

Zalecana jest kompilacja PHP z użyciem prefiksu (parametr --prefix), aby zachować obecną na dysku wersję PHP (jeżeli takową posiadamy). Jak zwykle, zaczynamy od wy-konania polecenia configure:

./configure –prefix=/usr/local/php-5.1.1

make

make install (wykonujemy tę operację zalogowani jako root)Następnie przechodzimy do katalogu php_qt i wpisujemy:

./configure

--with-php_qt[=/path/to/qtheaders]

--with-qtlib[=/path/to/qtlib]

--with-php-config=/usr/local/php-5.1.1/bin/php-config

Ostatni parametr wskazuje skrypt php-config, drugi ścieżkę dostępu do skompilowanej bi-blioteki Qt, a pierwszy – pliki nagłówkowe Qt. Możemy teraz skompilować kod źródłowy wykonując make install (musimy być zalogowani jako root). Po udanej kompilacji oraz instalacji powinniśmy móc uruchomić tutoriale dołączone do pakietu PHP-Qt poleceniem:

/usr/local/php-5.1.1/bin/php-qt/tutorials/t1/main.php

Jesteśmy gotowi, aby napisać nasz pierwszy program: jak zwykle będzie to Hello World (przykład z tutoriala 1), którego efekt działania pokazujemy na Rysunku 2:

if(!extension_loaded('php_qt')) {

dl('php_qt.' . PHP_SHLIB_SUFFIX);

}

$app = new Qapplication($argc,$argv);

$hello = new QPushButton("Hello world!");

$hello->show();

$app->exec();

Rysunek 1. Kalkulator stworzony w PHP-Qt

Rysunek 2. Hello World w PHP-Qt

Page 14: PHP Solutions 01 2007 PL

PHP-Qt

www.phpsolmag.org14

Dla początkujących

PHP Solutions Nr 1/2007

cji ($app->exec()). Zostanie ona za-trzymana jeżeli główny widget (okno) zostanie zniszczony lub po wywoła-niu exit().

Tworzymy kalkulatorPrzyjrzyjmy się teraz budowie kalkula-tora. Składa się on z dwóch klas: Cal-culator (calculator.php) i Button (but-ton.php) oraz głównego skryptu ma-in.php, który uruchamia całą aplikację (Listing 2). Plik calculator.php zawie-ra 390 linijek kodu, więc nie będziemy go szczegółowo omawiać: skupimy się na tych fragmentach, które będą nam potrzebne do wyjaśnienia jego działa-nia. Kompletny skrypt main.php, a tak-

że klasy Calculator i Button są do-stępne w pakiecie PHP-Qt (examples/calculator/calculator.php). Tam też mo-żemy od razu przetestować jego dzia-łanie.

Przejdźmy teraz do skryptu ma-in.php. Na samym początku sprawdza-my, czy rozszerzenie php_qt zostało za-ładowane i jeśli nie, ładujemy je. Następ-nie dołączamy plik calculator.php i po-dobnie jak w naszym poprzednim przy-kładzie, tworzymy instancję $app kla-sy QApplication. Potem inicjujemy okno główne kalkulatora, które u nas jest in-stancją $calc klasy Calculator, pokazu-jemy je ($calc->show() i uruchamiamy pętlę główną aplikacji ($app->exec()).

Okno główne: dziedziczenieJak już wspomnieliśmy, okno główne Calculator jest klasą pochodną wobec QDialog, tak więc wszystkie metody, sy-gnały i sloty tej drugiej są dziedziczone. Możemy je przystosować do naszych po-trzeb i tworzyć nowe, np. te, które odno-szą się do przycisków.

Potrzebujemy metod obsługujących działania użytkownika, czyli slotów. Bę-dą nimi: digitClicked() (kliknięcie klawi-sza cyfry), unaryOperatorClicked() (klik-nięcie przycisku .....................), additive-OperatorClicked() (kliknięcie przycisku dodawania), multiplicativeOperator-

Clicked() (kliknięcie przycisku mnoże-nia), equalClicked() (kliknięcie przycisku równa się), pointClicked() (kliknięcie przycisku kropki), changeSignClicked() (kliknięcie przycisku +/- służącego do zmiany znaku), backspaceClicked() (klik-nięcie backspace, czyli kasowanie cy-fry), clear() (czyszczenie wpisanej lub wyliczonej wartości), clearAll() (czysz-czenie całego wyświetlacza), clearMem-ory() (czyszczenie pamięci kalkulatora), read _ Memory() (odczyt pamięci kalkula-tora), setMemory() (ustawianie wartości w pamięci kalkulatora) i addToMemory() (do-dawanie wartości w pamięci kalkulatora). Nazwy wszystkich slotów będą zapisane w tablicy $slots (Listing 3), dzięki której biblioteka Qt będzie je mogła obsłużyć.

Potrzebne będą też metody, które nie są slotami: createButton(), która tworzy przyciski, abortOperation() do wycofa-nia działania oraz calculate(), która bę-dzie obliczać wynik.

Sygnały i sloty – szczegółyPrzejdźmy teraz do bardziej szczegó-łowego omówienia zagadnienia sygna-łów i slotów. Jak już wiemy, są one jed-ną z podstawowych koncepcji w Qt, a ich zadaniem jest łączenie wydarzeń (np. kliknięcia myszką przycisku doda-wania – tym zajmują się sygnały) z me-todami, które je obsługują (np. dodawa-nie dwóch liczb, co z kolei jest zadaniem

Listing 1. Prosty przykład działania Qt: okienko zawierające przycisk Quit

$app = new QApplication($argc,$argv);

$window = new QWidget(); $window->resize(200,120);

$quit = new QPushButton("Quit", $window); $quit->setGeometry(10, 40, 180, 40);

$quit->connect($quit,SIGNAL("clicked()"),$app,SLOT("quit()"));

$window->show();

$app->exec();

Listing 2. Główny plik kalkulatora (main.php)

<?php

if(!extension_loaded('php_qt')){ dl('php_qt.'.PHP_SHLIB_SUFFIX);

}

require_once('calculator.php');

$app=new Qapplication($argc,$argv);$calc = new Calculator();$calc->show();

$app->exec();?>

Listing 3. Deklarujemy sloty w tablicy $slots – jest to wymagane przez Qt

private $slots = array( "digitClicked()",

"unaryOperatorClicked()",

"additiveOperatorClicked()",

"multiplicativeOperatorClicked()",

"equalClicked()",

"pointClicked()",

"changeSignClicked()",

"backspaceClicked()",

"clear()",

"clearAll()",

"clearMemory()",

"read_Memory()",

"setMemory()",

"addToMemory()"

);

private $signals = array("");

Rysunek 3. Główny widget w Qt

Page 15: PHP Solutions 01 2007 PL

PHP-Qt

www.phpsolmag.org 15

Dla początkujących

PHP Solutions Nr 1/2007

slotów). Slot jest wywoływany po wysła-niu przez widget połączonego z nim sy-gnału.

Sloty to zwyczajne metody w mode-lu obiektowym PHP5, które mogą być publiczne (public), chronione (protec-ted) lub prywatyne (private) i może-my je bezpośrednio wywoływać (nieko-niecznie wskutek wystąpienia zdarze-nia). Naturalną koleją rzeczy jest ich łą-czenie z sygnałami. Jeden sygnał mo-że być podpięty do wielu slotów, a jeden slot – do wielu sygnałów. Co więcej, mo-żemy łączyć sygnały między sobą. Bar-dzo ważne jest to, że w Qt klasa, któ-ra może korzystać z sygnałów i slotów, musi dziedziczyć po QObject. Więcej na ten temat możemy przeczytać w drugim tutorialu Qt.

Przyjrzyjmy się jeszcze raz pro-stemu przykładowi z Listingu 1, któ-ry składa się wyłącznie z okna główne-go i przycisku Quit powodującego za-kończenie działania aplikacji. Wszystkie widgety dziedziczące z QWidget, w tym nasz przycisk QPushButton, wysyłają sy-gnały przy wystąpieniu dowolnego wy-darzenia. W naszym przykładzie jest to sygnał clicked(), wysyłany przez przy-cisk, który klikniemy myszką. Więcej o sygnałach i slotach można przeczytać w tutorialu 7 PHP-Qt. Do łączenia slo-tów z sygnałami służy metoda connect() danego widgetu, np.:

connect($quit,SIGNAL("clicked()"),

$app,SLOT("quit()"))

Metody SLOT() i SIGNAL() są wymaga-ne, aby zdefiniować sloty i sygnały – bez ich użycia nie będzie to możliwe. Metody te odpowiadają makrom SIGNAL i SLOT z Qt dla C++.

Aby rozłączyć sloty i sygnały, mo-żemy użyć metody disconnect(), ale przeważnie nie jest to wymagane, gdyż Qt rozdziela je automatycznie w

momencie zniszczenia obiektu, które-go one dotyczą. Obecna wersja PHP-Qt nie obsługuje jeszcze slotów z pa-rametrami: funkcjonalność ta jest pla-nowana w najstępnych wersjach tej bi-blioteki.

Wszystkie spośród używanych przez nas przycisków są obiektami klasy QPush-Button, która dziedziczy z QAbstractBut-ton. Z tej drugiej dziedziczą również in-ne klasy przycisków, takie jak Q3Button, QCheckBox czy RadioButton.

Wyświetlaczem kalkulatora będzie pole tekstowe – obiekt $display klasy QLineEdit, która. reprezentuje pojedyn-czą linię tekstu z możliwością edycji. Jak w prawdziwym kalkulatorze, przy inicja-cji tej klasy wpisujemy wartość 0 (ja-ko parametr wysłany do konstruktora). Tekst zawarty w tym polu odczytamy korzystając z metody $display->text(), zaś do wpisania go użyjemy metody setText().

Definiowanie wyglądu (layoutu) okienkaZdefiniujmy teraz wygląd (layout) nasze-go kalkulatora. Określa on sposób or-ganizacji widgetów w oknie. Podstawo-wą klasą służącą do definiowania lay-outu (menedżerem layoutu, ang. layout manager)jest QLayout, z której dziedzi-czą inne, takie jak QHBoxLayout, QVBox-Layout czy QGridLayout. Główną zale-tą menedżerów layoutu jest to, że auto-matycznie rozmieszczają one elementy w oknie, wymagając od programisty je-dynie podania podstawowych parame-trów (np. kolumny i wersu).

W naszym kalkulatorze użyjemy klasy QGridLayout, która traktuje okno aplikacji jako siatkę (ang. grid) podzie-loną na wiersze i kolumny. Przyciski na-szego kalkulatora są pogrupowane wg funkcji: operatory [[unary]], dodawania i mnożenia, cyfry oraz inne (np. kasowa-nie cyfr). Każda z grup ma po jednym

slocie. Przyciski są tworzone z uży-ciem wspomnianej już metody create-Button(), która wymaga dwóch para-metrów: opisu, który zostanie wyświe-tlony na klawiszu oraz slotu. Slotami będą metody wymienione w zmiennej $slots z Listingu 3, które będą połą-czone z sygnałem clicked() odpowied-nich przycisków (np. slot additiveOper-atorClicked() połączymy z sygnałem clicked() przycisku dodawania).

Sposób rozmieszczenia przycisków reprezentujących cyfry przedstawia-my na Listingu 4. Korzystając z meto-dy addWidget() obiektu $this->main-

Layout() klasy QGridLayout, każdemu z nich przypisujemy konkretną kolumnę i wers, np. equalButton (przycisk równa się) będzie miał położenie (5,5). Meto-da addWidget wymaga podania trzech parametrów: obiektu (np. przycisku), wersu i kolumny. Dodatkowo, możemy zdefiniować dwa opcjonalne parame-try: rowSpan i colSpan, które pozwalają na łączenie kilku wersów lub kolumn w jedną, podobnie jak ma to miejsce w ta-belach HTML-owych.

Przeciążenie metod (overloading)Powiedzieliśmy, że parametry rowSpan i colSpan są opcjonalne. Przyciski w naszym kalkulatorze, poza backspace-Button, clearButton() i clearAllBut-

ton(), są dodawane do layoutu metodą addWidget() jedynie z trzema parame-trami (obiekt, wers i kolumna). Opcjo-nalność rowSpan i colSpan nie jest osiągana przez przypisywanie im war-tości domyślnych w deklaracji metody addWidget(), tylko przez przeciążenie (ang. overloading) tej metody. Parame-trem o wartości domyślnej jest nato-miast Alignment, ustawiony standardo-wo na 0. Nagłówki metody addWidget() z rowSpan i colSpan przetłumaczone na PHP wyglądają następująco:

QGridLayout::addWidget

($widget, $fromRow,

$fromColumn, $rowSpan,

$columnSpan, $alignment = 0)

A oto wersja bez parametrów pozwalają-cych na łączenie wersów i kolumn:

QgridLayout::addWidget

($widget, $row,

$column, $alignment = 0)

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

for ($i = 1; $i < $this->NumDigitButtons; ++$i) {

$row = ceil(((8 - ($i+1))) / 3) + 2; $column = ceil((($i-1) % 3)) + 1; $this->mainLayout->addWidget($this->digitButtons[$i],

(int) $row, (int) $column);

}

Page 16: PHP Solutions 01 2007 PL

PHP-Qt

www.phpsolmag.org16

Dla początkujących

PHP Solutions Nr 1/2007

Na koniec nadajemy okienku tytuł PHP Solutions Calculator.

Zmiana typów (ang. type casting)Zobaczmy teraz, w jaki sposób klasa Cal-culator odnajduje przycisk wciśnięty przez użytkownika. W tym celu przyjrzy-my się metodzie unaryOperatorClicked() (Listing 5).

Do określenia, który przycisk zo-stał wciśnięty służy metoda sender() – zwraca ona obiekt, który wysłał sy-gnał. Metoda ta należy do klasy QOb-ject (z której dziedziczy każdy wid-get, również przycisk), a dostęp do niej jest możliwy dzięki $this. Widzimy już, dlaczego klasa Calculator dzie-dziczy z QDialog, która z kolei jest kla-są pochodną wobec QObject. Dokład-niejsze informacje na temat dziedzicze-nia klas w Qt znajdują się pod adresem http://www.trolltech.com/products/qt/learnmore/classchart/.

No dobrze, ale metoda sender() zwraca obiekt klasy QObject, a nam jest potrzebny przycisk. Użyjemy więc funkcji qobject _ cast(), która zamie-ni obiekt typu QObject na takowy. Wy-maga ona podania dwóch parametrów: istniejącego obiektu oraz nowej, anoni-mowej instancji (w tym przypadku But-

ton("")) i zwraca obiekt docelowy (tej samej klasy, co obiekt podany jako dru-gi parametr).

Następnie odczytujemy liczbę wpi-saną przez użytkownika. W tym ce-lu skorzystamy z metody text() kla-sy obiektu $display (naszego wyświe-tlacza). Otrzymany rezultat będzie ty-pu QString, a my potrzebujemy liczby, na której będziemy mogli wykonywać działania. Przekonwertujemy więc łań-cuch na liczbę przy użyciu metody to-Double(): jeśli konwersja się nie powie-dzie, wynikiem będzie 0.0 i wywołana zostanie metoda abortOperation() kla-sy Calculator.

QString: obsługa łańcuchów w QtPrzyjrzyjmy się teraz możliwościom Qt w dziedzinie łańcuchów. Biblioteka ta oferuje szerokie możliwości obsłu-gi standardu unicode, łańcuchów i po-jedynczych znaków. Ułatwia też kon-wersję typów znaków oraz internacjo-nalizację.

Na Listingu 5 korzystamy z meto-dy tr(), która należy do klasy QObject i klas pochodnych wobec niej. Zwra-ca ona tłumaczenie podanego łańcu-cha lub ten sam łańcuch, jeżeli nie ma dla niego tłumaczenia. Zaleca się jej

stosowanie wobec wszystkich napi-sów, które chcemy wyświetlać. PHP-Qt automatycznie konwertuje wszyst-kie łańcuchy PHP na obiekty klasy QString.

Większość metod Qt również zwra-ca łańcuchy tego typu. Korzystaniez QString daje wiele rozmaitych moż-liwości manipulacji łańcuchami, takich jak ich liczenie, łączenie, zastępowa-nie, kasowanie, dzielenie czy konwer-sja standardów (ASCII/Unicode/UTF8/UTF16/Latin1 oraz typy numeryczne i niektóre operatory). Wszystkie łańcu-chy przechowywane w Qt są domyśl-nie typu Unicode: stosowanie tego ty-pu wobec łańcuchów podawanych jako parametry metod gwarantuje, że będą wyświetlane poprawnie.

PodsumowanieZademonstrowaliśmy podstawowe moż-liwości PHP-Qt i na ich podstawie moż-na ocenić, że rozwój tej biblioteki zmierzaw dobrym kierunku.

Obecnie, twórcy tego pakietu zaj-mują się integracją ze SMOKE (któ-ry zostanie użyty w następnych wer-sjach PHP-Qt i jest dołączony w obec-nym wydaniu tego pakietu; jego celem jest utworzenie powiązań (ang. bin-dings) pomiędzy PHP a Qt/KDE) oraz przenosinami PHP-Qt do działające-go w systemie Subversion repozyto-rium KDE.

Nic więc nie stoi na przeszkodzie, aby wprowadzić do PHP-Qt pozostałe klasy należące do Qt i KDE. Co wię-cej, PHP-Qt ma być dostępne nieza-leżnie od KDE i nie wymagać żadnych pakietów oprócz parsera PHP i biblio-teki Qt. Lista mailingowa i repozyto-rium Subversion pozwalają natomiast śledzić rozwój pakietu PHP-Qt, który z każdą wersją staje się coraz lepszy. n

Thomas Mönicke studiuje informa-tykę na Politechnice Brandenburskiejw Cottbus. Jest autorem biblioteki PHP-Qt. Tworzy aplikacje GIS- i webowe dla Niemieckiego Instytutu Archeologiczne-go, a także pracuje nad systemem P2P do widekonferencji o nazwie BRAVIS.

Kontakt z autorem:[email protected]

Listing 5. Zastosowanie metod qobject_cast i tr() klasy QObject

function unaryOperatorClicked() {

$clickedButton = qobject_cast($this->sender(), new Button("")); $clickedOperator = $clickedButton->text();

$operand = $this->display->text()->toDouble();

$result;

if ($clickedOperator->toAscii() == $this->tr("Sqrt")->toAscii()) { if ($operand < 0.0) { $this->abortOperation();

return; }

$result = sqrt($operand);

} else if ($clickedOperator->toAscii()==$this->tr("x\262")->toAscii()) { $result = pow($operand, 2.0);

} else if ($clickedOperator->toAscii()==$this->tr("1/x")->toAscii()) { if ($operand == 0.0) { $this->abortOperation();

return; }

$result = 1.0 / $operand;

}

$this->display->setText(QString::number($result));

$this->waitingForOperand = true;

}

O autorze

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

www.phpsolmag.org18

Projekty

PHP Solutions Nr 1/2007

PunBB

www.phpsolmag.org 19

Projekty

PHP Solutions Nr 1/2007

Możemy też wypróbować też SMF jak wiele innych skryp-tów. Co jednak mamy zro-

bić gdy chcemy lekkie, funkcjonalnei proste w zarządzaniu forum? Roz-wiązaniem jest punBB, skrypt rozwi-jany od 2003 roku przez Rickarda An-derssona. PunBB korzysta z bazy da-nych, do wyboru może to być MySQL, PostgreSQL lub SQLite. Skrypt mo-że działać zarówno pod PHP z serii 4.3 jaki i PHP5. Instalacja skryptu jest bardzo prosta.

Wystarczy pobrać archiwum ze stro-ny projektu, rozpakować i przenieść na nasz serwer i otworzyć w przeglądarce plik install.php. Pojawi się prosty, intu-icyjny instalator. Jeżeli chcemy prowa-dzić forum w języku innym niż angielski to wystarczy pobrać ze strony punBB odpowiedni pakiet językowy i umieścić go w katalogu lang a następnie ustawić go domyślnym w panelu admina i profilu administratora.

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.

RozwójBieżąca stabilna wersja to 1.2.14 a ko-lejne wydania z tej serii ukażą się wy-łącznie w przypadku odkrycia błędów lub luk bezpieczeństwa. Aktualizacje bezpieczeństwa ukazują się nie póź-niej niż 48 godzin od zgłoszenia. Infor-macje o odkrytych błędach i konieczno-ści aktualizacji są podawane na stronie projektu oraz na specjalnej liście dys-kusyjnej.

Obecnie trwają prace nad punBB 1.3, nową wersją rozwojową, która wpro-wadzi nowe funkcjonalności takie jak:

PunBB – nowoczesne forum dyskusyjnePiotr Maliński

W SIECI

1. http://www.punbb.org– Strona punBB;

2. http://www.punres.org – Strona z modyfikacjamii skórkami;

3. http://punbb.tox.pl– Polskie Wsparcie punBB;

4. http://www.tibiaswe.com/foru – Jedno z największych for dyskusyjnych opartych o punBB;

5. http://www.phpclasses.org/browse/package/2765.html – Forum Integrator, klasa ułatwiające integrację punBB i phpBB;

Stopień trudności: lll

Co obiecujemy:Poznasz podstawy PHP i HTML.

Co powinieneś wiedzieć:Umiejętność integrowania punBB z ze-wnętrznymi skryptami a także umiejęt-ność migracji danych z innych skryptówforum.

Page 19: PHP Solutions 01 2007 PL

www.phpsolmag.org18

Projekty

PHP Solutions Nr 1/2007

PunBB

www.phpsolmag.org 19

Projekty

PHP Solutions Nr 1/2007

l łatwy w zarządzaniu system rozsze-rzeń (tzw. Wtyczek);

l przyjazne linki dla wyszukiwarek;l usprawniony interfejs forum.

Pierwsza stabilne wydanie z tej serii prze-widziane jest jeszcze na bieżący rok.

Możliwości forumTabela 1 prezentuje dostępne jaki brakują-ce względem innych skryptów funkcjonal-ności punBB. Zestawienie pochodzi z da-nych serwisu forummatrix.org.

WydajnośćAutor artykułu przeprowadził proste testy wydajnościowe z wykorzystaniem profilera Xdebug (wersja 2.0.0 beta 5) pracującego z PHP 5.1.2 pod kontrolą 64 bitowego li-

nuksa (Gentoo). Każdy z testowych skryp-tów posiadał dwie kategorie oraz jeden te-mat z jedną odpowiedzią. W celu otrzyma-nia powtarzalnych wyników autor wyko-rzystał funkcję xdebug_peak_memory_usage w celu pomiaru maksymalnego zużycia pamięci przez wykonujący się kod forum dyskusyjnego. Wyniki zestawione są po-niżej.Maksymalne zużycie pamięci:

l punBB (1.2.10): 0,742095 MB;l phpBB (2.0): 1,699279 MB;l IPB (2.0): 3,683769 MB;l SMF (1.1 RC 2): 3,769836 MB.

Bardzo dobre wyniki punBB można czę-ściowo uzasadnić brakiem komponentów takich jak prywatne wiadomości czy roz-

szerzony system użytkowników i upraw-nień obecnych w konkurencyjnych roz-wiązaniach.

WdrożeniaPunBB mimo iż w sieci nie jest powszech-nie znane zostało wdrożone w wielu ser-wisach. TibiaSwe to jedno z największych for opartych o ten skrypt mogące poszczy-cić się ponad 320 tysiącami postów. Fo-rummatrix – serwis zajmujący się porów-nywaniem różnych skryptów tego typu ja-ko forum dostępne w serwisie dla użyt-kowników również wybrał punBB. Twórcy tego serwisu wybrali punBB ze względu na system użytkowników i uprawnień, któ-ry bardzo łatwo wykorzystać w zewnętrz-nych skryptach oraz jest łatwy w zarzą-dzaniu od strony forum.

Migracja danychNa stronie skryptu znajdziemy również na-rzędzie o nazwie „PunBB Migration To-ol” umożliwiające migrację danych z kilku znanych skryptów. By skorzystać z narzę-dzia wystarczy rozpakować je i umieścić katalog converters w katalogu z instala-cją punBB, a następnie otworzyć w prze-glądarce zawarty w tym katalogu plik in-dex.php. Na dzień dzisiejszy wspierany jest import danych z:

l Invision Power Board 1.3;l Invision Power Board 2.0;l MiniBB 1.7d;l phpBB 2.0;l PHPNuke 7.4;l vBulletin 3.0.0;l YabbSE 1.5.5;l SMF 1.0.5;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.

INTEGRACJEW ł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-bicia, ale mimo to możliwości punBB oka-

Tabela 1. Wady i zalety punBB

Obsługa MySQL, PostgreSQL i SQLite Wsparcie utf-8

Bbcode, emotikony, cytowanie Wsparcie Oracle

Przejście do ostatniego postu Załączniki

Przekierowanie jako forum Zagnieżdżone fora

Kanały RSS/Atom, powiadomienia email Forum archiwum/kosz

Awatary, rangi, sygnatury Reputacja/ocena użytkownika

Użytkownicy na forum Prywatne wiadomości (jako dodatek)

Przenoszenie tematów, przyklejonetematy

dzielenie tematów (jako dodatek)

Wyszukiwanie pełnotekstowe i zaawan-sowane

Własne tagi BBcode

Lista nieprzeczytanych tematów Edytor szablonów

Statystyki Ankiety (jako dodatek)

Banowanie użytkowników, adresów IP Przyjazne linki (jako dodatek)

Flood control Ostrzeżenia

Czyszczenie forum Archiwizacja

Import danych z innych for dyskusyjnych

Rysunek 1. Strona spinkBB - generatora arkuszy CSS dla punBB

Page 20: PHP Solutions 01 2007 PL

PunBB

www.phpsolmag.org20

Projekty

PHP Solutions Nr 1/2007

żą się wystarczające dla większości sytu-acji. Jednakże możemy napotkać proble-my jako że uzyskanie dostępu do zaso-bów punBB polega na dołączeniu pliku include/common.php forum. Dołączenie elementu forum może doprowadzić do ko-lizji nazw funkcji i zmiennych.

Dostęp do elementów punBBBy uzyskać dostęp do tablic z danymi bie-żącego użytkownika, ustawieniami forum czy podstawowymi tłumaczeniami wystar-czy kilka linijek kodu co przedstawia listing 1. Stała PUN_ROOT oznacza ścieżkę do ka-talogu ze skryptem forum (bezwzględną ścieżkę systemową lub ścieżkę względną względem położenia pliku skryptu w któ-rym wykonujemy ten kod)

Oprócz tablic zyskujemy dostęp do innych elementów punBB. Kolejnym ele-mentem jest zmienna $db przechowująca obiekt, za pomocą którego możemy ope-rować na bazie danych. Przykład widzi-my na listingu 2. Jeżeli chcemy stworzyć aplikację obsługującą wszystkie trzy ba-zy to możemy przyjąć rozwiązanie punBB – pisanie w razie potrzeb trzech zapytań dla każdej bazy danych. Pomocna może okazać się zmienna $db_type przecho-wująca nazwę używanej przez skrypt ba-zy danych.

Możemy też pod patrzeć kod punBB i wykorzystać pewne elementy w naszych skryptach. Przykładowo formularz logowa-nia logujący użytkownika na forum i prze-kierowujący na stronę formularza wyglą-dałby tak jak na listingu 3.

Klasa „Forums Integrator”Dostępna na phpclasses.com klasa uła-twia integrację punBB jak i phpBB. Oprócz 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 GALLERYCPG 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.

Zaczynamy od zainstalowania gale-rii CPG ustawiając ten sam login i hasła administratora jaki podaliśmy dla punBB;

Następnie w katalogu z galerią umiesz-czamy plik punbb.php klasy Forums Inte-grator i rozpoczynamy integrację;W pliku login.php wyszukujemy:

if ( $USER_DATA = $cpg_udb-

>login( addslashes($_POST['username']),

addslashes($_POST['password']), isset

($_POST['remember_me']) ) ) {

I poniżej dodajemy:

include 'punbb.php';

$pun = new punbb('/ścieżka/do/punbb/');

eval($pun->set_define());

$pun->set_variables($pun_user,

$pun_config);

$pun->login($_POST['username'],

$_POST['password']);

Otwieramy logout.php i dodajemy po:

$referer = 'index.php';

kod:

include 'punbb.php';

$pun = new punbb

('/ścieżka/do/punbb/');

eval($pun->set_define());

$pun->set_variables($pun_user,

$pun_config);

$pun->logout();

Otwieramy register.php i wyszukujemy wiersz zawierający zapytanie:

$sql = "INSERT INTO

{$CONFIG['TABLE_USERS']} ".

Rysunek 2. Prosty interfejs importera danych

Listing 1. Dostęp do podstawowych elementów punBB

define('PUN_ROOT', 'upload/');

// ścieżka do skryptu forum

require PUN_ROOT.'include/

common.php';

echo '<pre>

PUN_CONFIG:<BR>';

print_r($pun_config);

echo '<HR>

PUN_USER:<BR>';

print_r($pun_user);

echo '<HR>LANG

COMMON:<BR>';

print_r($lang_common);

echo '<HR>BANS:<BR>';

print_r($pun_bans);

Listing 2. Wykonywanie zapytania z pomocą obiektu $db

IF($result = $db->query($query)) {

while ($row = $db->fetch_assoc($result))

{

print $row;

}

}

Page 21: PHP Solutions 01 2007 PL

PunBB

www.phpsolmag.org 21

Projekty

PHP Solutions Nr 1/2007

"(user_regdate, user_active,

user_actkey, user_name,

user_password, user_email,

user_profile1,

user_profile2, user_profile3,

user_profile4,

user_profile5, user_profile6) ".

"VALUES (NOW(), '$active',

'$act_key',

'" . addslashes($user_name) . "', '" .

addslashes($encpassword) . "', '" .

addslashes($email) . "', '$profile1',

'$profile2', '$profile3', '$profile4',

'$profile5', '$profile6')";

Poniżej dodajemy:

include 'punbb.php';

$pun = new punbb('/ścieżka/do

/punbb/');

eval($pun->set_define());

$pun->set_variables($pun_user,

$pun_config);

$pun->register($user_name,

$password, $email);

Wyszukujemy:

function check_user_info(&$error)

{

global $CONFIG; //, $PHP_SELF;

I zastępujemy:

function check_user_info(&$error)

{

global $CONFIG, $db,

$pun_config, $pun_user;

//, $PHP_SELF;

Integracja gotowa, operacje logowania, wylogowania i rejestracji wykonają te sa-me operacje w punBB automatycznie. By systemy użytkowników pozostały zsyn-chronizowane zmieniamy lub usuwamy odnośniki rejestracji i logowania na fo-rum na te z CPG.

W powyższym kodzie użyliśmy trzech metod klasy punBB – login,logout i register, umieszczając wywoła-nie tych metod w miejscach, w których Coppermine Gallery wykonuje te sa-me operacje. Ostatnia zmiana, dodanie trzech zmiennych punBB jako global-nych była konieczna by wykorzystywa-ne elementy punBB działały poprawnie. Innym rozwiązaniem byłoby przekazanie

do funkcji (czy klasy) obiektu klasy inte-grującej jako argumentu.

MIGRACJA FORUM:jakilinux.orgAdministratorzy serwisu jakilinux.org po-stanowili rozpocząć migrację forum opar-tego o skrypt phpBB by Przemo. Obecnie forum zawiera ponad 4000 postów i 500 użytkowników. Autor serwisu, Borys Mu-sielak tak uzasadnia podjętą decyzję:

„Plusem phpBB jest spora liczba funkcji i popularność. Niestety, system ten zupełnie nie sprawdza się, gdy wy-magana jest jakakolwiek elastyczność. Kod phpBB jest trudny w modyfikacji – system zaprojektowany został z uży-ciem przestarzałych metod (dotyczy to zarówno rdzenia aplikacji jak i części od-powiedzialnej za wygląd). W odróżnieniu, kod punBB napisany jest w sposób przej-

R E K L A M A

Listing 3. Formularz logowania z przekierowaniem

<form id="login" method="post" action="'.PUN_ROOT.'login.php?action=in"

onsubmit="return process_form(this)">

<input type="hidden" name="form_sent" value="1" />

<input type="hidden" name="redirect_url" value="'.

$_SERVER['SCRIPT_NAME'].'" />

<B>Login</B><BR />

<input type="text" name="req_username" size="15" maxlength="25"

/><BR /><BR />

<B>Password</B><BR />

<input type="password" name="req_password" size="15" maxlength=

"16" /><BR /><BR />

<input type="submit" name="login" value="Login" />

</form>

Page 22: PHP Solutions 01 2007 PL

PunBB

www.phpsolmag.org22

Projekty

PHP Solutions Nr 1/2007

rzysty – umożliwia on praktycznie dowol-ne przeprojektowanie interfejsu użytkow-nika, dzięki umiejętnemu zastosowaniu arkuszy styli (CSS) przez jego twórców. Pewne niedostatki funkcjonalności (doty-czy wersji podstawowej aplikacji) rekom-pensowane są natomiast przez świetny mechanizm wtyczek.”

Za migrację odpowiedzialny był autor niniejszego artykułu.Plan migracji obejmował:

l Import danych z phpBB do punBB;l Konwersja kodowania z latin2 do

utf-8;l Zainstalowanie dodatków do punBB

zapewniających tą samą lub lepszą funkcjonalność jak w phpBB by Prze-mo;

l Stworzenie własnej skórki.

Kodowanie danych zmieniono poprzez zmianę kodowania pliku zrzutu bazy da-nych, który następnie zaimportowano na testowym serwerze. Import danych czy-li treści forum jak i kont użytkowników przeprowadzono za pomocą „PunBB Migration Tool”. Migracja przebiegła bez problemów mimo iż phpBB by Przemo zawierało liczne modyfikacje.

Kolejnym etapem była instalacja od-powiednich dodatków – systemu pry-watnych wiadomości (Private_Messa-ge_Mod), ankiety (Easy_Poll) oraz do-konano modyfikacji kodu punBB w ce-lu zamiany pól profilu użytkownika doty-czących komunikatorów AOL IM i Yahoo Messenger na Gadu-Gadu i Tlen.pl. Na obecnym etapie nie wykonywano innych zmian poza dodaniem ogólnodostępnych modyfikacji dodających brakujące podsta-

wowe opcje. Po wprowadzeniu modyfika-cji zauważono że dane kontaktowe Gadu-Gadu i Tlen.pl uległy importowi z phpBB by Przemo, a to za sprawą iż w tej mody-fikacji phpBB zastąpiono te same pola ko-munikatów profilu użytkownika.

Kolejnym etapem było udostępnie-nie bieżącej wersji do testów zespołowi prowadzącemu serwis oraz przygotowa-nie skórki przez grafików.

CODE IGNITER i punBBCode Igniter to prosty lecz funkcjonalny framework PHP. Nie oferuje aż tylu moż-liwości co Prado czy Symfony lecz wielu programistów bardzo go sobie ceni.

Integracja punBB ma tą wadę że po-lega na dołączeniu pewnych plików forum, co w przypadku Code Ignitera stwarza je-den problem. Otóż pomocnik url zawie-ra funkcję redirect. punBB również za-wiera taką funkcję i dochodzi do konflik-tu. Musimy zmienić nazwę funkcji, którą znajdziemy w pliku system/helpers/url_helper.php.

Integracja:W kontrolerach, które mają korzystać z integracji przed kodem klasy wystarczy dodać:

define('PUN_ROOT',

'ścieżka/do/punbb/');

require PUN_ROOT.

'include/common.php'

W konstruktorze należy ustawić zmienną pun_user jako globalną:

global $pun_user;

$this->pun = $pun_user;

Przykład:

function __construct()

{

global $pun_user;

parent::Controller();

$this->pun = $pun_user;

unset($pun_user);

}

Czy jestem zalogowany?Oto metoda kontrolera zwracająca war-tość logiczną oznaczającą stan bieżą-cego użytkownika, True dla zalogowa-nego i False dla wylogowanego użyt-kownika:

function _check_login()

{

IF($this->pun['group_id'] =

= 3) return false;

IF($this->pun['username'] =

= 'Guest') return false;

IF($this->pun['password'] =

= 'Guest') return false;

IF($this->pun['id'] == 1)

return false;

return true;

}

Ostatnie 10 aktywnychtematówW tym przypadku wystarczy skorzystać z biblioteki Code Ignitera i wykonać proste zapytanie do bazy danych:

$query = $this->db->query

("SELECT * FROM PREFIX_topics

ORDER BY last_post

DESC LIMIT 10");

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

Piotr Maliński jest studentem Politech-niki Warszawskiej na kierunku Techno-logia Chemiczna. Od czterech lat zaj-muje się tworzeniem aplikacji w PHP jaki od niedawna w Pythonie. Jest również autorem serwisów o nazwie „Biblioteka Riklaunima”.Kontakt: [email protected]

O autorze

Rysunek 3. Forum jakilinux.org po migracji danych prezentujące dwie skórki punBB

Page 23: PHP Solutions 01 2007 PL
Page 24: PHP Solutions 01 2007 PL

www.phpsolmag.org24 PHP Solutions Nr 1/2007

Dla zaawansowanych

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

XAJAX Dla zaawansowanych

AJAX to podejście do tworzenia aplikacji internetowych polegają-ce na połączeniu możliwości ist-

niejących już technologii w nową jakość. Termin AJAX użył po raz pierwszy Jes-se James Garrett w swoim artykule pt. „Ajax: A New Approach to Web Applica-tions” opublikowanym na początku roku 2005. Jego tekst był próbą odpowiedze-nia na pytanie, które wówczas zadawa-ło wiele ludzi, niekoniecznie profesjonal-nie związanych z tworzeniem stron www. Pytanie to brzmiało i brzmi nadal – czym jest ta rewolucyjna technologia wprowa-dzona przez Google?

Z perspektywy czasu można powie-dzieć, że to właśnie Google zapoczątko-wało światowy boom na AJAX, prezentu-jąc przełomowe na dzień dzisiejszy pro-dukty. Aplikacje internetowe zaoferowane przez Google charakteryzują się ponad-przeciętnymi wartościami użytkowymi, ale to co je wyróżnia od innych, to wyso-ki stopień interakcji z użytkownikiem. Re-

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.

wolucją jest tu bowiem fakt, że zmiany w aplikacjach internetowych Google doko-nują się nieomal w czasie rzeczywistym. Wszystko to właśnie dzięki AJAX.

Źródła inspiracji?Od strony użytkownika korzyści są wi-doczne gołym okiem. Dla zwykłego in-ternauty witryna wykorzystująca AJAX to strona, która niekoniecznie musi się przeładować by zmienić swoją zawar-tość. W taki sposób można najkrócej wyjaśnić ideę AJAX. Niestety, rozumo-

XAJAX łatwy AJAXPaweł Grzesiak

W SIECI

1. http://www.xajaxproject.org/ – strona główna projektu XAJAX.

2. http://wiki.xajaxproject.org/ – dokumentacja wiki do pro-jektu.

3. http://adaptivepath.com/publications/essays/archives/000385.php– artykuł Ajax: A New Appro-ach to Web Applications.

4. http://developer.mozilla.org/pl/docs/AJAX– więcej informacji o samej technice AJAX na stronach Mozilla Developer Center.

Stopień trudności: lll

Powinieneś wiedzieć:Wymagana jest dobra znajomość PHP oraz nabyte pewne podstawowe umiejęt-ności posługiwania się JavaScript.

Obiecujemy:Szybki start w tworzeniu stron opartych o AJAX. Szybkie wdrażanie nowych pomy-słów dzięki XAJAX.

Page 25: PHP Solutions 01 2007 PL

www.phpsolmag.org24 PHP Solutions Nr 1/2007

Dla zaawansowanych

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

XAJAX Dla zaawansowanych

wanie wyłącznie w kontekście same-go AJAX-a nie daje prawdziwego obra-zu zastosowania tej techniki. Najlepiej więc zasięgnąć przykładów, kierując się w stronę działających aplikacji Google. Rysunek 1 prezentuje aplikację Google Spreadsheets (http://spreadsheets.google.com), która nie tylko wyglądem, lecz i funkcjonalnością przypomina typowy ar-kusz kalkulacyjny. Co więc robi ta apli-

kacja, tkwiąc uwięziona w przeglądar-ce internetowej? Odpowiedź jest dość prosta – działa, i to wcale nie najgo-rzej. Czy już czas zmienić swoje przy-zwyczajenia i pisać dokumenty w edy-torze tekstu umieszczonym na stronie www? Rysunek 2 to przykład aplikacji internetowej niemal żywcem przeniesio-nej z pakietu biurowego. Writely (http://writely.com) to produkt Google aspirują-

cy do miana internetowego Worda. In-ne duże korporacje internetowe też nie próżnują. Yahoo ze swoim serwisem zdjęciowym Flickr (http://www.flickr.com) także aktywnie wykorzystuje możliwości AJAX. Choćby obracanie zdjęć bez ko-nieczności przeładowania to tylko jed-na z robiących wrażenie na użytkowni-kach funkcji.

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-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-czątek procesu wygląda dokładnie w ten

Rysunek 1. Google Spreadsheets, internetowy arkusz kalkulacyjny

Rysunek 2. Writely, internetowy edytor tekstu od Google

Page 26: PHP Solutions 01 2007 PL

XAJAX

www.phpsolmag.org26

Dla zaawansowanych

PHP Solutions Nr 1/2007

sam sposób, jak przy metodzie klasycz-nej – patrz rysunek 5. Strona zostaje w pełni załadowana. Gdy użytkownik stro-ny wykonania określoną akcję (kliknie na przycisk), pałeczkę przejmuje JavaScript. Odpowiedni skrypt napisany w tym języ-ku najpierw pakuje odpowiednie da-ne wejściowe (parametry, które chcemy przekazać) do formatu XML, a następ-nie tworzy instancję klasy XMLHttpRequ-est. To właśnie ta klasa okazuje się klu-czowa. XMLHttpRequest pozwala na wy-syłanie i odbieranie przez przeglądarkę żądań w formie osobnej sesji, niezależ-nej od aktualnie wyświetlonej strony. W ten sposób do serwera trafia żądanie o określonych parametrach i do pracy za-biera się skrypt przygotowany do wyge-nerowania odpowiedzi. To właśnie do skryptu pracującego po stronie serwera (napisanego np. w PHP) dostarczone 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

na wysłaniu i pobraniu danych. Za każ-dym razem nie wymaga to od przeglą-darki przeładowania. AJAX może rów-nie i dobrze pracować w pełni w tle prze-glądarki. W takiej sytuacji użytkownik na-wet nie spostrzeże, iż dane, które wpisu-je do formularza są defacto wysyłane do serwera.

Możliwości, jakie daje zastosowanie techniki AJAX pozwalają zatem na two-rzenie witryn, które swoim wyglądem i za-chowaniem przypominają tradycyjne pro-gramy komputerowe.

Wywołania AJAX mogą być obsługi-wane:

• Synchronicznie – w określonych od-stępach czasu (przydatne przy zapisie kopii aktualnie pisanego dokumentu);

• Asynchronicznie – na żądanie (uru-chamiane na akcję użytkownika).

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.

Z AJAXem jest jednak podobnie jak z innymi nowinkami. Wśród programistów zawsze znajdują się konserwatyści, uwa-żający AJAX za nic nadzwyczajnego oraz liberałowie, mniej lub bardziej zafascyno-wani techniką i skorzy do jej wdrażania. Prędzej, czy później każdy z nich będzie zmuszony do tworzenia aplikacji AJAX.

Większość obecnie tworzonych stron w żaden sposób nie przypomina aplikacji w rodzaju Google Spreadsheets, czy Wri-tely. Dlatego też rzadziej używamy w sto-sunku do nich terminu strona www. Stro-na powinna raczej pełnić rolę informacyj-ną (dostarczać treści), a zadaniem tych aplikacji jest wyłącznie realizacja konkret-nej usługi. Klienci indywidualni i korpora-cyjni zainteresowani stworzeniem nowego rozwiązania w sieci, zdecydowanie najrza-dziej decydują się na stworzenie tego ty-pu usługi. Trudno więc pisać o technologii AJAX w kontekście odsuniętym od realiów rynku. Strony internetowe potrzebują prze-

Rysunek 3. Flickr, serwis zdjęciowy od Yahoo!

������������

���������������������

����������

��������������������������������������

Rysunek 4. Schemat działania klasycznej strony www

Page 27: PHP Solutions 01 2007 PL

XAJAX

www.phpsolmag.org 27

Dla zaawansowanych

PHP Solutions Nr 1/2007

myślanej dawki technologii AJAX. W myśl tego twierdzenia dochodzimy do wniosku, że AJAX mógłby być wykorzystany na wi-trynie firmowej, czy na forum dyskusyj-nym. Czemu nie.

Jest wiele sytuacji, w których zasto-sowanie techniki AJAX ma ogromne zna-czenie. Witryny i portale tematyczne, ser-wisy usługowe i informacyjne napotykają na co najmniej kilka sytuacji, w których użycie AJAX mogłoby pomóc w zapew-nieniu wyższej funkcjonalności strony.

Kluczem do poprawnego wdrażania technik AJAX jest przestrzeganie kilku re-guł przy projektowaniu:

• Ładowanie dużych partii tekstu za po-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-nie funkcjonować;

• AJAX doskonale nadaje się do two-rzenia przełączników, np. „dodaj to zdjęcie do obserwowanych”, któ-re aktualizują bazę i zmieniają napis na przełączniku – „usuń z obserwo-wanych”. Dzięki AJAX można umoż-liwić szybkie dokonywanie zmian, np. zmiana tytułu artykułu bez koniecz-ności klikania na „wyślij” i przełado-wania strony. W momencie, gdy użyt-kownik przestanie pisać, uruchamia-ne jest żądanie AJAX a treść tytułu zapisywana do bazy. Pomimo oczy-wistej korzyści dla użytkownika, ko-nieczne jest zapewnienie oprogra-mowania, które zadziała przy wyłą-czonej obsłudze JS.

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 jak opisywany Writely, czy G. Spreadshe-ets. W takich sytuacjach wyłączenie ob-sługi JavaScript powoduje całkowitą nie-dostępność usługi.

BibliotekiW celu ułatwienia pracy przy tworzeniu aplikacji internetowych opartych o AJAX programiści sięgają po gotowe bibliote-ki. Nie ma nic w tym złego, bo bibliote-ki realizują większość krytycznych funk-cji, będąc odpowiedzialne za faktyczny transport danych pomiędzy klientem a serwerem. Biorąc pod uwagę ciągły pro-ces udoskonalania i popularność niektó-rych bibliotek, można śmiało stwierdzić, że tworzenie całej aplikacji od zera mi-ja się z celem, podwyższając w dodatku budżet produkcyjny.

������������

���������������������

����������

���������������������������������������

��������

�������������

����������

�������������������������������

��

��������������

Rysunek 5. Schemat działania strony opartej o AJAX

Rysunek 6. XAJAX to narzędzie do szybkiego wdrażania AJAX na strony tworzonew oparciu o PHP

Page 28: PHP Solutions 01 2007 PL

XAJAX

www.phpsolmag.org28

Dla zaawansowanych

PHP Solutions Nr 1/2007

Możemy rozróżnić dwa rodzaje biblio-tek wspomagających programowanie, ze względu na nacisk, który położono na pro-gramowanie w:

• JavaScript;• PHP.

Położenie większego nacisku, na któ-ryś z powyższych języków programowa-nia może wydawać się nieco niejasne.W bibliotece, w której nacisk położono na PHP zadania programisty ograniczają się w zasadzie wyłącznie do pisania nowych funkcji obsługi żądań po stronie serwera. Biblioteka poradzi już sobie z resztą ge-nerując odpowiednie skrypty JavaScript do obsługi. Oczywiście nie obędzie się 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ł.

XAJAXXAJAX 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-

miany danych) generuje skrypt Java-Script odpowiedzialny za obsługę żą-dań. W momencie, gdy nastąpi żądanie, uruchamiany jest ten skrypt, który po-przez obiekt XMLHttpRequest komuni-kuje się z obiektem xajax mieszczącym się po stronie serwera. Ten wywołuje już tylko funkcję PHP odpowiedzialną za re-alizację żądania. Gdy funkcja PHP zo-stanie zrealizowana, xajax zwróci odpo-wiedź w formie dokumentu XML. Ta zo-stanie przetworzona parser xajax pracu-jący po stronie klienta (JavaScript). Od-powiedź zostanie zwrócona przez tenże skrypt JavaScript – zazwyczaj w formie aktualizacji danych na stronie.

XAJAX posiada wiele interesujących cech i właściwości:

• 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-go aktualnie tekstu, ale także i styl css elementów, czy zaznaczyć pola checkbox lub radio formularzy;

• XAJAX posiada przyjazny mechanizm umożliwiający debugowanie napisane-go wcześniej kodu. W formie okien Ja-vaScript, XAJAX informuje o aktualnie podejmowanych przez bibliotekę dzia-łaniach. To przyspiesza programowa-nie i wyklucza przypadkowe błędy;

• XAJAX oferuje bardzo prosty mecha-nizm obsługi formularzy. Przy użyciu jednej funkcji otrzymujemy tablicę z danymi, które następnie można obro-bić, wrzucić do bazy danych lub zwró-cić użytkownikowi informację o błędnie wypełnionych polach;

• Przy obsłudze żądania możliwe jest zwrócenie dodatkowej funkcji Java-

Rysunek 7. Wygląd gotowego systemu zakładek

Rysunek 8. Wygląd gotowego systemu dodawania do obserwowanych

Page 29: PHP Solutions 01 2007 PL

XAJAX

www.phpsolmag.org 29

Dla zaawansowanych

PHP Solutions Nr 1/2007

Script, która zrealizuje bardziej za-awansowane zadanie (np. wyśle formularz, gdy ten zostanie spraw-dzony przez AJAX na obecność błędów);

• XAJAX porównuje dane, które mają zostać uaktualnione na stronie, z tymi, które już w danym miejscu się znajdu-ją. Jeżeli nic nie ulega zmianie, xajax nie podejmuje działań. W ten sposób

nie obserwujemy migania charaktery-stycznego dla aplikacji XAJAX opar-tych o model synchroniczny;

• Dla każdej z funkcji PHP może zostać przypisana inna metoda obsługi (POST lub GET). To pozwala zwiększyć nieco bezpieczeństwo całej aplikacji i zapo-biega przypadkowym błędom;

• Dane przesyłane pomiędzy klientem a serwerem są kodowane w standar-

dzie UTF-8. To zapewnia poprawną obsługę narodowych znaków diak-trycznych;

• XAJAX bardzo łatwo integruje się z wszelkimi systemami szablonowymi. Od strony systemu szablonowego ko-nieczne jest dodanie wyłącznie jednej zmiennej. W jej miejsce zostaną wy-generowane odwołania do skryptów JavaScript odpowiedzialnych za reali-zację żądań;

• XAJAX w bardzo dobry sposób ra-dzi sobie z wszelkimi skryptami Java-Script. Kod źródłowy strony przed i po wprowadzeniu tej biblioteki w życie nie różni się znacząco.

Instalacja XAJAXZadaniem tego artykułu jest zaprezento-wanie praktycznych rozwiązań, które moż-na niemal od zaraz wdrożyć na własną stronę. Zanim jednak przystąpimy do pro-gramowania, warto zapoznać się ze struk-turą biblioteki oraz dostępnymi metodami.

XAJAX można pobrać ze stro-ny mieszącej się pod adresem: http://www.xajaxproject.org/. Dokumentację doprojektu w formie wiki można odnaleźć pod adresem: http://wiki.xajaxproject.org/.

Do prawidłowej implementacji XAJAX potrzebne są trzy pliki. Dwa z nich pracu-ją po stronie serwera. Są to następujące skrypty PHP:

• xajax.inc.php – główna klasa biblio-teki;

• xajaxResponse.inc.php – klasa do ge-nerowania odpowiedzi;

• Po stronie klienta pracuje jeden skrypt JavaScript;

• xajax.js – klasa do obsługi żądań po stronie klienta;

Przyglądając się kodowi źródłowemu xa-jax.js łatwo zauważyć, iż został on po-zbawiony biały znaków. Ze względu na utrudnienia w dokonywaniu zmian w takim skrypcie udostępniono wersję z typowym formatowaniem – xajax_uncompressed.js. Do późniejszej kompresji posłuży bibliote-ka xajaxCompress.php.

Wymagania sprzętowe odnośnie bi-blioteki:

• Serwer Apache lub IIS (Windows XP/2003);

• PHP 4.3.x lub 5.x;• Przeglądarka IE 5.5, Firefox 1.0, Sa-

fari 1.3, Opera 8.5.

Listing 1. Kod źródłowy systemu zakładek

<?php

require('lib/xajax.inc.php');

function tabarea($tabId) {

sleep(1);

$objResponse = new xajaxResponse(); for($x=1; $x<=6; $x++) { $x == $tabId ? $className = 'active' : $className = '';

$objResponse->addScript("document.getElementById('tab".$x."').

className='$className'");

}

$objResponse->addAssign("maintabarea", "innerHTML",

implode('', file('tpl/tab_content_'.$tabId.'.html')));

return $objResponse->getXML();}

$xajax = new xajax();$xajax->registerFunction('tabarea');

$xajax->processRequests();

?>

<html>

[..]

<?=$xajax->printJavascript()?>

</head>

<body>

<script type="text/javascript"><!--

xajax.loadingFunction = function(){xajax.$('loading')

style.display='block';};

function hideLoadingMessage() { xajax.$('loading').

style.display='none'; }

xajax.doneLoadingFunction = hideLoadingMessage;

// --></script>

<div class="content"> <ul class="tabs" id="maintab">id="tab1" class="active"><a href="?show=tab1" onclick="xajax_tabarea('1'); return false;">Tab 1</a></li>

<li id="tab2"><a href="?show=tab2" onclick=

"xajax_tabarea('2'); return false;">Tab 2</a></li>

id="tab3"><a href="?show=tab3" onclick=

"xajax_tabarea('3'); return false;">Tab 3</a></li>

id="tab4"><a href="?show=tab4" onclick=

"xajax_tabarea('4'); return false;">Tab 4</a></li>

id="tab5"><a href="?show=tab5" onclick=

"xajax_tabarea('5'); return false;">Tab 5</a></li>

id="tab6"><a href="?show=tab6" onclick=

"xajax_tabarea('6'); return false;">Tab 6</a></li>

</ul>

<div class="insider"> <div id="loading">Ładowanie...</div>

<div id="maintabarea">

<? include('tpl/tab_content_1.html') ?>

</div>

</div>

</div>

</body>

</html>

Page 30: PHP Solutions 01 2007 PL

XAJAX

www.phpsolmag.org30

Dla zaawansowanych

PHP Solutions Nr 1/2007

Opis podstawowych metodZaletą biblioteki XAJAX jest możliwość bardzo szybkiego startu. Podczas co-dziennej pracy z XAJAX wykorzystamy stosunkowo niewielką ilość metod, będą-cych częścią dwóch klas PHP. Warto po-krótce nakreślić charakterystykę najważ-niejszych z nich.Klasa xajax (xajax.inc.php):

• debugOn() / debugOff() – włącza / wyłącza przydatny tryb usuwania błę-dów;

• registerFunction($nazwaFunkcji) lub registerFunction(array($nazwa-

Funkcji, $nazwaKlasy, $nazwaMetody)) – rejestruje funkcję PHP, do której będzie można odwołać się poprzez JavaScript;

• processRequests() – uruchamia silnik odpowiedzialny za obsługę przycho-dzących wywołań;

• printJavascript() / getJavascript – wyświetla / zwraca kod JavaScript, który musi zostać umieszczony w sek-cji head strony.

Klasa xajaxResponse (xajaxResponse.inc.php):

• addAssign($idElementu, $atrybut,

$dane) – pozwala na zamianę wartości elementu HTML o id $idElementu;

• addScript($kodJs) – uruchamia kod JavaScript umieszczony w zmiennej $kodJs;

• getXML() – zwraca odpowiedź do przeglądarki użytkownika;

• Część XAJAX odpowiedzialna za kod JavaScript (xajax.js) także posia-da swój zestaw metod. Wykorzystuje się je w kodzie HTML strony:

• x a j a x _ N a z w a F u n k c j i ( $ p 1 ,

$p2,...) – wywołuje zarejestro-waną funkcję PHP o nazwie Na-zwaFunkcji, przekazując parame-try $p1, $p2,....;

• xajax.getFormValues($idFormul

arza) – pobiera wszystkie dane, które użytkownik wpisał do formu-larza o id $idFormularza.

ZakładkiJednym z najbardziej praktycznych i naj-popularniejszych efektów stosowanych na stronach www są obecnie zakładki. Choć podobny mechanizm można zrealizować bez użycia techniki ajax, pokażemy jak

Listing 2. Kod źródłowy systemu zakładek

<?php

mysql_connect('localhost', 'root', 'root');

mysql_select_db('test');

require('lib/xajax.inc.php');

function fetchObserve($id) {

return @mysql_result(mysql_query('SELECT 1 FROM obserwowane WHERE article_id = "'.$id.'"'), 0);

}

function checkObserve($id) {

if(fetchObserve($id))

// zaprzestan obserwowania

return 'Nie obserwuj'; else

//rozpocznij obserwowanie

return 'Obserwuj'; }

function observe($id) {

if(fetchObserve($id))

mysql_query('DELETE FROM obserwowane WHERE article_id = "'.$id.'"');

else

mysql_query('INSERT INTO obserwowane

VALUES ("", "'.$id.'")');

$objResponse = new xajaxResponse(); $objResponse->addAssign($id,

"innerHTML", checkObserve($id));

return $objResponse->getXML();

}

$xajax = new xajax();$xajax->registerFunction('observe');

$xajax->processRequests();

?>

<html>

<head>

[..]

<?=$xajax->printJavascript()?>

</head>

<body>

<div class="content"> <h3>Tematy zbliżaj±cych się artykułów</h3>

<p style="color: red;">Klikaj±c na [..]</p>

<h5>51: Użyteczność[..]</h5>

<p>[..]</p>

<p><a href="" onclick="xajax_observe('51');

return false;" id="51"><?=checkObserve('51')?></a></p>

<h5>50: Okiełznać[..]</h5>

<p>[..]</p>

<p><a href="" onclick="xajax_observe('50');

return false;" id="50"><?=checkObserve('50')?></a></p>

<h5>49: SEO[..]</h5>

<p>[..]</p>

<p><a href="" onclick="xajax_observe('49');

return false;" id="49"><?=checkObserve('49')?></a></p>

</div>

</body>

Page 31: PHP Solutions 01 2007 PL

XAJAX

www.phpsolmag.org 31

Dla zaawansowanych

PHP Solutions Nr 1/2007

sługi JavaScript strona pracowała w mia-rę poprawnie. Stąd linki do kolejnych za-kładek posiadają parametry ?show=tabx. Oczywiście z uwagi na brak miejsca, w powyższym kodzie brakuje obsługi takiej sytuacji.

Poszczególne funkcje w XAJAX wy-wołuje się stosując konstrukcję xajax_

NazawFunkcji (Parametry). Jak łatwo za-uważyć, ilość kodu JavaScript zastosowa-nego w tym przykładzie jest znikoma. Za-stosowany dodatkowy parametr przy wła-ściwości onclik – return false powoduje, iż przeglądarka nie podąża za linkiem (ele-ment href). Parametr przekazywany do funkcji xajax_tabarea pozwala rozróżnić poszczególne zakładki, które odczytamy z plików szablonowych.

Pierwsza połowa Listingu 1 zawie-ra kompletny kod potrzebny do obsługi wszystkich zdarzeń. Programowanie roz-poczynamy od załadowania części biblio-teki XAJAX napisanej w PHP. Opuśćmy na chwilę deklarację funkcji tabarea, by przyjrzeć się instancji klasy xajax miesz-czącej się zaraz poniżej. Wszystkie funk-cje, które mają być zbierane przez bi-bliotekę JavaScript xajax muszą zostać uprzednio zarejestrowane. Nazwa funk-cji jest oczywiście zgodna z nazwą wystę-pującą w kodzie XHTML. Metoda proces-sRequest() generuje odpowiedni kod Ja-vaScript, który jest odpowiedzialny za ob-sługę żądań. Skompletowany w ten spo-sób kod JS wrzucamy sekcji HEAD do-kumentu XHTML, korzystając z funkcji printJavascript(). Wynik działania tej funkcji to dołączenie do strony części bi-blioteki XAJAX napisanej w JavaScript. Funkcja zwraca ponadto do kodu źródło-wego strony także wszystkie inne dane potrzebne bibliotece do obsługi żądań.

Ponieważ w systemie zakładek ma-my do czynienia wyłącznie z jedną funk-cją, do jej obsłużenia musimy odpowied-nio stworzyć jedną funkcję PHP. Nazwa 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-nej klasie. XajaxResponse odpowiada za generowanie odpowiedzi dla klienta. Pa-rametr wejściowy funkcji $tabId to liczba z zakresu 1-6. W kolejnych plikach mie-szących się w katalogu tpl umieszczona jest zawartość kolejnych zakładek. Oczy-wiście w tym miejscu można posłużyć się bazą danych lub bardziej skompliko-wanym skryptem do pobierania danych,

Listing 3. Kod źródłowy systemu logowania – część pracująca po stronie serwera

<?php

mysql_connect('localhost', 'root', 'root');

mysql_select_db('test');

define ('XAJAX_DEFAULT_CHAR_ENCODING',

'ISO-8859-2');

require('lib/xajax.inc.php');

if($_SERVER['QUERY_STRING'] == 'wszystko_ok_loguj') { echo 'yeah! zalogowany';

return 0;

}

function loginform($d) {

$objResponse = new xajaxResponse(); $email = $d['aEmail'];

$pass = $d['aPass'];

// pytam baze o istnienie loginu

$data = @mysql_fetch_array(mysql_query

('SELECT email, password, registered FROM

uzytkownicy WHERE email="'.$email.'"'));

if(!$email OR !$pass) $out = 'Proszę podać e-mail i login.';

else { if($email != $data['email']) { $out = 'Konto o podanym adresie nie istnieje.';

} else { if($pass != $data['password']) $out = 'Hasło do konta jest nieprawidłowe.'; else { if($data['registered'] == '0') $out = 'Użytkownik nie potwierdził rejestracji.';

else { $out = 'Proszę czekać. <b>Logowanie</b>...';

$objResponse->addScript('document.loginform.submit();');

}

}

}

}

$objResponse->addAssign("logblad", "innerHTML", $out);

return $objResponse->getXML();

}

$xajax = new xajax();$xajax->registerFunction('loginform');

$xajax->processRequests();

?>

ich wszędzie tam, gdzie dojdzie do zmian na stronie. Podstawowym kontenerem, do którego trafia tekst jest maintabarea. Jak łatwo zauważyć poprzedza go kontener loading, który domyślnie jest schowanych. W momencie, gdy XAJAX przystępuje do załadowania nowej zawartości, pojawia się informując użytkownika o trwającym procesie ładowania. Bez takiej informacji użytkownik może poczuć się zdezorien-towany. Dokument XHTML jest skonstru-owany tak, by nawet po wyłączeniu ob-

stworzyć zakładki, do których dane są po-bierane dopiero w momencie kliknięcia na nieaktywną zakładkę.

Tworzenie systemu zakładek rozpo-czynamy od zbudowania podstawowe-go kodu XHTML, składającego się z kilku kontenerów oraz listy punktowanej (druga połowa listingu 1). Przy użyciu stylów CSS dokonujemy zmiany wyglądu poszczegól-nych elementów, tak, by przypominały za-kładki. XAJAX rozpoznaje elementy po ich identyfikatorach, stąd istotne jest dodanie

Page 32: PHP Solutions 01 2007 PL

XAJAX

www.phpsolmag.org32

Dla zaawansowanych

PHP Solutions Nr 1/2007

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 obserwowanychKolejny przykład może wydawać się banalny, lecz jego zastosowanie jest nie do podważenia. Zakładamy, iż użyt-kownik jest zalogowany na naszej stro-nie. Chcemy mu umożliwić dokonywa-nie szybkich wyborów, polegających na dodawaniu wybranych zdjęć, artyku-łów, filmów do listy swoich ulubionych. W klasycznym wydaniu oznacza to ko-nieczność przeładowania strony. AJAX pozwala taką operacje przeprowadzić w tle. Użytkownik klika na element, któ-rym jest zainteresowany. Baza danych jest uaktualniana, a jego przycisk z do-daj do obserwowanych automatycz-nie zamienia się na usuń z obserwo-wanych.

Mechanizm widoczny na Listingu 2 jest bardzo zbliżony do tego, który ob-serwowaliśmy w pierwszym przykła-dzie. Posiadamy trzy przełączniki, od-wołujące się do funkcji o nazwie ob-serve. Ładując po raz pierwszy stronę pobieramy z bazy danych informacje o aktualnie ustawionych przełącznikach. Jeżeli rekord dla danego identyfikato-ra artykułu istnieje, wówczas przełącz-nik został już włączony. W ten sposób powstaje strona pamiętająca poprzed-nie ustawienia użytkownika. Klikając na przycisk na stronie, z bazy danych pobierana jest informacja o aktualnym stanie przełącznika i podejmowana jest akcja – dodanie lub usunięcie rekordu z informacją.

Listing 4. Kod źródłowy systemu logowania – część pracująca po stronie klienta

<html>

<head>

[..]

<?=$xajax->printJavascript()?>

</head>

<body>

[email protected]<br/>

mojehaslo<br/>

<div class="bar"> <h3>Zaloguj się</h3>

<form action="?wszystko_ok_loguj" method="post" class="login" name="loginform" id="loginform" style="margin:0;">

<table>

<tr>

<td><label for="name">E-mail:</label></td> <td class="f"><input type="text" name="aEmail" value=""></td>

</tr>

<tr>

<td><label for="name">Hasło:</label></td> <td class="f"><input type="password" name="aPass"></td>

</tr>

<tr>

<td></td>

<td style="text-align: right;"><div id=

"logblad"></div><input type="submit" value=

"Loguj" onclick="xajax_loginform

(xajax.getFormValues('loginform'));

return false;"></td>

</tr>

</table>

</form>

</div>

</body>

</html>

Rysunek 9. Wygląd gotowego systemu logowania

Page 33: PHP Solutions 01 2007 PL

XAJAX

www.phpsolmag.org 33

Dla zaawansowanych

PHP Solutions Nr 1/2007

LogowanieProces logowania na stronie www prze-biega szablonowo. Gdy użytkownik wy-pełni formularz, ten wysyłany jest meto-dą POST do serwera – użytkownik jest lo-gowany. Co się jednak dzieje, gdy wpisa-ny przez niego login lub hasło są niepra-widłowe? Użytkownik trafi czas, otrzymu-jąc komunikat o niepoprawnych danych dopiero po przeładowaniu strony. Stwórz-my zatem system logowania, który po wciśnięciu przycisku loguj sprawdzi po-prawność wprowadzonych danych. Jeże-li będą one poprawne, formularz zostanie wysłany metodą POST, a użytkownik zo-stanie zalogowany. Jeżeli dane będą nie-poprawne, użytkownik bez konieczności przeładowania strony otrzyma informację o niepoprawnym loginie, bądź haśle. Ten sposób rozumowania zapewnia, że nawet przy wyłączonej obsłudze AJAX użytkow-nik będzie mógł skorzystać z usługi.

W poprzednich przykładach pominę-liśmy kwestię kodowania. Problem nie był zauważalny. By dane przesyłane z serwera poprzez XAJAX miały popraw-ne kodowanie, należy ustalić domyślny standard kodowania.

Mechanizm działania tego przykładu uwzględnia nową właściwość, a miano-wicie pobieranie danych, które użytkow-nik wprowadził do formularza. Na koń-cu Listingu 4 widoczne jest odwołanie do skryptu JS odpowiedzialnego za obsłu-gę żądania. Wewnątrz funkcji xajax_lo-

ginform znajduje się metoda xajax.get-FormValues, gdzie jej parametrem jest identyfikator przypisany do formularza. To właśnie ta linijka jest esencją tego przykładu. Do funkcji loginform widocz-nej na Listingu 3 trafiają wszystkie dane wprowadzone przez użytkownika w for-mie tablicy asocjacyjnej $d. Na podsta-wie danych, które wprowadził użytkow-nik pobieramy z bazy danych użytkowni-ków informacje. W tym przykładzie może rozpatrujemy zbyt dużą ilość przypadków w których użytkownik popełnia błąd, lecz ma to na celu pokazanie jak szybko i ła-two przekazać użytkownikowi informację o niepoprawnym wprowadzeniu danych. Dopiero, gdy informacje są w pełni po-prawne, następuje logowanie. Polega ono na wyświetleniu informacji proszę czekać oraz uruchomieniu skryptu, który automatycznie wyśle formularz.

PodsumowanieXAJAX to biblioteka, która pozwala pro-gramiście przejść od nauki do programo-wania po zaledwie kwadransie. Popraw-ne działanie oraz pełnia automatyzacja sprawia, iż implementacja technik opar-tych o AJAX staje się nieskomplikowana i przez to osiągalna dla każdego. W XA-JAX-ie urzeka nie tylko prostota i efektyw-ność działania, lecz także mała inwazyj-ność w kod już istniejących aplikacji. Przy-kładem na to jest kod JavaScript, o któ-rym praktycznie zapomina się w momen-

cie dołączenia biblioteki xajax.js do sekcji head strony. Pozostałe czynności związa-ne z JS ograniczają się już tylko do two-rzenia odwołań do funkcji PHP. XAJAX spisuje się dobrze, nawet gdy pod uwa-gę wziąć kwestię obsługi rodzimych zna-ków diaktrycznych. Bibliotekę tą można uznać za idealną dla wszystkich tych pro-gramistów PHP, którzy cenią sobie stałość i przewidywalność środowiska programi-stycznego jakim jest język PHP. Umiejęt-nie napisany kod PHP do obsługi XAJAX pozwala na bardzo szybkie zmiany, dzię-ki czemu nakłady dodatkowej pracy przy usuwaniu usterek są minimalne. W arty-kule udało się pokazać tylko najpopular-niejsze metody oferowane przez bibliote-ki XAJAX. Więcej informacji o pozostałej funkcjonalności biblioteki można znaleźć w dokumentacji. n

Paweł Grzesiak jest projektantem wi-tryn internetowych z sześcioletnim do-świadczeniem. Zajmuje się tworzeniem rozbudowanych witryn w oparciu o sys-tem CMS własnego autorstwa. Jest au-torem ponad 50 publikacji w Magazynie Internet, Internet Maker oraz phpSolu-tions. Obecnie pracuje nad książką, która ukaże się nakładem wydawnictwa Helion pod koniec tego roku.

Kontakt: [email protected]

O autorze

R E K L A M A

Page 34: PHP Solutions 01 2007 PL

www.phpsolmag.org34 PHP Solutions Nr 1/2007

Dla zaawansowanych

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

Reflection API Dla zaawansowanych

Istnieją techniki programistyczne uła-twiające tworzenie kodu, którego prawie nie trzeba modyfikować w

momencie, gdy pojawią się jakieś nowe wymagania. Wiele z tych technik opisy-wałem w poprzednich artykułach( Serwi-ce Data Objects czyli uniwersalny stan-dard dostępu do danych cześć pierwsza i druga, Wzorce projektowe w akcji czy-li czyli ciąg dalszy niezbędnika dewelo-pera PHP, Zenda Framework,Budujemy własny kontener IoC, czyli jak to się robi w Hollywood), w tym chciałbym się sku-pić na Reflection API i możliwościach jego zastosowania w aplikacjach webo-wych.

Czym jest Reflection APIReflection API to zestaw klas i funkcji przy pomocy, których programista mo-że zdobyć informację o budowie dowol-nej klasy, obiektu lub funkcji, wbudowa-nej w PHP lub napisanej w PHP. Jeże-

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ć.

li istnieje taka potrzeba można przy je-go pomocy powołać do życia instancję dowolnej klasy, wykonać publiczną me-todę dowolnego obiektu lub wykonać dowolną funkcję. Reflection API bywa bardzo przydatnym narzędziem w każ-dej sytuacji, gdy z pewnych powodów podczas tworzenia kodu nie możemy bezpośrednio wywołać jakieś metody lub funkcji. Na przykład dlatego, że nie znamy jej nazwy lub listy parametrów, a wiemy, że poznamy je dopiero pod-czas wykonywania programu. Najczę-ściej ma to miejsce w przypadku frame-worków gdzie nieznajomość klas i funk-

Budowanie obiektów z requestu przy pomocy Reflection APIPiotr Szarwas

Stopień trudności: lll

Co powinieneś wiedzieć:Należy znać zasady projektowania obiek-towego w PHP 5.

Co obiecujemy:Pokażemy jak budować aplikacje odpor-ne na zmiany wymagań.

Page 35: PHP Solutions 01 2007 PL

www.phpsolmag.org34 PHP Solutions Nr 1/2007

Dla zaawansowanych

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

Reflection API Dla zaawansowanych

cji aplikacji zbudowanej na danym fra-meworku jest czymś naturalnym. Rza-dziej można znaleźć zastosowanie dla Reflection API w typowych aplikacjach. Aby lepiej je zrozumieć przyjrzyjcie się prostemu przykładowi (Listing 1), w któ-rym front kontroler aplikacji ma za zada-nie na podstawie zewnętrznych parame-trów powołać do życia jakąś klasę i wy-wołać na niej metodę command z para-metrami.

Oczywiście przykład ten nie pokazu-je wszystkich możliwości Reflection API, pokazuje jednak sedno jego możliwości – powoływanie do życia dowolnych obiek-tów i wywoływanie na nich dowolnych

publicznych metod sprawdzając dodat-kowo czy metoda istnieje i jest publiczna. Pełne opisanie czym jest Reflection API i do czego można by je zastosować mo-gło by zapewne stanowić pokaźny roz-dział jakiejś książce, dlatego nie oczekuj-cie, że zmieści się on w jednym artyku-le. Wszystkich zainteresowanych zazna-jomieniem się ze szczegółami API od-syłam do dokumentacji na stronie http://www.php.net/manual/en/language.oop5.reflection.php. Znajdziecie tam też wiele przykładów pokazujących jak stosować Reflection API.

Reflection API jest stosunkowo świe-żym elementem PHP, pojawiło się dopie-

ro w wersji 5.0. Zapewne dlatego jest ma-ło znane. Od momentu swojego pojawie-nia się jest stale rozbudowywane o nowe klasy i metody. Dlatego jeżeli na prawdę będziecie chcieli korzystać z tego narzę-dzia polecam używanie ostatniej stabilnej wersji PHP jaka jest dostępna. Jeżeli nie macie takich możliwości na stronach PHP znajdziecie dokładne informacje o tym, które funkcjonalności API są dostępne w której wersji. Dodam, że cały kod napisa-ny na potrzeby tego artykułu był urucha-miany w środowisku PHP 5.1.6 i niestety nie wiem jak zachowa się we wcześniej-szych wersjach PHP.

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.

Świat przed Reflection APIZanim 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-czenia. Po pierwsze jest mniej elastycz-ne gdyż wymaga dokładnej znajomości

Rysunek 2. Schemat blokowy algorytmu budowy obiektów biznesowych aplikacjiz danych pochodzących z formularza, wraz z przykładowym przebiegiem

�����

��������������

�����

������

�������

�����

��������

����������������

�����������������

��������������

��������������������

����

������

������

������

�����

������

��������������������

�����������������������

������������������

�������������������������

��������������������������

��������������������������

��������������

��������

���������

�������

����������

��������

���������

�������

����������

�����

������

����

�������

��������

���������

�������

����������

�����

������

����

�������

����

����

Rysunek 1. Schemat procesu mapowania danych pochodzących z formularza na obiekty biznesowe

Page 36: PHP Solutions 01 2007 PL

www.phpsolmag.org36 PHP Solutions Nr 1/2007

Reflection APIDla zaawansowanych

ilości parametrów zarówno w przypadku konstruktora jak i metody, którą chce-my w ten sposób wywołać. Po drugiew przypadku błędu PHP przerwie wyko-nywanie kodu i zwróci Fatal Error, które-go nie możemy kontrolować. Jeżeli za-stosujemy Reflection API każde niepo-wodzenie będzie sygnalizowane przy pomocy wyjątku, który możemy złapać i obsłużyć.

Budowanie obiektówz requestuSpróbujmy teraz zdobytą wiedzę o Re-flection API wykorzystać do rozwiązania pewnego problemu. Wyobraźcie sobie, że na wielu stronach waszej aplikacji wy-stępuje formularz, za każdym razem in-ny. Formularz ten w kodzie mapowany jest do obiektu, a obiekt jest dalej wali-dowany, zapisywany, modyfikowany lub

kasowany wszystko zależy od akcji po-wiązanej z danym formularzem. Proces mapowania jest konieczny gdyż chcemy oddzielić funkcje biznesowe aplikacji od specyfiki warstwy prezentacji WWW. Wy-konywanie mapowania ręcznie jest bar-dzo żmudnym zajęciem podczas, które-go może pojawić się wiele błędów. Do-datkowo jeżeli, któryś z obiektów lub for-mularzy ulegnie zmianie, mapowanie też

Listing 1. Implementacja prostej klasy front kontrolera, której przy pomocy Reflection API powoływane są obiekty klas akcji, a następnie na każdym z nich wywoływana jest metoda command

class FrontController { public function doService(HttpRequest $request){

if ($request==null){ return null; }

$className = $request->

getVar();

$classObj = $this->createObject($className);

return $this->invokeMethod($classObj,"command"

,$request);

}

private function createObject($className){

if ($className==null){ return null; }

//Zakładamy że plik z klasą jest już załadowany

$relfObj = new ReflectionClass($className);

if (!$relfObj->isInstantiable()){ return null; }

//Zakładamy że konstruktor

nie ma parametrów

return $relfObj->newInstance();

}

private function invokeMethod($object,$method

Name,$parameters){

if ($object==null || $methodName==null){

return null; }

//Zakładamy że plik z klasą

jest już załadowany

$relfObj = new ReflectionObject($object);

if (!$relfObj->hasMethod($methodName)){

return null; }

return $relfObj->getMethod($methodName)->invoke

($object,$parameters);

}

}

Listing 2. Klasy biznesowe wykorzystywane w przykładzie. Ich charakterystyczną cechą jest to że dostęp do ich atrybutów odbywa się poprzez settery i gettery

class Group { private $name; public function __construct() {

}

public function setName($name){

$this->name = $name; }

public function getName(){ return $this->name; }

}

class News { private $title; private $author; private $date; private $content; public function __construct() {

}

public function setTitle($title){

$this->title = $title; }

public function getTitle(){ return $this->title; }

public function setAuthor($author){

$this->author = $author; }

public function getAuthor(){ return $this->author; }

public function setDate($date){ $this->date = $date; }

public function getDate(){ return $this->date; }

public function setContent($content){

$this->content = $content; }

public function getContent(){ return $this->content; }

}

Page 37: PHP Solutions 01 2007 PL

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

Reflection API Dla zaawansowanych

musi uleć zmianie, tak więc aplikacja nie jest odporna na tego typu zmiany. Spró-bujmy więc zautomatyzować proces ma-powania, tak aby był on niezależny od zawartości formularza i budowy obiek-tu do którego dany formularz jest mapo-wany. Oczywiście wykorzystamy do tego zadania Reflection API. Aby zobrazować cały problem lepiej posłużyć się przy-kładem, w którym news będzie doda-wany do bazy danych. Formularz new-sa zawiera następujące pola: grupa, ty-tuł, autor, data, treść. Formularz ten bę-dzie mapowany do dwóch obiektów: gru-py i newsa (Rys.1).

Kod mapujący składa się z jednej me-tody bind, która ma dwa parametry. Pierw-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).

bind($request, $object);

Zmienna $request jest jedynie sumą tablic $_GET i $_POST. Zasada działania metody jest następująca (Rys.2):

l przy pomocy Reflection API pobie-ramy z obiektu informację o wszyst-kich publicznych setterach, w naszym przypadku będą to wszystkie settery obiektów klas Group i News;

l dla każdego setera sprawdzamy czy w requescie jest zmienna, która od-powiada nazwie settera z pominię-ciem ciągu „set ” i zmianą pierwszej litery na małą w pozostałej części settera, czyli setTitle zmieni się na title;

l przy pomocy Reflection API wywo-łujemy odpowiedniego setter z odpo-wiednią wartością z requestu;

l proces powtarzamy aż ostatni setter zostanie ustawiony.

Jak łatwo zauważyć zaproponowany al-gorytm ma tylko dwa wymagania, jeże-li chcemy ustawić jakąś zmienną musi-my mieć zdefiniowany dla niej settera i nazwa parametru w requescie musi być poprzez swoją nazwę skorelowana z set-terem. Nie są to założenia, które wpro-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

Listing 3. Zawiera kod prostszej wersji metody bind

class SimpleBinder { public static function bind($request, $object){ if($request==null || !is_array($request) || $object==null){ return null; }

//Tworzymy obiekt Reflection API

$reflectionObject = new ReflectionObject($object); //Pobieramy informacje o wszystkich metodach obiektu

$methods = $reflectionObject->getMethods();

foreach($methods as $method){

//Sprawdzamy czy metoda jest publicznym setterem

$methodName = $method->getName();

if (substr($methodName,0,3)=="set" && $method->isPublic()){ //Na postawie settera tworzymy nazwę pola

$fieldName = strtolower($methodName[3]).substr($methodName,4);

//Sprawdzamy czy w requescie jest zmiena o nazwie pola

if (isset($request[$fieldName])){ $method->invoke($object,$request[$fieldName]);

}

}

}

}

}

Listing 4. Klasy biznesowe wykorzystywane w przykładzie

class Address { private $country; private $town; private $street; private $zipCode; private $flatNumber; public function setCountry($country){ public function getTown(){ return $this->town; }

public function setStreet($street){ $this->street = $street; }

public function getStreet(){ return $this->street; }

public function setZipCode($zipCode){ $this->zipCode = $zipCode; }

public function getZipCode(){ return $this->zipCode; }

public function setFlatNumber($flatNumber){ $this->flatNumber = $flatNumber; }

public function getFlatNumber(){ return $this->flatNumber; }

}

class Person { private $nameFirst; private $lastName; private $address; public function __construct() { $this->address = new Address(); }

public function setFirstName($firstName){

Page 38: PHP Solutions 01 2007 PL

www.phpsolmag.org38 PHP Solutions Nr 1/2007

Reflection APIDla zaawansowanych

związanych z dostępem do atrybutów obiektu poprzez settery i gettery.

Cały kod metody bind przedstawiony jest na Listingu 3. Jak widać nie jest dłu-gi. Na samym początku sprawdzamy czy parametry metody są poprawne, następ-nie inicjalizujemy obiekt ReflectionObject, który zawiera metainformacje o naszym obiekcie. Wydobywany z niego tablicę

wszystkich metod w postaci obiektów ty-pu ReflectionMethod. Dla każdego obiek-tu ReflectionMethod sprawdzamy czy w requescie istnieje klucz odpowiadający nazwie settera. Jeżeli tak to przy pomocy metody invoke obiektu ReflectionMethod ustawiamy wartość spod tego klucza.

Metoda bind jest odporna na wiele zmian związanych z zawartości obiek-

tu, na przykład bez problemu może-cie dodać lub usunąć dowolne pole z obiektu newsa i kod bindera pozosta-nie bez zmian. Niestety nasz binder ma jedną poważną wadę, nie obsługu-je ustawiania zmiennych na zagnież-dżonych obiektach. Co mam na myśli? Wyobraźcie sobie prosty przykład, ma-my obiekt klasy Person (Listing 4) za-wierający w sobie obiekt klast Address. Zakładając, że z requestu nie przycho-dzą obiekty, a jedynie łańcuchy znako-we nie możemy obsłużyć ustawienia atrybutów dla obiektu klasy Address. Ich charakterystyczną cechą jest to że dostęp do ich atrybutów odbywa się poprzez settery i gettery.

Dodatkowo klasa Person w swoim konstruktorze inicjuje obiekt klasy Ad-drese dzięki temu metoda getAddress zawsze zwróci obiekt Dlatego na ko-lejnym listingu (Listing 5) umieszczo-na jest wersja algorytmu, który roz-wiązuje ten problem. Do poprzednich dwóch założeń związanych z jego dzia-łaniem dodałem jeszcze dwa. Pierw-sze, które mówi jak nazywać zmienne, które są zagnieżdżone. Jeżeli chce-my ustawić taką zmienną musimy po-dać do niej pełną ścieżkę w posta-ci „obciętych” nazw getterów i sette-rów oddzielonych kropkami. Na przy-kład dla atrybutu street w obiekcie ad-dress w requesie będzie musiał istnieć klucz address.street, co w normalnym odwołaniu w kodzie odpowiada nastę-pującemu wywołaniu getAddress()-

>setStreet($wartość). Drugie, któ-re mówi że obiekty wewnętrzne mu-szą być wstępnie inicjowane (tak jak ma to miejsce na listingu pokazującym obiekt Person (Listing 4)). To założenie wynika z faktu, że bez wstępnej inicja-lizacji wywołanie kodu getAddress()-

>setStreet($wartość) nie powiodło-by się bo getAddress zwróciłoby war-tość NULL.

Jak widać tym razem algorytm nie jest już taki prosty. Ze względu na ko-nieczność obsłużenia zagnieżdżonych atrybutów zmieniliśmy sposób iteracji tym razem wykonujemy ją po każdym kluczu znajdującym się w requescie. Dla każdej 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-

Listing 4a. Klasy biznesowe wykorzystywane w przykładzie

$this->firstName = $firstName; }

public function getFistrName(){ return $this->firstName; }

public function setLastName($lastName){ $this->lastName = $lastName; }

public function getLastName(){ return $this->lastName; }

public function setAddress($address){ $this->address = $address; }

public function getAddress(){ return $this->address; }

}

Listing 5. Zawiera kod wersji metody bind umożliwiającej mapowanie zagnieżdżonych obiektów

class ComplexBinder { public static function bind($request, $object){ if($request==null || !is_array($request) || $object==null){ return null; }

//Tworzymy obiekt Reflection API

$reflectionObject = new ReflectionObject($object); foreach($request as $attrName => $attrValue){

//Zakładamy że możemy składać zagnieżdzone obiekty

$dotPosition = strpos($attrName,".");

if ($dotPosition===false){ //Jeżeli atrybut nie jest zagnieżdzony to sprawdzamy

czy obiekt ma opowiedniego settera i ustawiamy

dla niego wartość

$setterName = "set".ucwords($attrName);

$setterObj = $reflectionObject->getMethod($setterName);

if ($setterObj!=null && $setterObj->isPublic()){ $setterObj->invoke($object,$attrValue);

}

} else { //Jeżeli mamy doczynienia z zagnieżdzonym atrybutem

to pobieramy ten atrybut i na nim ustawiamy odpowiednią wartość

$getterName = "get".ucwords(substr($attrName,0,$dotPosition));

$getterObj = $reflectionObject->getMethod($getterName);

if ($getterObj!=null && $getterObj->isPublic()){ $nestedObject = $getterObj->invoke($object);

self::bind(array(substr($attrName,$dotPosition+1)

=>$attrValue),$nestedObject);

}

}

}

}

}

Page 39: PHP Solutions 01 2007 PL

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

Reflection API Dla zaawansowanych

dający w nazwie kropkę, to z części na-zwy przed pierwszą kropką tworzymy na-zwę gettera i przy jego pomocy pobiera-my obiekt odpowiadający getterowi. Na-stępnie na tym obiekcie wywołujemy me-todę bind. Zwróćcie uwagę, że w dzięki rekurencyjnemu wywołaniu metody bind nasz algorytm obsługuje dowolnie dłu-gie ścieżki. Może na przykład mieć struk-turę obiektów, której odpowiada ścieżka: obiekt1.obiekt2.obiekt3.atrybut1.

FlexiMam nadzieje, że część z was śledzi całą serię artykułów o wzorcach i do-brych praktykach programistyczny i wie że cały kod, który pojawia się w ramach tych artykułów jest publikowany na sour-ceforge pod szyldem frameworka o na-zwie Flexi (http://flexi.sourceforge.net/).

Tym razem nie będzie inaczej, ale jako, że przedstawiony do tej pory kod jest oderwany od całości frameworku chciał-bym w kliku zdaniach napisać gdzie jest on umieszczony w Flexi. Metoda bind będzie częścią abstrakcyjnej klasy akcji, dzięki czemu w każdej klasie akcji dzie-dziczącej po tym obiekcie programista będzie mógł wywołać tą metodę. Do-datkowo jeżeli ktoś nie będzie chciał ko-rzystać z abstrakcyjnej klasy akcji meto-da będzie dostępne w klasie FLReflec-tionUtils.

PodsumowaniePrzedstawiony powyżej przykład jest tylko namiastką możliwości Reflecion API. Mam jednak nadzieje, że udało mi się zwrócić waszą uwagę na ten bar-dzo pożyteczny moim zdaniem element

PHP. Możliwości zastosowania Reflec-tion API można wymieniać długo. M.in. można budować formularze z obiektów, listy prezentujące dane, automatycznie budować pytania zapisujące i modyfi-kujące dane w bazie. n

Piotr Szarwas ma wieloletnie doświad-czenie w programowaniu i tworzeniu apli-kacji WWW (PHP, Java). Jest konsultan-tem w jednej z największych polskich firm IT, a także doktorantem na Wydzia-le Fizyki Politechniki Warszawskiej. Od dawna pisze artykuły dla PHP Solutions.

Kontakt z autorem:[email protected]

O autorze

R E K L A M A

Page 40: PHP Solutions 01 2007 PL

www.phpsolmag.org40 PHP Solutions Nr 1/2007

Dla zaawansowanych

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

Model aplikacji Dla zaawansowanych

W modelu tym istnieje tylko umowne podzielenie aplika-cji na części i hierarchię. Do-

konywanie zmian w takim modelu jest dość uciążliwe z powodu dużych powią-zań występujących wewnątrz kodu. Był to podstawowy powód dla którego po-wstał model warstwowy.

Opis warstw modeluModel będący przedmiotem niniejszego artykułu składa się z kilku warstw. Klu-czowym krokiem jest logiczne ich zdefi-niowanie w stadium projektowania apli-kacji. Przykładowy i dość często stoso-wany model składa się z czterech war-stw(rysunek 1): dostępu do danych, biz-nesowej, serwisów i interfejsu użytkow-nika. W warstwie dostępu do danych powinny znajdować się modele (obiek-ty, tablice asocjacyjne itp.), z których będziemy korzystać w aplikacji. War-stwa biznesowa to zbiór funkcji wyko-nujących określone zadania na mode-

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.

lach z warstwy danych. Warstwa serwi-sów udostępnia zestawy funkcji pośred-niczące między warstwą biznesową,a interfejsem użytkownika. Ostatnia war-stwa – prezentacji – służy do wizualiza-cji danych, które zostały przetworzone przez niższe warstwy modelu.

W tym artykule opiszę sposób imple-mentacji aplikacji modelu warstwowego na przykładzie katalogu samochodowe-go, który następnie rozszerzę o kolejny obiekt – motocykl. Przed rozpoczęciem omawiania modelu warstwowego na kon-kretnym przykładzie należy utworzyć ta-

Warstwowy model aplikacjiPaweł Klimczyk

Stopień trudności: lll

Co obiecujemy:Nowoczesne spojrzenie na tworzenie średnich i dużych aplikacji. Sposób na proste zarządzanie kodem aplikacji.

Co powinieneś wiedzieć:Zaawansowane techniki programowania. Podstawy baz danych. Logiczne myśle-nie w czasie procesu projektowania.

Page 41: PHP Solutions 01 2007 PL

www.phpsolmag.org40 PHP Solutions Nr 1/2007

Dla zaawansowanych

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

Model aplikacji Dla zaawansowanych

belę, gdzie będą przechowywane dane samochodów.

CREATE TABLE Cars

(

idCar INTEGER NOT NULL

AUTO_INCREMENT,

model VARCHAR(25) NOT NULL,

engineNumber VARCHAR(50)

NOT NULL,

wieght VARCHAR(16) NOT NULL,

color VARCHAR(20) NOT NULL,

PRIMARY KEY(idCar)

);

Warstwa dostępu do danychWarstwa dostępu do danych (DAL – Data Access Layer) to najniżej leżąca warstwa modelu. Zawiera ona obiek-ty reprezentujące dane wykorzystywa-ne w programie. Wszystkie informacje, nie zależnie od sposobu ich przecho-

wywania (baza danych, pliki) powin-ny mieć swoje odzwierciedlenie mo-delowe w warstwie DAL. Przykładowąimplementację warstwy DAL można zobaczyć na Listingu 1.

Plik zawiera definicję klasy Car. Nazwy składowych są takie same jak nazwy pól w bazie danych. Na tym etapie implementacji nie ma jeszcze żadnych funkcji – są definiowane w warstwie BLL.

Warstwa biznesowaCelem tworzenia warstwy biznesowej jest budowa zestawu funkcji używa-jących danych z warstwy DAL. Funk-cje te powinny wykonywać podstawowe zadania, np. uzyskać konkretny obiekt, do którego odwołują się warstwy wyż-sze, uzyskać listę obiektów bądź wyko-nać na obiekcie jakiekolwiek przekształ-cenie (edycję) zapisane następnie w wy-branej przez programistę formie. Do-brym zwyczajem jest grupowanie od-powiednich funkcji w klasy managerów. Przykładowo carManager będzie klasą warstwy biznesowej zawierającą funk-cje odnoszące się do wszystkich opera-cji na obiekcie Car. Dzięki takiemu roz-wiązaniu programista, bądź zespół pro-gramistów będzie odruchowo wiedział

Tabela 1. Warstwa dostępu do danych

Presentation Layer

Services Layer

Business Logical Layer

Data Access Layer

Listing 1. Przykładowa implementacja warstwy DAL

car.inc

<?php

class Car{

var $id;

var $model;

var $engineNumber;

var $weight;

var $color;

}

?>

Rysunek 1. Warstwa prezentacji

gdzie szukać/poprawiać/dodawać funk-cje do konkretnych obiektów. Przykłado-wa implementacja warstwy BLL znajduje się na Listingu 2.

Kod na listingu 2 zawiera kilka pod-stawowych funkcji ułatwiających mani-pulację obiektem i listą obiektów Car. Nazwy funkcji zostały dobrane zgodnie z ich działaniem. Funkcja AddCar do-daje obiekt do bazy danych, DeleteCar usuwa z bazy, UpdateCar aktualizujeinformacje, GetCarById odczytuje infor-macje o samochodzie o identyfikatorze idCar podanym w parametrze. Wszystkie wymienione powyżej funkcje wykonują operacje na pojedynczym obiekcie Car. Jedyny wyjątek w klasie carManager sta-nowi funkcja GetCarList, która zwracalistę obiektów. Funkcja ta będzie następ-nie używana do dostarczenia danych na potrzeby przeglądania wszystkich skata-logowanych w bazie samochodów.

Klasa carManager korzysta z klasy sqlManager, która jest interfejsem po-średniczącym między aplikacją, a źró-dłem danych. Klasa sqlManager zosta-ła zdefiniowana osobno, ponieważ jej funkcje mogą być z powodzeniem użyte w innych klasach warstwy BLL, których istnienie w obecnej fazie projektu nie zo-stało przewidziane.

Warstwa serwisówWarstwa serwisów (Service Layer) jest interfejsem dla warstwy prezentacji. Jej zadaniem jest zarówno dostarcze-nie warstwie BLL zwalidowanych obiek-tów, które mają np. zostać zapisane w bazie danych, jak również udostępnie-nie warstwie prezentacji danych, któ-re zostały np. posortowane bądź prze-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 została wprowadzona prosta walidacja

Page 42: PHP Solutions 01 2007 PL

Model aplikacji

www.phpsolmag.org42

Dla zaawansowanych

PHP Solutions Nr 1/2007

Listing 3. Przykładowa warstwa serwisów

?php

require ($config["ManagerDir"].

"carManager.inc");

class carService{

function getCarById($idCar)

{

$carManager = new carManager; return $carManager->GetCarByID($idCar);

}

function getCarList()

{

$carManager = new carManager; return $carManager->GetCarList(); }

function deleteCar($idCar)

{

$carManager =

new carManager; return $carManager->DeleteCar($idCar);

}

function updateCar($car)

{

$carManager = new carManager; $carManager->updateCar($car);

ShowInfo

("Car successfully updated!");

return; }

function addCar($car)

{

if(strlen($car->model)<3 || strlen($car->

engineNumber)<3 || strlen

($car->weight)<3

|| strlen($car->color)<3)

{

ShowError("Fill all data!");

}

else {

$carManager =

new carManager; $carManager->addCar($car);

ShowInfo

("Car successfully added!");

}

return ; }

}

?>

otrzymanych od użytkownika danych. Użyte zostały funkcje ShowInfo oraz Sho-wError, których celem jest komunikacja z użytkownikiem.

Warstwa prezentacjiKiedy stworzone są już solidne fun-damenty (BLL) do wykonywania ope-racji na danych(DAL) przy użyciuodpowiednich interfejsów (Serwisy)

Listing 2. Implementacja warstwy BLL

carManager.inc

<?php

/*

Car Manager

*/

require_once 'sqlManager.inc';

class carManager{

function GetCarByID($idCar)

{

$sqlManager= new sqlManager(); $sqlManager->createConn();

return $sqlManager->QueryObj("SELECT *

FROM cars where idCar=".$idCar);

}

function GetCarList()

{

$arr = array();

$sqlManager= new sqlManager(); $sqlManager->createConn();

$obj=$sqlManager->QueryArray

("SELECT *

FROM cars");

while ($row = mysql_fetch_object($obj)) {

$arr[]=$row;

}

return $arr; }

function UpdateCar($car)

{

$sqlManager=

new sqlManager(); $sqlManager->createConn();

$sqlManager->updateObj

(sprintf("UPDATE cars SET

`model`='%s' ,

`engineNumber`='%s' , `weight`=

'%s' , `color`='%s' WHERE

`idCar`='%s'",

$car->model,$car->engineNumber,

$car->weight,$car->color,$car

->idCar));

}

function DeleteCar($idCar)

{

$sqlManager= new sqlManager(); $sqlManager->createConn();

$sqlManager->deleteObj(sprintf

("DELETE FROM cars where idCar=

%s",$idCar));

}

function AddCar($car)

{

$sqlManager= new sqlManager(); $sqlManager->createConn();

$sqlManager->addObj(sprintf

("INSERT INTO

cars ( `idCar` , `model` ,

`engineNumber` , `weight` ,

`color`) VALUES (

'', '%s', '%s', '%s', '%s')",$car-

>model,$car-

>engineNumber,$car->weight,

$car->color));

?>

należy zatroszczyć się o ich wizuali-zację użytkownikowi. Zadanie to jest realizowane w warstwie prezenta-cji. Programista nie musi przejmować się jak wyciągnąć potrzebne dane.Wystarczy, że wywoła odpowiednią– stworzoną wcześniej w warstwie serwisów – funkcję. Na Listingu 4 została przedstawiona przykładowaimplementacja warstwy prezentacji.

Page 43: PHP Solutions 01 2007 PL

Model aplikacji

www.phpsolmag.org 43

Dla zaawansowanych

PHP Solutions Nr 1/2007

Paweł Klimczyk jest pasjonatem tech-nicznym. W kręgu głównych zaintere-sować komputerowych znajduje się: tworzenie aplikacji webowych (asp.net, php), wszelakie aspekty bezpieczeń-stwa i administracja serwerowa syste-mów Linux. Aktualnie pracuje w firmie o globalnym zasięgu – TRW Automotive –na stanowisku programisty i rozwija apli-kacje wewnętrzne firmy.

Kontakt z autorem: [email protected]

O autorze

Jak widać przedstawienie listy ska-talogowanych samochodów jest dziecin-nie prostym zadaniem. Sprowadza się do stworzenia obiektu serwisu i wywoła-nia jego metody getCarList. W efekcie w zmiennej carArray otrzymujemy listę sa-mochodów zapisanych w bazie danych. Efekt działania warstwy prezentacji widać na Rysunku 2.

Ewolucja aplikacjiProjekty programistyczne często nie posiadają sztywno narzuconych granic funkcjonalności. Jest to podyktowane różnymi względami, niekoniecznie zro-zumiałymi przez zespół programistycz-ny. Z biznesowego punktu widzenia w aplikacji, która posłużyła za przykład do tego artykułu przydałby się rów-nież katalog innych środków transpor-tu, np. motocykli bądź rowerów. Oczy-wiście w każdym modelu aplikacji (np. warstwowym lub monolitycznym) jest możliwość dodania takiej funkcjonal-ności. Kluczowym aspektem jest tutaj czas, w jakim programista może tego

dokonać. Aplikacja o charakterze mo-nolitycznym z pewnością będzie mno-żyć pytania w stylu:„Dlaczego funk-cja getCarById zwraca sformatowa-ny tekst HTML, a nie obiekt? I gdzie ona jest w ogóle zdefiniowana?!”. Na-tomiast w przypadku aplikacji warstwo-wej zapewne od razu – nawet średnio-zaawansowanemu programiście – rzu-ci się w oczy logiczne ułożenie całe-go projektu. W związku z czym, będzie mu zdecydowanie łatwiej dodać nową funkcjonalność.

PodsumowaniePrzedstawiony w tym artykule spo-sób modelowania aplikacji jest prze-znaczony zdecydowanie dla aplikacji średnich bądź dużych. Użycie mode-lu warstwowego w aplikacjach mniej-szych można porównać do celowania z armaty do muchy, aczkolwiek należy w fazie projektu przemyśleć, czy cza-sem mały z pozoru projekt nie nosi znamion większego serwisu. Uważny czytelnik z pewnością zauważył, że w

projekcie służącym za przykład wyko-rzystania modelu warstwowego zosta-ły pominięte aspekty bezpieczeństwa, graficznej prezentacji danych, a funk-cjonalność katalogu przedstawia wie-le do życzenia. Jest to zamierzone działanie, mające na celu nie zaciem-nianie głównego tematu artykułu. Po-wyższe aspekty zostały świadomie pominięte. n

R E K L A M A

Page 44: PHP Solutions 01 2007 PL

PHP Solutions Nr 1/2007

Narzędzia

www.phpsolmag.org44

LIZ DB

PHP Solutions Nr 1/2007

Narzędzia

www.phpsolmag.org 45

W PHP5 nie ma jeszcze odpo-wiedniego modułu, który by umożliwiał pracę z nowymi

opcjami bazy MySQL 5. Tak – możemy oprogramować wszystko samemu, tyl-ko czy trzeba nam wymyślać ponownie koło? Czy wszystko musimy robić ręcz-nie? Oczywiście, że nie. Możemy sobie ułatwić pracę korzystając z gotowej bi-blioteki.

LIZ DB – z wszystkiego po trochu: Java, .NETPodtytuł tego paragrafu może być dość mylący. Pewnie każdy z nas pomyślał, że musi mieć PHP5 z mnóstwem dodatko-wych modułów. Otóż nie – potrzebujemy oczywiście PHP5 z tylko jednym (z punk-tu widzenia LIZ DB) modułem – MySQLi. Moduł ten wypiera starszą implementacje MySQL w PHP i jest dostępny również w wersji PHP4.

LIZ DB jest narzędziem napisanym w PHP5 i nie będzie chodził na starszej

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.

wersji PHP4. Głównie z powodu używa-nia zaawansowanej obiektowych, in-terfejsów oraz mechanizmu wyjątków dla sygnalizowania sytuacji nieprawi-dłowych i błędów. LIZ DB jest dostęp-nym na sourceforge.net. Możemy ścią-gnąć najnowszą wersję kodów źródło-

LIZ DB– zaawansowane możliwości bazy MySQL 5Łukasz Budnik

Stopień trudności: lll

Co obiecujemy:Nauczysz się korzystać z zaawansowa-nej biblioteki LIZ DB, dzięki niej nauczysz się pisać szybko programy bazodanowe począwszy od prostych zapytań, zapy-tań przygotowanych a skończywszy na wywołaniach procedur składowanych. Zapoznasz się z nowymi możliwościa-mi MySQL 5, poznasz metody tworze-nie składowanych procedur i funkcji oraz dowiesz się jak i kiedy stosować je w praktyce.

Co powinieneś wiedzieć:Powinieneś mieć ogólną wiedzę z obiek-towości PHP5, powinieneś dobrze znać MySQL (nie koniecznie MySQL 5).

Page 45: PHP Solutions 01 2007 PL

PHP Solutions Nr 1/2007

Narzędzia

www.phpsolmag.org44

LIZ DB

PHP Solutions Nr 1/2007

Narzędzia

www.phpsolmag.org 45

wych wraz z obszernymi przykłada-mi ze strony głównej projektu: http://sourceforge.net/projects/lizdb, dodatko-we informacje można znaleźć na stro-nie http://www.komputery-internet.net/php/.

Twórca tej biblioteki oprócz tego, że jest programistą PHP jest również progra-mistą Java i MS .NET, w których również oprogramowuje bazy danych. LIZ DB za-wiera parę zapożyczeń koncepcji z JDBC oraz .NET.

Można powiedzieć, że z każdej tech-nologii wybrane zostało to, co najlepsze. A co dla nas, jako końcowych użytkowni-

ków najważniejsze to, że powstał bardzo dobry i o dużych możliwościach silnik do obsługi baz danych MySQL 5.

Po przeczytaniu tego artykułu uzmysłowimy sobie, że zaawansowa-ne możliwości baz danych wcale nie są takie straszne jak by się mogło wyda-wać i bez problemu możemy z nich ko-rzystać, nawet jeśli dopiero zaczynamy programować w PHP5.

W ostatniej części tego artyku-ły omówimy jakie należy nadać prawa użytkownikom MySQL aby móc two-rzyć, zamieniać i oczywiście wykony-wać procedury składowane. Omówimy

także składnie tworzenia takich proce-dur i funkcji.

LIZ DB – bibliotekado obsługi MySQL 5LIZ DB to narzędzie napisane w nowym obiektowym PHP5. Jakie są jego możli-wości? Są spore! Oto najważniejsze:

• pobieranie danych na różne sposoby – Select (zbiory rekordów), SelectOne (pojedynczy rekord), SelectColumn (zbiór kolumn);

• pełne wsparcie i wykonywanie in-strukcji DML (INSERT, UPDATE, DE-LETE) oraz DDL (CREATE, ALTER, CHANGE, DROP);

• przygotowywanie i wykonywanie za-pytań w stylu Java'y: setInt(1, $pa-ram), setString(2, $param), setBlob(3, $param) etc.;

• zarządzanie i wspomaganie zaawan-sowanych transakcji: commit, roll-back, savepoint, rollback do założo-nych savepointów;

• przygotowywanie i wykonywanie procedur i funkcji składowanych z pełną obsługą parametrów we wszystkich możliwych kierunkach: IN, INOUT, OUT w stylu .NET;

• logowanie, na różnych poziomach, wszystkich wykonywanych zapytań;

LIZ DB definiuje interfejsy klas służących do połączeń do bazy, zapytań przygoto-wywanych (ang. prepared statements), procedur składowanych i dostarcza ich implementację właśnie dla MySQL5. Omówię po kolei każdy z interfejsów. Spis interfejsów oraz klas ich implemen-tujących znajdziesz w ramce.

IDB – interfejs połączenia do bazyImplementacją tego interfejsu jest klasa MySQLimp, znajduje się ona w katalogu LIZDB/classes.

Dostarcza ona podstawowej funk-cjonalności związanej z pracą na bazie. Dzięki niej połączymy się z bazą danych i będziemy mogli wykonywać podstawo-we operacje na operacje, takie jakie wy-konujemy dziesiątki tysięcy dziennie.

Ale od początku jak wygląda kod PHP5 co musimy włączyć do nasze-go skryptu aby móc rozpocząć pracę z LIZ DB.

Nowe możliwości MySQL 5• Procedury i funkcje składowane (ang. Stored Procedures) – procedury i funkcje

umieszczane na serwerze, mogą wykonywać skomplikowane operacje, które z punktu widzenia programisty sprowadzają się do wykonania jednej operacji – wywołania pro-cedury, znacznie więcej na ten temat w artykule

• Wyzwalacze (ang. Triggers) – procedury wykonywane gdy zachodzą pewne zdarze-nia w bazie (np. wstawienie, edycja czy usunięcie rekordu)

• Widoki (and. Views) – mechanizm poprawiający bezpieczeństwo danych, jeśli ma-my tabelę pracownicy i nie chcemy aby każdy mógł ją przeglądać (np. kolumnęz płacami), wówczas tworzymy widok jako polecenie: CREATE VIEW „w _ pracownicy”

AS SELECT id _ p, imię, nazwisko, dział, pozycja, staż FROM pracownicy. Na-stępnie odbieramy prawa SELECT do tablicy pracownicy i nadajemy je do widoku„w _ pracownicy”

• Bazę i schematy meta danych (ang. metadata, Information Schema) – w bazieinformation _ schema – znajdziemy informacje o bazie i jej schematach, znajdu-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ń-stwie oraz oczywiście ciała procedur i funkcji

• Możliwość dołączania i odłączania silników bazy na zasadzie pluginów, dodano tak-że nowe silniki: archiwizacje (ang. Archive) – jest to silnik, który przechowuje dane w postaci skompresowanej dzięki czemu zajmują one mniej miejsca na dysku twardym oraz rozproszone (ang. Federated) – które umożliwiają stworzenie tablicy, która wi-doczna jest dla użytkowników jako lokalna a w rzeczywistości przechowująca dane na innym serwerze

Interfejsy i klasy LIZ DBInterfejsy i ich implementacje:

• 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ą-cą ten interfejs jest MySQLimp

• IPreparedStatement - definiuje 8 metod służących do obsługi przygotowywanych za-pytań, służące głównie do ustawiania wartości zapytania klasą implementującą ten interfejs jest MySQLimpPreparedStatement

• IStoredProcedure - definiuje 9 metod służących do obsługi składowanych proceduri funkcji, interfejs ten definiuje także trzy typu kierunków parametrów: IN, INOUT oraz OUT jak również typy: STORED _ PROCEDURE (dla procedur) STORED _ FUNCTION (dla funkcji) klasą implementującą ten interfejs jest MySQLimpStoredProcedure

Page 46: PHP Solutions 01 2007 PL

LIZ DB

PHP Solutions Nr 1/2007

Narzędzia

www.phpsolmag.org46

Przede wszystkim pobrać najnow-szą wersję z sourceforge.net i rozpako-wać ją do swojego testowego katalogu. Możemy od razu podejrzeć przykłady – są one w katalogu examples jest tam także katalog sql, w którym znajdzie-cie wszystkie potrzebne definicje tabel (wraz z przykładowymi rekordami) oraz definicje procedur i funkcji składowa-nych używanych w przykładach.

Spójrzmy jak powinien wyglądać skrypt PHP5 korzystający z LIZ DB:

define('LIZDB_PATH', '/home/xh/public_

html/testy/

LIZDB');

require LIZDB_PATH . '/classes/

MySQLimp.inc.php';

// wstaw swoje dane kolejno: serwer,

login, hasło oraz

baza danych do której masz prawo

$db = new MySQLimp

('localhost', 'xh', 'secret', 'test');

Środowisko LIZ DB do pracy potrzebu-je zdefiniowania stałej LIZDB_PATH, nie jest ona bynajmniej użyta przeze mnie jako elegancki sposób wskazania ścieżki. Stała ta jest używana przez LIZ DB do wczytania wszystkich definicji in-terfejsów i klas ich implementujących. Dzięki temu my, jako programiści, wy-konujemy tylko jedno włączenie skryptu – podajemy ścieżkę do pliku z definicją klasy MySQLimp.inc.php.

Następnie zwyczajnie tworzymy obiekt MySQLimp. Zapytania SQL nie będące zapytaniami przygotowanymi czy też procedurami składowanymi są definiowane jako publiczne pole Query. I tak możemy napisać:

$db->Query = „SELECT * FROM `lizdb_test_

table`”;

Lub inne dowolne zapytanie DDL, DML.Zapytania pobierające dane – SE-

LECT – są wykonywane przy użyciu następujących metod: Select (zbiory rekordów), SelectOne (pojedynczy re-kord), SelectColumn (zbiór kolumn). Zapytania DDL lub DML z kolei są wy-konywane przez wywołanie metody RunQuery.

LIZ DB rozpozna czy przypadkiem nie chcemy wykonać RunQuery na za-pytaniu SELECT lub też czy nie próbu-jemy utworzyć tabeli za pomocą metody SelectColumn – wówczas LIZ DB wyrzu-

ci wyjątek z komunikatem, informującym nas o właściwej metodzie jaką powinni-śmy użyć aby prawidłowo wykonać i ob-służyć wynik naszego zapytania.

A wyniki mogą być różne np. dla za-pytań DML RunQuery zwróci odpowied-nio dla: INSERT – ID wstawionego re-kordu, UPDATE, DELETE – ilości rekor-

dów które uległy zmianie, dla zapytań trupy DDL (CREATE/DROP) RunQuery zwróci: prawdę jeśli operacja się powio-dła oraz fałsz jeśli wystąpił problem.

Dla przykładowej tablicy, jaką mamy pokazaną na Listingu 1, za pomocą LIZ DB możemy wykonać podstawowe ope-racje pokazane na Listingu 2.

Listing 1. Przykładowa tabela używana w artykule

CREATE TABLE `lizdb_test_table` ( `id` mediumint(9) NOT NULL auto_increment,

`char_column` varchar(255)

NOT NULL default '', `int_column` int(11) NOT NULL, `double_column` double NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB

DEFAULT CHARSET=latin2;

Listing 2. Pokaz podstawowych możliwości LIZ DB - pobieranie zbiorów danych

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

do której masz prawo$db = new MySQLimp('localhost', 'xh', 'secret', 'test');$db->Query = 'SELECT * FROM `lizdb_test_table`';

$records = $db->Select();

// $records jest tabelą, którą możemy przeglądać np. za pomocą instrukcj

i foreach echo '<ul>';foreach($records as $r) { // każdy element jest kolejną asocjacyjną tablicą

// nazwa kolumny jest indeksem w tablicy, możemy więc napisać:

echo '<li>' . $r['id'] . ', ' . $r['char_column'] . ', ' . $r['int_column'] . ',

' .$r['double_column'] . '</li>';

}

echo '</ul>';

// aby pobrać tylko jeden rekord, np. jeśli szukamy po kluczu głównym

lub kolumnie UNIQUE

// należy użyć poniższej metody -- jest ona zoptymalizowana

do pobierania 1 wiersza$db->Query = 'SELECT * FROM `lizdb_test_table` ORDER BY

id DESC LIMIT 1';

$record = $db->SelectOne();

echo '<p>Ostatnim rekordem jest: ';echo $record['id'] . ', ' . $record['char_column'] . ', ' .

$record['int_column'] . ', ' .$record['double_column'];

echo '</p>';

// możemy wybierać zbiory kolumn, używane gdy we

frazie SELECT występuje jedna kolumna

$db->Query = 'SELECT `double_column` FROM

`lizdb_test_table` WHERE `double_column` < 0';

$negativeDoubles = $db->SelectColumn();

echo 'ujemne wartości double to:' . implode(',', $negativeDoubles); // nie musimy zamykać połączenia, twórca LIZ DB

przewidział że część programistów jest leniwa

// wykorzystywany jest mechanizm destructorów

PHP5, metoda __destruct wołana przy

// niszczeniu obiektu MySQLimp

rozłącza się automatycznie z bazą danych

$db->CloseConnection();

Page 47: PHP Solutions 01 2007 PL

LIZ DB

PHP Solutions Nr 1/2007

Narzędzia

www.phpsolmag.org 47

Przykład wykorzystania LIZ DB do zapytań DDL oraz DML pokazany jest na Listingu 3.

IPreparedStatement – interfejs przygotowywanych zapytańPrzygotowywane zapytania to zapytania, których szablony są przechowywane na serwerze, a dane wysyłane oddzielnie, w dodatku serwer bazodanowy przejmu-je na siebie odpowiedzialność związaną ze zneutralizowaniem potencjalnie nie-bezpiecznych znaków i sekwencji SQL – dzięki temu zwiększamy bezpieczeń-stwo i minimalizujemy praktycznie do ze-ra ewentualne problemy z atakami typu SQL Injections.

Jeśli nie korzystałeś do tej pory z przygotowywanych zapytań to może po-ra się przerzucić? Zobaczmy jakie to pro-ste z LIZ DB.

Przygotowane zapytania tworzymy za pomocą metody PrepareStatement zdefi-niowanej w interfejsie IDB. Argumentem metody PrepareStatement jest szablon zapytania, natomiast zwracany jest obiekt implementujący interfejs IPreparedState-ment w naszym przypadku tym obiektem będzie MySQLimpPreparedStatement.

Napiszemy więc tak:

$stmt = $db->PrepareStatement

(„INSERT INTO `lizdb_test_table

` VALUES (NULL, ?, ?, ?)”);

Patrząc na Listing 1 (definicja bazy da-nych) wiemy, że pod pierwszym marke-rem (znak zapytania „?”) jest kolumna typu VARCHAR, drugim INT a w ostat-niej kolumnie przechowywane są warto-ści DOUBLE.

Wypełniamy nasz szablon danymi, ro-bimy to w stylu Java'y i JDBC:

$stmt->SetString(1, “przykładowy tekst ze

znakami:

' or 1 LIKE %1% ? !@#”);

$stmt->SetInt(2, mt_rand());

$stmt->SetDouble(3, mt_rand() /

mt_getrandmax());

Tak przygotowane i wypełnione zapyta-nie SQL możemy uruchomić na serwerze SQL, robimy to następująco:

$result = $db->Execute($stmt);

Listing 3. Pokaz podstawowych możliwości LIZ DB - obsługa i wykonywanie zapytań DDL oraz DML

// mając już połączenie z bazą, chcę wykonać operacje typu INSERT

$chars = "some text";

$int = mt_rand();

$double = mt_rand() / mt_getrandmax();

// standardowy sposób bez wykorzystania

przygotowywanych zapytań

$db->Query = "INSERT INTO `lizdb_test_table`

VALUES (NULL, '{$chars}', {$int}, {$double})";

$id = $db->RunQuery();

echo '<p>Nowy rekord w systemie posiada ID: ' . $id . '</p>';

$db->Query = "UPDATE `lizdb_test_table` SET `

double_column` = 0.0 WHERE `id` = '{$id}'";

$updatedRows = $db->RunQuery();

echo '<p>Ilość zaktualizowanych wierszy: ' .

$updatedRows . '</p>';

$db->Query = "DELETE FROM `

lizdb_test_table` WHERE `id` = '{$id}'";

$deletedRows = $db->RunQuery();

echo '<p>Ilość usuniętych wierszy: ' .

$deletedRows . '</p>';

// możemy również Tworzyć tabele,

indeksy, klucze obce etc.

$db->Query = "CREATE TABLE `t` (`f` int)";

if ($db->RunQuery()) { echo '<p>Nowa tabela stworzona!</p>';}

$db->Query = "DROP TABLE IF EXISTS `t`";

if ($db->RunQuery()) {

echo '<p>Tabela została usunięta!</p>';

}

Listing 4. Wykonywanie przygotowywanych zapytań w obiektowym MySQLi

// ponownie ustawiamy nasze dane

$mysqli = new mysqli('localhost', 'xh', 'secret', 'test');// przygotowujemy szablon zapytania

$stmt = $mysqli->prepare('SELECT `id`, `char_column`,

`int_column` FROM `lizdb_test_table` WHERE

`char_column` LIKE ? AND `int_column` > ?');

// jeśli szablon jest poprawny wypełnimy go danymi

if ($stmt) { $string = '%record%';

$int = 0;

// pierwszym parametrem jest ciąg znaków reprezentujący

typy kolejnych parametrów

// s -- łańcuchy znaków, i - int, d - double, b - blob

// UWAGA! -- użytkownicy wcześniejszych

wersji PHP5 pod Windowsami

// -- możecie dostać komunikat mówiący o

nieprawdiłowej ilości parametrów

$stmt->bind_param('si', $string, $int);

// wypełnione zapytanie można wykonać

$stmt->execute();

// aby pobrać wyniki musimy skorzystać z dość

niewygodnego mechanizmu wiązania

// rezultatów do zmiennych PHP

$stmt->bind_result($id, $string, $int);

// następnie w pętli pobieramy dane do związanych

zmiennych i wyświetlamy zawartość

while ($stmt->fetch()) { printf ("%d: %s, %d\n", $id, $string, $int); }

}

$mysqli->close();

Page 48: PHP Solutions 01 2007 PL

LIZ DB

PHP Solutions Nr 1/2007

Narzędzia

www.phpsolmag.org48

I to wszystko, prawda, że proste? Dodat-kowo przygotowanym zapytaniem mo-że być SELECT, wówczas $result będzie zawierało zbiór tablic asocjacyjnych z re-kordami. Wszystko jest automatycznie rozpoznawane i odpowiednio wykonywa-ne przez LIZ DB – w przeciwieństwie do ręcznego wykonywania w PHP przedsta-wionego na listingu 4.

IStoredProcedure – interfejs do wywoływania procedur i funkcji składowanychJest to najważniejsza i najpotężniejsza część całej biblioteki LIZ DB. Ale najpierw odpowiedzmy sobie na pytania – co to są tak na prawdę te procedury i gdzie znaj-dują one swoje zastosowanie. Procedu-ry składowane są to fragmenty najczę-ściej sparametryzowane i często używa-ne instrukcje SQL, które mogą wykony-wać operacje aktualizacji lub tylko pobie-rania danych. Fragmenty procedur może-my opakować np. w transakcje.

Procedury mogą przysłaniać przed końcowym użytkownikiem cały mecha-nizm swoich operacji, np. procedura, któ-ra podaje średnie koszty, przychody ze sprzedaży, ukrywa w swoim wnętrzu ta-bele, z których pobiera dane, co więcej użytkownik wykonujący tę procedurę mo-że nie mieć dostępu do pewnych zaso-bów, ale dzięki zastosowaniu mechani-zmu jaki ofertu MySQL5, procedura mo-że zostać wykonana w kontekście praw użytkownika, który ją utworzył a nie któ-ry ją wykonuje.

Projektując bazę dla szpitala może-my stworzyć np. procedurę dodajPacjen-ta (z odpowiednimi parametrami) – może-my sprawdzić w niej czy podany adres ist-nieje już w bazie danych (np. ktoś z rodzi-ny już jest zapisany) – jeśli tak to pobiera-my ID adresu (z tabeli adresów), jeśli nie, dodajemy nowy rekord, później możemy wstawić dane pacjenta, dane takie jak: imię, nazwisko, PESEL wstawiamy do ta-beli osoby (jeśli w systemie przechowuje-my też pracowników możemy wyodręb-nić tabelę nadrzędną) a dane specyficz-ne dla pacjenta wstawiamy do tablicy pa-cjenci – w naszej procedurze oczywiście zachowujemy pełną kontrolę nad klucza-mi obcymi, możemy tu także wykorzystać mechanizm transakcji. Dzięki zastosowa-niu procedury znacznie uprościliśmy ca-ły mechanizm procesu dodawania nowe-go pacjenta z punktu widzenia programi-

sty, który w swoim kodzie będzie wykony-wał tylko jedną instrukcję SQL.

Kolejnym przykładem może być przy-kład dużej firmy – zakładu ubezpieczeń, może firmy telekomunikacyjnej. Mamy setki oddziałów, może miliony klientów. Działamy też w środowisku w którym bar-dzo często zmienia się prawo czy profil usług. Każda zmiana przepisów wymu-sza na nas pewne zmiany czy to w struk-turze bazy danych czy też w samych za-pytaniach. Musielibyśmy w takim razie wykonywać co miesiąc setki (miliony?) aktualizacji oprogramowania użytkowni-ków końcowych – znacznie prościej zde-finiować interfejs procedury czy funkcji

i później modyfikować funkcjonalność biz-nesową tylko w jednym miejscu – bazie danych.

Wszechwładny i okazać by się mogło wszystko posiadający phpMyAdmin nie potrafi rozpoznawać i wykonywać proce-dur składowanych, my za pomocą LIZ DB będziemy w stanie wywołać każdą funkcję czy procedurę składowaną, nawet jeśli do-piero zaczynamy naszą przygodę z PHP.

Spójrzmy na przykładową funkcję składowaną i procedurę o wszystkich możliwych kierunkach parametrów: IN, INOUT, OUT – listing 5.

Nie jesteśmy pismem dla admini-stratorów baz danych, ale dla porządku

Listing 5. Definicje przykładowych procedur i funkcji składowanych

drop procedure if exists sayMyName;delimiter //

CREATE PROCEDURE sayMyName (OUT param1 INT, INOUT param2 CHAR(200), IN param3 CHAR(100)) BEGIN SELECT COUNT(*) INTO param1 FROM `lizdb_test_table`;

SET param2 = concat(param2, param3); END;//

delimiter ;

drop function if exists hello;CREATE FUNCTION hello (s CHAR(20)) RETURNS CHAR(50)

RETURN CONCAT('Hello, ',s,'!');

Charakterystyki MySQL• DEFINER - użytkownik, który stworzył procedurę, jeśli posiadamy prawo SUPER może-

my stworzyć procedurę na konkretne konto, związane to może być np. z sytuacją, w której nie chcemy aby procedura posiadała prawa bieżącego użytkownika (np. admini-stratora bazy)

• LANGUAGE SQL - język w jakim napisana została procedura, nie musimy tego definio-wać, MySQL5 na razie obsługuje tylko i wyłącznie procedury w języku SQL i taką ma wartość domyślną ta charakterystyka

• DETERMINISTIC | NOT DETERMINISTIC - zachowanie procedury, domyślnie MySQL używa NOT DETERMINISTIC, charakterystyka ta pomaga określić MySQL czy pro-cedura jest bezpieczna podczas replikacji (ang. replication-safe), deterministyczna znaczy tyle, że zawsze dla pewnego zestawu parametrów wejściowych wynik proce-dury będzie taki sam

• SQL SECURITY INVOKER | SQL SECURITY DEFINER - poziom bezpieczeństwa proce-dury, definiuje czy procedura ma być wykonywana z prawami użytkownika wywołują-cego procedurę czy użytkownika, który ją utworzył, domyślna wartość: SQL SECU-RITY DEFINER

• CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA - tryb pracy procedury, zacznę przekornie: obecnie MySQL nie bierze pod uwagę tej charaktery-styki dla np. ograniczeń bezpieczeństwa, domyślną wartością jest CONTAINS SQL, który oznacza tyle, że procedura nie czyta ani nie pisze nic, NO SQL, że nie zawiera w ogóle instrukcji SQL, READ SQL DATA - odczytuje dane z bazy, MODIFIES SQL DATA - może (nie musi) modyfikować zawartość danych

• COMMENT 'zawartość komentarza' - dodanie komentarza.

Page 49: PHP Solutions 01 2007 PL

LIZ DB

PHP Solutions Nr 1/2007

Narzędzia

www.phpsolmag.org 49

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:

CREATE DEFINER = 'xh'@'%' PROCEDURE

simpleproc (OUT param1 INT) LANGUAGE SQL

DETERMINISTIC SQL SECURITY INVOKER

NO SQL COMMENT 'ot taki komentarz'

BEGIN

SELECT 123 INTO param1;

END;

Nie uda się – jak napisaliśmy wcześniej aby utworzyć procedurę z wartościąDEFINER inną niż bieżący użytkownik – lizdb_user powinien posiadać przywi-lej SUPER.

Zmodyfikujmy więc powyższy kodi napiszmy tak:

CREATE DEFINER = CURRENT_USER

PROCEDURE simpleproc (OUT param1 INT)

LANGUAGE SQL DETERMINISTIC SQL

SECURITY INVOKER NO SQL COMMENT

'ot taki komentarz'

BEGIN

SELECT 123 INTO param1;

END;

Lub w ogóle omijamy DEFINER = CURRENT_

USER

ponieważ jest to domyślne zachowanie

MySQL.

Jak w ogóle wykonać nasze procedury i funkcje w MySQL? Utwórzmy procedury i zalogujmy się do MySQL. Zakładamy, że pracujemy na bazie test:

$ mysql -u root -p -D test < examples/

stored_

procedures.sql

Zauważmy, że podałem tutaj parametr informujący do jakiej chcę się połączyć bazy danych (-D test) – jest to ważne ponieważ procedury utworzone w bazie test będą widoczne tylko i wyłącznie w

Rysunek 1. Ręczne wykonanie procedur składowanych i funkcji w MySQL

Listing 6. Wywoływanie składowanych funkcji i metod za pomocą bibliotekiLIZ DB

$call = $db->PrepareCall('sayMyName (?, ?, ?)',

IStoredProcedure::STORED_PROCEDURE);

$parameter = array();// przykład parametru INOUT

$parameter['type'] = IstoredProcedure:

:INOUT_PARAMETER;

$parameter['value'] = 'testujemy parametry

wejściowe i wyjściowe';

// możemy definiować parametry w dowolnej

kolejności, powyższy jest drugim parametrem

$call->SetParameter(2, $parameter);

// parametr OUT wyjściowy

$parameter['value'] = 'ta wartość jest nie istotna i tak

zostanie nadpisana';

$parameter['type'] = IstoredProcedure:

:OUT_PARAMETER;

// to jest pierwszy paramter

$call->SetParameter(1, $parameter);

// standardowy typ IN

$parameter['value'] = 'przyklej mnie do

drugiego parametru!';

$parameter['type'] = IstoredProcedure:

:IN_PARAMETER;

// ustaw jako trzeci parametr

$call->SetParameter(3, $parameter);

$db->ExecuteCall($call);

$parameters = $call->GetParameters();

echo '<p>INOUT parametr (#2) ma wartość: ' . $parameters[2]['value'] . '</p>';

echo '<p>OUT parametr (#1) przypisano nową wartość:

' . $parameters[1]['value'] . '</p>';

// teraz wykonajmy funkcję składowaną

// pierwszym argumentem jest ponownie szablon,

drugim jest typ STORED_FUNCTION

$call = $db->PrepareCall('hello (?)', IstoredProcedure:

:STORED_FUNCTION);

$parameter = array();$parameter['type'] = IstoredProcedure:

:IN_PARAMETER;

$parameter['value'] = 'Łukaszu';

$call->SetParameter(1, $parameter);

$result = $db->ExecuteCall($call);

echo '<p>Wynikiem wykonania funkcji hello(?) jest: ' . $result . '</p>';

Page 50: PHP Solutions 01 2007 PL

LIZ DB

PHP Solutions Nr 1/2007

Narzędzia

www.phpsolmag.org50

obrębie tej bazy. Nie możemy utworzyć procedury globalnej, która będzie dzia-łała we wszystkich bazach – procedury działają na konkretnych tabelach, w jed-nej konkretnej bazie.

Następnie połączmy się do bazy i utwórzmy użytkownika z takimi prawami:

CREATE USER lizdb_user@localhost

IDENTIFIED BY 'lizdb';

GRANT

SELECT, INSERT, UPDATE, DELETE,

CREATE, DROP, INDEX, ALTER,

CREATE ROUTINE, ALTER ROUTINE

EXECUTE

ON `test`. * TO lizdb_user@localhost

IDENTIFIED BY 'lizdb';

Zauważymy od razu nowe opcje, które nie są dostępne w MySQL4 (podałem je w osobnej linii) są to: CREATE ROUTINE, ALTER ROUTINE, EXECUTE – służące ko-lejno: do tworzenia, zmieniania oraz wy-konywania procedur i funkcji składowa-nych. ROUTINE jest tu użyte jako słowo klucz i zostało wprowadzone – aby nie nadawać osobno praw typu: CREATE PROCEDURE, CREATE FUNCTION.

Prze logujmy się na nowego użytkow-nika (do bazy test), którego przed chwilką utworzyliśmy. Wywołanie funkcji wykonu-je się w połączeniu z frazą SELECT – po-nieważ chcemy „coś” pobrać – tu wynik działania funkcji. Piszemy następująco:

mysql> SELECT hello ('Łukaszu');

Aby wywołać procedurę użyjemy in-strukcji CALL, dodatkowo zauważmy, że gdy chcemy dostać odpowiedź od MySQL przez parametr nie możemy podać wartości a zmienną! To się ty-czy jedynie parametrów o kierunkach OUT oraz INOUT. Dodatkowo parame-try INOUT jak widzimy posiadają war-tość, którą wprowadzamy do procedu-ry a która jest wewnątrz modyfikowa-na. Musimy więc do takiej zmiennej naj-pierw przypisać wartość. Piszemy więc w konsoli MySQL:

mysql> set @zmienna = 'Do tego łańcucha

dokleję coś w procedurze...';

mysql> CALL sayMyName(@ileRekordow,

@zmienna, ' np. to dokleje ;)');

mysql> SELECT @zmienna, @ileRekordow;

Wynik powyższych sekwencji instrukcji SQL możemy zobaczyć na Rysunku 1.

Spójrzmy na problemy z jakimi spo-tkalibyśmy się gdybyśmy wykonywa-li wszystko ręcznie w PHP. Przede wszystkim wiele problemów nastarczyło by nam samo oprogramowanie parame-trów o kierunkach OUT czy INOUT. Mu-sielibyśmy wykonywać zawsze ustawie-nie zmiennych, potem musielibyśmy wy-wołać procedurę i jeszcze raz zapytać się o zmienne. W dodatku musielibyśmy tak robić dla każdej naszej procedury co może być męczące.

LIZ DB automatyzuje cały ten proces, ci z was, którzy programowali w .NET za-uważą pewne analogie. Ale od początku jak wykonujemy takie rzeczy w LIZ DB? Mając już obiekt $db tworzymy obiekt im-plementują interfejs IStoredProcedure:

$call = $db->PrepareCal

l('sayMyName (?, ?, ?)',

IstoredProcedure:

:STORED_PROCEDURE);

Pierwszym argumentem jest szablon na-szej procedury składowanej, drugim pa-rametrem jest typ – jak już wiemy inaczej woła się funkcje a inaczej procedury. W przypadku funkcji hello napisalibyśmy tak:

$call = $db->PrepareCall

('hello (?)',

IstoredProcedure:

:STORED_FUNCTION);

Markery ustawiamy analogicznie jakw przypadku przygotowywanych zapytań:

$call->SetParameter

(1, $parameter);

Z jedną różnica $parameter nie jest tutaj zmienną skalarną reprezentującą kon-kretną wartość a tablicą asocjacyjną, która posiada dwa ważne pola:

$parameter['value'] =

'tutaj podajemy wartość

parametru';

$parameter['type'] = IstoredProcedure:

:IN_PARAMETER;

Typ decyduje o tym jak zostanie obsłużo-ny nasz parametr. Nie musimy ustawiać wartości dla parametru typu OUT_PA-RAMETER ponieważ cokolwiek podamy zostanie i tak nadpisane. Jeśli ustawimy już wszystkie pola naszej procedury wy-konujemy ją bardzo prosto:

Listing 7. Najkrótsza i najprostsza wersja wywołania procedury getRecords()w MySQLi

$mysqli = new mysqli('localhost', 'xh', 'secret', 'test');// musimy wykonać jako zapytanie typu MULTI

aby MySQL nie zerwał połączenia

// jeśli zajrzymy w kod LIZ DB zobaczymy, że tam

nie ma takich wybiegów,

// dodatkowo LIZ DB do wywołań procedur używa

wewnętrznie przygotowywanych zapytań

// zauważmy, że gdybyśmy chcieli oprogramować

samemu markery i przygotowywane zapytania

// jak w poprzednich przykładach,

najprawdopodobniej dodalibyśmy tu jeszcze kilka

// lini kodu obsługi do każdego takiego parametru

$mysqli->multi_query('CALL getRecords()');

// pobieramy rezulat

$result = $mysqli->store_result();

// iterujemy po wynikach

while ($row = $result->fetch_row()) { // musimy znać ilość pól, ich nazwy

// LIZ DB automatycznie za nas to zrobi na

podstawie meta danych

$values['id'] = $row[0];

$values['char_column'] = $row[1];

$values['int_column'] = $row[2];

$values['double_column'] = $row[3];

$records[] = $values;

}

$result->close();

// końcowa odpowiedź

var_dump($records);

$mysqli->close();

Page 51: PHP Solutions 01 2007 PL

LIZ DB

PHP Solutions Nr 1/2007

Narzędzia

www.phpsolmag.org 51

$db->ExecuteCall($call);

Metoda ExecuteCall pobiera przez referen-cje obiekt $call, wykonuje procedurę i wpisu-je do niej nowe wartości (w przypadku para-metrów OUT bądź INOUT). Aby później po-brać nowe wartości musimy napisać:

$parameters = $call->GetParameters();

$parameters jest teraz tablicą parametrów – wszystkich, które ustawiliśmy przed wy-wołaniem metody (włącznie z parametrami IN). Pod indeksem 1 znajduje się pierwszy parametr itd. Parametry mają dokładnie tę samą strukturę, pod kluczem vale znajdzie-my nową wartość parametru. Na listingu 6 możemy zobacz pełny przykład wykona-nia składowanej funkcji i procedury za po-mocą LIZ DB.

Aby uzmysłowić sobie ile pracy jest wy-konywanych za nas pokażę ostatni bardzo wykorzystywany przy procedurach składo-wanych mechanizm – mechanizm pobiera-nia zbiorów danych. Jeśli nasza procedu-ra nie posiada żadnych parametrów kod upraszczamy drastycznie z użyciem LIZ DB, napiszemy tylko dwie linie kodu:

$call = $db->PrepareCall('getRecords()',

IStoredProcedure::STORED_PROCEDURE);

$records = $db->ExecuteCall($call);

LIZ DB tworzy odpowiedź w jak najbar-dziej wygodnej dla nas postaci. W powyż-szym kawałku kodu $records jest tablicą tablic asocjacyjnych, których indeksy są nazwami kolumn.

Ręczna obsługa procedury getRecords zamieszczona jest na listingu 7. Wywołanie tej procedury wybrałem na przykład stan-dardowego kodu PHP5 i MySQLi ponieważ jest ona najkrótsza. Zauważmy, że nie uży-liśmy tutaj żadnego parametru – kod PHP, który nie korzystałby z LIZ DB a który pró-buje wykonać procedury składowane z róż-nymi parametrami miałby co najmniej kilka-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-cedury. Mógłbym próbować zwiększyć je-go reużywalność, ale chciałem za wszelką cenę zmniejszyć ilość kodu tak aby zbliżyć się do 2 linii jakie musieliśmy napisać uży-wając biblioteki LIZ DB.

Używając LIZ DB nie musimy się za-głębiać w definicje procedur, nie musimy znać nazw kolumn zwracanych przez nią, nie musimy tworzyć żadnych mapowań

wartości na kolumny – LIZ DB na podsta-wie meta danych potrafi odtworzyć struk-turę zbioru wynikowego.

Nadmienię tylko, że przy takich pro-cedurach składowanych wykonywanych z poziomu PHP, standardowymi metoda-mi, MySQL zrywa połączenia. Procedu-ra zwracająca zbiór jest nietypowa – My-SQL obsługuje wywołanie, zwraca stero-wanie do klienta, ale też alokuje bufory z wynikiem i czeka na ich pobranie. Jeśli ich nie odbierzemy i później nie zwolnimy tych zasobów MySQL uważa to za błąd i przy próbie wykonania nowego zapytania rozłącza połączenie.

PodsumowanieLIZ DB to potężne środowisko znakomi-cie ułatwiające prace programistom. Nie zdążyłem nawet omówić części LIZ DB związanej z logowaniem wykonywanych zapytań, w całości pominąłem wsparcie dla zaawansowanych transakcji – takich jak obsługa savepointów, cofanie zmian do wcześniejszych stanów bazy danych, odwoływania całych transakcji, opcje Au-toCommit (każde zapytanie jest automa-tycznie zatwierdzane) czy CommitOnClo-se (wszystkie zmiany są utrwalane w ba-zie dopiero przy zamykaniu połączenia).

Autor projektu jest otwarty na współ-pracę i współudział w rozwijaniu tej biblio-teki (nie tylko dla bazy MySQL), najbliż-sze plany zakładają wbudowanie systemu cache, obecnie w repozytorium projektu znajdują się już interfejsy i przykładowa implementacja cache – wykorzystująca PECL APC. W najbliższej przyszłości zo-stanie także wypuszczona wersja oferują-ca tworzenie obiektów poprzez wzorzec projektowy singleton oraz mechanizm tworzenia połączeń persystentnych.

Jeśli przekonałem Ciebie do LIZ DB – nie czekaj tylko pobierz najnow-sze wersje źródeł i przykładów z http://sourceforge.net/projects/lizdb lub http://www.komputery-internet.net/php/. n

Łukasz Budnik jest studentem V roku Informatyki na Politechnice Gdańskiej, uczestniczy w projektach nad rozwija-niem systemów zbierania i analizy danych w postaci XML, jest również administrato-rem serwisu www.komputery-internet.net.

Kontakt z autorem:[email protected]

O autorze

Page 52: PHP Solutions 01 2007 PL

PHP Solutions Nr 1/2007

Narzędzia

www.phpsolmag.org52

Wielojęzyczna konfiguracja

PHP Solutions Nr 1/2007

Narzędzia

www.phpsolmag.org 53

Ten artykuł opisuje, jak konfiguro-wać wielojęzyczne strony z uży-ciem eZ publish, udostępniając

stronę webową międzynarodowej grupie użytkowników. eZ publish w wersji 3.8 zawiera wiele ulepszeń do swojego mo-delu wielojęzycznej zawartości strony. Te ulepszenia są opisane w specyfikacji wielojęzycznej (http://ez.no/community/developer/specs/improved_multi_langu-age_in_ez_publish_rev_2).

Ten samouczek przedstawi, jak tworzyć wielojęzyczne strony webo-we z użyciem eZ publish, dodawać nowe języki do istniejących instalacji i tłumaczyć zawartość strony na róż-ne języki.

WymaganiaeZ publish pracuje na serwerze webo-wym Apache. Zaleca się używać ostat-niej wersji z gałęzi 1.3. Upewnij się, że używasz wersji 4.4 PHP. Zalecamy rów-nież używać ostatniej wersji z gałęzi 4.4

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ć.

zainstalowanej jako moduł Apache'a (mod_php). (Zwracamy uwagę, że eZ publish nie działa z PHP w wersji 5). PHP musi mieć wbudowaną obsługę al-bo MySQL 4.1 lub nowszego, albo Post-greSQL 7.3 lub nowszego.

Wielojęzyczna konfiguracja stron z użyciem eZ publishŁukasz Serwatka

Stopień trudności: lll

Co obiecujemy:Po przeczytaniu tego artykułu czytelnik będzie umiał zainstalować eZ publish z obsługą kilku języków, zmieniać usta-wienia i konfigurację systemu pod ką-tem obsługi wielu języków. Tworzyć wła-sne rozszerzenia językowe dla eZ pu-blish. Dodawać nowe języki do istnieją-cej już instalacji.

Tłumaczyć i tworzyć treść w dostęp-nych w eZ publish językach.

Co powinieneś wiedzieć:Artykuł jest adresowany do osób, któ-re mają niewielkie doświadczenie lub dopiero zaczynają swoją przygodę z eZ publish, potrzebna jednak będzie podstawowa wiedza z zakresu tworze-nia witryn internetowych.

Page 53: PHP Solutions 01 2007 PL

PHP Solutions Nr 1/2007

Narzędzia

www.phpsolmag.org52

Wielojęzyczna konfiguracja

PHP Solutions Nr 1/2007

Narzędzia

www.phpsolmag.org 53

InstalacjaTen rozdział opisuje aspekty procesu in-stalacji eZ publish, które wpływają na wielojęzyczną konfigurację. (Kompletny proces instalacji jest opisany szczegóło-wo w dokumentacji online na http://ez.no/doc/ez_publish/technical_manual/3_8/installation.)

Baza danychAby udostępnić obsługę wszystkichzestawów znaków, skonfigurujemy ko-dowanie UTF-8 (unikod). Aby używać UTF-8, baza danych musi mieć ob-sługę unikodu. PostgreSQL i MySQL (wersja 4.1 lub nowsza) w pełni obsłu-gują unikod. (Rysunek 1). Skonfiguru-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).

Kreator ustawieńW wersji 3.8 eZ publish, można włączyć unikod podczas instalacji. Kreator usta-wień eZ publish włączy unikod (UTF-8) dla wewnętrznego kodowania i konwer-sji strony kodowej. To ustawienie jest za-pisane w pliku:

settings/override/i18n.ini.append.php.

<?php /* #?ini charset="iso-8859-1"?

[CharacterSettings]

Charset=utf-8

*/ ?>

Poniższy zrzut ekranu pokazuje opcje wy-szczególnione w kreatorze ustawień:

Wybierz „English (United Kingdom)” jako język podstawowy oraz „French (France)” i „German” jako języki dodat-kowe. Po zapytaniu o „site type”, wy-bierz „new site”.

Konfiguracjapo instalacyjnaPo zainstalowaniu eZ publish i uzy-skaniu dostępu do interfejsów publicz-nych i administracyjnych, należy zmie-nić konfigurację, by udostępnić stro-nę w wielu językach. Domyślnie kre-ator ustawień tworzy dwa „siteaccess-y”(zestawy plików konfiguracyjnych, któ-re przesłaniają ustawienia domyślne):

Rysunek 1. Tworzenie bazy

Rysunek 2. Opcje wyszczególnione w kreatorze ustawień

Listing 1. Struktura katalogów i umiejscowienie plików konfiguracyjnych

settings/override/ globalne ustawienia dla wszystkich siteaccesses

settings/siteaccess/gb pliki konfiguracyjne dla angielskich siteaccess

settings/siteaccess/de pliki konfiguracyjne dla niemieckich siteaccess

settings/siteaccess/fr pliki konfiguracyjne dla francuskich siteaccess

settings/siteaccess/site_admin pliki konfiguracyjne dla siteaccess

administratorskich

Page 54: PHP Solutions 01 2007 PL

Wielojęzyczna konfiguracja

PHP Solutions Nr 1/2007

Narzędzia

www.phpsolmag.org54

jeden do użytku publicznego („news_si-te”) i jeden do administracji („news_site_admin”). Użyjemy tych plików konfigura-cyjnych utworzonych przez kreator usta-wień jako wzór dla innych konfiguracjidostępu do stron (siteaccess). Zmień na-zwę katalogu news_site na „gb”. Utwórz nowe katalogi „de” i „fr” pod „settings/siteaccesses”, a potem zmień nazwę katalogu „news_site_admin” na „site_admin”. Skopiuj pliki konfiguracyjneINI z folderu „settings/siteaccesses/gb” do „settings/siteaccesses/de” i „settintgs/siteaccesses/fr ”. Nie zmieniaj plików kon-figuracyjnych w site_admin. Teraz mamy mniej więcej taką strukturę (Listing 1).

Stworzyliśmy zatem po jednym si-teaccess dla języka. eZ publish będzie przeglądać pliki konfiguracyjne zapi-sane w tych ostatnich katalogach, gdy użytkownik zażąda URL-a z końców-ką języka:

www.example.com/gb > settings/siteaccess/gb

www.example.com/de > settings/siteaccess/de

Globalny plik konfiguracyjny settings/override/site.ini.append.php zawiera in-formacje o dostępnych siteaccess-ach (Listing 2).

Te ustawienia informują eZ publish, że nasz domyślny siteaccess (Default-Access) jest „gb” (angielski). Gdy użytkow-nik łączy się z naszą stroną nie specyfiku-jąc siteaccess-u (np. przez www.exam-ple.com albo www.example.com/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 mechanizmbuforują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ązanaz 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ń

Listing 2. Globalny plik konfiguracyjny

settings/override/site.ini.

append.php

<?php /*

[...]

[SiteSettings]

DefaultAccess=gb

SiteList[]

SiteList[]=gb

SiteList[]=de

SiteList[]=fr

[SiteAccessSettings]

CheckValidity=false

AvailableSiteAccessList[]

AvailableSiteAccessList[]=gb

AvailableSiteAccessList[]=de

AvailableSiteAccessList[]=fr

AvailableSiteAccessList[]=

site_admin

RelatedSiteAccessList[]

RelatedSiteAccessList[]=gb

RelatedSiteAccessList[]=de

RelatedSiteAccessList[]=fr

RelatedSiteAccessList[]=

site_admin

[...]

*/ ?>

Listing 3. Główny plik konfiguracyjny

<?php /*

[...]

[RegionalSettings]

Locale=eng-GB

ContentObjectLocale=eng-GB

SiteLanguageList[]=eng-GB

SiteLanguageList[]=fre-FR

SiteLanguageList[]=ger-DE

TextTranslation=disabled

[FileSettings]

VarDir=var/news_site

[...]

*/ ?>

Page 55: PHP Solutions 01 2007 PL

Wielojęzyczna konfiguracja

PHP Solutions Nr 1/2007

Narzędzia

www.phpsolmag.org 55

lation.ts) i skompiluje do natywnych pli-ków PHP dla szybszego uruchamiania. To znacznie zmniejszy czas ładowania i powinno być zawsze używane. Bufor translacji jest zapisany w systemie pliku pod katalogiem var w katalogu tłumaczeń (var/(site)/cache/translation).

Dla angielskich stron (eng-GB) TextTranslation i TranslationCache są domyślnie wyłączone, gdyż domyślne

Rysunek 4. Wybór kilku opcji jednocześnie przy użyciu Contral

Listing 4. Części plików konfiguracji niemieckiej i francuskiej

settings/siteaccess/de/

site.ini.append.php

<?php /*

[...]

[RegionalSettings]

Locale=ger-DE

ContentObjectLocale=ger-DE

SiteLanguageList[]=ger-DE

SiteLanguageList[]=eng-GB

SiteLanguageList[]=fre-FR

TextTranslation=enabled

[FileSettings]

VarDir=var/news_site

[...]

*/ ?>

settings/siteaccess/fr

/site.ini.append.php

<?php /*

[...]

[RegionalSettings]

Locale=fre-FR

ContentObjectLocale=fre-FR

SiteLanguageList[]=fre-FR

SiteLanguageList[]=eng-GB

SiteLanguageList[]=ger-DE

TextTranslation=enabled

[FileSettings]

VarDir=var/news_site

[...]

*/ ?>

Listing 5. Ustawienia Path Prefix

settings/siteaccess/de/site.

ini.append.php:

PathPrefix=german

settings/siteaccess/gb/site.

ini.append.php:

PathPrefix=english

settings/siteaccess/fr/site.

ini.append.php:

PathPrefix=french

Listing 6. Konfiguracja dla rozszerzenia tłumaczeń

<?php /*

[RegionalSettings]

TranslationExtensions[]=

mytranslationext

*/ ?>

Listing 7. Źródło:

extension/mytranslationext/

translations/untranslated

/translation.ts

<!DOCTYPE TS><TS>

<context>

<name>extension/

mytranslationext</name>

<message>

<source>Example label

</source>

<comment>Example

comment</comment>

<translation type=

"unfinished"></translation>

</message>

<message>

<source>More examples

</source>

<translation type=

"unfinished"></translation>

</message>

</context>

</TS>

Rysunek 5. Ustawienia polityki po wybraniu siteaccess-ów

etykiety są po angielsku, więc nie ma potrzeby dokonywać tłumaczenia.

Z przyczyn wydajnościowych, waż-ne jest, by włączyć TranslationCache razem z TextTranslation dla stron wie-lojęzycznych.

Ponieważ w naszej wielojęzycznej konfiguracji użyjemy jednego z admini-stracyjnych siteaccess-ów dla zarządza-nia zawartością wszystkich stron, ważne

Page 56: PHP Solutions 01 2007 PL

Wielojęzyczna konfiguracja

PHP Solutions Nr 1/2007

Narzędzia

www.phpsolmag.org56

jest, by zarówno publiczny siteaccess, jak i siteaccess Interfejsu Administracyjnego używały tego samego katalogu (umiesz-czonego poniżej katalogu var). W przeciw-nym razie niektóre składniki strony (jak pli-ki) przerzucone przez interfejs administra-cyjny będą niedostępne publicznie, bo nie będą mieć dostępu do katalogu 'var' site-access-u administracyjnego. Należy się też upewnić, że Apache ma wystarczają-ce prawa do utworzonych katalogów:

[FileSettings]

VarDir=var/news _ site

Katalog 'var' zawiera pliki buforowe (ca-che files) i logi. Zawiera również części, które nie będą przechowywane w bazie (obrazki i pliki) (Listing4).

I konfiguracja jest gotowa. Następny krok to ustawienie odpowiednich praw dla użytkownika anonimowego do okre-ślonych publicznych siteaccess-ów (gb,

fr, de). W eZ publish możemy ograni-czyć prawa użytkowników tylko do wy-branych siteaccess-ów. To oznacza, że użytkownicy mogą się zalogować tyl-ko na strony, na których mają gwaranto-wane prawa dostępu przez administrato-ra. Ponieważ zmieniliśmy istniejącą kon-figurację, musimy przekazać eZ publish, które siteaccess-y są teraz dostępne pu-blicznie.

Zaloguj się jako administrator do In-terfejsu Administracyjnego za pomocą użytkownika i hasła skonfigurowanego przez kreator ustawień. Nowy URL do Interfejsu Administracyjnego będzie po-dobny do www.example.com/site_admin lub www.example.com/index.php/site_admin, zależnie od nowych ustawień konfiguracyjnych i od tego, czy używasz metody Virtual Host dla URL-a. Po zalo-gowaniu się, przejdź do zakładki Setupi kliknij „Roles and policies”. W liście ról, kliknij rolę „Anonymous” i przycisk „Edit”. W liście bieżących polityk znajdź nastę-pujący wiersz:

Module: user, Function: login,

Limitations: SiteAccess()

Kliknij ikonę „Edit” (symbol pióra po prawej) i wybierz siteaccess-y „gb”, „de” i „fr”. Możesz wybrać wiele opcji jedno-cześnie, przytrzymując klawisz Control.(Rysunek4)

Po wybraniu siteaccess-ów, kliknij „OK”. eZ publish zapisze ustawienia poli-tyki (Rysunek 5).

Module: user, Function: login, Limita-tions: SiteAccess( gb , fr , de ).

Wyjdź z trybu edycji ról klikając „OK”. Zakończyliśmy zatem aktuali-zację praw eZ publish, a teraz należy 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

Listing 8. Łącza tekstowe

{def $locales=fetch( 'content',

'translation_list' )}

{foreach $locales as $locale}

<a href={concat( "index.php/"

, $locale.country_code|downcase(),

"/", $DesignKeys:used.url_alias )

|ezroot}>

{$locale.country_code }

</a>

{delimiter}

|

{/delimiter}

{/foreach}

Listing 9. Łącza z obrazkiem flagi

{def $locales=fetch( 'content',

'translation_list' )}

{foreach $locales as $locale}

<a href={concat

( "index.php/",

$locale.country_code|

downcase(), "/"

, $DesignKeys:used.

url_alias )|ezroot}>

<img src={concat

( "share/icons/flags/",

$locale.locale_code, ".

gif" )|ezroot()} alt=

"" border="0" />

</a>

{/foreach}

Page 57: PHP Solutions 01 2007 PL

Wielojęzyczna konfiguracja

PHP Solutions Nr 1/2007

Narzędzia

www.phpsolmag.org 57

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łumaczeniaProces 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-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 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ęzyczneNowa 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 9. Widok edycji dla nowego tłumaczenia

Rysunek 10. Lista dostępnych tłumaczeń dla bieżącego obiektu

Rysunek 8. Definiowanie języków dodatkowych podczas instalacji

Page 58: PHP Solutions 01 2007 PL

Wielojęzyczna konfiguracja

PHP Solutions Nr 1/2007

Narzędzia

www.phpsolmag.org58

dostępu do zawartości w różnych języ-kach. Powiedzmy, że chcemy mieć nie-zależne tłumaczenia, zatem zawartość dla czytelnika angielskojęzycznego bę-dzie inna, niż zawartość dla czytelnika francuskojęzycznego. W naszej konfigu-racji mamy trzy języki, więc powinniśmy stworzyć trzy foldery (po jednym dla każdego języka) w drzewie zawartości. Te foldery będą przechowywały zawar-tości stron specyficzne dla języka.

Zaloguj się do Interfejsu Administra-cyjnego i stwórz trzy foldery w głównym drzewie katalogów, po jednym dla każde-go języka: „English”, „French” i „German”. (Rysunek 11).

To wszystko. Teraz mamy zdefinio-wane katalogi główne dla zawartości wie-lojezycznej. Zawartość angielska będzie przechowywana w folderze „English”, francuska w „French” itd. To pozwala na segregację zawartości w różnych języ-kach i dostarczania zawartości w okre-ślonym języku podanym w aliasie URL-a.

Następnym krokiem jest dodanie usta-wień konfiguracyjnych do każdego site.

ini.append.php dla publicznego site-access-u (gb, fr, de), które odetnie na-zwę folderu języka z każdego URL-a.W przeciwnym razie eZ publish bę-dzie używał ścieżek np.: http://localhost/ezpublish/index.php/gb/english, gdzie „gb”jest nazwą siteaccess-u, a „english” na-zwą katalogu języka pod drzewem głów-nym eZ publish. Używając ustawienia Pa-thPrefix możemy nakazać eZ publish uży-wanie domyślnie katalogu „English”, ale nie używać go w URL-u. W ten sposób nasza ścieżka będzie wyglądać jak http://localhost/ezpublish/index.php/gb.

Dodaj następujące ustawienia do publicznych siteaccess-ów (gb, de, fr) w bloku [SiteAccessSettings]:

Tak samo, jeśli użytkownik wybierze angielski siteaccess, eZ publish będzie używał folderu „English” jako folder głów-ny angielskiej zawartości.

Własne tłumaczeniaPodczas tworzenia wielojęzycznych stron, czasem potrzebujemy przetłuma-czyć jakieś własne etykiety, które nie są dostępne w domyślnym pliku tłumaczeń eZ publish. Możemy zaimplementować tłumaczenie tych własnych etykiet jako rozszerzenie eZ publish (Rysunek 12).

W pliku extension/mytranslationext/settings/site.ini.append.php, potrzebujemyprzekazać eZ publish, że jest dostępne roz-szerzenie tłumaczeń. Ten plik domyślnie nie jest zakładany – należy go stworzyć.

eZ publish zapisuje tłumaczenia ja-ko XML w plikach o nazwie translation.ts. Poniższy zrzut ekranu pokazuje program QT Linguist użyty do tłumaczenia zawar-tości w pliku XML. To jest plik źródłowy dla innych tłumaczeń użytych jako roz-szerzenie.

Plik translation.tsto zwykły plik tekstowy w formacie XMLWe wzorcach, operator wzorca i18n ozna-cza napis do przetłumaczenia:

{'Example'|i18n( 'extension

mytranslationext' )}

Operator pobiera trzy opcjonalne pa-rametry: „context”, „comment” i „argi-ments”. Parametr „context” może być uży-ty do określenia grupy, do której powi-nien być zaliczony parametr wejściowy. W naszym przykładzie jest to „extension/mytranslationext”

Rysunek 12. Struktura katalogów rozszerzenia tłumaczeń

Łukasz Serwatka jest developerem sys-temu w EzSystems. W swojej pracy sku-pia się głównie na rozwoju kontaktów ze-wnętrznych. Jest autorem wielu aplikacji i suplementów. Współtwórca największej strony o PHP w Polsce www.php.pl.

Kontakt z autorem: [email protected]

O autorze

Rysunek 11. Drzewo zawartości

Więcej informacji na temat i18n we wzorcach znajdziesz na stronie dokumen-tacji: http://ez.no/doc/ez_publish/technical_manual /3 _8 / reference / template_operators/formatting _and_internatio-nalization/i18n

Przełącznik językówMechanizm przełączania języków zale-ży od liczby języków skonfigurowanych dla strony. Mając tylko trzy języki, może-my wyświetlać łącza tekstowe, które po-zwalają użytkownikowi na zmianę języ-ka. Jednak jeśli mamy dużo języków, za dużo miejsca byłoby potrzebne na poka-zanie wszystkich łączy, zatem zamiast łączy pokażemy wybór języka poprzez listę rozwijalną. Przedstawione przykła-dy kodu mogą zostać użyte albo w pa-gelayout.tpl (główny wzorzec eZ pu-blish), albo we wzorcach węzłów.

Oto przykład przełącznika języków, który wyświetla tekst lub łącza obrazkowe dla każdego języka:

Jeśli używasz ustawień Virtual Host na swojej stronie, usuń „index.php” z URL-a w przykładowym kodzie. Ten przykład będzie działał z metodą dostępu URI. Dla metody dostępu HOST kod bę-dzie podobny. Załóżmy, że mamy skonfi-gurowane hosty jak następuje:

PodsumowanieW tym artykule objaśniliśmy, jak skonfi-gurować wielojęzyczną stronę za pomo-cą eZ publish, używając cech dostęp-nych w wersji 3.8. Przedstawiliśmy prak-tyczny przykład, który objaśnił ustawie-nia konfiguracyjne strony i pokazał jak tworzyć nowe tłumaczenia dla obiek-tów strony. Strona wynikowa posiada trzy niezależne językowe siteaccess-y, wszystkie uruchamiane z jednego In-terfejsu Administracyjnego. Z nowymicechami eZ publish 3.8 można dotrzeć do międzynarodowej publiczności przez dodanie języków do twojej strony. n

Page 59: PHP Solutions 01 2007 PL
Page 60: PHP Solutions 01 2007 PL

www.phpsolmag.org60

Testy

PHP Solutions Nr 1/2007

Dwa lata temu Telewizja Interneto-wa TVNET, szukała providera, który

sprzeda i utrzyma odpowiednią domenę, umożliwi zakładanie i administrację konta-mi pocztowymi oraz wymianę dużych pli-ków przez ftp. Najważniejszy jednak był dla nas szybki dostęp do materiałów zgro-madzonych na serwerze przez wiele tysię-cy osób w jednym czasie. Nie mniej ważne było to, żeby serwerem można łatwo admi-nistrować za pośrednictwem jakiegoś pro-stego programu internetowego. Takim pro-gramem jest Active.admin – obsługujący usługę hostingową dostępną w firmie Ne-

tArt w serwisie nazwa.pl. Przejrzysty inter-fejs i wszystkie podstawowe opcje do za-rządzania serwerem (podział powierzchni pomiędzy dowolnymi usługami, zakłada-nie nowych baz danych, zakładanie kont e-mail) bardzo mi się spodobały ze wzglę-du na ogromną prostotę działania.

Po wstępnej selekcji rozpoczęliśmy analizę ofert dwóch firm – NetArt i Ho-me. Obie należą do czołówki dostawców usług internetowych i pozostawiły konku-rencję w tyle. Przy porównaniu cen NetArt wypadł lepiej zarówno przy domenach, jak i serwerach WWW, dodatkowo zapewnia-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-jomych, korzystających z usług obu firm– więcej osób radziło nam NetArt. Ja-ko minus ich usług można wymienić brak możliwości definiowania użytkowników kont ftp, tak by każdy mógł mieć dostęp tylko do przydzielonych im plików. Nato-miast na plus oceniam kontakty z Biurem Obsługi Klienta. Działa w dogodnych go-dzinach, pracownicy zawsze cierpliwie odpowiadają na nawet najbardziej zawi-łe i skomplikowane pytania – tak jak ży-

czyłby sobie tego każdy nieco zagubio-ny klient. Zarówno przestrzeń dyskowa, wielkość transferu, jak i możliwość swo-bodnego podziału przestrzeni są dosko-nałym rozwiązaniem dla firm takich, jak moja gdzie na jednym serwerze prowadzi się kilka niezależnych serwisów interneto-wych, oceniamy na plus.

Dzisiaj prócz serwisu Telewizji Inter-netowej www.TVNET.com.pl na serwe-rze są jeszcze dwie nasze domeny. Dlate-go szukając firmy, w której postawimy ser-wer dystrybucyjny braliśmy również Net-Art pod uwagę, ale rozwiązania informa-tyczne, niezbędne do prowadzenia naszej działalności przemawiały za firmą AirBi-tes Polska, która dostarcza nam łącze in-ternetowe. Wiąże się to z tym, że pomimo dużego transferu serwer Active nie jest serwerem przeznaczonym do nadawania programów TV. A posiadając łącze u jed-nego dostawcy bez dodatkowych proble-mów umieściliśmy tam serwer dystrybu-ujący strumień wideo – było to bardziej dogodne rozwiązanie pod względem or-ganizacyjnym i formalnym. Dziś dokona-libyśmy tego samego wyboru. Ocena: 4.5/5

Prowadząc firmę, której jednym z dzia-łów są usługi dotyczące multime-

diów oraz usługi wykorzystujące możli-wości współczesnego internetu – poszuki-wałem na rynku możliwie najlepszego do-stawcy usług hostingowych. Spośród kilku dostawców tych usług, jakie miałem moż-liwość przetestować w okresie ostatnich kilku lat, firmę ,,NetArt'' oceniam najwy-żej, i tę polecam wszystkim moim zlece-niodawcom.

Przy wyborze dostawcy hostingu, istotnym dla klienta czynnikiem jest oczy-wiście cena – tu firma NetArt wychodzi naprzeciw oczekiwaniom nowych klien-tów, proponując bardzo atrakcyjne ceno-wo promocje. W moim przypadku nie to było głównym kryterium wyboru właśnie tej firmy – czynnikiem, który ułatwił mi podjęcie decyzji było bezpieczeństwo da-nych, obsługi i łatwość administrowania serwerem. Dzięki programom Active.ad-

min i Active.mail nie stanowi to większe-go problemu. Twórcy tych aplikacji posta-wili na intuicyjną obsługę, a ponadto za-wsze mamy do dyspozycji obszerny sys-tem pomocy on-line, kontakt e-mailowy z firmą lub kontakt telefoniczny z konsul-tantem technicznym czy dyżurnym admi-nistratorem systemu.

Kwestia bezawaryjności to kolejna klu-czowa kwestia – strona internetowa jest niekiedy jedynym sposobem komunikacji z klientami, którzy mogą zechcieć odwiedzić strony niezależnie od pory dnia (i nocy!) Nie można pozwolić sobie na częste awarie, bo przypomina to niegdysiejsze wywieszki na drzwiach sklepu ,,przyjęcie towaru” al-bo ,,remanent” – co dla wielu firm oznacza to wymierne straty finansowe. Posiadam serwer w nazwa.pl od ponad dwóch lat– i do tej pory nie wystąpiły żadne po-ważne problemy z jego funkcjonowaniem. Wszelkie prace konserwacyjne wykonywa-

ne są niezwykle sprawnie, poza ,,godzina-mi szczytu”. Pozytywnie należy też oce-nić serwery pod względem parametrów technicznych: spora przestrzeń dyskowa, duży (choć jednak ograniczony) transfer, możliwość posiadania nielimitowanej licz-by domen, nielimitowana liczba kont e-mail wraz z wysoce wydajną i sprawną ochroną przed spamem i wirusami, dodat-kowe konto FTP – to kolejne atuty oferty „NetArt”. Należy dodać, że stosunek tych parametrów do ceny należy do bardzo atrakcyjnych. Dotychczasowe kontakty z Biurem Obsługi Klienta były bez zarzu-tu – bardzo miła i kompetentna obsługa, a otrzymane informacje rzeczowe i wy-czerpujące. Podobnie kilkakrotne kontak-ty e-mail z administratorami spotkały się z szybka reakcją – udzielone odpowiedzi pozwalały rozwiać wątpliwości związane z konfiguracją serwerów i sprawnie popra-wić działanie aplikacji.

Jacek Kmiecikwww.kmiecik.com.pl

Jarek LitwaTelewizja Internetowa TVNET

Page 61: PHP Solutions 01 2007 PL

Testy konsumenckie

www.phpsolmag.org 61

Testy

PHP Solutions Nr 1/2007

Jednym z głównych źródeł docho-dów mojej firmy jest tworzenie

stron WWW opartych o systemy za-rządzania treścią (CMS). Dostarczam rozwiązań zarówno dla klientów z Pol-ski, jak i zagranicy, którzy nie zawsze chcą i potrafią administrować swoimi serwisami internetowymi. Wymagają natomiast ode mnie, żebym umieścił gdzieś ich witryny – dla nich oczywi-stym jest, że strony będą widoczne w sieci bez przerw, a z poczty będą mo-gli korzystać także przez przyjazny in-terfejs WWW.

Poszukiwałem usług wydajnych, niezawodnych o przyzwoitej cenie oraz wielojęzycznych interfejsach do odczy-tu poczty przez strony WWW. Bardzo mi zależało, aby program do obsługi poczty przez WWW był maksymalnie prosty w obsłudze. Te cechy połączy-ły usługi nazwa.pl, dodatkowo w obsłu-dze poczty traktuję możliwość darmo-wego otrzymywania smsów z powia-domieniami o przychodzącej poczcie. Duże znaczenie miała także elastycz-ność serwera, czyli możliwość dowol-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

nowych wersji MySQL. Wbrew pozo-rom jest to ważne, bo świadczy o tym, że firma rozwija swoją infrastrukturę.

Spośród wszystkich innych ofert pod uwagę brałem tylko rozwiąza-nia głównego konkurenta nazwa.pl – home.pl, ale niestety ich interfejsy do obsługi poczty przez WWW nie po-siadają wersji niemieckiej (posiada tylko polską i angielską). Oprócz te-go jakość samego programu do admi-nistracji serwerem oraz obsługi pocz-ty przez WWW, jest znacznie wyższa w nazwa.pl – choć jest to zupełnie su-biektywne odczucie i nie każdy się z nim zgadza. Także stosunek ceny do oferowanego produktu wypada na ko-rzyść nazwa.pl. No i pozostaje kwestia korzystania z programu partnerskiego – choć niestety żadna poważna firma nie oferuje pieniędzy za poleconych klientów, to nazwa.pl ma znacznie bo-gatszy i bardziej rozwinięty taki pro-gram. Dla mnie udział w nim to czysty zysk, gdyż, jeśli polecę jednemu klien-towi zakup serwera to praktycznie dru-gi serwer mam gratis i mogę go wyko-rzystywać do własnych potrzeb – np. umieszczać na nim serwisy WWW in-nych moich klientów. Gdzie indziej nie ma takiego przelicznika, że jeden pole-cony serwer daje mi serwer gratis a w nazwa.pl tak – to był jeden z argumen-tów, który przemawiały za nazwa.pl.

Ogólnie rzecz biorąc jestem zado-wolony z usług nazwa.pl, choć braku-je mi możliwości zakładania kont pocz-towych o takiej samej nazwie na jed-nym serwerze dla różnych domen, np. [email protected] oraz [email protected]. Jednak mam świadomość, że wynika

to z tego, iż jest to usługa hostingowa, a nie serwer wirtualny i stąd te ograni-czenia.

Podsumowując chwale sobie sta-bilność serwera – praktycznie, od kie-dy korzystam z serwerów w nazwa.pl nie miałem żadnych przerw w wyświe-tlaniu stron co zdarzało się u mojego poprzedniego dostawcy, aktualizację php'a i MySQL'a, program partnerski, infolinie 0801, szybkość przypisywania domen do serwera, pomoc techniczną oraz przejrzystość panelu administra-cyjnego zarówno serwera jak i poczty.

Gdybym miał ponownie podjąć de-cyzję o zakupie usługi hostingowej by-łaby ona taka sama.

O nazwa.pl dowiedziałem się z re-klam internetowych i prasowych. Tylko nazwa.pl i home.pl to firmy hostingo-we prowadzące działania marketingo-we na wysokim poziomie. Wbrew po-zorom jest to ważne, bo swoim klien-tom oferuję usługi znanych firm – prak-tycznie każdy mój klient kiedyś spotkał się z reklamami nazwa.pl i to daje po-czucie bezpieczeństwa oraz pośrednio wpływa na mój wizerunek. Skoro w ra-mach stworzenia serwisu WWW doda-ję jego umieszczenie u znanego ope-ratora, to znaczy, że traktuję klientów poważnie i nie szukam oszczędności kosztem jakości usług oraz mogę gwa-rantować jakość tych usług.

Uważam, że usługę, z której korzy-stam mogę bez wahania ocenić na 4,5 gwiazdki, 0,5 gwiazdki zabieram wła-śnie za względu na brak możliwości zakładania kont pocztowych o takiej samej nazwie na jednym serwerze dla różnych domen.

Sebastian Zawaliret.pl

Page 62: PHP Solutions 01 2007 PL

Testy konsumenckie

www.phpsolmag.org62

Testy

PHP Solutions Nr 1/2007

Nasza firma istnieje już od prawie 10 lat. Koncentrujemy się na dostar-

czaniu usług serwerów małym i średnim firmom. Ostatnio szeregi naszych klien-tów powiększają się stopniowo także o użytkowników indywidualnych. Rosną-ca liczba klientów nie jest tylko wynikiem atrakcyjnej ceny, chociaż ta faktycznie w przeciągu kilku ostatnich lat bardzo się zmniejszyła. Obniżenie progu cenowe-go kupna serwera do 50 zł netto sprawi-ło, że w potocznym mniemaniu przestał on być uważany za usługę drogą, bę-dącą poza zasięgiem małego przedsię-biorcy, a tym bardziej osoby prywatnej. Oferta NetArt przyciągnęła rzesze klien-tów, którzy mogli dzięki temu przekonać się o korzyściach wynikających z posia-dania serwera WWW.

Widać, że nasi klienci doceniają ja-kość naszych usług i ich sprawne funk-cjonowanie. Trzeba zdawać sobie jed-nak sprawę, iż jest ono efektem wielu lat doświadczenia w dostarczaniu hostingu oraz bardziej zaawansowanych usług serwerów. To niezbędny czas, by osią-gnąć wysoki poziom usług, opracować funkcjonalne oprogramowanie, zbudo-

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-wać w rok czy dwa.

Nasze Data Center znajduje się w Polsce, co znacznie skraca czas reak-cji na ewentualne problemy. Nie mu-simy korzystać z łańcucha pośredni-ków, aby móc wyjaśnić każdy, nawet najmniejszy problem w działaniu usłu-gi konkretnego klienta. Doświadcze-nie w diagnozowaniu problemów, z ja-kimi zgłaszają się do nas użytkownicy internetu i dogłębna wiedza na temat serwerów to natomiast kapitał, który zbieraliśmy przez wszystkie lata na-szej działalności.

Na każdą z naszych usług patrzy-my przez pryzmat naszego klienta. Wiemy, że jest grupa klientów bardzo zaawansowanych, którzy w pełni wy-korzystają serwery. Jednak dla dużej części klientów jest to pierwszy kon-takt z serwerem WWW. Dlatego bar-dzo istotne było dla nas opracowanie aplikacji, które umożliwią administro-wanie serwerem i zarządzanie pocz-tą w jak najprostszy sposób. Efektem naszej pracy są programy Active.ad-min i Active.mail, które wciąż są udo-skonalane i modyfikowane. Ich intu-icyjność to czynnik często podkreślany przez naszych klientów. Dzięki ich pro-stocie i funkcjonalności klienci nie boja się sami administrować swoimi usługa-mi, nie nastręcza to bowiem żadnych problemów.

Stabilność działania i systematycz-ny rozwój to czynniki, które umożliwia-ją nam inwestowanie w infrastrukturę. Na bieżąco staramy się aktualizować nasze oprogramowanie, dbamy także o najwyższą jakość rozwiązań hardwa-rowych.

Najlepszą dla nas nagrodą jest za-dowolenie naszych klientów. Cieszą sło-wa Panów, którzy odpowiedzieli na py-tania redakcji PHP Solution. Widać tu-taj, że nasze serwery spełniają wyma-gania nawet najbardziej wymagających klientów. Służą nie tylko do budowania najprostszych serwisów, ale pozwalają także na budowanie zaawansowanych serwisów multimedialnych. Cieszymy się, że wysiłki zmierzające ku zapewnie-niu klientom najwyższej jakości usług są

Justyna ZajączkowskaSpecjalista ds. Public Relations w NetArt

widoczne i doceniane. To pozytywny im-puls do tego, aby jeszcze intensywniej pracować.

Cieszymy się także, że coraz więk-sze uznanie zyskuje nasze Biuro Ob-sługi Klienta – od kilku lat intensyw-nie je powiększamy i wdrażamy kolej-ne standardy obsługi klienta. Chcemy zapewnić bezproblemowy kontakt z naszymi konsultantami i fachową ob-sługę bez długiego okresu oczekiwa-nia na połączenie telefoniczne. Zdaje-my sobie sprawę, że dla części klien-tów administrowanie serwerem może czasem generować problemy – dlate-go też kilkudziesięciu konsultantów po-maga uporać się nie tylko z kwestiami technicznymi, ale także administracyj-nymi.

Nasi klienci zgłaszają oczywiście drobne zastrzeżenia – takie jak limit transferu czy brak kont FTP zdefinio-wanych dla każdego użytkownika. Fak-tycznie można uznać to za pewne nie-dogodności, ale pamiętajmy, że roz-mawiamy tutaj o hostingu. Jest to usłu-ga podstawowa, która z definicji pew-ne parametry musi mieć ograniczone. Osoby pragnące posiadać nieograni-czony transfer czy więcej kont FTP de-cydują się na usługi bardziej zaawan-sowane, takie jak serwer wirtualny czy dedykowany.

Wiemy, że potrzeby i wymagania naszych klientów nieustannie rosną, tak samo jak zwiększa się zakres ich działalności. Dlatego staramy się tak konstruować nasze usługi, aby każ-dy klient mógł znaleźć coś dla siebie. Użytkownicy, którzy potrzebują rozbu-dowanych możliwości zarządzania, al-bo których serwery generują bardzo duży ruch mogą skorzystać z nasze-go serwisu – serwery.pl, gdzie zakupić można bardziej zaawansowane usługi, takie jak serwer dedykowany, serwer wirtualny czy kolokację. Wierzymy, że szeroka gama usług, ich wysoka ja-kość oraz przystępna cena sprawiają, że grono naszych klientów tak szybko się powiększa.

Page 63: PHP Solutions 01 2007 PL

Testy konsumenckie

www.phpsolmag.org 63

Testy

PHP Solutions Nr 1/2007

Własna domena, szata graficzna oraz funkcjonalność strony inter-

netowej jest dziś istotnym elementem polityki marketingowej firmy. Bez niej firma w oczach Klientów z pewnością jest mniej wiarygodna. Działania pro-mocyjne i reklamowe skupiające się na wizerunku firmy i jej obecności na rynku z pewnością odnoszą znacznie większy skutek gdy firma podaje własny adres internetowy związany z jej działalno-ścią lub nazwą.

Wdrażając w życie kolejny serwis internetowy, potrzebowaliśmy stosun-kowo taniej, a dobrej oferty serwera wirtualnego.

Funkcjonując w sieci od 2001 roku, mając dosyć dobre rozeznanie w ofer-cie usług hostingowych na rynku polskim (aktualnie korzystamy z 11 serwerów wir-tualnych różnych dostawców), przy za-chowaniu pewnych kryteriów wynikają-cych z dotychczasowych doświadczeń, kwestią czasu było odnalezienie produk-tu odpowiadającego naszym wymaga-niom. Przy wyszukiwaniu ofert nie suge-rowaliśmy się reklamami, ale sprawdzali-śmy firmy hostingowe z czołowych pozy-cji w wyszukiwarkach. Pod uwagę brane były parametry:

• pojemność konta,• transfer,• cena,• ilość obsługiwanych domen/ subdomen,• ochrona antywirusowa,• pomoc techniczna 24h,• panel administracyjny konta.

Uwagę zwróciła oferta Miracle Systems Cybermedia (Miracle.pl).

Serwer o wystarczającej pojemności 1 GB z miesięcznym pakietem ruchu z/do sieci Internet 10GB, nieograniczoną ilo-ścią subdomen, nielimitowana ilość kont pocztowych, ochrona m antywirusowa, całodobowa pomoc techniczna, panel itp. Całość w cenie 99 zł.

Przyszedł czas na sprawdzenie funk-cjonalności oferty czyli wykorzystanie 7 dniowego okresu testowego.

Sprawdzaliśmy bardzo podstawową funkcjonalność konta jak: szybkość łado-wania się średniej wielkości strony, ochro-nę antywirusową, „uptime” serwera, prze-sył danych pomiędzy komputerem a ser-werem czy praca obszerniejszej bazy da-nych, co przy rozwoju serwisu i wzrostu liczby użytkowników ma znaczenie. Wie-le firm hostingowych mniejszych, więk-

szych operuje całodobową pomoc tech-niczną administratora. Otóż prawda czę-sto bywa zupełnie inna. Administrator jest ale w ograniczonym czasie.

Moim zdaniem, kluczowym elemen-tem atrakcyjności danej oferty prócz ce-ny i parametrów konta jest właśnie bardzo dobry kontakt z administratorami serwera. Sposób dowolny (przez formularz kontak-towy, telefon czy po prostu zwykły e-ma-il). Wiele prac związanych z funkcjono-waniem danej witryny internetowej, doko-nuje się w godzinach wieczorno nocnych, gdzie ruch w sieci internet jest stosunko-wo mniejszy i niekiedy są to operacje wy-magające kontaktu z administratorem.

W przypadku testowanego konta w ofercie hostingowej Miracle.pl wszystkie parametry jak obsługa techniczna wypa-dły bardzo dobrze i zapadła decyzja o za-kupie.

Aktualnie blisko pół roku korzy-stamy z zakupionego konta na serwe-rze. Wszystkie zadeklarowane w ofer-cie, sprawdzone w okresie testowym pa-rametry jaki i kontakty z administratorem sprawdzają się w 100%. Nasza współpra-ca z pewnością będzie kontynuowana.

Gdybym miał możliwość ocenienia użytkowanego konta w skali 1 do 5 ocenił bym to 5 przysłowiowych gwiazdek.

Maksymilian DrążekGrupa 505

Page 64: PHP Solutions 01 2007 PL

Testy konsumenckie

www.phpsolmag.org64

Testy

PHP Solutions Nr 1/2007

Wybraliś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 PHP proces konfiguracji hostingu i dosto-sowania kodu zajął nam kilka dni.

Oprócz home.pl korzystamy jeszcze z usług pair.com i xon.pl każdy z provie-derów posiada specyfikę i jest przez nas wykorzystywany w różnych zastosowa-niach.

Zalety miracle.pl to: szybkie transfe-ry, bezpieczeństwo zdecydowanie ponad standard, dobra obsługa, elastyczność i dobra cena.

Wadą jest brak wielu klas IP C ta ce-cha była przez nas szczególnie pożądana średni czas reakcji może być akceptowal-ny i jest to zwykle kilka godzin.

Pierwszy hosting zakupiliśmy w ma-ju 2006 w październiku kolejny jeśli firma Miracle.pl będzie się rozwijała planować będziemy osadzanie kolejnych projektów.

Polecamy usługi Miracle dla średnio wymagającego klienta przy niektórych lub dla dodatkowych zastosowań dla wy-magającego klienta.

W skali 1-5 oceniamy usługi Miracle.pl na 4 gdyby z naszych doświadczeń wyklu-czyć te związane z home.pl byłaby to 5.

Grzegorz Tarnowskiwww.4hotele.pl

Na wstępie dziękuję „Phpsolmag”za zainteresowanie się Miracle.pl i jego

ofertą.Dziękuję także klientom za wyrażenie

opinii na łamach magazynu, cieszę sięże usługi które Wam świadczymy spoty-kają się z pozytywnym odbiorem z Wa-szej strony.

Nie poprzestajemy jednak „na laurach” ciągle staramy się ulepszać jakość usług(jako że zadowolenie klientów jest naj-ważniejsze i bardzo motywujące) przy-kładowo kilka dni temu wprowadziliśmy nowy, bardzo funkcjonalny i prawdopo-dobnie najlepszy na świecie panel użyt-kownika – Cpanel, a od 1 grudnia zo-stała wprowadzona promocja miesięcz-na związana ze świętami co ma zachę-cić Państwa do skorzystania z oferty Mi-racle.pl.

Średni czas reakcji w ostatnim cza-sie został bardzo skrócony w związku z wprowadzeniem telefonicznej pomocy technicznej - pod numerem tel. 600 61 00 51 mogą Państwo uzyskać wszelką po-moc.

Odnośnie klas IP, to są one nieroz-łącznie związane z nowymi serwerami, w chwili obecnej serwis miracle.pl jest

dynamicznie rozwijany, co będzie wiąza-ło się z dokupywaniem nowych serwerów na różnych klasach IP.

Nasza firma zajmuje się usługami in-ternetowymi od 1997 roku, posiada kil-ka serwisów internetowych na Polskimrynku co pozwala nam dotrzeć do bar-dzo szerokiego grona odbiorców, na-sze usługi oferujemy także w sprzedażybezpośredniej (projektowanie stron, kon-figuracja serwerów). W związku z szyb-kim rozwojem Internetu i wzrostem kon-kurencji na rynku w 2006 roku podjęli-śmy decyzję o stworzeniu serwisu Mirac-le.pl. Serwis ten oferuje wysoką jakośćusług w dobrych cenach, oferta skiero-wana jest głównie do małych i średnichfirm, oraz klientów indywidualnych. Sta-ramy się kłaść nacisk na jakość ofero-wanych usług, oraz dobre i indywidual-ne podejście do klienta, bo to klient jest najważniejszy, a Jego zadowolenie gwa-rantuje sukces każdej firmy. Zapraszam do zapoznania się z naszą ofertą i aktu-alnymi promocjami.

Łukasz GórskiSpecjalista od Reklamy i Marketingu Cybermedia.pl

Page 65: PHP Solutions 01 2007 PL
Page 66: PHP Solutions 01 2007 PL

Zaprenumeruj swoje ulubione magazyny i zamów archiwalne numery!

Już teraz w kilka minut możesz zaprenumerować swoje ulubione pismo.Gwarantujemy:- preferencyjne ceny- bezpieczną płatność on-line- szybką realizację Twojego zamówienia Bezpieczna prenumerata on-line wszystkich tytułów Wydawnictwa Software!

www.buyitpress.com zamówienie prenumeraty

Page 67: PHP Solutions 01 2007 PL

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: [email protected]. 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)............................................................................................................................................................................

zamówienie prenumeraty

1 Cena prenumeraty rocznej dla osób prywatnych 2 Cena prenumeraty rocznej dla osób prenumerujących już Software Developer’s Journal lub Linux+3 Cena prenumeraty dwuletniej Aurox Linux

Jeżeli chcesz zapłacić kartą kredytową, wejdź na stronę naszego sklepu internetowego:

www.buyitpress.com

automatyczne przedłużenie prenumeraty

Suma

Tytuł Ilość numerów

Ilość zamawianych prenumerat

Od numeru pisma lub miesiąca

Opłata w zł

z VATSoftware Developer’s Journal (1 płyta CD)– dawniej Software 2.0Miesięcznik profesjonalnych programistów

12 250/1801

SDJ Extra (od 1 do 4 płyt CD lub DVD)– dawniej Software 2.0 Extra!Numery tematyczne dla programistów

6 150/1352

Linux+DVD (2 płyty DVD)Miesięcznik o systemie Linux 12 199/1791

Linux+Extra! (od 1 do 7 płyt CD lub DVD)Numery specjalne z najpopularniejszymi dystrybucjami Linuksa 8 232/1982

PHP Solutions (1 płyta CD)Dwumiesięcznik o zastosowaniach języka 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

Page 68: PHP Solutions 01 2007 PL

triki w php

PHP Solutions Nr 1/2007

Narzędzia

www.phpsolmag.org68

triki w php

PHP Solutions Nr 1/2007

Narzędzia

www.phpsolmag.org 69

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

Pisząc skrypty w PHP często zdarza się, że należy zajrzeć do źródła wyge-nerowanej strony aby sprawdzić czy wszystkie elementy zostały wydruko-wane poprawnie. Niestety jeżeli skrypt jest w całości napisany za pomocą ję-zyka PHP i nie ma w nim miejsc, w któ-rych zastosowany jest czysty HTML zo-rientowanie się w źródle programu bę-dzie bardzo ciężkie ze względu na brak nowych linii. Całość strony WWW zosta-nie wypisana linia za linią bez znaków nowego wiersza. Można tego uniknąć stosując specjalne znaki, które pomo-gą w nadaniu dla źródła strony WWW odpowiedniego formatowania. Znakiem specjalnym jest między innymi \n - czyli znak oznaczający nową linię.

Po zajrzeniu do źródła takiej strony zo-baczymy całość tekstu w jednej linii mimo iż wypisywaliśmy ja w kilku linijkach w ko-

dzie PHP. Jest to spowodowane tym iż nie ma znaków nowej linii.

W celu uniknięcia takiego problemu możemy zastosować znaki nowej linii na zakończeniu każdego wiersza.

W tym przypadku źródło strony bę-dzie podzielone na osobne linie w których umieściliśmy tekst. Nowe linie powstały w miejscu gdzie umieściliśmy znak \n.

Przekształcanie zmiennych wysłanych za pomocą metody GET i POST w zwykłe zmienne

W PHP możesz także przetworzyć zmienne z tablicy w zwykłe zmienne. Musisz tylko wybrać, którą tablicę masz zamiar przetwarzać. Jest to zwłasz-cza przydatne, kiedy funkcja register_globals jest wyłączona. Funkcję register_globals wyłącza się specjal-nie w celu uczynienia skryptów bardziej bezpiecznych pod względem użytkowa-

Listing 1. Skrypt PHP bez zastoso-wania znaków nowej linii

<?php

echo 'Ala ma kota';

echo '<br />';

echo 'Kot ma Ale';

?>

Listing 2. Formatowanie strony z użyciem znaku nowej linii

<?php

echo "Ala ma kota\n";

echo "<br />\n";

echo "Kot ma Ale\n";

?>

Listing 3. Skrypt przetwarzający zmienne z tablicy $_GET

<?php

if( is_array($_GET) ){

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 2. Wygląd źródła strony z zastosowaniem 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 wiemy kto z nich korzysta.

Znaki specjalne

Page 69: PHP Solutions 01 2007 PL

triki w php

PHP Solutions Nr 1/2007

Narzędzia

www.phpsolmag.org68

triki w php

PHP Solutions Nr 1/2007

Narzędzia

www.phpsolmag.org 69

Listing 5. Wyrażenie regularne do sprawdzenia, czy tekst jest popraw-nym adresem e-mail

<?php

preg_match( "|^[-_\.a-z0-9]+

@[-_a-z0-9\.\+]+\.[a-z0-9]

{2,4}$|i", trim($email));

?>

Listing 6. Kod do sprawdzenia ad-resu e-mail

<?php

if(!preg_match( "|^[-_\.a-z0-9]+@[-_a-z0-9\.\+]+\.[a-z0-9]{2,4}$|i"

, trim($email)))

{

echo 'e-mail nie jest poprawny';

}

else{

echo 'e-mail jest poprawny';

}

?>

W momencie, gdy jakaś osoba będzie się rejestrowała na twojej stronie WWW będziesz miał możliwość walidacji czy-li sprawdzenia poprawności jej adresu e-mail. Użyjemy do tego wyrażenia re-gularnego i za pomocą odpowiedniej funkcji ereg sprawdzimy, czy e-ma-il został wprowadzony prawidłowo. Ad-res będzie przechowywany w zmiennej $email którą poddamy sprawdzeniu.

W tym momencie musimy jeszcze dokonać odpowiedniej czynności, gdy sprawdziliśmy już, czy adres e-mail zo-stał zweryfikowany. Najlepiej jest doko-nać tego za pomocą polecenia if.

Oprócz sprawdzenia czy adres e-mail jest poprawy czyli zawiera przynajmniej znak małpy „@” i jedną kropkę możemy jesz-cze stwierdzić czy host danego adresu istnieje. Zrobimy to poprzez sprawdzenie rekordu MX danego serwera. Oczywiście możemy to zrobić jedynie wtedy, gdy host serwera obsługuje port 25.

W ten sposób możemy od razu do-wiedzieć się czy adres który podano w formularzu jest poprawny pod względem faktu, iż serwer na którym się on znajdu-je istnieje.

Listing 7. Program sprawdzający dostępność hosta

<?php

list($Username, $Domain) =

split("@",$email);

if(getmxrr($Domain, $MXHost)){

echo 'adres e-mail jest

poprawny';

}

else{

if(fsockopen($Domain, 25, $errno, $errstr, 30))

{

echo 'adres e-mail jest poprawny';

}

else {

echo 'adres e-mail NIE jest

poprawny';

}

}

?>

Walidacja adresu e-mail Sprawdzenie hostaz adresu e-mail W PHP możesz także dokonać odświe-

żenia strony. Jest to także często stoso-wana instrukcja w kodzie HTML. Jed-nak dzięki zastosowaniu w tym przypad-ku kodu PHP nikt nie będzie mógł takiej instrukcji usunąć jak byłoby to możliwe w kodzie HTML.

Skrypt ten spowoduje odświeżenie się strony za 3 sekundy, które podajemy w parametrze. Po słowie url podajemy adres URL do którego strona ma przejść po odświeżeniu. W tym wypadku strona przeładuje się i wrócisz automatycznie na stronę główną.

Możesz także skonstruować ele-ment przekierowujący użytkownika na inną stronę. Ten skrypt jest trochę inny od użycia parametru location. W przy-padku location strona nie pojawiała się w przeglądarce tylko automatycznie się przeładowywała. W tym przypadku stro-na zostanie wyświetlona w przeglądar-ce, a następnie się przeładuje.

Listing 8. Automatyczne odświeże-nie strony

<?php

header( 'refresh: 3; url=/' );

echo '<h1>Zostaniesz

przeniesiony za 3 sekundy...</h1>';

?>

Listing 9. Przekierowanie na stronę

<?php

header('refresh: 0; url

=http://www.google.pl');

?>

Odświeżania strony

PHP przychodzi z pomocą w przypad-ku, gdy mamy potrzebę przekierowa-nia użytkownika w zależności od uży-wanej przeglądarki internetowej. Wy-starczy wówczas sprawdzić jakiej przeglądarki używa osoba odwiedza-jący naszą stronę WWW, a następnie za pomocą polecenia header przekie-rować ją pod odpowiedni adres w sie-ci Web.

W skrypcie za pomocą funk-cji strstr sprawdzamy, czy w zmien-nej $_SERVER['HTTP_USER_AGENT'], jest zawarta nazwa przeglądarki, o którą nam chodziło. Jeżeli jest za-

Listing 4. Przekierowanie użytkow-nika na odpowiednią stronę w zależ-ności od przeglądarki której używa

<?php

if ($name = strstr ($_SERVER['HTTP_USER_AGENT'], "MSIE"))

{

Header ("Location:

http://www.stronadomowa.pl/");

}

else {

Header ("Location:

http://www.innastrona.pl/");

}

?>

Przekierowanie w zależności od przeglądarkiwarta wówczas za pomocą polece-nia header przekierowujemy użytkow-nika na odpowiednią stronę WWW.W przypadku gdyby była to inna prze-glądarka, wówczas możemy użytkow-nika przekierować pod inny adres.

Bardzo ważne jest aby skrypt zna-lazł się zanim cokolwiek wydrukujesz do przeglądarki. Oznacza to, iż mu-si on znaleźć się na samym począt-ku pliku zanim cokolwiek wyjdzie ze skryptu gdyż wtedy nagłówek już zo-stanie wysłany i nie będziesz mógł już nic zrobić.

Page 70: PHP Solutions 01 2007 PL

triki w php

PHP Solutions Nr 1/2007

Narzędzia

www.phpsolmag.org70

Pewnie zauważyłeś wielokrotnie na stro-nie jest pokazany czas jej generowa-nia. Jest to bardzo proste do wykonania i umożliwi ci wzbogacenie swojej strony o dodatkowy element.

Pierwszą rzeczą, której będziemy po-trzebować to pobranie wartości z funkcji microtime i rozdzielenie jej na dwie części. Następnie dodamy te części do siebie aby uzyskać pełny czas. Następnie na samym końcu strony wykonujemy ponownie po-branie czasu z funkcji microtime, rozdzie-lenie jej na dwie części za pomocą pole-cenia explode i dodania do siebie czasów. Deklarujemy także zmienną która pozwoli nam na zaokrąglenie czasu do odpowied-niego miejsca po przecinku.

W celu uzyskania czasu ładowania się strony należy odjąć od czasu końcowego czas początkowy, który pobraliśmy na po-czątku ładowania się strony.

W następnym kroku wystarczy różnicę czasu już tylko wyświetlić zaokrągloną do odpowiedniej ilości miejsc po przecinku.

Listing 10. Pobranie czasu począt-kowego

<?php

$m_time = explode

(" ",microtime());

$m_time = $m_time[0] +

$m_time[1];

$starttime = $m_time;

?>

Listing 11. Pobranie czasu koco-wego

<?php

$round = 3;

$m_time = explode(" ",microtime());

$m_time = $m_time[0] +

$m_time[1];

$endtime = $m_time;

?>

Listing 12. Odjęcie czasu końcowe-go i początkowego

<?php

$totaltime = ($endtime

- $starttime);

?>

Listing 13. Wyświetlanie czasu ła-dowania strony

<?php

echo 'Strona ładowała się: '. round

($totaltime,$round) . ' sekund';

?>

Czas generowania strony

Listing 14. Zabezpieczanie zmien-nych

<?php

if(!get_magic_quotes_gpc()){

$_GET = array_map

('addslashes', $_GET);

$_POST = array_map

('addslashes', $_POST);

$_COOKIE = array_map

('addslashes', $_COOKIE);

$_REQUEST = array_map

('addslashes', $_REQUEST);

}

?>

Listing 15. Specjalna funkcja do za-bezpieczania danych przed wprowa-dzeniem ich do bazy danych

<?php

$zdanie = "Mark's laptop";

$zabezpieczone_zdanie =

mysql_real_escape_string($zdanie);

print($zabezpieczone_zdanie);

?>

Funkcje te pozwalają na dodawanie do ciągów znaków, które otrzymujemy od użytkowników z różnych formularzy czy tez adresów URL specjalnych znaków, które zabezpieczają takie ciągi przed wprowadzeniem do bazy danych wraz ze znakami które mogą spowodować błąd.

Dzięki tym funkcjom unikniemy ataków „SQL injection”. Ataki te polegają na odpo-wiednim spreparowaniu zapytań do baz danych, dzięki czemu można uzyskać róż-ne dane nie przeznaczone dla użytkowni-ka. Dzięki zastosowaniu tej funkcji nie bę-dziesz musiał za każdym razem używać funkcji addslashes() dla każdej zmiennej pobranej z adresu URL lub formularza.

Ten fragment kodu sprawdza czy funkcja automatycznego dodawania sla-shy jest włączona, jeżeli nie jest włączo-na używane są funkcje do automatycz-nego zabezpieczenia danych. Pamiętaj jednak iż jeżeli będziesz chciał użyć war-tości tych zmiennych w formularzach ge-nerowanych za pomocą PHP będziesz musiał dane poddać obróbce polece-niem stripslashes. Jest to spowodowane faktem iż jeżeli użytkownik wstawi jakiś tekst do formularza zostanie on automa-tyczne oznaczony znakami slash. Więc przed użyciem polecenia echo, print lub podobnego będziesz musiał usunąć sla-she z wartości tych zmiennych.

Można także skorzystać ze spe-cjalnej funkcji gdy mamy zamiar dodać wprowadzone dane do bazy MySQL. Funkcja mysql_real_escape_string okre-śli aktualnie używany w połączeniu ze-staw znaków i zabezpieczy wszystkie znaki uznane za niebezpieczne.

Dodawanie slashy do zawartości zmiennych

W przypadku gdy użytkownik Interne-tu podaje link do swojej strony WWW możesz od razu sprawdzić czy taka strona istnieje. Zrobisz to za pomocą funkcji fsockopen, która da ci informa-cję, czy wskazany przez ciebie host znajduje się w sieci, czy tez nie.

Funkcja fsockopen próbuje połą-czyć się z serwerem, który podasz mu w pierwszym parametrze. Pamię-taj, aby adres strony podać bez http:// z przodu ponieważ funkcja nie zadzia-ła w takim przypadku.

Drugi parametr to port którego uży-wa skrypt do połączenia się ze wska-zana stroną. Domyślnym portem dla strony WWW jest port 80 więc tego parametru nie powinieneś zmieniać. Następne dwa parametry są standar-dowymi błędami PHP które są wypi-sywane do tych zmiennych. Ostatnim z argumentów czyli 30 jest ilością se-

Listing 16. Sprawdzanie dostępno-ści adresu URL

<?php

$up = @fsockopen('www.google.pl',

80, $errno, $errstr, 30);

if($up){

echo '<a href=

"http://www.google.pl"

>Google.pl</a>';

}

else{

echo '<a href=

"http://www.google.pl"

>Google.pl nie działa</a>';

}

?>

Sprawdzanie adresu URLkund jaką ma czekać skrypt zanim przestanie próbować połączyć się z serwerem.

Page 71: PHP Solutions 01 2007 PL

triki w php

PHP Solutions Nr 1/2007

Narzędzia

www.phpsolmag.org 71

Listing 17. Skrypt pokazujący infor-macje o PHP

<?php

phpinfo();

?>

Listing 18. Strona WWW z włączo-ną kompresją

<?php

ob_start('ob_gzhandler');

?>

<html>

<head>

</head>

<body>

<p>Ta strona została

SKOMPRESOWANA!</p>

</body>

</html>

Kompresja pozwala na znaczne przy-spieszenie się ładowania strony na na-szym komputerze dzięki temu iż jest ona skompresowana i znacznie mniej czasu zajmuje jej przesłanie. Dla serwera jest to jednak obciążenie gdyż oprócz wyge-nerowania strony musi ją także skompre-sować.

W celu rozpoczęcia kompresji strony należy sprawdzić czy na naszym serwe-rze jest zainstalowana biblioteka zlib i czy jest ona włączona.

Skrypt pozwoli nam na sprawdzenie, czy biblioteka została włączona do inter-pretera PHP na serwerze. Wystarczy od-

Rysunek 3. Informacje na temat biblioteki zlib

Kompresja strony za pomocą zlibnaleźć fragment opatrzony etykietą zlib. Jeżeli znajduje się tam obok napisu ZLib Support napis enabled oznacza to, iż bi-blioteka jest włączona.

Następnie wystarczy dodać mały frag-ment skryptu do naszej strony WWW. Pa-miętaj, iż musi się on znaleźć zanim co-kolwiek wyślesz do przeglądarki. W takim przypadku spowoduje to błąd. Skrypt mu-si znaleźć się na samej górze strony

W niektórych przeglądarkach takich jak na przykład Internet Explorer 6 kom-presowanie strony niestety nie działa. Przeglądarka najczęściej zawiesza się przy próbie przeczytania takiej strony. Naj-

lepiej w takim przypadku zrobić detekcje przeglądarki internetowej i dla odpowied-niej zastosować kompresję.

Jeżeli będziesz musiał przekierować użyt-kownika do innej strony i będziesz chciał zrobić to za pomocą PHP z pomocą przyj-dzie w tym momencie polecenie header. Pozwala ono na przeniesienie użytkowni-ka na inną stronę bez jego wiedzy o tym fakcie. Możesz na przykład za pomocą te-go polecenia zrobić system zliczania ilości pobierania pliku. Najpierw tworzysz stronę na której dodajesz jeden do licznika po-brań programu, a potem przekierowujesz użytkownika do pliku który chciał pobrać.

Listing 19. Automatyczne przekie-rowanie użytkownika

<?php

header('location:

http://www.google.pl/');

?>

Przekierowanie w PHPSkrypt ten przekieruje użytkownika

na stronę http://www.google.pl bez poka-zywania mu jakichkolwiek komunikatów. W celu zmiany adresu URL wystarczy, iż w skrypcie zmienisz tylko adres który jest tam obecnie. Funkcja header której uży-łem w tym skrypcie służy do wysyłania nagłówka dokumentu. Jest w niej użyty parametr location co oznacza, iż serwer ma przejść na odpowiednią stronę WWW. Funkcja ta zadziała tylko wówczas gdy zostanie ona wywołana na samym po-

czątku pliku. Jeżeli wypiszesz już coś do przeglądarki wówczas generowanie stro-ny zakończy się błędem.

Listing 20. Plik z rozszerzeniem pli-ków PHP

<?php

$RozszerzeniePHP = 'php';

?>

Listing 21. Włączanie pliku z roz-szerzeniem zawartym w zmiennej

<?php

include('rozszerzenie.inc');

include('plik. '.$RozszerzeniePHP);

?>

Bardzo często podczas przenoszenia pli-ków na inny serwer możemy natknąć się na błąd w ich rozszerzeniu. W większości serwerów jako pliki zawierające skrypty w języku PHP uznawane są pliki posia-dające rozszerzenia: .phtml, .php3, .php i .php5. Jeżeli będziemy budować stronę najlepiej jest sobie zapisać rozszerzenie plików w osobnym pliku, który będzie je przechowywał, gdyż na różnych serwe-rach są obsługiwane różne rozszerzenia i pomoże to nam uniknąć błędu. Dla prze-chowywania rozszerzenia stwórz plik roz-szerzenie.inc, w którym zapisz je w dowol-nej zmiennej. Następnie w pliku, w którym

Rozszerzenie plikówbędziemy chcieli używać funkcji include() należy zaimportować wcześniej przygoto-wany kod. Później podczas włączania kodu PHP z innych plików wystarczy tylko wyko-rzystać zmienną $RozszerzeniePHP, która zawiera rozszerzenie obsługiwane na na-szym serwerze.

W ten sposób będziemy mogli przeno-sić nasze skrypty na dowolny serwer, na którym rozszerzenie plików zawierających skrypt PHP jest zupełnie inne od zazwy-czaj stosowanych. Wówczas wystarczy tyl-ko pozmieniać rozszerzenia plików i war-tość zmiennej w pliku rozszerzenie.inc, a cały nasz skrypt będzie działał bez błędów.

Page 72: PHP Solutions 01 2007 PL

triki w php

PHP Solutions Nr 1/2007

Narzędzia

www.phpsolmag.org72

Listing 22. Zmiana ustawień PHP<?php

ini_set('magic_quotes_gpc', '1');

?>

Listing 23. Wyłączenie opcji w ustawieniach PHP

<?php

ini_set('magic_quotes_gpc', '0');

?>

Listing 24. Zmiana opcji konfigura-cyjnych za pomocą piku .htaccess

php_value

magic_quotes_gpc 1

Niewiele osób wie o fakcie iż mogą zmie-niać ustawienia interpretera PHP bez po-trzeby uzyskiwania dostępu do panelu kon-figuracyjnego samego interpretera. W ten sposób możesz sam ustawić sobie funkcje z których chcesz korzystać. Opcje które możesz ustawić za pomocą funkcji ini_set() są zdefiniowane na stronie: http://pl2.php.net/manual/pl/ini.php#ini.list. Funk-cja ta zmieni ustawienia tylko lokalnie dla danego skryptu. Natomiast cała reszta ele-mentów na serwerze pozostanie przy stan-dardowych ustawieniach. W przykładzie opcja magic_quotes_gpc została włączona. 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-dajesz nazwę wartości którą chcesz zmie-nić, natomiast w drugim parametrze poda-jesz jej nową wartość. Ustawianie wartości w php.ini za pomocą serwera Apache.

W przypadku korzystania z serwe-ra Apache możesz także ustawiać własne wartości zmiennych konfiguracyjnych PHP. 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. Do tego celu używamy wartości php_value. Następnie po niej deklarujemy opcję któ-rą mamy zamiar ustawić oraz podajemy jej wartość. Niestety możliwość ustawia-nia opcji konfiguracyjnych występuje tylko na niektórych serwerach. Najczęściej są to 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.

Własne ustawienia w pliku php.ini Różne przeglądarki różnie interpretują sty-

le CSS dołączone do naszych plików stron sieci Web. Style CSS służą formatowaniu stron WWW więc dobrze byłoby dobrać odpowiedni arkusz CSS dla odpowiedniej przeglądarki internetowej.

W skrypcie tym PHP za pomocą funk-cji strstr sprawdzane jest, czy w zmien-

Listing 25. Włączenie odpowiedniego arkusza w zależności od przeglądarki

<?php

if ($name = strstr ($_SERVER['HTTP_USER_AGENT']

, 'Opera'))

{

?>

<link rel="stylesheet" href=

"opera_stylesheet.css">

<?php

}

elseif ($name = strstr

($_SERVER['HTTP_USER_AGENT'],

'Firefox'))

{

?>

<link rel="stylesheet" href=

"firefox_stylesheet.css">

<?php

}

elseif ($name = strstr ($_SERVER

['HTTP_USER_AGENT'], 'MSIE'))

{

?>

<link rel="stylesheet" href=

"ie_stylesheet.css">

<?php

}

else

{

?>

<link rel="stylesheet" href=

"o_stylesheet.css">

<?php

}

?>

Arkusz styli CSS zależny od przeglądarkinej $_SERVER['HTTP_USER_AGENT'] znaj-duje się odpowiedni opis przeglądarki. W zależności od tego jaka jest to prze-glądarka skrypt drukuje załączenie od-powiedniego arkusza styli. W przypadku, gdyby przeglądarka nie została rozpozna-na wówczas wydrukuje domyślny arkusz styli dla strony.

Page 73: PHP Solutions 01 2007 PL

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

Agencja Interaktywna– br-design.plKreowanie oraz obsługa serwisów interne-towych, programowanie aplikacji interneto-wych według indywidualnych potrzeb klienta, realizacja projektów graficznych i prezentacji multimedialnych. www.br-design.pl

Firma Informatyczna „Saulewicz”Wdrażamy technologie internetowe w opar-ciu o serwery linuxowe i rozwiązania „Open Source”. Oferujemy aplikacje bazodaniowe pracujące w środowisku PHP. Prowadzimy konsultacje dotyczące bezpieczeństwa sys-temów sieciowych.www.saulewicz.com.pl.

v

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

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

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.

HostingElastyczny 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: [email protected],

Pren

umer

ata

PRO

Wię

cej i

nfor

mac

ji: patrycja.wadolowska@

software.com.pl

tel.:

022

887

-13-

45

Page 74: PHP Solutions 01 2007 PL

www.phpsolmag.org74

Wywiad

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

Wywiad

PHP Solutions Nr 1/2007

Wywiad z Rafałem Mrzygłockim – twórcą i pomysłodawcą serwisu ILOGGO

Patrycja Wądołowska: Dlaczego zde-cydował się Pan stworzyć taki serwis?

Rafał Mrzygłocki: Wszystko zaczę-ło się od mojej prywatnej strony starto-wej, Zawsze miałem niesamowity bała-gan w bookmarkach. Dodawałem bardzo dużo stron, próbowałem porządkować je i grupować w katalogach, ale i tak znale-zienie później jakiejś informacji zajmowało mi sporo czasu. Żaden istniejący portal nie oferował mi satysfakcjonującego rozwiąza-nia, dlatego pomyślałem o stworzeniu wła-snej strony. Nie jestem programistą, ko-rzystam jedynie z podstawowych aplikacji, dlatego zrobiłem prostą siatkę w HTML-u, na której umieściłem logotypy ulubionych stron. Z czasem pomysł podchwycili moi znajomi-coraz więcej osób prosiło mnie o dodawanie kolejnych logotypów i ustawiało sobie siatkę jako stronę startową.

Podsunęło mi to pomysł na stworze-nie ogólnodostępnej siatki, którą każdy użytkownik zdefiniuje, w sposób odpo-wiadający jego potrzebom. Zainteresowa-ło mnie także to, że niektóre strony miały ogromną ilość użytkowników i odwiedzin, a inne w ogóle. Wiedziałem, że nie decy-

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.

dowała o tym jakaś wyszukiwarka, która zbiera po drodze wszystkie możliwe lin-ki. Po przeanalizowaniu wpadłem na po-mysł, co pozwoli użytkownikom szyb-ko i łatwo dojść do wartościowych stron. Dlatego oprócz siatki logotypów, powsta-ła także wyszukiwarka działająca wśród sprawdzonych i wartościowych stron użyt-kowników. Według mnie Internet to użyt-kownicy, to oni go tworzą i są najlepszym wyznacznikiem, które portale są warto-ściowe i godne polecenia.

PW: Jaki jest dzienny przyrost użyt-kowników serwisu?

RM: Po zaledwie kilku dniach od ofi-cjalnego startu każdego dnia w iloggo re-jestruje się około 100 nowych użytkowni-ków. To dla nas informacja, że Internau-tom spodobała się idea serwisu. Najwięk-szym zaskoczeniem jest dla nas szyb-kość, z jaką rośnie katalog iloggo – każda minuta to kilkanaście dodanych stron.

Chcemy, żeby iloggo rozwijało się i zmieniało, dotrzymując kroku użytkowni-kom. W każdym miejscu i w każdej chwili ma spełniać ich wymagania i odpowiadać na ich potrzeby – po to właśnie stworzyli-

śmy ten serwis. Pracujemy już nad nowy-mi funkcjami, które zapewnią użytkowni-kom jeszcze większą wygodę i usprawnią korzystanie z sieci.

PW: Jakich technologii użyto do stwo-rzenia serwisu? Zakładając, że będzie miał wielu użytkowników, musi działać bardzo wydajnie. Jakie zastosowano rozwiązania?

RM: U podstaw konstrukcji serwisu le-żały idee elastyczności i skalowalności. Poprzez te pojęcia rozumiemy możliwość szybkiej reakcji na zmieniające się potrze-by naszych użytkowników i klientów, w tym często trudny do przewidzenia wzrost ich liczby. Zdecydowaliśmy się na rozwiązania open-source nie tylko ze względów ekono-micznych, ale w dużej mierze ze względu na możliwość kontroli ich działania. Uwa-żamy ponadto, że w tej chwili naszą praw-dziwą siłą jest nie tylko sam publicznie do-stępny serwis, ale przede wszystkim zbiór sprawdzonych narzędzi i procesów, wspo-magających wytwarzanie oprogramowa-nia. Dzięki temu możemy nie koncentro-wać się wyłącznie na problemach techno-logicznych, ale skutecznie rozwiązywać nowe biznesowe wyzwania.

Rafał Mrzygłocki

Page 75: PHP Solutions 01 2007 PL

www.phpsolmag.org74

Wywiad

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

Wywiad

PHP Solutions Nr 1/2007

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ę.

Page 76: PHP Solutions 01 2007 PL

PHP ALMANACHAutor: 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 5oraz 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

«««««

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 i MySQL. Tworzenie aplikacji WWW

Autor: Marc Wandschneider

«««««

Recenzje

Page 77: PHP Solutions 01 2007 PL
Page 78: PHP Solutions 01 2007 PL

www.phpsolmag.org78

Felieton

PHP Solutions Nr 1/2007

Własne życieAleksander Cynarski

Pojęcie potęgi informacji w naszych czasach jest już na tyle banalne i powszechnie używane, że ge-

neralnie nie ma sensu o tym wspominać. Ale.. no właśnie. Jak rozejrzymy się do-okoła najdzie nas myśl – integracja.

Otoczeni komórkami, laptopami, cały czas „w sieci” – mnie często aż korci, żeby przenieść tam swoją tożsamość. Wstęp-nie pomysł nieco futurystyczny, ale czy tak bardzo nie realny? Oczywiście nie mówię tu o wizjach filmowych, ale o czysto „in-formacyjnym przeniesieniu”. Większość z nas posiada blogi, często bawimy się w tzw. „social networking” (grono.net czy lin-kedin.com) – piszemy tam o sobie, co ro-bimy, co chcielibyśmy robić. Nasza tożsa-mość przechodzi ze świata realnego do wirtualnego bardzo naturalnie. Gramy w popularne ostatnio gry MMORPG. Często nie zdajemy sobie sprawy, że aby kogoś poznać wystarczy go po prostu poszukać i to w dodatku bez wychodzenia z domu. Współczesne systemy operacyjne, wszech-obecne oprogramowanie publikujące da-ne on-line, książki adresowe importowane z telefonów i wędrujące gdzieś do baz da-nych. Kalendarze, którymi możemy dzielić się ze znajomymi. Ciekaw jestem ilu z Was pozbawionych dostępu do sieci ma wraże-nie, że czegoś brakuje – ten komputer jest taki nie pełny. Świat rzeczywisty i ten, w któ-rym żywo uczestniczymy w zaciszu własne-go biurka są już ze sobą bardzo powiązane. Czy można pójść dalej? Czy możemy jesz-cze głębiej zanurzyć się w wirtualne morze powiązanych informacji?

Myślę, że tak. Wystarczy odrobina wy-obraźni, łącze do internetu i parę elektro-nicznych zabawek, które zabieramy ze so-bą nawet do kawiarni. Po co nasi znajomi, mają dzwonić i pytać gdzie jesteśmy? Wy-starczy, że wejdą na naszego bloga i zo-baczą gdzie aktualnie spędzamy czas, czy mamy ochotę na to by ktoś się przyłączył, czy też nie. Prawie wszystko możemy ak-tualnie przerobić na bity i wypuścić ich strumień w globalną sieć. A najważniejsze

jest to, że tzw. nowoczesne zabawki nie są już na tyle drogie, że może sobie na nie pozwolić tylko mała grupa bogatych szcze-niaków. Dzięki szybkiemu rozwojowi tech-nologii jesteśmy w stanie przenieść do sie-ci właściwie całe swoje aktualne życie.

Należę do tej grupy ludzi, którzy sie-dzą przed komputerem cały czas – praca, przyjemność – to jedno i to samo. Chcę jak największą część swojego realnego życia przenieść na informacje i publikować, publi-kować ile się da. Wracając do przykładu z kawiarnią. Wyobraźcie sobie, że wasza ko-mórka – a raczej palmofon, który kupiliście na jednej z aukcji internetowych ma wbudo-wany GPS oraz EDGE lub GPRS. Wysyła-my informację do naszego bloga obsługu-jącego XMLRPC, w treści której jest nasza aktualna pozycja. Wszystko mamy oczywi-ście zintegrowane z frappr.com – pokazuje gdzie jesteśmy. Jeżeli spotkanie jest na ty-le ciekawe, że nie chcemy aby ktokolwiek nam przeszkadzał klikamy „do not disturb” i już na blogu pokazuje się informacja – „je-stem tu i tu, ale nie radzę przeszkadzać”. Wszystko to mamy w zasięgu ręki, wystar-czy ją tylko wyciągnąć. Najlepszą chyba rzeczą we współczesnym świecie jest nie-skończona możliwość tworzenia. Czy aby nie warto było by do tego naszego bloga dodać jeszcze informację o kamerach on-li-ne znajdujących się najbliżej miejsca w któ-rym się znajdujemy, czy też ściągać dyna-micznie prognozy pogody. Zaś dodając no-we informacje wszystko to automatycznie trafia do grupy zainteresowanych osób, któ-re za pomocą jednego z wielu dostępnych mechanizmów dostają je na swoje małe przenośne zabaweczki w jakiejkolwiek for-mie. Wszystkie te informacje możemy do-wolnie filtrować, przerabiać i modyfikować w taki sposób, aby trafiały tam gdzie powin-ny. Aktualnie dostępne technologie dyna-micznej wymiany danych (Publish subscri-be) naprawdę dają wielkie możliwości.

Dzięki całej masie dynamicznie gene-rowanych stron, blogów mogących się in-tegrować, portalom tematycznym, z któ-

rych możemy pobierać „na żywo” informacje – uważam, że może. Wystarczy tylko odro-bina samo zaparcia, trochę czasu, no i oczy-wiście pomysł. Przecież te wszystkie obraz-ki, teksty i filmy dostępne on-line za pomocą coraz to bardziej zaawansowanych wyszuki-warek tworzą już wiele nowych przestrzeni, które możemy eksplorować tak samo jak uli-ce nowo poznanych miast. Idąc dalej w roz-myślania nad ożywieniem naszego wirtual-nego ja, możemy zastanowić się nad „per-sonalizacją” nas dla innych. Wiem, że dziw-nie brzmi, ale już wyjaśniam o co mi cho-dzi. Otóż często spotykamy się z możliwo-ścią zmiany wyglądu strony, jej rozłożenia. Ale co w przypadku, jeżeli chcemy być dla wszystkich „trendi” w realnym życiu nie je-steśmy w stanie, ale „tam” możemy. Skoro można personalizować pojęcie „jak” to cze-mu nie możemy zrobić tego samego z „co”. Umieśćmy małą sondę przy wejściu na blo-ga i już. Niech się pokazują tylko te wpisy które mogą pasować do proflu osoby oglą-dającej. Każdy z nas ogląda filmy science fiction – częstym motywem w takowych, któ-re traktują o innych cywilizacjach jest zbioro-wa świadomość. Umiejętność pewnej gru-py do swobodnej wymiany informacji. Czy obecne formy publikowania w sieci, nie są namiastką? Owszem, że do generowania pełnego obrazu osobowości jeszcze mamy daleko, ale myślę – że to kwestia czasu, no i oczywiście tego jak się rozwinie technologia, w jakim kierunku pójdą producenci sprzętu i dostawcy usług. Ciekawe czy kiedyś du-że firmy ISP wejdą w spółki z firmami pro-dukującymi hardware i zaczną sprzedawać nie tyle dostęp, co całe zintegrowane plat-formy działające całkowicie on-line. W do-mach będziemy mieli gniazda światłowodo-we do których będziemy podłączać stacjo-narne lub przenośne terminale. Zaś całe na-sze codzienne i wirtualne życie będzie odby-wać się jednocześnie. Technologie potrzeb-ne do wdrażania takich pomysłów już istnie-ją, lecz niestety tak daleka integracja na ra-zie jest tylko fantastyczną wizją, przynajm-niej jeżeli chodzi o problem skali. n

Page 79: PHP Solutions 01 2007 PL

Serwis prezentujący prace kobiet, zajmujących się zawodowo bądź dla własnej przyjemności grafiką, webdesignem, rysunkiem, fotografią, malarstwem, rzeźbą, itp.

womaninaction.net

Jeden z ważniejszych polskich portali dla we-bmasterów i programistów PHP. Istnieje już cał-kiem długo, co potwierdza zawartość zarówno serwisu jak i forum.

webcity.pl

Oficjalny serwis magazynu PHP Solutions. Można stąd pobrać przykładowe artykuły, li-stingi z artykułów, skorzystać z forum, bądź za-poznać się z aktualnościami.

www.phpsolmag.org

Serwis poświęcony zagadnieniom związanym z komputerami klasy PC, choć nie tylko. Prezen-towane są tam informacje związane z Open So-urce i światem Internetu.

pcmaniak.pl

Oficjalny serwis czytelników magazynu Softwa-re Developer’s Journal. Często aktualizowany, posiada wszystkie informacje przydatne czytel-nikom magazynu, ale nie tylko.

www.software20.org

Obszerny i bogaty w informacje serwis poświę-cony Sieci. Zawiera informacje dotyczące bez-pieczeństwa, programowania, sieci bezprze-wodowych i inne.

www.webhat.pl

Oficjalny serwis magazynu Hakin9. Można stąd pobrać darmowe artykuły, zapoznać się z zawartością aktualnych i archiwalnych nume-rów lub skorzystać z bogatego forum.

www.haking.pl

Serwis poświęcony aktualnej, piątej wersji ję-zyka PHP. Jego zwięzła i skromna forma nie rozprasza i pozwala szybko odnaleźć szukane informacje, które zawarto w serwisie.

www.php5.pl

Dziennik Internautów – czyli gazeta dla użyt-kowników Internetu, to bogaty i dobrze zapla-nowany serwis prezentujący informacje pogru-powane w działy.

www.di.com.pl

Recommended sites >>>

Recommended sites

Jeśli prowadzisz ciekawą stronę internetowąi chcesz abyśmy przedstawili ją w ramach akcji Recommended sites,

skontaktuj się z nami pod adresem [email protected]

Page 80: PHP Solutions 01 2007 PL

www.phpsolmag.org80 PHP Solutions Nr 1/2007

Klub techniczny

Rozszerzanie serweroweZend 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 i pozwalają uniknąć niedogodności związanych z tym procesem. Reasumując, przy stosowaniu platformy Zend, zarówno Twój czas jak i zasoby fi-nansowe będziesz mógł w całości wykorzystać na tworzenie pięknych aplikacji PHP, nie martwiąc się problemami związanymi z ich uruchamianiem i utrzymywaniem.”

Ostatnie zdanie w opisie przedstawionym przez Zend na pierwszy rzut oka wydaje się za-latywać napuszonym żargonem marketingowym, jednakże tak naprawdę w pełni oddaje istotę pro-duktu. Mówiąc prosto, Zend Platform 2 to gru-pa plików, które siedzą między silnikiem PHP a skryptami PHP i powodują przyśpieszenie dzia-łania skryptów, potrafią śledzić błędy, wykrywają potencjalne problemy i udostępniają śliczny inter-fejs webowy, który pozwala użytkownikowi moni-torować wszystko co dzieje się na jego serwerze

(bądź serwerach). Spróbujmy przekonać się jak to wszystko jest możliwe.

ZACZYNAMYW momencie przygotowywania niniejszego tekstu opisywany produkt jest dostępny w postaci aplika-cji nieokienkowej. Do testowania platformy użyłem dystrybucji Linux Debian.

Na początku należy pobrać pakiet instalacyjny Zend Platform 2. Pakiet ten, w postaci próbnej jest dostępny za darmo na stronie domowej firmy Zend (http://www.zend.com). Przed pobraniem paczki instalacyjnej trzeba mieć założone konto.

Po ściągnięciu pakietu na serwer czas brać się za instalowanie produktu. Warto w tym miejscu nadmienić, że na stronie Zend umieszczony jest bardzo dobry przewodnik instalacji, gdzie można znaleźć bardzo szczegółowe informacje na temat całego procesu. Ten sam przewodnik jest umiesz-czony w pobranym archiwum tar. Archiwum to na-leży rozpakować korzystając z komendy gunzip -c <package name> | tar –xvf

Aby rozpocząć instalację należy przejść do katalogu utworzonego w trakcie rozpakowywania pakietu i sprawdzić czy znajduje się tam plik in-

stall.sh. Jeśli rzeczywiście tak jest, to należy wspo-mniany plik uruchomić; można to zrobić komendą:

./install

Skrypt instalacyjny powinien uruchomić graficz-nego czarodzieja (ang. Wizard). Teraz wystar-czy wykonywać po kolei instrukcje pojawiające się na ekranie. Nie będę w tym miejscu zawierał szczegółowego opisu całego procesu (złożone-go z około 20 kroków) – opis taki można znaleźć w wymienionym wcześniej przewodniku instala-cji. Chciałbym za to zwrócić uwagę na dwa istot-ne szczegóły:

• przy wybieraniu typu serwera wybrałem opcję Cluster Manager/Standalone. Użytkownicy ko-rzystający z pojedynczego serwera, lub insta-lujący pierwszy serwer w klastrze, muszą rów-nież wybrać tę opcję;

• w trakcie instalacji otrzymujemy pytanie o pewne informacje systemowe; na przykład o lokalizację pliku php.ini, lokalizację kontrole-ra apache, wersję zainstalowanego silnika PHP itd. Warto otworzyć przed instalacją dodatko-

Ian Morse mieszka w Kanadzie – na Wyspie Księcia Edwarda; jest właścicielem i kierow-nikiem firmy konsultingowej specjalizującej się w technologiach webowych. Witrynę Iana można obejrzeć pod adresem: http://www.geckoware.com

Zend Platform 2

Rysunek 1. Rezultaty testów

Page 81: PHP Solutions 01 2007 PL

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

Zend Platform 2 Klub techniczny

we okno terminala, dzięki czemu można póź-niej łatwo sprawdzić te informacje.

Po zakończeniu procesu instalacji użytkownik otrzymuje podsumowanie, na którym widać czy wszystkie komponenty platformy zainstalowały się pomyślnie. Na tym kończy się pierwsza war-stwa cebuli Zend Platform. Średnio zaawansowa-ny użytkownik może w tym miejscu zakończyć interakcję z platformą i zacząć pracować ze swo-imi aplikacjami PHP. Użytkownik taki zauważy, że wspomniane aplikacje działają teraz o wiele szyb-ciej i stabilniej – i to mu wystarczy. Bardziej za-awansowani użytkownicy mogą uruchomić prze-glądarkę internetową i rozpocząć monitorowanie, testowanie i optymalizację swoich rozwiązań, cie-sząc się pełną gamą możliwości platformy.

ROZBIERANIE CEBULIAby uzyskać dostęp do webowego interfejsu Zend Platform 2 należy wpisać w przeglądarce URL okre-ślający miejsce instalacji środowiska. Domyślnie jest to: http://<nazwa serwera>/ZendPlatform

Na początku należy się zalogować (domyślna nazwa użytkownika to Admin, hasło zaś definiuje-my sami w trakcie procesu instalacji). Po pomyśl-nym zakończeniu tego krok użytkownik jest powi-tany i na wejściu otrzymuje podstawowe informa-cje systemowe. Przy pierwszym logowaniu inter-fejs może wydawać się dość ubogi, jednak polecam

dla zabawy stworzyć oraz uruchomić skrypt in-tensywnie korzystający z zasobów pamięciowych i zobaczyć co się stanie. Ja użyłem skryptu poka-zanego na Listing 1.

Przedstawiony skrypt uruchomiłem dzie-sięć razy z włączonymi opcjami Code Accelera-tion oraz Dynamic Content Caching, a następnie powtórzyłem tę czynność – tyle, że wspomnia-ne opcje były wyłączone. Co ciekawe, w obydwu przypadkach wydajność była podobna. Może to wydawać się zaskakujące, jednak należy zauwa-żyć, że rozważany skrypt nie jest przeznaczony do testowania obsługi żądań; został on zaprojek-towany w taki sposób, aby platforma mogła za-reagować na potencjalnie niewłaściwy kod – co w rzeczywistości nastąpiło!

Jeśli przejdziemy teraz ponownie do zakład-ki Zend Central to zauważymy, że zanotowano no-we zdarzenie. Jeśli uruchomimy odpowiednio du-żo odmiennych skryptów to zaobserwujemy, że niektóre zdarzenia opisują błędy, zaś inne infor-mują nas o tym, że kod wykonywany na skrypcie jest zbyt wolny. Każdy wpis zawiera informacje o czasie wykonania, o serwerze na którym docelo-wy skrypt był uruchomiony oraz o URL, który wy-wołał zadany skrypt. Informacje te to prawdziwa ko-palnia złota – szczególnie jeśli mamy do czynienia z klastrem serwerów.

Po kliknięciu na wybrany wpis otrzymujemy nowe okienko typu pop-up, gdzie można znaleźć jeszcze bardziej szczegółowe informacje na temat skryptu. Znajdziemy tu miedzy innymi szczegóło-we zapisy na temat czasu wystąpienia usterki, dłu-gości jej trwania oraz informacje o zmiennych prze-kazanych do skryptu, a także o dołączonych przez niego plikach. Ukoronowaniem tych wszystkich udogodnień jest fakt, iż Zend Platform 2 integru-je się z Zend Studio dzięki czemu możemy z miej-sca naprawiać błędy w kodzie. Dla użytkowników nie posiadających tego ostatniego pakietu przewi-dziano możliwość przeglądania kodu bezpośrednio z przeglądarki.

Zend Platform 2 oferuje olbrzymią gamę wła-ściwości, o których można by pisać oddzielne, duże artykuły – warto tu wspomnieć chociażby mechanizm obsługi klastrów serwerowych oraz pomost integracyjny dla platformy Java (ang. Java Integration Bridge), który (według zapew-nień umieszczonych na witrynie Zend) pozwala firmom inwestującym w serwery aplikacji oparte na platformie J2EE korzystać z zalet PHP. Oczy-wiście wszystkie te stwierdzenia muszą mieć pokrycie w konkretnych benchmarkach. Mnie in-teresują konkretne liczby. Jak dobra jest tak na-prawdę platforma Zend? Łatwo to sprawdzić, ja-ko że benchmark testujący jest wbudowany bez-pośrednio w system – można go znaleźć pod za-kładką Performance. Na Rysunku 1 przedstawi-łem rezultaty testów wykonanych dla jednego

z moich Serwerów Pobierających (ang. Down-load Server). Na podstawie zamieszonych tam informacji można się przekonać, że wyniki sta-ją się coraz bardziej imponujące, proporcjonal-nie do zwiększania się częstotliwości występo-wania równoległych żądań do serwera. Przy sto-sowaniu Zend Platform ponad połowa z 45 rów-nolegle przychodzących żądań została obsłużo-na w czasie krótszym niż sekunda. Dla mniejszej liczby żądań wzrost wydajności wyraźnie spa-da, jednak rezultaty są i tak o wiele lepsze niż w przypadku nie korzystania z platformy.

Pozostałe benchmarki oferują testy wydaj-nościowe, testy kompresji oraz testy skryptów. We wszystkich tych przypadkach rezultaty są podobne: korzystając z Zend Platform otrzymu-jemy mniej więcej dwukrotną poprawę parame-trów będących przedmiotem testowania. Nale-ży pamiętać, iż twórcy platformy zaznaczają bar-dzo mocno, że rezultaty testów będą miarodajne w przypadku występowania odpowiednio wzmo-żonego ruchu na serwerze webowym – takim, który odzwierciedla typowe obciążenie określo-nej witryny.

PODSUMOWANIEZend Platform 2 jest dobrze zaprojektowaną i wysoce wydajną warstwą serwerową, która po-trafi przyśpieszyć i uczynić bardziej niezawod-ną każdą niemalże aplikację PHP. Wydaje się, iż każdy system jest w stanie skorzystać z za-let wynikających ze stosowania platformy, jed-nakże najwięcej korzyści czerpać tu będą nie-wątpliwie witryny pracujące pod bardzo dużym obciążeniem. Rozwiązanie jest wręcz nieodzow-ne dla podmiotów, które nie mogą inwestować w nową infrastrukturę sprzętową i są zmuszone do wyciskania wszystkiego co najlepsze z posia-danych zasobów. Zend Platform 2 jest również bardzo przydatne w sytuacji kiedy monitorowa-nie serwera przy pomocy ogólnodostępnych na-rzędzi staje się zbyt uciążliwe. Wzrost wydajno-ści, który pociąga za sobą stosowanie platformy jest ewidentnie znaczący.

Listing 1. Skrypt użyty przy pierwszym logowaniu

// testowanie przyśpieszenia kodu

$test_array1 = array();

$test_array2 = array();

// zapisywanie czasu początkowego testu

$start = time();

// sztuczne obciążenie serwera

for($i = 0; $i < 25000; $i++) {

$test_array[$i] = rand();

}

for($j = 0; $j < 25000; $j++) {

$test_array2[$j] = rand();

}

asort($test_array);

asort($test_array2);

$test_array3 = array_merge($test_array,

$test_array2);

asort($test_array3);

// zapisywanie czasu końcowego testu

$end = time();

// obliczanie różnicy czasów

$difference = $end - $start;

// wyświetlenie wyników

echo "Start: ".$start;

echo "<br />End: ".$end;

echo "<br />Difference: ".$difference;

Tabela 1. Zend Platform 2

PHP: 4.3.9 i wyżej, 4.4.x, 5.0.x, 5.1

Wersja pro-duktu

2.1.2

O/S:Linux/Unix, FreeBSD, Solaris, Mac OS X

Cennik:

Pakiet darmowy w wersji próbnej. W przypadku zaist-nienia chęci stosowania plat-formy w trybie komercyjnym należy skontaktować się z fir-mą Zend.

Adres w sieci: http://www.zend.com/

Page 82: PHP Solutions 01 2007 PL

W sprzedaży od lutego

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

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

ROZWIĄZANIA

n Prototype z PHP Pokażemy, jak budować nowatorskie systemy rankingowe w oparciu o bibliotekę script.aculo.us

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

NARZĘDZIA

n eZ publish jako Mulisite CMS jedna instalacja wiele stron.

n Konfiguracja eZ publish, Apache, etc.

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

UWAGA KOLEJNY TEST KONSUMENCKI

n Relokacje serwerów

NOWE ARTYKUŁY W DZIAŁACH:

n dla początkujących

n dla zaawansowanych

n narzędzia

Page 83: PHP Solutions 01 2007 PL
Page 84: PHP Solutions 01 2007 PL