Professional Documents
Culture Documents
PHP Solutions 05 2006 PL
PHP Solutions 05 2006 PL
Spis treści
Przedstawiamy garść najciekawszych wiadomo-
ści dla developerów PHP.
Opis CD 8
W Egipcie nas nie lubią!
W redakcji uważamy, że lepiej jest robić pismo Dla deweloperów PHP, niż Prezentujemy zawartość płyty i sposób działania
pismo O PHP. Różnica między Dla i O jest dość istotna. W pierwszym przy- najnowszej wersji naszej dystrybucji PHP Solu-
padku pismo traktuje o wszystkim, co może potencjalnie zainteresować tions Live.
i przydać się programiście PHP. Natomiast pismo O PHP jest poświęcone
wyłącznie (lub prawie) tej technologii. WYWIAD
My tworzymy magazyn w pierwszym wariancie. Dlatego w obecnym
Wywiad z Tobiasem Schlittem,
numerze znajdziecie artykuł o video streamingu, w którym omawiamy jak
jednym z głównych deweloperów
opublikować własną galerię filmów we Flashu na WWW, na wzór popular-
platformy eZ components 10
nego Google Video. Dowiecie się też, jak zarobić na PHP i czy opłaca się
zostać Freelancerem. Dariusz Pawłowski
Jeśli interesuje Was, co IBM ma wspólnego z PHP, zachęcam do artyku- Tobias pracuje jako deweloper w firmie eZ sys-
łu o łączeniu DB2 i PHP. Ten mariaż to dowód na ogromne zainteresowanie tems. Obecnie zajmuje się rozwijaniem platfor-
gigantów informatycznych naszą technologią. Przedstawimy też bardzo faj- my eZ components. Jest dobrze znanym eksper-
nego i profesjonalnego CMS-a – TYPO3. System w nowej odsłonie oferuje tem PHP. Udziela się też m.in. w projekcie PE-
naprawdę ogromne możliwości. Jeśli szukasz CMS-a do stworzenia własnej AR, gdzie rozwija kilka pakietów.
witryny, koniecznie musisz zapoznać się z TYPO3! Bardzo prawdopodobne,
że to właśnie na niego padnie wybór.
Nie zabraknie też artykułów dla bardziej zaawansowanych: pokażemy, DLA POCZĄTKUJĄCYCH
jak budować elastyczne aplikacje w oparciu o kontenter IoC, czy tworzyć
Łączymy DB2 i PHP 12
własne rozszerzenia dla PHP z wykorzystaniem Zend API.
Na koniec ciekawostka: mapka zamieszczona poniżej przedstawia wy- Artur Wroński, Piotr Pietrzakk
korzystanie PHP w różnych regionach świata. Kolor zielony oznacza naj- Tworzysz rozbudowaną aplikację, którą bę-
większe (np. Ukraina – 69%), a czerwony najmniejsze zainteresowanie (np. dziesz często rozbudowywał i chcesz uniknąć
Egipt 3,93 %) technologią PHP. Kolor żółty oznacza średnią. Z rysunku wyni- żmudnych, czasochłonnych i podatnych na błę-
ka, że najbardziej lubią nas na Ukrainie i w Rosji. Kto wie, może zaczniemy dy modyfikacji struktury tabel i relacji bazodano-
wydawać w tych językach). wych. Przedstawiamy Ci DB2: solidną i rozbu-
dowaną bazę, która umożliwia przechowywanie i
Przyjemnej lektury, operacje na danych w postaci XML-owej.
Redakcja PHP Solutions
BEZPIECZEŃSTWO
Zaawansowane ataki SQL
Injection 20
Mike Shema
Ataki SQL Injection są wymierzone w trzon apli-
kacji webowej – bazę danych – i umożliwiają in-
truzowi zdobycie, modyfikację lub usunięcie do-
wolnych danych. Zrozumienie zasad działania
SQL Injection jest konieczne do wypracowania
odpowiednich metod obrony.
NARZĘDZIA
TYPO3 od kuchni, czyli wymarzony
portal w zasięgu ręki 28
Jean-Gael Rouchon
Źródło: http://www.nexen.net/ Zarządzasz witryną internetową, która ma zhie-
rarchizowaną strukturę stron, a ich zawartość
jest uzupełniana przez wielu redaktorów. Zależy
Ci na pełnej swobodzie projektowania tego sajtu
oraz łatwości jego tworzenia i rozbudowy. Przed-
stawiamy TYPO3: potężny, elastyczny i solidny
system CMS klasy Enterprise, który jest łatwy w
rozbudowie, co umożliwia ciągłe dostosowywa-
Jeśli jesteś zainteresowany zakupem licencji na wydawanie naszych pism prosimy o kontakt: nie go do Twoich potrzeb.
Monika Godlewska monikag@software.com.pl tel.: 48 22 887 12 66, fax: 48 22 887 10 11
Własne Google Video, czyli video Redakcja dokłada wszelkich starań, by publikowane w piśmie i na towarzyszących mu nośnikach informacje
streaming w PHP 72
i programy były poprawne, jednakże nie bierze odpowiedzialności za efekty wykorzystania ich; nie gwarantuje
także poprawnego działania programów shareware, freeware i public domain.
Uszkodzone podczas wysyłki płyty wymienia redakcja.
Rafał Malinowski Wszystkie znaki firmowe zawarte w piśmie są własnością odpowiednich firm
i zostały użyte wyłącznie w celach informacyjnych.
Zastanawiałeś się, jak działa odtwarzanie fil-
mów z poziomu WWW? Podoba Ci się Go- Redakcja używa systemu automatycznego składu
Do tworzenia wykresów i diagramów wykorzystano program firmy
ogle Video? Poznaj video streaming od kuchni i
Osoby zainteresowane współpracą prosimy o kontakt: cooperation@software.com.pl
stwórz własną, webową galerię filmów. Wystar-
Druk: ArtDruk
czy podstawowa znajomość PHP. To wszystko!
Wysokość nakładu obejmuje również dodruki. Redakcja nie udziela pomocy technicznej w instalowaniu
i użytkowaniu programów zamieszczonych na płytach CD-ROM dostarczonych razem z pismem.
Zapowiedzi 82
Sprzedaż aktualnych lub archiwalnych numerów pisma po innej cenie niż wydrukowana na okładce
– bez zgody wydawcy – jest działaniem na jego szkodę i skutkuje odpowiedzialnością sądową.
eZ publish
Nowości w Google Lab Online Editor
– teraz za darmo!
P rojekty Google ciągle zaskakują Edytor WYSIWYG, za który jeszcze nie dawno
trzeba było zapłacić $99, teraz dostaniemy zu-
nas innowacyjnością. Przykładowo pełnie za darmo. System początkowo sprzeda-
Google Notebook pozwala na wygodne wany był jako dodatkowo płatny komponent do
CMS-a eZ publish.
zapisywanie treści (teksty, obrazki, lin- Produkt oferuje wszystkie funkcje dobrego WY-
ki) podczas przeglądania stron WWW w SIWYG-a. Obsługuje kilka języków w tym pol-
specjalnym miejscu, na stronie Google. ski, francuski, hiszpański i włoski. Pracuje z In-
ternet Explorerem od wersji 5.5, jak również z
W każdym momencie możemy po nie przeglądarkami opartymi na Mozilli. Na stronie
sięgać, wystarczy posiadać konto Go- projektu można wypróbować wersje DEMO.
http://ez.no/products/add_ons/ez_publish_on-
ogle, np. Gmail. Dodatkowo mamy możli- line_editor
wość publikacji zbieranych przez nas in- lacyjnych na WWW. Arkusze mogą być
formacji na swojej stronie WWW. aktualizowane przez wiele osób jedno- DutchPIPE
To projekt, który oferuje nowe podejście two-
Google Trends z kolei pokazuje, jak cześnie. Bez problemu można też im- rzenia stron dla większej grupy użytkowników.
bardzo popularne są szukane informa- portować i eksportować dokumenty do Strona staję się abstrakcyjnym światem zbu-
dowanym na obiektach, które mogą być swo-
cje, np. możemy podać przyjkładową formatów CSV i XLS. Jedna kopia do- bodnie przemieszczane między poszczególny-
frazę XOOPS, Drupal, aby zobaczyć ja- kumentu na stronie WWW przyda się na mi sajtami.
Jednemu światu odpowiada jeden określony
kie było zainteresowanie tymi produkta- pewno, nawet jeśli mielibyśmy pracować zestaw obiektów. Jeśli umieścisz jakiś obiekt
mi na przestrzeni ostatnich miesięcy, a nad nim w pojedynkę. Bardzo przydatne na stronie, ktoś inny może z niego skorzystać i
przenieść go do siebie.
nawet lat (co przedstawia Rysunek). Ko- i niezmiernie praktyczne rozwiązanie!
DutchPIPE może być wykorzystany do budo-
lejnym bardzo ciekawym pomysłem jest wania różnych internetowych społeczności,
Google Spreadsheets, rozwiązanie któ- http://labs.google.com dla chatroomów, gier RPG czy sklepów online.
Ogranicza nas tylko wyobraźnia.
re pozwala na tworzenie arkuszy kalku- Licencja: MIT
http://dutchpipe.org/
Zend
poMMo – dobry email marketing za darmo Framework 0.1.4
Pojawiła się kolejna wersja rozwojowa Zend
p
Frameworka. Dodano nowe komponen-
oMMo to prosty i praktyczny system ty oraz dokumentację w 10 językach. Na stro-
newslettera dla niewymagających. In- nie projektu stworzono między innymi Com-
munity Wiki, system do zgłaszania własnych
stalacja jest zupełnie bezbolesna, a sam
pomysłów/zmian, czy miejsce do śledzenia
program nie przytłacza ilością opcji (jak zmian (Issue tracker) w projekcie. Naprawiono
na przykład PHPList), przez co administra- też wiele błędów oraz dokonano wiele ulepszeń
np. możliwość stosowania czcionki TrueType w
cja jest intuicyjna i łatwa. Narzędzie pomi- generowanych dokumentach PDF czy wspra-
mo że nie skomplikowane, znakomicie cie dla bazy DB2.
Licencja: BSD
sprawdza się w email marketingu. Moż- http://devzone.zend.com/node/view/id/606
na stworzyć formularz z kilkoma newslet-
terami i pytać użytkowników, które z nich PHP-QT
Dostępne jest już trzecie wydanie PHP-Qt, roz-
chcą otrzymywać. Bez problemu zintegru- szerzenia dla PHP5, które pozwala na wykorzy-
jemy też poMMo ze sklepem online, że- stanie narzędzia Qt (Qt4 Framework) do two-
rzenia aplikacji w PHP. Pakiet z nową wersją
by powiadamiać użytkowników o naszych ili na minutę). Mamy możliwość zatrzyma- zawiera siedem tutoriali i przykładową aplikację.
produktach. Użytkownicy mogą sami zmie- nia, a następnie wznowienia procesu wy- Została zaimplementowana też między innymi
lepsza obsługa błędów.
niać swój email, wypisywać się lub aktuali- syłki, a po utracie połączenia i jego wzno-
Licencja: GNU GPL
zować preferencje. wieniu, wysyłka jest kontynuowana. Im- http://php-qt.berlios.de/
Maile wysyłane są bardzo wydajnie. port i eksport użytkowników odbywa się z
Portale
System może wykorzystywać 4 użytkow- wykorzystaniem formatu CSV. Wysyłając
rankingowe
ników serwera SMTP i kontrolować ruch mailing, mamy do dyspozycji WYSIWYG Software-Wydawnictwo, wydawca magazy-
podczas wysyłki (np. ilość wysłanych ma- (w przypadku maili w formacie HTML), a nu PHP Solutions, uruchomiło pierwsze porta-
le newsowo-rankingowe w języku angielskim.
raz puszczony mail, może posłużyć ja- Obecnie działają już distrorankings.com oraz
ko szablon przy kolejnych wysyłkach. Do PDFdev.com.
Pierwszy z nich to ranking dystrybucji Linuksa,
wad programu na pewno trzeba zaliczyć drugi to portal dla deweloperów używających
brak opcji zbierania odbić (ang. bounces) standardu PDF.
Już niedługo, przy współpracy z naszym maga-
i jeden poziom dostępu – Administrator.
zynem, uruchomione zostaną kolejne projekty
Zanim zdecydujemy się na instalację, (m.in. poświecone systemom CMS) i to w kilku
najlepiej zacząć od wersji DEMO dostęp- wersjach językowych.
http://distrorankings.com
nej na stronie projektu. http://PDFdev.com
Licencja: GPL
http://www.iceburg.net/pommo/
Materiały dodatkowe
Rozwiązanie z artykułu
w PHP Solutions Live
Narzędzia w dystrybucji
Typo3
Kompletne środowisko do programo-
wania w PHP Studio Developer
na naszej stronie internetowej pod adresem www.phpsolmag.org/pl
Dariusz Pawłowski: Jak rozpocząłeś swo- ły czas szukamy dobrych programistów, ciażby dzięki pracy nad różnymi projek-
ją przygodę z eZ systems? Czy mógłbyś więc śmiało przysyłajcie swoje aplikacje. tami Open Source w przeszłości. Jakkol-
dać kilka wskazówek dla młodych progra- DP: Jak wygląda Twoja współpraca wiek, dwa razy do roku (czasami częściej)
mistów PHP marzących o pracy dla takiej z eZ systems? Masz jakieś długotermi- przyjeżdżam do Norwegii na kilka tygodni,
firmy jak Twoja? nowe zadania? Jak się komunikujecie na aby porozmawiać i podyskutować na ży-
Tobias Schlitt: Hehe, to był w pew- co dzień? wo o nowych zadaniach i projektach.
nym sensie przypadek. Kiedy przeprowa- TS: W chwili obecnej prawie wyłącz- DP: Jak rozpoczął się projekt eZ com-
dziłem się do Dortmund, mój przyjaciel nie pracuję dla eZ systems. Na początku ponents? Jaka przyświecała mu idea i jak
Sandro zasugerował mi, że powinienem kontynuowałem jeszcze prowadzenie mo- pracujecie nad nim obecnie?
starać się o pracę w eZ. Tak też zrobiłem. jej małej firmy konsultingowej, ale po ja- TS: Idea stworzenia eZ components
Dostałem pracę. Na początku zapowiada- kimś czasie poczułem się tak związany i wzięła się z planu przepisania naszego
ło się na to, że będę pracował nad projek- zidentyfikowany z eZ, że postanowiłem CMS-a eZ publish z PHP4 na PHP5. eZ
tami klientów eZ systems, ale potem De- zawiesić własną działalność i w całości publish stał się bardzo rozbudowanym
rick Rethans skierował mnie do eZ com- poświęcić się pracy dla eZ systems. Oczy- systemem, ze złożoną strukturą i więk-
ponents. I tak się tu znalazłem. wiście, mam długoterminowe zadania. Je- szość jego wewnętrznych bibliotek ma
Jeśli chcielibyście pracować dla eZ stem członkiem teamu odpowiedzialnego dziwne API, dodatkowo bez dobrej doku-
system, musicie spełniać trzy warunki: a) za eZ components i zapowiada się na to, mentacji. Tak więc postanowiliśmy prze-
powinniście kochać PHP, bo jeśli kochasz że tak przez najbliższy czas zostanie. Po- nieść kod wszystkich bibliotek do jedne-
to co robisz, robisz to dobrze, b) powinni- nieważ mieszkam w Dortmund, a prawie go niezależnego projektu – eZ compo-
ście kochać Open Source i filozofię, któ- cała reszta zespołu w Skien, w Norwegii, nents. W trakcie tworzenia komponen-
ra się za tym kryje; eZ systems jak najbar- przeważnie komunikujemy się przez email tów dokonywana jest refaktoryzacja ko-
dziej opiera się na tej idei, c) powinniście lub skype'a. Ten sposób współpracy działa du i tworzona nowa dokumentacja. Pro-
umieć pracować w zespole, zgranie się z całkiem dobrze, ponieważ cały team przy- jekt eZ components ma teraz na celu:
całą firmą jest dla nas bardzo ważne. Ca- wykł do tego rodzaju komunikacji, cho- a) stanowić fundament dla eZ publish,
b) stanowić solidną i profesjonalną plat- nej integracji. Poza standardowymi kom- na jeśli chodzi o sam język programowa-
formę dla innych. ponentami, które znajdziemy też w Zend nia. Tak naprawdę to nie widzę specjal-
Tworzenie kodu oparte jest o testy i Framework i w wielu innych framewor- nie nowych funkcjonalności, jakie miały-
dokumentację. Oznacza to, że najpierw kach, posiadamy wiele fajnych rozwiązań, by się pojawić w PHP w przyszłości. Ok,
projektujemy wszystkie API, potem je do- które są jeszcze unikalne w świecie PHP. można pomyśleć o przestrzeni nazw (ang.
kumentujemy, następnie piszemy testy Jako przykład możemy podać ImageCo- name spaces), co było dyskutowane już w
jednostkowe, a na koniec przechodzimy nversion component (w przypadku trans- przeszłości czy o przeciążaniu operatorów
do realnej implementacji. W chwili obec- formacji Thumbnail dokonywane jest ska- (ang. operator overloading), co w końcu
nej mamy wersję 1.1, będącą już ulepsze- lowanie obrazków, kompresowanie, kon- nie zostanie wdrożone. Dodanie obsługi
niem poprzedniej. wersja i zapisanie w formacie JPEG) Unicode w PHP6 jest bardzo ważnym kro-
Po ukazaniu się kolejnej wersji ca- Innym ciekawym rozwiązaniem jest kiem, podobnie jak usunięcie takich relik-
ły zespół spotyka się. Wtedy decyduje- Mail component. Nie tylko tworzy on zło- tów jak register_globals. Ale samo PHP6
my, które z ulepszeń zostaną zaimple- żone maile (załączniki czy kilka typów nie będzie jakimś rewolucyjnym posunię-
mentowane w następnych wersjach (wła- MIME mails), wysyła je za pomocą PHP- ciem, tak jak to miało miejsce pomiędzy
śnie takie spotkanie miało miejsce nie- owej funkcji mail() lub serwera SMTP), PHP4 a PHP5, czy też PHP3 i PHP4. Nie
dawno podczas konferencji eZ, gdzie dys- ale także odczytuje maile z serwerów chciałbym się też wypowiadać w kwestii
kutowaliśmy o wersji 1.2). Ustalamy nowe POP / IMAP. Mamy naprawdę wiele świet- PHP7, gdyż byłoby to wróżenie z fusów.
funkcjonalności i ulepszenia dla obecnych nych komponentów, tak więc zachęcamy Jestem pewien, że praca nad języ-
oraz nowych komponentów. Taki proces do zapoznania się z nimi. kiem będzie przebiegała w większym
tworzenia oprogramowania działa bardzo DP: Lubisz Open Source, czy preferu- stopniu na tworzeniu fajnych rozszerzeń
dobrze biorąc pod uwagę, że stawiamy na jesz swoje własne rozwiązania? niż na rozwijaniu samego języka. Ale po-
elastyczność i rozszerzalność podczas TS: Osobiście kocham Open Source. czekajmy, jak zdecydują ludzie odpowie-
implementacji. Jeśli macie jakieś pomysły Od ponad 2 lat używam wyłącznie Linuksa dzialni za rozwój PHP.
i propozycje dla eZ components, śmiało i jestem z niego bardzo zadowolony. Głów- DP: Jaki jest roadmap dla eZ compo-
możecie je zgłaszać na naszej liście ma- ny plus oprogramowania Open Source po- nents i Twoje plany na najbliższy rok, dwa?
ilingowej. Zawsze jesteśmy otwarci na no- lega na tym, że jest tworzone przez ludzi, TS: Zakres prac nad eZ components
we pomysły. którzy faktycznie go używają i wiedzą, ja- ostatnio nieco się zmienił i poszerzył wraz
DP: Czy według Ciebie Zend Frame- kich funkcjonalności potrzebują. Dzięki te- z ulepszaniem eZ platform, które zapewni
work stanowi konkurencję dla eZ compo- mu powstaje dużo lepsze oprogramowa- w przyszłości kompletną platformę do two-
nents? Czy mógłbyś opowiedzieć o kil- nie w porównaniu do wytwarzanego przez rzenia aplikacji w PHP. eZ platform będzie
ku najważniejszych funkcjach eZ compo- zamkniętą grupę kilku deweloperów, któ- podstawą do zbudowania nowej wersji eZ
nents i odnieść się do Zend Framework? rzy nie są zainteresowani późniejszym wy- publish Telemark. eZ components będą
TS: Nie wydaje mi się, że Zend Fra- korzystaniem efektu swojej pracy. Poza stanowiły najniższy poziom rozwijania apli-
mework stanowi konkurencję dla eZ com- tym lubię dewizę, która mówi: spraw, aby kacji. Na komponentach zbudowany zo-
ponents. Oczywiście, mają trochę podo- najlepsze oprogramowanie przetrwało, w stanie eZ application server – kompletna
bieństw, ale tak naprawdę każde z nich przeciwieństwie do spraw, żeby przetrwała platforma do budowania aplikacji. Na jego
działa inaczej. eZ components to nie fra- firma z najlepszym cash-flow. Ponadto ko- bazie powstanie właśnie nowe eZ publish.
mework, podczas gdy nazwa Zend Fra- rzystając z Open Source mogę swobodnie Oznacza to, że eZ components będą cią-
mework wskazuje już na framework. eZ samemu dodać brakujące funkcjonalności. gle rozwijane i już teraz spodziewajcie się
components to kolekcja luźno powiąza- Już kilkukrotnie zdarzało mi sie dodawać wielu nowych i potrzebnych komponentów
nych, przeważnie niezależnych kompo- taką brakującą funkcjonalność. (takich jak eZ Graph czy eZ Feed).Ciągle
nentów do budowy aplikacji. Korzystając DP: Czy wzorujesz się na rozwiąza- też rozwijamy obecne komponenty doda-
z typowego frameworka, w mniejszym lub niach Javy czy ASP w swoich projektach? jąc określone funkcjonalności (jak wspie-
większym stopniu, jesteśmy zmuszeni do TS: Nie, właściwie to nie lubię obu ranie relacji dla PersistentObject).
budowania aplikacji z wykorzystaniem je- tych technologii. Kodowałem dużo w Ja- Ogólnie rzecz biorąc, chcemy zrobić
go specyficznego podejścia itd. My daje- vie na uniwersytecie, ale nie przypadła mi kompletną platformę dla każdego, gdzie
my Ci możliwość wyboru i sposobu uży- ona do gustu. Jeśli chodzi o ASP, to nie ludzie będą mogli wybrać, czego chcą
cia odpowiednich komponentów z naszej mam potrzeby korzystania z tego języka, używać: eZ components jako część na-
kolekcji. Możesz łączyć je z innymi roz- od kiedy znam i kocham PHP. Obecnie szych bibliotek, eZ application server ja-
wiązaniami takimi jak PEAR. Dla przykła- pracuję trochę w C# (i Mono). Język ten ko cała platforma lub eZ publish jako kom-
du: jeśli chciałbyś użyć nasz system sza- jest naprawdę fajny i używam go głów- pletny CMS. Moje osobiste plany na naj-
blonów, ale nie podoba ci się komponent nie do tworzenia GUI, nie dla aplikacji sie- bliższe 2 lata to: a) skończenie studiów, b)
do internacjonalizacji, nie musisz stoso- ciowych. pomaganie eZ systems w robieniu świet-
wać ich razem. DP: Jaki będzie według Ciebie kolejny nych produktów. Myślę, że oba punkty są
Tak więc, najważniejsze cechy obu krok w rozwoju języka PHP? do wykonania.
platform różnią się, gdyż w eZ compo- TS: To jest dość trudne pytanie. Obec- DP: Dzięki za rozmowę!
nents nie wymuszamy praktycznie żad- na wersja PHP jest już prawie komplet- TS: To była przyjemność!
B
aza danych IBM DB2 była za- godniu. Co ważne, nie nakłada ograni-
wsze kojarzona z obsługą du- czeń na rozmiar bazy danych czy licz-
żych, krytycznych dla działalno- bę obsługiwanych połączeń. Możemy
ści firmy systemów. Przez ostatnie lata również wykorzystywać DB2 Express-
IBM położył bardzo duży nacisk na do- C do celów komercyjnych, a także roz-
pracowanie funkcji autonomicznych, któ- powszechniać go razem z naszymi apli-
re umożliwiają stosowanie bazy także w kacjami. Razem z bazą dostarczane
małych i średnich systemach, w których są narzędzia graficzne do administra-
W SIECI głównym priorytetem jest bezobsługowa cji. Najnowsza wersja DB2 zawiera tak-
i niezawodna praca. Edycja DB2 Express że DB2 Developer Workbench – opar-
jest przykładem takiego silnika baz da-
• http://ibm.com/db2/v9/ nych – w pełni funkcjonalnego, nadają-
– strona domowa DB2 9 cego się do zastosowania na kompute- Co powinieneś wiedzieć...
• http://ibm.com/ Potrzebna będzie znajomość skład-
developerworks/db2 – rach mających maksymalnie po dwa pro-
ni SQL-a i podstaw programowania w
portal dla deweloperów cesory i działających pod systemami Li- PHP (4 i 5) z wykorzystaniem baz da-
korzystających z DB2
• http://www.redbooks.
nux i Windows. nych. Przydatna będzie również wie-
ibm.com/abstracts/ Dla wszystkich deweloperów aplika- dza na temat PDO i prepared state-
sg247218.html – książka o ments.
cji PHP szczególnie interesujący jest dar-
tworzeniu aplikacji PHP dla
IBM DB2 mowy odpowiednik DB2 Express: DB2 Co obiecujemy...
• http://www.ibm.com/ Pokażemy, jak się łączyć z bazą da-
Express for Community, zwany również
developerworks/db2/library/ nych DB2 Express oraz korzystać z
techarticle/dm-0511singh/ a DB2 Express-C. nowego typu danych pozwalające-
– tutorial o używaniu funkcji Darmowa edycja różni się od komer- go na przechowywanie dokumentów
XML-owych DB2 XML.
• http://www.zend.com/core/
cyjnej głównie brakiem całodobowego
ibm/ – Zend Core for IBM wsparcia technicznego przez 7 dni w ty-
Szybki start
Do rozpoczęcia pracy z DB2 i PHP po-
trzebne są:
Użycie Zend Core for IBM (http:// przy użyciu konsoli dostępnej pod adre- kół DRDA (Distributed Relational Data-
www.zend.com/core/ibm/) pozwala na sem http://server:port/ZendCore/ (Ry- base Architecture).
automatyzację całego procesu instala- sunek 1). Komunikacja interfejsu bazodanowe-
cji i konfiguracji. Zend Core for IBM jest Interfejs konsoli administracyjnej go po stronie PHP z DB2 następuje po-
zintegrowanym środowiskiem do budo- Zend Core for IBM jest czytelny i intu- przez wykorzystanie innego, natywnego
wy aplikacji z użyciem PHP i baz DB2 icyjny (Rysunek 2). Pozwala na zmia- interfejsu CLI (Call Level Interface), któ-
lub Cloudscape (wersja opensourco- nę wszystkich niezbędnych parametrów ry jest rozszerzeniem języka PHP napi-
wa jest udostępniana pod nazwą Apa- konfiguracyjnych silnika PHP (php.ini) sanym w C, skompilowanym z biblioteka-
che Derby). Jest to certyfikowana przez przy użyciu przeglądarki internetowej mi obsługi DB2 i należącym do repozyto-
Zend i IBM wersja PHP dla serwerów oraz włączanie i wyłączanie dostępnych rium PECL.
baz danych IBM, zawierająca wszelkie w PHP rozszerzeń, np. obsługi SOAP Dla PHP 5.x istnieje kilka rozsze-
niezbędne dodatki i sterowniki potrzeb- czy XML-RPC. rzeń, które pozwalają na komunikację
ne do komunikacji z wymienionymi ba- Przydatna jest również możliwość z silnikiem DB2 oraz korzystanie z da-
zami danych. Zend Core for IBM jest podglądu bieżącego obciążenia serwera nych i obiektów. Są to:
środowiskiem darmowym. Opcjonalnie HTTP i silnika PHP oraz uzyskania infor-
można zamówić płatne wsparcie tech- macji o liczbie błędów wygenerowanych • Unified ODBC,
niczne firmy Zend lub dokupić dodatko- w poszczególnych warstwach działania • PDO_ODBC,
we narzędzia do tworzenia oprogramo- naszej aplikacji (Rysunek 3). • IBM_DB2.
wania w PHP. Serwer DB2 Express-C może zostać
Jeżeli nie posiadamy działającego automatycznie pobrany przez program Unified ODBC
serwera HTTP, możemy zainstalować instalacyjny Zend Core for IBM. Możemy Zanim powstały rozszerzenia IBM_DB2
Apache 2.0.55 w trakcie instalacji Zend go też ściągnąć ze strony http://ibm.com/ i PDO_ODBC, jedynie Unified ODBC
Core for IBM. db2/express. umożliwiało łączenie się z DB2 lub Clo-
Po instalacji DB2 na naszym serwe- udscape z poziomu aplikacji PHP. Tak
rze umieszczona zostanie również przy- Dostęp do danych DB2 samo, jak w przypadku nowszych roz-
kładowa aplikacja o nazwie DB2 Sam- z poziomu aplikacji PHP szerzeń, obsługa DB2 w Unified ODBC
ple Application for PHP, która będzie Dostęp aplikacji PHP-owych do baz opiera się na natywnych wywołaniach
dostępna pod adresem http://server: DB2 lub Cloudscape jest możliwy dzię- CLI; nie jest jednak możliwe uruchamia-
port/ZendCore/DB2Sample/. Natomiast ki rozszerzeniom korzystającym z API nie procedur składowanych z parametra-
zarządzanie i konfiguracja środowi- klienta DB2. Klient ten łączy się z silni- mi OUT/INOUT. Niezależnie od bazy da-
ska Zend Core for IBM będzie możliwe kiem bazy danych wykorzystując proto- nych, z którą się łączymy (DB2 czy Clo-
udscape), używamy tych samych metod tomiast zastosowanie połączenia ska- Z bazą danych DB2 możemy się
dostępu i korzystania z danych. Zamiast talogowanego może być przydatne, gdy również łączyć korzystając ze starego,
Unified ODBC zaleca się obecnie korzy- chcemy wykorzystać specyficzne funkcje nieopartego na PDO interfejsu bazoda-
stanie z rozszerzeń IBM_DB2 lub PDO_ możliwe do realizacji przy pomocy klienta nowego. Używamy w tym celu dwóch
ODBC. DB2 (np. szyfrowanie komunikacji pomię- funkcji: db2 _ connect() i db2 _ pcon-
dzy klientem, a serwerem DB2). nect(). W przypadku db2 _ connect()
PDO_ODBC
PDO_ODBC jest sterownikiem (ang. dri- Listing 1. Łączenie się z bazą DB2 przy użyciu PDO_ODBC
ver) baz zgodnych z ODBC, wykorzy-
stywanym przez będące już standardem <?php
rozszerzenie PDO (PHP Data Objects).
try {
PDO, o którym pisaliśmy już w artykule // przygotowanie danych potrzebnych do nawiązania połączenia z DB2
PDO – przyszły standard dostępu do baz $constrng = 'odbc:DSN={IBM DB2 ODBC DRIVER};HOSTNAME=localhost;
danych w PHP Solutions 5/2005, umożli- PORT=50000;DATABASE=dlrshp;PROTOCOL=TCPIP;UID=db2inst1;PWD=123;';
wia zunifikowany dostęp do różnych źró-
// utworzenie obiektu klasy PDO, z którego będziemy korzystać
deł danych z wykorzystaniem tych sa-
$dbh = new PDO($constrng);
mych metod. W połączeniu z oprogramo- echo 'Connected';
waniem klienta DB2, PDO_ODBC umoż- }
liwia dostęp do baz DB2, Cloudscape i catch (PDOexception $exp) { // jeśli połączenie się nie udało
Apache Derby. Podobnie, jak w pozosta- echo 'Exception: '.$exp->getMessage();
}
łych przypadkach, dostęp ten jest możli-
?>
wy dzięki CLI. Na Listingu 1 przedstawia-
my przykład użycia PDO_ODBC do połą- Listing 2. Łączymy się z DB2 przy użyciu db2_connect
czenia się z bazą DB2.
<?php
połączenie (link) z bazą danych jest Parametry połączenia przekazujemy ko- durami składowanymi, widokami, itp. Co
automatycznie zamykane po wykona- rzystając z $conn _ string. Obsługę błę- więcej, jest dostępny również dla wer-
niu się skryptu, jeżeli natomiast stosu- dów zapewni nam sprawdzenie, czy ist- sji PHP wcześniejszych niż PHP5. Jak
jemy db2 _ pconnect(), połączenie bę- nieje zmienna $conn – jeśli tak, to połą- można się domyślić, interfejs IBM_DB2
dzie cały czas aktywne (nie można go czenie się powiodło. opiera się więc na tradycyjnym progra-
zamknąć nawet korzystając z polecenia IBM_DB2 umożliwia nie tylko wy- mowaniu proceduralnym. Ma również
db2 _ close()). Na Listingu 2 przedsta- syłanie kwerend SQL-owych, ale rów- wiele wbudowanych funkcji służących
wiamy przykład użycia db2 _ connect(). nież pracę z dokumentami XML, proce- m.in. do pobierania informacji o stanie i
konfiguracji serwera DB2, co następuje
Listing 3. Wstawiamy opis nowego produktu z aplikacji PHP poprzez wysyłanie do serwera zapytań
dotyczących tabel słownika systemowe-
// nawiązujemy połączenie z bazą danych DB2 go DB2 (system catalog tables).
$conn =db2_connect($dbname, $dbuser, $dbpass);
Niewątpliwą nowością w IBM_DB2
// odczytujemy plik p1.xml i tworzymy na jego podstawie dokument XML $dom
jest możliwość natywnej obsługi doku-
$fileContents = file_get_contents("products/p1.xml"); mentów i danych składowanych w for-
$dom = simplexml_load_string($fileContents); macie XML.
ding). Zastosowanie obiektów LOB po- Załóżmy, że chcemy utworzyć sklep rzystaniu instrukcji INSERT, tak samo, jak
zwala na szybkie wstawienie i pobranie internetowy, który będzie przechowywał w przypadku zwykłych danych relacyj-
całego dokumentu XML, ale ma poważ- informacje o produktach w bazie danych nych. Ponieważ identyfikator produktu
ną wadę, którą jest konieczność dyna- korzystającej z silnika DB2 9. Taka tabela jest przechowywany w oddzielnym polu
micznego parsowania dokumentu, któ- mogłaby wyglądać następująco: tej tabeli (pid), musimy go wyodrębnić z
ra bardzo negatywnie odbija się na wy- dokumentu XML. Możemy to zrobić wy-
dajności zapytań. Dokumenty XML są w create table product ( korzystując interfejs PHP SimpleXml lub
całości umieszczane w polu binarnym. pid int, wykorzystując mechanizmy DB2, takie
Struktura dokumentu jest przetwarzana info xml jak funkcja XMLTABLE , polecenie DECOM-
dopiero w momencie realizacji zapyta- ) POSE XML DOCUMENT czy procedura xdb-
nia, w wyniku którego zwracane są ele- DecompXML .
menty tego XML-a. Atrybut pid byłby identyfikatorem pro- Zwróćmy uwagę na użycie tech-
Wydajniejszą metodą przeszukiwa- duktu, podczas gdy info zawierałby niki prepared statements (db2 _ pre-
nia dokumentów XML jest uprzednia de- szczegółowy opis produktu, będący ze- pare()) przy wstawianiu danych do ba-
kompozycja każdego z nich do posta- stawem danych specjalnego typu XML . zy: występujące we wzorcu znaki zapy-
ci relacyjnej. Jest ona przeprowadza- Opisy produktów dla omawianego syste- tania zostaną zastąpione przez id pro-
na przez odpowiedni kod bazy danych mu byłyby dostarczane w postaci doku- duktu ($prodid) oraz zserializowaną za-
podczas przesyłania dokumentu XML mentów XML. Wstawienie opisu nowego wartość odczytanego pliku XML ($file-
do bazy. Polega na wyodrębnianiu ele- produktu z aplikacji PHP mogłoby prze- contents). W bazie danych dokument
mentów dokumentu XML oraz ich wsta- biegać jak na Listingu 3. ten będzie miał postać hierarchiczne-
wianiu do odpowiednio przygotowanych Zawartość dokumentu XML została go drzewa odzwierciedlającego struk-
tabel relacyjnych (dokument XML zosta- wstawiona do tabeli product przy wyko- turę XML.
je pocięty na fragmenty, które stają się
rekordami w bazie; dobrze oddaje to an- Listing 6. Przetwarzanie listy pobranej z dokumentu XML na format HTML
gielskie określenie shredding). (XQuery)
Zasadniczą wadą shreddingu jest
$xquery =for $i in $t/product
natomiast brak elastyczności, wynikają-
let $thumb := $i/description/images/image[@type="thumbnail"]
cy z konieczności uprzedniej znajomo-
where $i/description/category = " . htmlentities($category) . "
ści struktury przesyłanego dokumen- return
tu, utworzenia tabel bazodanowych za-
wierających odpowiednie atrybuty oraz <div class="float">
<a href="product.php?pid={$i/@pid}">
przypisania tych ostatnich do poszcze-
<img border="0" src="data/images/{$thumb}.jpg" height="100" width="100"/>
gólnych elementów XML-a. Łatwo so-
</a>
bie wyobrazić, jak skomplikowana sta- <p>
je się wtedy prosta modyfikacja struk- <a href="product.php?pid={$i/@pid}">{$i/description/name}</a>
tury formularza na stronie WWW: razem </p>
</div>;>
z nim musimy zmieniać strukturę doku-
mentu XML i bazy danych – to ostatnie
$stmt = db2_prepare($conn, "SELECT XMLSERIALIZE(XMLQUERY(
jest bardzo uciążliwym i czasochłonnym $xquery' PASSING BY REF T.DESCRIPTION AS \"t\"
procesem. RETURNING SEQUENCE) AS CLOB(32K)) FROM xmlproduct AS t");
Ograniczeń obu metod (obiektów bi- db2_execute($stmt);
narnych oraz shreddingu) możemy unik-
while(list($product) = db2_fetch_array($stmt)){echo $product;}
nąć korzystając z dedykowanych baz
XML-owych. Listing 7. Deklarujemy zbiór wynikowy c_cur z klauzulą WITH RETURN
W DB2 9 zaimplementowano sil-
nik pureXML®, który jest oparty o hierar- CREATE PROCEDURE getProduct(IN id VARCHAR(10))
DYNAMIC RESULT SETS 1
chiczną bazę danych i przechowuje dane
LANGUAGE SQL
XML w wewnętrznym formacie odpowia- BEGIN
dającym strukturze dokumentu XML. Ar- DECLARE c_cur CURSOR WITH RETURN FOR
chitekci DB2 położyli bardzo duży nacisk SELECT XMLSERIALIZE(XMLQUERY /* treść zapytania XQuery */
nie tylko na wydajną pracę bazy XML- OPEN c_cur;
END
owej, ale także na jej integrację z silni-
kiem relacyjnym. Język zapytań doku- Listing 8. Uruchamiamy procedurę składowaną przy użyciu instrukcji CALL
mentów XML XQuery/XPath jest obsłu-
giwany na równi z językiem SQL, a kom- $stmt = db2_prepare($conn, "CALL getProduct(?)");
db2_execute($stmt, array($pid));
pilator kwerend bazodanowych DB2 po-
zwala na łączenie ze sobą zapytań do list($product) = db2_fetch_array($stmt);
danych relacyjnych z tymi kierowanymi do echo $product;
danych XML.
Podsumowanie
System bazodanowy DB2 daje ogrom-
ne możliwości, z których najważniejsze
to te wprowadzone w wersji 9, które do-
tyczą przechowywania danych w posta-
ci dokumentów XML.
Korzystając z nich możemy znacznie
uprościć i przyspieszyć tworzenie struk-
tur danych oraz uczynić ich przetwarza-
nie w naszych aplikacjach elastycznym.
Będziemy o nich jeszcze pisali w następ-
nych artykułach.
Funkcjonalność i solidność poprzed-
niej, całkowicie darmowej wersji DB2 jest
również warta uwagi. Biorąc pod uwa-
Rysunek 4. Dokumenty XML przechowywane są w DB2 9 w postaci hierarchicznej gę te cechy oraz łatwość łączenia DB2
z PHP, warto się poważnie zastanowić
Korzystamy z XQuery Dla wygody możemy umieścić zapy- nad jej zastosowaniem w swoich projek-
Do pobrania i prezentacji kategorii każde- tanie XQuery w procedurze składowanej tach. n
go produktu, przechowywanej jako ele- i przekazać jego wynik w postaci zbioru
ment dokumentu XML, możemy użyć pro- wynikowego.
stego zapytania XQuery: Procedura powinna być zadeklaro-
wana z klauzulą DYNAMIC RESULT SETS,
for $i in db2-fn:xmlcolumn( która oznacza liczbę zwracanych zbio-
'PRODUCT.INFO')/product/description rów wynikowych. By zwrócić zbiór wy- O autorach
return $i/category/text() nikowy, kursor c _ cur musi zostać za-
deklarowany z klauzulą WITH RETURN (Li- Artur Wroński: Jest pracownikiem
Pamiętajmy, że przedstawiony kod jest sting 7). działu oprogramowania IBM i jest od-
wykonywany na serwerze baz danych Jedynym, co nam pozostało do zro- powiedzialny za rozwiązania z zakre-
i nie jest fragmentem skryptu PHP (mimo bienia w aplikacji PHP jest uruchomienie su baz danych. Od 12 lat specjalizuje
się w silnikach baz danych, migra-
podobnego zapisu nazw zmiennych). procedury składowanej przy użyciu in- cjach oraz narzędziach dla hurtowni
Możemy utworzyć widok Categories, strukcji CALL oraz odczytanie wyników danych.
który będzie odpowiadał zapytaniu XQu- naszej kwerendy (Listing 8). Po raz ko- Kontakt: artur.wronski@pl.ibm.com
ery – pozwoli nam to używać zapytania lejny, zwróćmy uwagę na użycie techniki
Piotr Pietrzak: Jest architektem sys-
SQL w celu wykonania operacji dostępu prepared statements. temów w dziale Systems & Technology
do danych XML (Listingi 4 i 5). Group w polskim oddziale firmy
W DB2 9 XQuery pozwala nie tylko Indeksy w XML-u IBM. Od ponad 11 lat związany jest
na prezentację listy pobranej z dokumen- Aby działanie i korzystanie z zapytań by- z branżą IT. Jest autorem wielu tech-
nicznych publikacji dotyczących archi-
tu XML, ale także na przetwarzanie jej w ło wydajne, potrzebne są indeksy. DB2 9 tektury sprzętu oraz programowania.
klauzuli return do formatu HTML na eta- pozwala na tworzenie indeksów dotyczą- Kontakt: piotr.pietrzak@pl.ibm.com
pie zwracania wyników (zob. Listing 6). cych elementów dokumentu XML, któ-
K
ażdy administrator serwera WWW do baz MySQL, techniki da się zasto-
powinien znać techniki, które mo- sować na każdej platformie bazodano-
gą być wykorzystane do identyfi- wej – w większości przypadków bez
kacji podatności na SQL Injection (patrz modyfikacji. Techniki te w swojej istocie
Artykuł Tobiasa Glemsera Ataki SQL In- są wymierzone w język SQL. Określo-
jection na PHP i MySQL, hakin9 2/2005) ne rozszerzenia baz danych zwyczaj-
W SIECI i być świadomy ryzyka, jakie niosą. Pod- nie ułatwiają zastosowanie omawia-
stawowa metodologia SQL Injection pole- nych technik.
ga na określeniu wektora ataku, a następ-
• http://www.spidynamics.com/ nie jego wykorzystaniu za pomocą zmo-
papers/SQLInjectionWhiteP
aper.pdf – bardzo dobry ar- dyfikowanych zapytań SQL – wszystko Co należy wiedzieć...
Musisz bardzo dobrze znać składnię ję-
tykuł o atakach SQL Injec- przez przeglądarkę internetową. zyka SQL, do tego powinieneś znać ję-
tion,
• http://msdn.microsoft.com/ Określenie potencjału luki jest waż- zyk PHP na średnio zaawansowanym
msdnmag/issues/04/09/ ne, ale jeszcze ważniejsza jest moż- poziomie.
SQLInjection/ – Stop SQL
liwość oceny jego wpływu. W niektó-
Injection Attacks Befo-
re They Stop You (strona rych przypadkach wektor SQL Injec- Co obiecujemy...
MSDN), tion może nie wykraczać poza możli- Po przeczytaniu artykułu nauczysz się
• http://www.sqlsecurity.com/ w jaki sposób atakować składnię zapy-
– wszystko o słabych punk- wość wygenerowania błędów składni,
tań SQL, dowiesz się jak przeprowa-
tach SQL, takich jak próby przekształcenia łań- dzane są ataki na składnię języka SQL,
• http://www.imperva.com/
application_defense_center/ cuchów (strings) w wartości numerycz- poznasz również metody agresji na lo-
white_papers/sql_injection_ ne. W innych sytuacjach wektor umoż- gikę SQL, nauczysz się kilku dodatko-
signatures_evasion.html wych sztuczek SQL Injection oraz po-
liwia atakującemu pełne przejęcie kon-
– automatyczne, samopro- znasz ogólne zasady obrony przed ata-
gramujące ataki na SQL. troli nad informacjami z bazy danych. kami SQL Injection.
Chociaż nasze przykłady odnoszą się
Dla odświeżenia wodu źle sformatowanej składni (nieza- ASCII. Atakujący może wstrzyknąć cudzy-
pamięci mknięty pojedynczy cudzysłów): słowy przez zastosowanie parzystej lub
Testy SQL Injection można podzielić na nieparzystej liczby powtórzeń łańcuchów
trzy kategorie w oparciu o to, w który • SELECT foo FROM bar WHERE a = CHAR(0x27) – szesnastkowa wartość 0x27
aspekt zapytań SQL są wymierzone: ''';, reprezentuje kod ASCII apostrofu. To waż-
• SELECT foo FROM bar WHERE a = '/ ne, ponieważ atak składa się ze znaków
• atak na składnię zapytania – wstawia- *;, alfanumerycznych i nawiasów. W związ-
nie typowych znaków SQL mające na • SELECT foo FROM bar WHERE a = ';-- ku z tym monitorowanie danych wejścio-
celu wygenerowanie błędów ułatwiają- ;, wych pod kątem cudzysłowów nie zareje-
cych identyfikację potencjalnego wek- • SELECT foo FROM bar WHERE a = '#;. struje ani nie zablokuje ataku.
tora ataku,
• atak na składnię języka – wycelowany Chociaż apostrof (ASCII 0x27) jest najpo- Znaczenie zmiennych
w sam język SQL, zamierzeniem jest pularniejszym przykładem, wiele znaków Błędy baz danych mogą być także wywo-
wygenerowanie błędów bazy danych może być użytych do zakłócenia składni, łane przez ataki na typy zmiennych. Jest
lub wykonanie prostych kwerend po- między innymi: to najskuteczniejsze w przypadku warto-
przez manipulację konstruktami języ- ści numerycznych, ale podatne są także
ka i tożsamościami semantycznymi, • niepasujący cudzysłów, zmienne czasu czy daty. Oto przykładowa
• atak na logikę zapytania – przepisanie • średnik, lista różnych wartości, na których można
zapytania mające na celu otrzymanie • znak komentarza – /*, #, lub --. wypróbowywać parametry spodziewające
dowolnych danych z tabel, do których się liczb dziesiętnych:
twórcy nie przewidzieli dostępu. Filtry poprawności, które zabraniają wy-
łącznie znaków pojedynczego cudzysłowu • 8-, 16-, 32- i 64-bitowe wartości – 256,
Techniki te mogą być łączone w celu oce- (lub tylko małego zestawu znaków) mogą 65536, itd.,
nienia aplikacji webowej i określenia jej zabezpieczać przed pełnym wykorzysta- • przepełnienia całkowite – 2^8 + 1,
podatności na ataki SQL Injection. niem podatności, ale zwykle są niewystar- 2^16 +1, 2^32 + 1, or 2^64 + 1,
W następnych sekcjach przykłado- czające. Mogą po prostu zaciemniać bar- • wartości nienazwane kontra nazwane
we ładunki (ang. payload) SQL Injec- dziej podstawowe problemy z architekturą – wstawianie wartości ujemnych,
tion będą prezentowane bez całego ad- połączeń aplikacji z bazą danych. • przepełnienia zmiennoprzecinkowe – na
resu (URL). Ułatwi to zrozumienie tech- przykład 3.40282346638528860e+38,
nik bez niewygodnych parametrów i tek- Cudzysłowy kontra ukośniki 1.79769313486231570e+308,
stu. Innym powodem jest to, że wstrzyk- Podczas tworzenia silnych filtrów popraw- • alternatywne przedstawienia – dwój-
nięcie tych ładunków jest całkiem proste. ności programiści PHP stają przed kilkoma kowe, ósemkowe, szesnastkowe lub
Przy założeniu, że mamy URL w postaci wyzwaniami i potencjalnie mylącymi za- notacja naukowa.
http://witryna/page.cgi?a=foo&b=bar, atak leceniami. Funkcja magic_quotes() auto-
SQL Injection zastępuje wartość podat- matycznie kasuje (ang. escape) wszystkie Te ataki liczbowe często się udają (gene-
nego parametru swoim ładunkiem: http: apostrofy znakiem odwróconego ukośnika rują błędy), ponieważ zmienne używane
//witryna/page.cgi?a=<ładunek SQL Injec- (\). Jeśli jednak ta możliwość jest połączo- do śledzenia tych wartości nie mają ści-
tion>&b=bar. Dla dalszego przypomnie- na z wywołaniem funkcji strip_slashes(), śle określonego typu. W języku PHP ty-
nia: trzeba pamiętać o kodowaniu spacji i znaki kasowania zostaną usunięte: pem parametru dla wszystkich zmiennych
innych znaków w ładunku, aby nie zakłó- $_REQUEST jest łańcuch (string). Ozna-
cały one składni adresu. • SELECT foo FROM bar WHERE a = '\ cza to, że – mimo możliwości wykonywa-
''; – apostrof wykasowany, nia operacji na zmiennych ($a = 1; $a++)
Ataki na składnię • SELECT foo FROM bar WHERE a = '''; – typ zmiennej powinien być traktowa-
zapytań – odwrócony ukośnik wycięty, zapyta- ny jako łańcuch liczbowy. Zmienna mo-
Pojedynczy cudzysłów, zwany apostrofem nie źle sformatowane. że być nawet po cichu zmieniona z licz-
(') – choć jest zdecydowanie najpopular- by na łańcuch liczbowy, przy którym war-
niejszym znakiem stosowanym do iden- Innym niebezpieczeństwem nadmiernej tość zwykle skutkowałaby przepełnieniem,
tyfikacji wektorów SQL Injection – nie jest koncentracji na pojedynczym cudzysłowie wartością inf (ang. infinity – nieskoń-
w żadnym wypadku jedynym znakiem po- jest fakt, że programiści mogą nie znać czoność) lub NaN (ang. not a number
trzebnym do wygenerowania błędu bazy pełnego zakresu znaków i technik, które – nie jest liczbą). Na przykład funkcja
danych. Ta technika obejmuje najbardziej atakujący mógłby wykorzystać przy atako- PHP is_numeric("1e308") zwróci war-
podstawowe testy potencjalnych luk po- waniu zapytania SQL. Intruz może łączyć tość prawdziwą (bo jest to liczba), ale
przez użycie metaznaków lub znaków for- funkcje SQL, by generować błędy skład- is_numeric("1e309") zwróci fałsz – nie
matujących języka MySQL do zakłócenia ni zapytania. jest to ani liczba, ani łańcuch liczbowy, po-
składni oryginalnego zapytania. Na przy- Do wywołania błędów można również nieważ znajduje się poza zakresem typu
kład następujące wyrażenia nie mogą być użyć wbudowanych funkcji SQL. Funkcja PHP double float. Zmienna musi być prze-
przetworzone do poprawnej postaci z po- CHAR() drukuje odpowiednik argumentu w stawiona w tryb numeryczny bezpośred-
• rowid = 111,
• rowid = 0x6f,
• rowid = 0157 (reprezentacja ósem-
kowa),
• rowid = 110+1 (w praktyce używajmy
110%2b1, ponieważ znak + w adresie
oznacza spację),
• rowid = 112–1,
• rowid = MOD(111,112),
• rowid = REPEAT(1,3),
• rowid = COALESCE(NULL,NULL,111).
Liczenie kolumn
Drugi problem także nie jest wielkim
wyzwaniem, ale wymaga kilku powta-
rzalnych kroków. Wstrzyknięte wyraże-
Rysunek 4. Udany atak UNION SELECT
nie UNION będzie miało albo za mało,
ale jeśli dane mają być umieszczone w za- Następnie można odwrócić zapytanie albo zbyt dużo kolumn, nam zaś potrze-
pytaniu, powinny być bezpośrednio przypi- tak, aby było poprawne, w ten sposób ba poprawnej liczby. Jeśli mamy możli-
sane (rzutowane) do odpowiedniego typu sprawdzając wektor wstrzyknięcia – / wość obserwacji komunikatów o błędach
danych. W przypadku języków interpreto- *!32302+AND+1+*//* (może być konieczne generowanych przez bazę, zobaczymy
wanych jak PHP, Perl, C# czy Visual Basic zakończenie zapytania). coś w rodzaju The used SELECT sta-
przypisanie powinno być bezpieczne lub tements have a different number of co-
generować błąd konwersji. Jeśli aplikacja UNION SELECT lumns (Użyte wyrażenia SELECT mają
webowa używa języka kompilowanego (C, Po identyfikacji parametru jako wektora różną liczbę kolumn).
C++), to rzutowanie typów musi być trak- dla ataków SQL Injection, następnym kro- Niedoszacowanie kolumn można po-
towane ostrożnie i sprawdzane pod kątem kiem jest określenie tego, na co podatna prawić poprzez dodanie do wyrażenia
wyjątków – uczulamy na ataki z wykorzy- jest baza danych. Osiągamy to przez ma- SELECT dodatkowych kolumn lub miejsc na
staniem łańcuchów formatujących (patrz nipulowanie logiką oryginalnego zapyta- nie (Rysunek 4), na przykład za pomocą
Artykuł Nadużycia z wykorzystaniem cią- nia. Większość podstawowych zapytań ma następujących wyrażeń:
gów formatujących, hakin9 5/2004). postać SELECT foo FROM bar WHERE a=b;,
gdzie b z równania a=b jest parametrem, • SELECT user FROM mysql.user;
Ataki na logikę którym można manipulować. Co za tym • SELECT 1,user FROM mysql.user;
zapytania idzie, nowe zapytanie musi brać pod uwa- • SELECT 1,1,user FROM mysql.user;
Manipulacje składnią zapytań są użytecz- gę wcześniejsze SELECT. Najszybszą tech- • SELECT user,user,user,user FROM
ne przy identyfikacji podatności na SQL niką jest użycie słowa kluczowego UNION. mysql.user;
Injection, ale tylko wskazują na istnienie Wyrażenie UNION łączy wiele wy-
problemu. Prawdziwym ryzykiem związa- rażeń SELECT i jest obsługiwane przez Każde z tych zapytań pobiera nazwę
nym z atakami SQL Injection jest dostęp większość systemów bazodanowych. Je- (lub nazwy) użytkownika z domyślnej ta-
do dowolnych danych. go podstawowa forma ma postać SELECT blicy mysql.user. W każdym z powyż-
MySQL obsługuje charakterystyczne foo FROM bar WHERE a=b UNION SELECT szych przykładów liczba kolumn wzrasta
makro komentarzowe, które wyświetla wer- foo2 FROM bar2 WHERE c=d;. Użytecznym z 1 do 4. W praktyce lepiej powtórzyć na-
sję bazy danych: /*!<wersja> */, gdzie aspektem UNION jest wyświetlanie nazwy zwę kolumny aby upewnić się, że wartość
<wersja> jest pięciocyfrową wartością re- użytkownika, który nawiązał połączenie z jest wyświetlana przez aplikację. Pierw-
prezentującą wersję MySQL. Na przykład bazą danych. W MySQL robi się to za po- sze miejsce na kolumnę działa, ale trud-
wersja 3.23.02 wygląda jak 32302, wer- mocą funkcji SELECT USER(). Żądanie mo- no powiedzieć, którą kolumnę wyświetli
sja 4.1.10 to 40110, zaś 5.0.3 wygląda jak głoby wyglądać następująco: aplikacja.
50003. Najszybszym sposobem sprawdze- Przeszacowania kolumn mogą być
nia możliwości wbudowanych ataków na SELECT text FROM articles poprawione za pomocą wyrażenia CONCAT.
MySQL jest połączenie komentarza z wyra- WHERE id=0 Przeszacowania pojawiają się, gdy pierw-
żeniem skutkującym błędem zapytania: UNION SELECT USER(); sze wyrażenie SELECT spodziewa się
mniejszej liczby kolumn niż zawarto w za-
• /*!32302+AND+0+*/, Przy stosowaniu wyrażeń UNION w ata- pytaniu. Wyrażenie CONCAT rozwiązuje ten
• /*!32302+AND+0+*//* (może być ko- kach SQL Injection pojawia się kilka pro- problem poprzez połączenie każdej ko-
nieczne zakończenie zapytania). blemów: lumny w pojedynczy łańcuch – większa
Prosimy wypełnić czytelnie i przesłać faksem na numer: (22) 887 10 11 lub listownie na adres: Software-Wydawnictwo Sp. z o.o.,
Piaskowa 3, 01-067 Warszawa, e-mail: pren@software.com.pl. Przyjmujemy też zamówienia telefoniczne: (22) 887 14 44
Dokładny adres....................................................................................................................................................................................................................
Tytuł
Ilość Od numeru Opłata
Ilość
zamawianych pisma lub w zł
numerów
prenumerat miesiąca z VAT
Software Developer’s Journal (1 płyta CD)
– dawniej Software 2.0 12 250/1801
Miesięcznik profesjonalnych programistów
SDJ Extra (od 1 do 4 płyt CD lub DVD)
– dawniej Software 2.0 Extra! 6 150/1352
Numery tematyczne dla programistów
Suma
TYPO3 od kuchni,
czyli wymarzony portal
w zasięgu ręki
Stopień trudności: lll
Jean-Gael Rouchon
T
YPO3 jest potężnym i elastycz- pozwalający na łatwe dodawanie kolejnych
nym systemem zarządzania treścią możliwości.
(CMS, ang. Content Management Historia TYPO3 zaczęła się od wspo-
System) napisanym w PHP. Jest aplikacją magania rozwoju portali korporacyjnych
opensourcową, dostępną na licencji GNU w Internecie (głównie B2C, ang. Busi-
GPL (General Public License). Jest CMS- ness-to-Customer, czyli przeznaczonych
em wielojęzycznym (48 wersji językowych do kontaktu między firmą a jej klientami).
w maju 2006) i wielowitrynowym (potrafią- Dzięki systemowi rozszerzeń i wspomnia-
cym obsłużyć wiele witryn z jednej instala- nemu frameworkowi, system może rów-
cji). TYPO3 daje użytkownikowi ogromną nież obsługiwać witryny B2B, intranety,
swobodę tworzenia strony, a jego architek- extranety, a także wspomagać tworzenie
tura jest zorientowana na strony (ang. page- pojedynczych aplikacji.
W SIECI centric paradigm). Oferuje rozwinięte moż-
liwości zarządzania grupami oraz dosto-
Co powinieneś
sowywania funkcjonalności pod kątem au-
wiedzieć...
• http://www.typo3.org – głów- torów i gości. Posiada również wbudowa- Przydatna będzie podstawowa znajo-
na strona TYPO3
ny system wersjonowania oraz funkcje mość konfigurowania PHP oraz wiedza
• http://wiki.typo3.org – oficjal-
na encyklopedia TYPO3 przekierowywania URL-i (ang. URL rewri- na temat systemów CMS.
• http://web.inselhof-triemli.ch/ ting). Jedną z największych zalet TYPO3
index.php?id=98&type=3
– wprowadzenie do Typo3 jest system rozszerzeń, który pozwala do- Co obiecujemy...
Testsite dawać nowe funkcje bez modyfikacji rdze- Pokażemy, jak przy pomocy TYPO3
• http://opensourcecms.com stworzyć od podstaw kompletną witrynę
– witryna poświęcona CMS-
nia systemu. Obecnie dostępnych jest po-
internetową, zawierającą forum dyskusyj-
om nad 1400 rozszerzeń (maj 2006). Dodatko- ne i moduł newsów.
wo, twórcy TYPO3 udostępniają framework
Łączymy się z
BackEndem
Podobnie jak większość systemów CMS,
TYPO3 został podzielony na FrontOffi-
ce (witryna widoczna dla użytkownika)
i BackOffice (interfejs administracyjny).
W TYPO3 witryna jest nosi nazwę Fron-
tEnd (FE), a interfejs administracyjny, w Rysunek 1. BackEnd TYPO3 (istotne kroki zostały podświetlone na czerwono)
którym modyfikujemy zawartość – Bac-
kEnd (BE). Między tymi warstwami istnie- ich ustawień. Na górze strony z ustawie- rą chcemy wyedytować (w naszym przy-
je wyraźny podział, gdyż dane użytkowni- niami możemy zmienić język (mamy do padku Test).
ków FE i BE znajdują się w osobnych ta- wyboru wiele wersji językowych, włącznie Po prawej stronie ekranu pokażą się
belach bazodanowych (istnieje możliwość z angielską, polską, niemiecką, francuską przyciski i menu ułatwaiające nam wyko-
połączenia tych tabel, ale nie jest to dla i włoską). Dostępność każdego z języków nywanie rozmaitych operacji na wybranej
nas ani niezbędne, ani pożądane). zależy od tego, czy zainstalowaliśmy Lan- stronie: oglądanie historii jej zmian, edycja
Zaczniemy od zalogowania się jako guage Pack (możemy to zrobić korzysta- właściwości, przenoszenie strony, doda-
zwykły redaktor zawartości witryny, który jąc z opcji Ext Manager w sekcji User tego wanie nowej strony lub jej zawartości oraz
korzysta z konta o nazwie redactor (hasło samego menu). Na stronie konfiguracyj- przeszukiwanie strony.
redactor), który ma ograniczone możliwo- nej możemy też zmienić ustawienia zwią- Wyedytujmy teraz treść strony: w tym
ści modyfikacji sajtu. UWAGA: nazwa kon- zane z rekurencyjnym kopiowaniem i ka- celu musimy po prostu kliknąć przykła-
ta redactor obowiązuje jedynie dla witryny sowaniem stron (określa ono, do którego dowy tekst pokazany poniżej nagłówka
demonstracyjnej i nie działa w przypadku poziomu mają być kopiowane lub kasowa- NORMAL lub przycisk Edit in Rich Text
instalacji tradycyjnej; w tej drugiej sytuacji ne podstrony wybranej strony). Zmienimy Editor umieszczony tuż pod tym tekstem.
korzystaj z konta administratora (login: ad- tu też nasze dane osobowe i dane konta Najlepiej wybrać pierwszy sposób, gdyż
min, hasło: password; w zastosowaniach (włącznie z hasłem). Aby zaakceptować po kliknięciu na Edit in Rich Text Editor nie
produkcyjnych należy zmienić hasło). zmiany, musimy przewinąć formularz i na wszystkie opcje i funkcje edytora będą do-
Interfejs BE jest podzielony na 3 czę- jego końcu kliknąć przycisk Save Confi- stępne (m.in. nie będziemy mogli zmienić
ści umieszczone w 2 ramkach (zob. Ry- guration, po czym się wylogować i zalogo- tytułu i typu treści ani przełączyć się na
sunek 1). Po lewej mamy główne menu, wać ponownie: to wszystko. tryb pełnoekranowy). Dobrym pomysłem
z którego wybieramy czynność do prze- jest kliknięcie przycisku Open in new win-
prowadzenia (edycja treści, zmiana usta- Zarządzanie treścią dow: jest on umieszczony na samym dole
wień użytkownika, zarządzanie plikami, Następnie, nadal zalogowani jako redac- całej ramki i ma kształt rombu.
itd.). W środkowej ramce (jeżeli jest ona tor lub admin, dodamy nową stronę do wi- W prawej części ekranu widzimy teraz
wyświetlana), pokaże się rozwijalne drze- tryny, po czym umieścimy w niej zawar- zawartość strony Test: znajduje się ona w
wo przedstawiające hierarchię zawartości tość. Później utworzymy 3 kolejne strony edytorze HTML-owym typu WYSIWYG,
naszej witryny. Wreszcie, w prawej czę- i zainstalujemy aplikację (forum dyskusyj- będącym aplikacją pochodną wobec edy-
ści ekranu ujrzymy efekty działań wybra- ne) na jednej z nich. tora HTMLArea, zmodyfikowaną poprzez
nych w części środkowej. Wrócimy do te- dodanie funkcji TYPO3 do obsługi linków
go później – zacznijmy od zmiany języka Modyfikacja treści i obrazów. Edytor ten pozwala nam na
używanego w BackEnd. Zacznijmy pracę z witryną demonstracyj- swobodne wprowadzanie tekstu, bieżą-
ną. Zalogowani jako redaktor, klikniemy cą zmianę ustawień czcionki, wstawianie i
Zmiana języka interfejsu na opcję Page w menu po lewej stronie zarządzanie tabelami oraz listami numero-
BackEnd ekranu (mała ikona oznacza tryb edy- wanymi i wypunktowanymi, cofanie i przy-
W menu po lewej stronie ekranu wybiera- cji). Następnie, korzystając z drzewa na wracanie przeprowadzonych działań, wy-
my opcję User–>Setup, aby dojść do swo- środku ekranu, wybieramy stronę, któ- szukiwanie i zastępowanie tekstu, itd. Kli-
Dodawanie strony ve document and view page): strona jest cego obrazy. Moglibyśmy ustawić pozycję,
TYPO3 jest CMS-em zorientowanym na gotowa. rozmiar, nagłówek i tytuł każdego obraz-
strony (ang. page-centric CMS). Ozna- Zanim umieścimy jakąkolwiek treść na ka. Aby zobaczyć więcej opcji, przewijamy
cza to, że pojedyncza strona internetowa naszej stronie, warto wiedzieć kilka rze- formularz i na jego samym dole zaznacza-
jest w nim podstawą całej witryny, umoż- czy. Po pierwsze, istnieje wiele sposo- my checkbox Show secondary options: w
liwiając nawigację i przechowując zawar- bów na dodawanie stron, m.in. użycie iko- formularzu pojawią się takie opcje, jak ja-
tość. Jest to zupełnie inne rozwiązanie niż ny Create new page w Page view czy też kość obrazu, efekty (np. obroty czy regula-
stosowane w takich CMS-ach jak Mambo, opcji new w menu uruchamianym po klik- cja kontrastu) czy click to enlarge. Użycie
gdzie zawartością zarządzamy przy uży- nięciu dowolnej ikony w ramach drzewa ostatniej opcji spowoduje, że po kliknięciu
ciu osobnego modułu, a potem linkuje- pośrodku ekranu. Po drugie, istnieją in- na obraz na stronie TYPO3 wyświetli go w
my ją do wybranych stron. Koncepcja i co- ne typy stron (wybieramy je z listy rozwi- nowym oknie, co jest bardzo przydatne w
dzienne zarządzanie witryną są więc zu- jalnej Type w opisywanym Wizardzie), ta- prostej galerii zdjęć.
pełnie inne niż w tamtych CMS-ach. kie jak skróty do innych części witryny, lin- Zmiana jakości (resampling) czy de-
Zależnie od swoich uprawnień, redak- ki zewnętrzne lub strony zaawansowane korowanie obrazka zachodzi automatycz-
tor może dodać stronę w wybranej części (advanced mode; dodajemy w nich słowa nie wobec wszystkich obrazów z zestawu
witryny. Drzewo stron jest całkowicie nie- kluczowe, opisy, itd). Możemy też dodać przy użyciu kombinacji bibliotek GD oraz
zależne od innych czynników, takich jak stronę typu Sysfolder: gromadzimy na niej ImageMagick.
zainstalowane moduły (w przeciwieństwie dane (zawartość, newsy, ustawienia, da- Kolejnym typem zawartości jest File-
np. do phpNuke i pochodnych). Każda no- ne użytkowników FE, itd), których będzie- links, którego używamy w celu wyświe-
wa strona jest automatycznie dodawana my mogli użyć w dowolnej części witryny. tlenia listy plików, z których każdy zawie-
do menu (jeżeli istnieje menu odpowied- Po trzecie, możemy tworzyć wiele stron ra krótki opis. Typ ten jest użyteczny, jeśli
niego poziomu). jednocześnie korzystając z menu Func- chcemy umieścić na stronie listę plików do
Dodajmy teraz parę stron do naszej tions po lewej stronie ekranu (jest to bar- pobrania (np. dokumentację, tutoriale czy
witryny: będzie to trochę podobne do mo- dzo przydatne, gdy budujemy witrynę od skompresowane aplikacje). Możemy zde-
dyfikacji zawartości strony. podstaw, gdyż skraca czas). finiować wygląd takiej listy korzystając z
W tym celu klikamy opcję Page w kilku gotowych wzorów.
menu po lewej stronie ekranu i wybie- Dodawanie bloku tekstowego Wracając do klasycznej zawartości
ramy stronę Test w znajdującym się po- Dobrze, mamy już naszą stronę, do któ- strony, mamy Menu Site Map, czyli ma-
środku ekranu drzewie stron. W ramce rej chcemy dodać zawartość: zróbmy to. pę witryny. Używamy jej, aby umieścić na
po prawej klikamy przycisk Create New W tym celu wybieramy Page –> Mypage stronie mapę całego sajtu lub jego czę-
Record: pojawi się w niej Wizard doda- –> Create new content. W wizardzie, któ- ści (korzystając z pola Starting Point: ma-
wania stron. Wybieramy w nim opcję Pa- ry się pojawi, wybieramy Page Content my do dyspozycji drzewo, które pozwa-
ge(Inside) – Click here for Wizard, a na- –> Click Here For Wizard. Otrzymamy li- la nam wybrać miejsce witryny, od które-
stępnie wybieramy docelowe położenie stę typów zawartość dostępnych dla użyt- go zaczniemy tworzenie mapy). Możemy
strony. kownika redactor (lub admin). Gdybyśmy też umieścić menu podstrony na poziomie
Pojawi się formularz dodawania stro- wybrali Regular Text, moglibyśmy ustalić, o jeden niższym niż sama strona. Jeżeli
ny, w którym wpiszemy jej tytuł (np. Mo- w której kolumnie chcemy umieścić za- podstrony są typu Advanced, i wypełnisz
ja Strona) – będzie on używany w ta- wartość (wybierzemy kolumnę Normal). pole opisu, możesz sporządzić np. pod-
gu <title> strony WWW oraz jako na- Na koniec widzimy ten sam formularz, któ- sumowanie (resume) podstron. Inną po-
zwa strony w drzewie. Jak widzimy, strona rego używaliśmy podczas modyfikacji ist- żyteczną sztuczką, którą możemy zasto-
jest domyślnie ukryta (poprzez zaznacze- niejącej treści. Przejdźmy teraz do listy sować na mapie witryny jest sporządze-
nie checkboksa Hide page), gdyż nie ma rozwijalnej Type i wybierzmy header: po- nie spisu treści stron na stronie aktywnej.
jeszcze żadnej zawartości: chcemy, aby zwala nam to na wstawienie samego na- Przydatne jest również zaznaczenie bok-
była widoczna na witrynie i w menu, więc główka, bez treści strony. su To top w formularzu edycyjnym każ-
odhaczymy tego checkboksa. Następnie Użycie typu Text w/ Images pozwoli- dego elementu strony (opcja secondary
klikamy na drugiej ikonie z dyskietką (Sa- łoby nam na wstawienie tekstu zawierają- options, umieszczona tuż poniżej listy roz-
użyjemy na naszej witrynie, jest klasycz- Rejestr Windows). Język został o pisany w nich (Constant i Setup) informują TYPO3,
na i opiera się na umieszczaniu specjal- osobnym manualu (TS Reference manual), że mamy do czynienia z nowym szablo-
nych znaczników w plikach HTML. Meto- a także w instrukcjach załączanych do każ- nem, który nie dziedziczy z głównego sza-
da ta jest prosta do zrozumienia i znajduje dego rozszerzenia (gdzie opis dotyczy kon- blonu (dziedziczenie po poprzednich sza-
zastosowanie przy tworzeniu rozszerzeń. figuracji tego rozszerzenia). blonach w linii root kodu TypoScript zosta-
Użycie MTB pozwoli nam się przyzwycza- je wykasowane). Trzecia opcja (Rootlevel)
ić do języka TypoScript. Natomiast druga Tworzymy własny szablon określa, że szablon jest korzeniem (ro-
metoda, Templavoila, pozwala na stoso- Aby utworzyć swój własny szablon sko- otem) witryny internetowej (główną stro-
wanie szablonów przy użyciu interfejsu ty- rzystamy z menu List po lewej stronie, wy- ną), a więc strona, na której zostanie uży-
pu point-and-click. bierzemy stronę Test w drzewie pośrodku ty, będzie stroną domową całej witryny.
Dla szablonów w TYPO3 przeznaczo- ekranu, klikniemy Create new record i ja- Możemy też dołączać (inkludować)
no osobny typ zawartości o nazwie Tem- ko typ treści wybierzemy Template. Uka- elementy innych szablonów i ustawień
plate oraz specjalny język TypoScript. Nie że nam się formularz dotyczący szablo- składowanych w bazie danych (Include
jest on językiem programowania, lecz ję- nu, w którym wypełnimy jedynie tytuł (bę- static) lub w plikach (Include static (from
zykiem opisowym, za pomocą którego dący nazwą szablonu). Możemy też usta- extensions)). Dodatkowo, możemy dołą-
definiujemy, jak szablony powinny dzia- wić nazwę witryny: zostanie ona użyta w czać całe szablony używając pola Include
łać – określamy sposób renderowania wi- tagu <title> przy nazwie strony (np. Moja- basis template field. My skorzystamy z po-
tryny, opisujemy obiekty dynamiczne Witryna : Strona1). la Include static (from extensions), wybie-
(np. menu) i konfigurujemy niektóre pluginy. Następnie w tym samym formularzu rając CSS Styled Content. Rezultatem tej
TypoScript używa notacji obiektowej w celu odhaczymy checkboksy Clear: Constant, operacji będzie dołączenie podstawowych
przedstawienia logiki drzewa (podobnie jak Clear: Setup i RootLevel. Dwa pierwsze z ustawień dotyczących renderowania, co
zaoszczędzi nam sporo pracy. Na koniec
Listing 1. Znaczniki TYPO3 wstawione do szablonu sunflower zapisujemy szablon korzystając ze znanej
już nam doskonale ikony z dyskietką.
<body>
<!--###DOCUMENT_BODY### start--> Zabawa z TypoScript
<div class="thebox">
Jeżeli zechcemy zobaczyć, jak wygląda
<div class="logo"><a href="#">###SITENAME###</a></div>
<!--###MENU1### start--> nasza witryna (np. http://localhost/typo3/),
<ul class="header"> zobaczymy komunikat o błędzie Error!.
<li><a href="#">Diary</a></li> Dzieje się tak, gdyż nie ustaliliśmy jeszcze
<li><a href="#">The Idea</a></li> metody renderowania i TYPO3 nie wie ani
<li><a href="#">Contact</a></li>
jakiej zawartości powinien użyć, ani w jaki
</ul>
<!--###MENU1### end--> sposób ją wyświetlić – poprawmy to.
<div class="side"> W naszym szablonie musimy wpisać
<!--###MENU2### start--> odpowiednie informacje w polach Con-
<h2>Archives</h2> stant i Setup. Constant to zmienna w ję-
<a href="#">March 2006</a><br/>
zyku TypoScript oraz miejsce, w którym
<!--###MENU2### end-->
<!--###SIDECONTENT### start--> można wygodnie umieszczać wartości wy-
<h2>Links</h2> korzystywane w polu Setup: później poka-
<a href="http://validator.w3.org/check/referer">XHTML</a><br/> żemy, jak to zrobić, a na razie zajmijmy się
<form method="get" action="#"> polem Setup.
<p><input size="12" style="border:1px solid #eee" type="text" id="q"
Pamiętajmy, że TypoScript ma skład-
name="q" /></p>
</form> nię obiektową, której używamy do konfigu-
<!--###SIDECONTENT### start--> rowania silnika renderującego (ang. ren-
</div> dering engine) oraz umieszczania obiek-
<div class="content"> tów na stronach WWW. Wprowadzimy
<!--###CONTENT### start-->
kod przedstawiony na Listingu 2 do po-
<h2><a href='#'>Sunflower</a></h2><h4>22 March 2006</h4><p>Sunflower validates
as XHTML la Setup. Zaczniemy od inicjalizacji stro-
1.1<br /><br />It has a liquid design or it will fit the available screen ny wpisując mypage = PAGE;, wskutek cze-
width.<br />If go powstanie obiekt mypage typu (klasy)
you like this theme, submit your comments in <a href=" PAGE. Nadamy mu domyślny typ typeNum.
http://www.kumi.co.nr/">www.kumi.co.nr</a><br /><br />Thank you^o^<br /></p>
Zauważmy, że pozwala nam to na zarzą-
<a href='#'>0 Comments</a><br/><p> </p>
<!--###CONTENT### end--> dzanie wieloma obiektami stron (np. ram-
</div><div class="footer"> kami) w jednym skrypcie TypoScript, a
© Copyright you | Design by <a href="http://www.kumi.co.nr">Kumiko</a> dzięki typeNum możemy korzystać z róż-
</div> nych metod renderowania (np. druk, PDF
</div><!--###DOCUMENT_BODY### end-->
czy WAP). Następnie zdefiniujemy ścież-
</body>
kę CSS do obiektu strony mypage (mypa-
ge.stylesheet). Jest to konieczne, gdyż
Metoda TemplaVoila daje bardzo duże zodanową i da możliwość zmiany opcji. W cji lub liczbę jednocześnie wyświetlanych
możliwości, aby je lepiej poznać, powinie- tym przypadku poprostu przewijamy stronę wiadomości, itd. My tylko pokazaliśmy, jak
neś przeczytać manual na temat Futuristic i zgadzamy się na instalację: moduł News go uruchomić i jak dodawać wiadomości.
template building. Najmocniejszą stroną jest gotowy do pracy. Do swojej dyspozycji mamy również
tej metody jest na pewno mapowanie przy UWAGA: ten sposób instalacji może narzędzie ułatwiające tworzenie rozszerzeń
użyciu narzędzi graficznych: wystarczy, okazać się niemożliwy przy powolnym po- (asystenta) o nazwie Extension Kickstarter.
że wybierzemy pożądany typ zawartości łączeniu z Internetem: skrypt może prze- Jego zadaniem jest automatyczne tworze-
(Content Column, Typoscript, Text Field, kroczyć maksymalny czas wykonywania nie wymaganych w każdym rozszerzeniu
itd), klikniemy na znaczniku, którego chce- (nastąpi timeout), który jest standardowo plików oraz tworzenie pustego kodu PHP
my użyć na danej stronie et voilà! – nasz ustawiony na 30 sekund. Aby temu zapo- (który później zastąpimy własnym). Może-
szablon jest gotowy. biec, musimy albo zmienić zawarte w pliku my użyć tego narzędzia do wstawiania no-
Działanie TemplaVoila zostało przed- php.ini ustawienie max_execution_time na wych pól do bazy danych. Co ciekawe, po-
stawione na filmie zrobionym we Flashu, 0 (skrypt będzie wykonywany w nieskoń- la te dodajemy używając oznaczeń typo-
dostępnym pod adresem: http://typo3.org/ czoność, aż do przerwania jego pracy), al- wych dla formularzy (textarea, selector,
documentation/articles/minute-website/. bo też ręcznie pobrać rozszerzenie, a na- file), a nie typów SQL-owych (np. varchar
Dla Twojej wygody, umieściliśmy ten stępnie zainstalować je z dysku lokalnego czy integer). Wydaje się to trochę dziwne,
film na naszej witrynie demonstracyjnej – identycznie, jak w przypadku opisanej lecz jest wydajne.
(TYPO3 –> English -> Cool Features). przez nas instalacji tt_board.
Mając już moduł newsów, dodamy go Podsumowanie
Dodawanie nowych do strony Test. W tym celu przechodzi- Opisaliśmy najbardziej użyteczne moż-
aplikacji my na stronę Test i klikamy Create new re- liwości TYPO3, dając Ci solidne podsta-
Jak już wiemy, jedną z najlepszych cech cord -> Page Content -> Click for Wizard. wy do podjęcia decyzji, czy chcesz ko-
TYPO3 jest system rozszerzeń, o któ- Następnie musimy wybrać plugin o nazwie rzystać z tego CMS-a, czy nie. Aby się o
rym już wspominaliśmy. Podobnie, jak in- News, który jest umieszczony na końcu li- tym upewnić, możesz zajrzeć pod adres
ne systemy wtyczek (np. z Firefoksa), po- sty w sekcji Plugins. Klikamy go i umiesz- http://typo3.com, gdzie znajduje się Eva-
zwala on na wzbogacanie naszej witryny czamy w kolumnie Normal. W formularzu luation Center – miejsce, w którym zgro-
o nowe funkcje bez modyfikowania silnika edycyjnym wpisujemy nagłówek (np. Moje madzone sa rozmaite informacje na te-
leżącego u jej podstaw (rdzenia). Działa- newsy) i wybieramy LATEST w What to di- mat TYPO3. Możliwości TYPO3 są dodat-
nie każdego rozszerzenia może dotyczyć splay: moduł będzie wyświetlał tytuł i pierw- kowo zilustrowane przy użyciu przykładów
FrontEndu, BackEndu lub obu z nich. sze słowa każdego newsa. Zapiszmy nasze we Flashu (http://typo3.com/Feature_
Rozszerzenia TYPO3 możemy pobrać modyfikacje korzystając (jak zwykle) z ikony list.1243.0.html).
z repozytorium znajdującego się pod ad- przedstawiającej dyskietkę. Niezwykłą funkcją TYPO3, która poja-
resem http://typo3.org/extensions (ponad Musimy jeszcze zaktualizować sza- wiła się w wersji 4.0, jest logika przestrzeni
1400 dostępnych rozszerzeń) lub zapisać blon, aby uwzględnić w nim newsy. W tym roboczych (ang. workspace logic). Pozwa-
na serwerze, na którym są tworzone i prze- celu przechodzimy do menu List i edytuje- la ona na określenie przestrzeni, w której
słać je na serwer produkcyjny. Każde roz- my szablon Test. Następnie do listy roz- będzie zapisawana treść, np. brudnopis
szerzenie jest zarchiwizowane w postaci szerzeń Include static from extensions do- czekający na akceptację redaktora.
pojedynczego pliku .t3x, który zawiera mo- dajemy CSS-based tmpl (tt_news) i zapi- Zachęcamy Cię do poznawania TY-
dyfikacje bazy danych, pliki konfiguracyjne i sujemy przeprowadzone zmiany. PO3 krok po kroku: zacznij od urucho-
samą aplikację (jej logikę biznesową). Możemy teraz umieścić wiadomości mienia małej witryny, naucz się Typo-
na naszej witrynie: klikamy więc Page –> Script, wypróbuj TemplaVoila i zainstaluj
Dodajemy i uruchamiamy Test –> Create new record i wybieramy rozszerzenia, których potrzebujesz. Dzięki
system newsów typ rekordu newsów korzystając z formu- własnej praktyce szybko staniesz się mi-
Zainstalujmy system newsów z repozy- larza, który się pojawi po prawej. Następ- strzem obsługi TYPO3. n
torium TYPO3 (TER). Będziemy do tego nie wpisujemy tytuł, odhaczamy checkbox
potrzebowali połączenia z Internetem. Po- hide i wpisujemy treść wiadomości w polu
dobnie, jak miało to miejsce przy instala- Text (jeżeli checkbox hide jest niewidocz-
cji tt_board, musimy zacząć od kliknięcia ny (nie ma go pod polem tytułu), to prze- O autorze
opcji Ext Manager w menu po lewej stro- wijamy stronę do samego końca i zazna-
nie ekranu (sekcja Tools). W ramce, która czamy box Show secondary options). Na- Jean-Gael Rouchon jest dyrektorem
pojawi się po prawej stronie ekranu, wybie- stępnie zapisujemy naszą wiadomość kli- badań i rozwoju (R&D director) we
rzemy Menu: Import extensions. Po przeła- kając ikonę dyskietki z lupą (Save docu- francuskiej firmie ONEXT, która spe-
dowaniu strony, wpisujemy tt_news w polu ment and view page) – gotowe. System cjalizuje się w opensourcowych syste-
Lookup i klikamy przycisk Lookup. Powin- newsów w środowisku produkcyjnym (np. mach CMS tworzonych w PHP. Pracu-
na się pojawić pozycja News – kliknijmy na na portalu korporacyjnym) powinien mieć je nad TYPO3 od 2002 i współadmini-
czerwoną strzałkę z lewej strony tej nazwy. osobną stronę do wyświetlania wszystkich struje portalem typo3.fr
Od tej chwili musimy postępować zgodnie wiadomości, archiwum, itd. Moduł new- Kontakt:
z instrukcjami programu instalacyjnego, sów w TYPO3 pozwala na te operacje, jean-gael.typo3@rouchon.org
który zapyta o to, czy utworzyć tabelę ba- możemy też zmieniać sposób prezenta-
Freelancing – zostań
wolnym strzelcem
Stopień trudności: lll
Krzysztof Trynkiewicz
N
ajogólniej mówiąc, freelancing Wszystkie oferty są przydzielone do za-
to rynek zleceń. Choć istniał już kresów cenowych, począwszy od drob-
wcześniej, do jego rozwoju w naj- nych zadań za dziesięć dolarów, do du-
większym stopniu przyczyniły się wyspe- żych zleceń wykonania całych portali za
cjalizowane serwisy freelancingowe, w kwoty sięgające tysięcy dolarów. Mno-
których jedni zgłaszają swoje pomysły, gość i różnorodność ofert powoduje, że
a inni je wykonują. Nad przebiegiem re- nawet mgliste pojęcie o jakimś zagadnie-
alizacji projektu i przekazania wynagro- niu wystarczy, by podołać niektórym za-
dzenia czuwają administratorzy tych wi- daniom. Przykładowo, jeśli nasza wiedza
tryn, którzy są tym samym pośrednikami na temat PHP wystarcza do zrozumienia
w kontakcie zleceniodawców z wykonaw- cudzego kodu, możemy się śmiało podjąć
cami (zleceniobiorcami). zaktualizowania już zainstalowanej apli-
kacji (np. osCommerce czy XOOPS) lub
Różnorodność ofert
W SIECI Freelancing to nie tylko programowanie
w PHP lub innych językach. Przegląda- Co należy wiedzieć...
jąc witryny pośredników natkniemy się Przydatna będzie podstawowa znajo-
• http://allfreelance.com - mość terminologii biznesowej.
– kompendium linków na multum dziedzin, w których możemy
freelancingowych składać oferty oraz podejmować zada-
• http://guru.com
• http://rentacoder.com nia. Znajdziemy więc zlecenia na pisanie Co obiecujemy...
• http://getafreelancer.com programów, artykułów, tłumaczenie tek- Pokażemy, jak działa freelancing na
• http://zlecenia.przez.net
stów, dostosowywanie skryptów do po- przykładzie najpopularniejszych ser-
– polskojęzyczny serwis wisów, które go organizują.
freelancingowy trzeb klienta, tworzenie grafiki i reklam, a
nawet rozwiązywanie zadań domowych.
nąć takich sytuacji, czyli uniemożliwić po- wątpliwości. Jeżeli jednak wciąż pojawia- nień. Niewątpliwą zaletą takiego rozwią-
dejrzenie szczegółów projektu przez nie- ją się niejasności, możemy poprosić o ra- zania jest mniejsza konkurencja w przy-
uczciwych wykonawców, niektóre serwi- dę facilitatora – przedstawiciela specjal- padku składania przez nas ofert. Jeżeli
sy freelancingowe wprowadziły tzw. Umo- nego oddziału serwisu freelancingowego, jednak to my szukamy wykonawcy, war-
wę o nieujawnianiu informacji (ang. Non- przedstawiając naszą sytuację i podając to wziąć pod uwagę różne, nie tylko naj-
disclosure Agreement). Jeśli dajemy zle- link do naszej aukcji. większe serwisy – liczy się bowiem także
cenie w trybie zgodnym z tą umową, wy- prowizja, jaką będziemy musieli zapłacić
konawcy będą widzieć jedynie podstawo- Wybór serwisów pośrednikowi. Z pewnością mniejsza po-
we informacje o naszym projekcie – jego pośredniczących pularność nie oznacza gorszych wyko-
typ, zakres cenowy i wprowadzone przez W sieci znajdziemy wiele ofert pośredni- nawców, więc jeśli nie jesteśmy zbyt wy-
nas publicznie dostępne wytyczne. By uj- ków. Ważne jest, by wybrać serwis z re- bredni, możemy podjąć niewielkie ryzyko
rzeć szczegóły, wykonawca musi wyrazić nomą, działający legalnie i obsługują- i spróbować zaoszczędzić.
chęć ich poznania przez podpisanie po- cy opisane w artykule zabezpieczenia
wyższej umowy, my zaś możemy udo- przed nieuczciwością i niesolidnością. Freelancing w Polsce
stępnić mu tajne dane lub nie. Rent a Coder (http://rentacoder.com) ofe- Niestety, w chwili pisania artykułu freelan-
ruje wszystkie wspomniane udogodnienia cing w naszym kraju był słabo rozwinię-
Właściwy wybór i z pewnością ma wielką renomę. W chwi- ty. W zasadzie tylko jeden polski serwis
wykonawcy li pisania artykułu posiadał 2 tys. otwar- freelancingowy, http://zlecenia.przez.net,
Będąc zleceniodawcą, powinniśmy się tych projektów oczekujących na oferty, był wart uwagi i to wyłącznie ze wzglę-
dobrze zastanowić przed wyborem wyko- 150 tys. zarejestrowanych wykonawców du na ilość aukcji, gdyż niestety nie ofe-
nawcy naszego projektu. Naszej decyzji i 60 tys. zleceniodawców. Prym we fre- ruje on wielu opisanych przez nas zabez-
nie powinniśmy podejmować wyłącznie w elancingu wiedzie jednak inny serwis – pieczeń i udogodnień. Miejmy nadzieję,
oparciu o cenę, zwłaszcza w informatyce, Guru.com (http://www.guru.com/). Liczba że w najbliższym czasie sytuacja ta ule-
gdzie przykładowo koszty stron WWW zarejestrowanych tam wykonawców jest gnie zmianie.
oscylują między 50zł a tysiącami dola- dziesięciokrotnie większa niż w przypad-
rów. Dokonując wyboru najlepiej zwró- ku Rent a Coder (568 tysięcy). Co cieka- Podsumowanie
cić uwagę na to, jak wiele zadań wykonał we, zleceniodawców jest dwukrotnie mniej Jako programistom, freelancing daje nam
nasz potencjalny zleceniobiorca oraz ja- niż w poprzednim serwisie (30 tysięcy), ogromne możliwości zarobienia pieniędzy,
kie opinie wyrażali o nim poprzedni zlece- natomiast ilość otwartych projektów jest nawiązania kontaktów biznesowych, wyro-
niodawcy i jakie oceny mu wystawili. Po- kilkukrotnie większa. Serwis ten oferuje bienia sobie renomy i doskonalenia swoich
winniśmy też zajrzeć do portfolio i resume również kluczowe udogodnienia, jednak umiejętności. Jeśli natomiast potrzebujemy
wykonawcy, gdzie dowiemy się o umiejęt- w chwili pisania artykułu nie funkcjono- wykonawców naszego projektu, to dzię-
nościach i doświadczeniu nabytym przez wał omawiany w artykule depozyt bezpie- ki rozbudowanym serwisom freelancingo-
niego poza serwisem freelancingowym. czeństwa zleceniodawcy (Seller Guaran- wym mamy dużą szansę znaleźć najbar-
Warto też zwrócić uwagę na języki, któ- tee Deposit). Możemy się spodziewać, że dziej odpowiednie osoby. W obu przypad-
rymi posługuje się nasz potencjalny zle- zabezpieczenie to zostanie bardzo szybko kach, warto się dobrze zapoznać z różny-
ceniobiorca – jeśli wykonanie naszego wprowadzone. Z kolei w serwisie Elance mi ofertami oraz opiniami o zamawiających
zadania będzie wymagało częstych kon- (http://elance.com) znajdziemy ponad 100 czy wykonawcach. Istotne jest również po-
sultacji, na pewno łatwiej będzie dojść do tysięcy projektów i obszerne informacje i ważne podejście do spraw formalnych –
porozumienia w języku ojczystym. Jeżeli porady na temat zamawiania i świadcze- zastosowanie się do opisanych przez nas
obowiązuje nas deadline, najważniejszą nia usług (w tym wzory umów, m.in. Non- wskazówek pozwoli zmniejszyć ryzyko
wytyczną będzie doświadczenie. Warto disclosure agreement). Listy serwisów fre- wystąpienia niemiłych niespodzianek czy
też zamieścić informację, że do jednego elancingowych znajdziemy pod adresami wręcz natknięcia się na oszusta. Życzymy
projektu możemy przydzielić kilku wyko- http://www.phpkitchen.com/index.php?/ udanych interesów! n
nawców. archives/670-PHP-Freelance.html (uwaga
Nie powinniśmy też zatrudniać wyko- – są tu również typowe serwisy do wyszu-
nawcy, który robił dotychczas projekty za kiwania ofert pracy, np. monster.com czy
stawki wielokrotnie niższe niż oferowane mojolin.com) oraz http://allfreelance.com
przez nas, gdyż ich waga i złożoność mu- (All Freelance). Pamiętajmy jednak, że O autorze
siała być znacznie mniejsza. Jeśli jednak oprócz dużych i często wykorzystywa-
mamy więcej czasu, niż pieniędzy, to mo- nych serwisów, znajdują się tam również Krzysztof Trynkiewicz od wielu lat zaj-
muje się tworzeniem witryn w PHP i
żemy rozważyć zatrudnienie początkują- takie, które niedawno zaczęły swoją dzia-
Flash. Współpracuje z magazynem PHP
cego freelancera – ostatecznie i tak po- łalność lub nie są zbyt popularne. Solutions, wykonuje także zlecenia fre-
siadamy zabezpieczenie naszych finan- Jeśli szukamy zleceń do wykona- elancingowe. Obecnie rozwija kilka rów-
sów w postaci escrow. Serwisy pośredni- nia, możemy zajrzeć również na ta- noległych projektów autorskich dostęp-
nych na witrynie http://eldoras.com.
czące oferują często możliwość komuni- kie serwisy, jak Get A Freelancer (http://
kacji z wykonawcami jeszcze przed za- getafreelancer.com/), który posiada bazę Kontakt z autorem:
akceptowaniem ich ofert w celu określe- kilku tysięcy otwartych projektów i może chris.trynkiewicz@gmail.com
nia szczegółów i wyjaśnienia wszelkich być przydatny mimo braku wielu udogod-
Z
end API jest interfejsem progra- CodeGen_PECL
misty, pozwalającym pisać roz- – przygotowujemy się
szerzenia dla PHP w języku C. do pracy
Do pisania bardzo prostych rozszerzeń Stworzenie rozszerzenia całkowicie samo-
W SIECI wystarczy podstawowa znajomość tego dzielnie jest zadaniem bardzo skompliko-
języka – jak zobaczycie dalej, dostęp- wanym i żmudnym. Szczególnie począt-
ne są narzędzia generujące cały szablon kowy etap implementacji jest dość złożo-
l http://www.php.net/manual/ takiego rozszerzenia za nas – jednak do ny. Na szczęście dziś w większości przy-
en/internals.php – informacje
na temat Zend API znajdują- pisania bardziej zaawansowanych pro- padków nie musimy się już o to martwić.
ce się w oficjalnej dokumen- gramów, potrzebna jest dobra znajomość Wystarczy na przykład skorzystać z Co-
tacji PHP – niestety dość
skromne C oraz zacięcie detektywistyczne, z po- deGen_PECL. Skrypt ten na podstawie
l http://somabo.de/talks/ wodu bardzo słabej dokumentacji niektó- pliku XML, w którym opisujemy tworzone
-- materiały z różnych kon-
rych elementów Zend API. Nie obejdzie- rozszerzenie, generuje dla nas wszystkie
ferencji dotyczących PHP
– znajdują się tu także dwie my się więc bez konieczności analizo-
dobre prezentacje porusza- wania źródeł rozszerzeń dostarczanych
jące problem rozszerzeń dla Co należy wiedzieć...
PHP standardowo z PHP. Potrzebna będzie podstawowa znajo-
l http://www.zend.com/php/ Na potrzeby tego artykułu wspólnie mość języka C i PHP.
internals/extension-writin-
g1.php – pierwsza część tu- stworzymy rozszerzenie wzbogacające
toriala na temat pisania roz- PHP o funkcję pozwalającą obliczać pro- Co obiecujemy...
szerzeń z wykorzystaniem Z artykułu dowiesz się, jak z wykorzy-
ste wyrażenia matematyczne – zawierają-
Zend API
l http://www.zend.com/php/ ce podstawowe operacje takie jak =, -, *, staniem Zend API zbudować przykła-
internals/extension-writin- dowe rozszerzenie dla PHP pozwala-
czy /. Będzie można także do woli korzy-
g2.php – druga część po- jące na wykonywanie prostych opera-
wyższego tutoriala stać z nawiasów okrągłych ( ), a także cji matematycznych.
kwadratowych [ ].
15 5 – 2 /
Opisujemy rozszerzenie za po-
mocą XML-a Więcej na temat ONP oraz algorytmów przekształcenia wyrażenia z zapisu in-
fiksowego (tradycyjnego) do ONP oraz algorytmów pozwalających na obliczenie
Gdy mamy już zainstalowany skrypt
tak przekształconego wyrażenia znaleźć można na przykład w Wikipedii: http://
CodeGen_PECL, możemy przystąpić do two- pl.wikipedia.org/wiki/Odwrotna_notacja_polska
rzenia pliku XML z opisem naszego roz-
szerzenia.
Cały opis rozszerzenia umieszcza się Skrypt CodeGen_PECL na podstawie in- <description>. Autorzy skryptu Code-
w znaczniku <extension>. Przyjmuje on formacji z pliku XML potrafi wygenero- Gen_PECL zalecają umieszczanie obu
jeden parametr będący nazwą tworzone- wać tabelkę z informacjami, która ukaże tych znaczników zaraz pod otwierają-
go rozszerzenia. Nasze rozszerzenie na- się na stronie zwracanej przez phpinfo(). cym znacznikiem <extension>.
zwiemy RPN – od Reverse Polish Nota- Nazwę rozszerzenia skrypt pobiera z pa- Za umieszczenie informacji o au-
tion – nazwy sposobu, w jaki będzie liczy- rametru name znacznika <extension>. Je- torach rozszerzenia odpowiada znacz-
ło wyrażenie (będzie ono zamieniane do śli chcemy w phpinfo() umieścić krótką nik <maintainers>, zawierający tag
postaci Odwrotnej Notacji Polskiej, a na- informację o rozszerzeniu (podsumowa- <maintainer> opisujący każdego z auto-
stępnie obliczane – więcej na temat ONP nie), należy ją umieścić wewnątrz znacz- rów (Listing 1). Na taki opis składa się je-
w ramce Odwrotna Notacja Polska). Opis nika <summary>: go nazwa (może to być np. nick) umiesz-
rozszerzenia umieszczamy zatem we- czona w znaczniku <user>, imię i nazwi-
wnątrz następującego bloku: <summary> sko umieszczone w znaczniku <name>,
Przykładowe rozszerzenie PHP - RPN e-mail umieszczony w znaczniku <email>
<extension name=”RPN”> </summary> oraz rola jaką on odgrywa w zespole ludzi
<!—tutaj będzie umieszczony pracujących nad rozszerzeniem umiesz-
opis rozszerzenia--> Główną informację o rozszerzeniu na- czona w znaczniku <role>. Znacznik
</extension> leży analogicznie umieścić w bloku <maintainers> może oczywiście zawierać
CodeGen_PECL
Skrypt CodeGen_PECL można zna-
leźć w repozytorium PEAR. Poprzed-
nio nosił on nazwę PECL_Gen i był
częścią repozytorium PECL. Skrypt
ten w znacznym stopniu ułatwia two-
rzenie rozszerzeń dla języka PHP, ge-
nerując na podstawie XML-a komplet-
ne szablony rozszerzeń. Dokumen-
tacja CodeGen_PECL znajduje się
pod adresem http://php-baustelle.de/
CodeGen_PECL/manual.htm, same
rozszerzenie zaś można pobrać albo
za pomocą programu pear wchodzą-
cego w skład PHP albo ze strony http:
//pear.php.net/package/CodeGen_
PECL/download.
Na Rysunku 1 znajduję się informacja Tabela 1. Typy danych dozwolone w opisach prototypów funkcji w pliku XML
phpinfo() o naszym rozszerzeniu. Nazwa typu Opis
Skrypt CodeGen_PECL zawsze sam
bool Typ logiczny przyjmujący wartości true oraz false
dodaje ramkę z informacjami o zmiennych
wymaganych przez rozszerzenie, ustawia- int Typ numeryczny – całkowity
nych z poziomu pliku php.ini. float Typ numeryczny – zmiennoprzecinkowy
Przyszedł czas na to, aby zastano- string Ciąg znaków – napis
wić się, jakie funkcje będą potrzebne array Tablica
w naszym rozszerzeniu. Niech będą to
object Obiekt
rpn_calculation() obliczająca wartość
mixed Nieokreślony jednoznacznie typ danych
wyrażenia, rpn_errormsg() wyświetlają-
ca ewentualną informację o błędzie oraz callback Funkcja zwrotna
rpn_error zwracająca true/false w zależ- resource Zasoby
ności od tego, czy błąd wystąpił nie. Tylko stream Strumień danych
funkcja rpn_calculation będzie przyjmo-
wała parametr, wszystkie natomiast będą W opisach funkcji można bezpośred- leży korzystać z sekcji CDATA, aby parser
zwracały wartości. Opiszmy więc w XML-u nio umieszczać kod w języku C. Dla przy- XML ignorował błędy XML, jakie mogły-
funkcje tak, aby skrypt CodeGen_PECL kładu w pliku XML umieściłem kod dla by powodować znaki umieszczone w ko-
mógł dla nas wygenerować ich szablony specjalnych funkcji Zend API: RINIT oraz dzie. Ze znacznika <code> możemy ko-
do wypełnienia kodem. Posłużymy się w RSHUTDOWN. Funkcje te są wywoływane au- rzystać także w funkcjach deklarowanych
tym celu znacznikiem <function>, przyj- tomatycznie odpowiednio przed oraz po przez nas samych (np. w naszych funk-
mującym parametr name, będący nazwą wykonaniu skryptu PHP lub w przypad- cjach rpn_calculation, rpn_errormsg i
tworzonej funkcji. Sama nazwa to jed- ku skryptów CGI / CLI zaraz po wystarto- rpn_error). Jest to wygodne w przypad-
nak za mało. Musimy jeszcze zdeklaro- waniu PHP (dokładniejszy opis wszystkich ku kodu tak prostego jak na Listingu 4,
wać prototyp funkcji, zawierający dodatko- funkcji systemowych znajduje się w Tabe- jednak gdy kod staje się bardziej złożony
wo informację o typie zwracanych danych li 2). Jeśli chcemy zdefiniować ciało funk- (taki jak np. kod funkcji rpn_calculation)
oraz nazwie i typie przyjmowanych para- cji specjalnej, trzeba użyć parametru rolę wygodniej jest kazać skryptowi CodeGen_
metrów. Na Listingu 3 znajduje się przy- znacznika <function>, ustawiając go na PECL wygenerować jedynie szablon funk-
kład opisujący nasze trzy funkcje. wartość internal, nazwę funkcji zaś usta- cji, a cały kod napisać w ulubionym edyto-
Jak widzimy owe prototypy funk- wić na jedną z wartości z Tabeli 2. Na Li- rze lub środowisku programistycznym.
cji – umieszczone w znaczniku <proto> stingu 4 znajduje się przykładowa deklara- Na koniec pozostało zdeklarowanie
– przypominają deklaracje funkcji w C. cja ciał funkcji RINIT oraz RSHUTDOWN. zmiennych ustawianych z poziomu pli-
Różnią się jednak one nazwami typów. Zauważmy, że kod funkcji został ku php.ini. W naszym przypadku zmien-
Dozwolone nazwy typów zebrane zosta- umieszczony w znaczniku <code> oraz za- ne te będą określały rozmiar stosu oraz
ły w Tabeli 1. mknięty w sekcji CDATA języka XML – na- kolejki wykorzystywanych podczas prze-
kształcania wyrażenia matematyczne-
Listing 4. Deklaracja ciał funkcji bezpośrednio w pliku XML go do Odwrotnej Notacji Polskiej oraz do
późniejszego przeprowadzenia obliczeń.
<function role="internal" name="RINIT"> Zmienne te będą nosiły odpowiednio na-
<code> zwy rpn_stack_size oraz rpn_queue_size.
<![CDATA[
Zmienne ustawiane z poziomu php.ini de-
memset(errorMessage, 0, 255);
isError = 0; finiuje się w bloku <globals>, korzystając
ze znacznika <phpini>. Znacznik <phpini>
int s = RPN_G(rpn_stack_size); przyjmuje 5 parametrów:
stack_initialize(s);
System Wartość zmiennej może być ustawiona w pliku php.ini lub konfiguracji
serwera HTTP Jeśli wszystko się udało, skrypt powinien
utworzyć nowy katalog o nazwie takiej,
Perdir Wartość zmiennej może być ustawiona w pliku .htaccess
jak nasze rozszerzenie, a w nim wszyst-
User Wartość zmiennej może być zmieniona w kodzie PHP
kie niezbędne pliki. Czas więc zacząć pro-
All Wartość zmiennej może być zmieniona w jakimkolwiek z wymienionych gramowanie!
wyżej miejsc.
Piszemy program
użyta zostanie standardowa metoda części artykułu – niestety skrypt Co- Przyjrzyjmy się teraz zawartości wygene-
OnUpdateString. Możemy tu zastoso- deGen_PECL w tym już nie umie po- rowanego przez skrypt katalogu. Wśród
wać metodę o nazwie OnUpdateTYP, móc), wielu plików znajdują się tam dwa w tej
gdzie TYP to nazwa typu z Tabeli 1 • access – informacja o tym, gdzie użyt- chwili dla nas najistotniejsze – RPN.c oraz
(pisana z dużej litery). Można także kownik może ustawić wartość danej php_RPN.h. Otwórzmy teraz plik RPM.c,
podać nazwę własnej funkcji, jednak zmiennej – parametr ten może przy- bo nim będziemy się zajmowali, a na-
trzeba ją wówczas samemu zdefinio- jąć jedną z wartości zebranych w Ta- stępnie odszukajmy po nazwie funkcję
wać (więcej na ten temat w dalszej beli 3. rpn_calculation.
Funkcja
Listing 5. Deklaracja zmiennych o wartości modyfikowalnej z poziomu pliku php.ini
rpn_calculation znajduje się w dwóch
<globals> miejscach – najpierw w tablicy RPN_
<phpini name="rpn_stack_size" type="int" value="50" functions, a następnie już jako defini-
onupdate="OnUpdateLong" access="perdir"> cja funkcji (definicja nie przypomina Wam
Stack size used for calculations.
zapewne języka C – o tym jednak w dal-
</phpini>
szej części artykułu) – nie licząc komenta-
<phpini name="rpn_queue_size" type="int" value="150" rzy, które dodawał po drodze CodeGen_
onupdate="OnUpdateLong" access="perdir"> PECL. Jak można zauważyć, w tablicy
Queue size used for calculations. zdefiniowane są wszystkie trzy funkcje
</phpini>
naszego rozszerzenia – Listing 6. Ele-
</globals>
menty tablicy opisującej funkcje są ty-
Listing 6. Definicja funkcji oferowanych przez rozszerzenie pu function_entry, który jest strukturą o
trzech polach. Nas jednak nigdy nie bę-
function_entry RPN_functions[] = { dą one interesowały. Do zdefiniowania
PHP_FE(rpn_calculation , NULL)
funkcji będziemy używali skryptu Code-
PHP_FE(rpn_errormsg , NULL)
PHP_FE(rpn_error , NULL) Gen_PECL, tak jak to zostało już zapre-
{ NULL, NULL, NULL } zentowane albo makra – np. PHP_FE, tak
}; jak to robi CodeGen_PECL. Jako że cza-
sami prawdopodobnie będziemy musieli
samodzielnie dodać jakąś funkcję do roz- Tabela 4. Makra służące do definiowania funkcji
szerzenia, powinniśmy zapoznać się z Nazwa Makra Opis
makrami ułatwiającymi to zadanie. W Ta-
ZEND_FE(name, arg_types) Definicja funkcji o nazwie name. Parametr
beli 4 zostały zebrane wszystkie makra
arg_types powinien być zawsze ustawio-
wspomagające samodzielne definiowa- ny na NULL. Zdeklarowana w ten sposób
nie funkcji. Należy pamiętać, że ostatnim funkcja będzie widoczna w PHP pod na-
elementem tablicy z Listingu 6 musi być zwą name, natomiast odwoływała się bę-
{NULL, NULL, NULL}. dzie do funkcji C zif_name
Sama deklaracja funkcji jest dość ZEND_NAMED_FE(php_name, name, Definicja funkcji widocznej w PHP pod
nietypowa jak na język C. Do deklaracji arg_types) nazwą php_name natomiast odwołująca
wykorzystano makro PHP_FUNCTION ko- się do funkcji C o nazwie name. Makro
to powinno być używane wówczas, gdy
respondujące z makrem PHP_FE (gdy ko-
nie chcemy, aby makro ZEND_FE auto-
rzystasz z makr z serii ZEND, do deklara- matycznie nadawało prefix naszym funk-
cji funkcji należy użyć analogicznego do cjom. Tak jak poprzednio parametr arg_ty-
PHP_FUNCTION makra ZEND_FUNCTION). Jak pes powinien być ustawiony na NULL
widać na Listingu 7, nie zostało tu w ty- ZEND_FALIAS(name, alias, arg_types) Makro to definiuje alias o nazwie alias do
powy sposób określone jakie, ani nawet funkcji PHP o nazwie name. arg_types
ile parametrów przyjmuje funkcja. Na powinno być ustawione na wartość NULL.
szczęście istnieje makro ZEND_NUM_ARGS PHP_FE(name, arg_types) Stary odpowiednik makra ZEND_FE
zwracające liczbę parametrów przeka- PHP_NAMED_FE(runtime_name, name, Stary odpowiednik makra ZEND_NA-
zanych do funkcji. Można je wykorzy- arg_types) MED_FE
stać do sprawdzenia, czy przekazana ze
skryptu PHP liczba argumentów jest po- Pierwszym argumentem jest liczba pa- • b –określa, że zmienna na pozycji te-
prawna. Jeśli nie, należy wywołać makro rametrów przekazanych do funkcji pod- go znaku ma być typu boolean,
WRONG_PARAM_COUNT, które kończy działa- czas jej wywołania, drugi to łańcuch • r – określa, że zmienna na pozycji te-
nie funkcji, informacją o błędzie zbliżo- znaków opisujący typ parametrów ocze- go znaku ma wskazywać na zasób
ną do tej: kiwanych przez funkcję, dalej są to już (ang. resource) – zwraca wartość ty-
zmienne, w których mają zostać zapisa- pu zval*,
Warning: Wrong parameter count for ne parametry. Ważny jest tu drugi para- • a – określa, że zmienna na pozycji
rpn_calculation in metr, czyli łańcuch znaków opisujący tego znaku ma być tablicą – zwraca
/home/marcin/public_html/test.php parametry. Łańcuch ten może składać wartość typu zval*,
on line 3 się z następujących znaków: • o – określa, że zmienna na pozycji te-
go znaku ma być obiektem dowolnej
Kod wygenerowany przez Code- • l – określa, że zmienna na pozycji klasy – zwraca wartość typu zval*,
Gen_PECL do parsowania parame- tego znaku ma być typu long, • O – określa, że zmienna na pozycji te-
trów podanych podczas wywołania funk- • d – określa, że zmienna na pozycji go znaku ma być obiektem takiej sa-
cji z poziomu skryptu PHP używa funkcji tego znaku ma być typu double, mej klasy jak klasa kolejnego parame-
zend_parse_parameters. Jest to funkcja o • s – określa, że zmienna na pozy- tru na liście wywołania funkcji zend _
zmiennej liczbie parametrów. Jej nagłó- cji tego znaku ma być typu string parse _ parameters (parametr ten nie
wek wygląda następująco: – oprócz napisu, funkcja zend _ będzie używany do przechowywania
parse _ parameters zwraca także wartości kolejnego parametru przeka-
int zend_parse_parameters jego długość (do kolejnego parametru zanego do skryptu PHP – w tym celu
( int num_args TSRMLS_DC, na liście parametrów wywołania funk- użyty zostanie kolejny parametr z li-
char* type_spec, ... ) cji zend _ parse _ parameters), sty parametrów) – zwraca wartość ty-
pu zval*,
• z – parametr dowolnego typu – zwra-
Listing 7. Deklaracja funkcji rpn_calculation
ca wartość typu zval*,
PHP_FUNCTION(rpn_calculation) • | (pionowa kreska) – oznacza, że na-
{ stępne parametry są opcjonalne,
const char * phrase = NULL;
• / – oznacza, że wartość poprzednie-
int phrase_len = 0;
go parametru ma zostać skopiowana,
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s/", a nie przekazana przez referencję,
&phrase, &phrase_len) == FAILURE) { • ! – oznacza, że poprzedni parametr
return; może przyjmować wartość NULL .
}
php_error(E_WARNING, "rpn_calculation: not yet implemented"); RETURN_FALSE;
Najwięcej wątpliwości może nasuwać
RETURN_DOUBLE(0.0); wartość O oraz s, gdyż korzystają one z
} dwóch parametrów. Skorzystanie z war-
tości s, jak widać na Listingu 7, powodu-
Tabela 5. Makra zwracające wartość z funkcji – należy używać w tworzonych funkcjach, Często przydatne i ułatwiające wie-
zamiast typowych instrukcji return wartosc le zadań może okazać się wywołanie z
Makro Opis poziomu naszego rozszerzenia jednej z
funkcji PHP. Nie da się tego zrobić w spo-
RETURN_RESOURCE(resource) Zwraca wskaźnik do zasobów
sób naturalny, tak jak zrobilibyśmy to wy-
RETURN_BOOL(bool) Zwraca typ logiczny wołując funkcje napisane w C. Na szczę-
ście dostępna jest w Zend API funkcja
RETURN_NULL() Zwraca wartość NULL call_user_function. Oto jej nagłówek:
RETURN_STRING(string, duplicate) Zwraca napis – drugi parametr określa, zval* retval_ptr, zend_uint param_count,
czy napis ma zstać zduplikowany zval* params[] TSRMLS_DC )
wnętrznych Zend API, definicja funkcji Czasami zdarza się, że chcielibyśmy tości queue_size, musimy jej nazwę
realizowana jest z wykorzystaniem od- napisać własną funkcję wykonywaną auto- umieścić jako czwarty parametr makra
powiednich makr. Makra te noszą na- matycznie podczas zmiany wartości zmien- STD_PHP_INI_ENTRY. Jako że często po-
zwy PHP_nazwaFunkcji_FUNCTION, gdzie nej z php.ini. Jest to zadanie bardzo proste trzebna może być nam także długość
nazwa funkcji to odpowiednio MINIT, i sprowadza się do użycia odpowiedniego nowej wartości (np. gdy jest to napis),
MSHITDOWN, RINIT, RSHUTDOWN oraz makra podczas tworzenia funkcji: poniżej przedstawiamy definicję makra
MINFO. Funkcja MINFO została już praw- PHP_INI_MH:
dopodobnie wystarczająco dobrze wy- PHP_INI_MH(OnChangeQueueSize)
generowana przez skrypt, można jed- { #define PHP_INI_MH (name)
nak się jej przyjrzeć i w razie konieczno- zend_printf("Wartość RPM.rpn_queue_size int name(php_ini_entry *entry,
ści zmodyfikować wygenerowany kod. to %s<br>", new_value); char *new_value,
Nasze rozszerzenie wykorzystuje dodat- return SUCCESS; uint new_value_length,
kowo funkcje RINIT oraz RSHUTDOWN do } void *mh_arg1,
zainicjowania stosu oraz kolejki wyko- void *mh_arg2, void *mh_arg3)
rzystywanej podczas obliczeń (RINIT), a Jak widać, nowa wartość przekazywa-
następnie zwolnienia wykorzystywanych na jest w zmiennej new_value. Oczy- Poszczególne parametry funkcji stworzo-
przez te struktury zasobów (RSHUTDOWN). wiście, aby funkcja ta była automa- nej za pomocą tego makra, to odpowied-
Jeśli dobrze pamiętamy, ciało tych funk- tycznie wywoływana po zmianie war- nio – struktura opisująca zmienną, nowa
cji zostało określone jeszcze na pozio-
mie pliku XML. Listing 9. Struktura opisująca nasze rozszerzenie oraz funkcje wewnętrzne Zend
API
Zmienne php.ini
Do pełni szczęścia brakuje nam jesz- zend_module_entry RPN_module_entry = {
STANDARD_MODULE_HEADER,
cze umiejętności odczytywania wartości
"RPN",
zmiennych konfigurowalnych z poziomu RPN_functions,
pliku php.ini. Zmienne te są deklarowane PHP_MINIT(RPN),
z wykorzystaniem makr (Listing 11). PHP_MSHUTDOWN(RPN),
Makro STD_PHP_INI_ENTRY infor- PHP_RINIT(RPN),
PHP_RSHUTDOWN(RPN),
muje PHP, która globalna zmienna ma
PHP_MINFO(RPN),
być modyfikowana z poziomu pliku "0.0.1",
php.ini – zajrzyjmy do pliku nagłówko- STANDARD_MODULE_PROPERTIES
wego php_RPN.h, tam są zdeklarowane };
zmienne globalne. Parametry makra, to
Listing 10. Struktura zend_module_entry
odpowiednio: nazwa zmiennej, pod ja-
ką ma ona być modyfikowana z pozio- typedef struct _zend_module_entry zend_module_entry;
mu pliku php.ini; wartość zmiennej, jaka
ma zostać użyta, gdy nie zostanie ona struct _zend_module_entry {
unsigned short size;
nadana w pliku php.ini; sposób dostępu
unsigned int zend_api;
do zmiennej (możliwe wartości to PHP_ unsigned char zend_debug;
INI_SYSTEM, PHP_INI_USER, PHP_INI_ALL unsigned char zts;
oraz PHP_INI_PERDIR – Tabela 3). Ko- char *name;
lejny parametr jest nazwą metody, któ- zend_function_entry *functions;
int (*module_startup_func)(INIT_FUNC_ARGS);
ra ma zostać wywołana w momencie
int (*module_shutdown_func)(SHUTDOWN_FUNC_ARGS);
zmiany wartości zmiennej. Dostępne int (*request_startup_func)(INIT_FUNC_ARGS);
są standardowe funkcje obsługi zdarze- int (*request_shutdown_func)(SHUTDOWN_FUNC_ARGS);
nia aktualizacji. Posiadają one nazwy void (*info_func)(ZEND_MODULE_INFO_FUNC_ARGS);
OnUpdateTyp, gdzie typ to odpowiednia char *version;
[pozostałe elementy struktury]
nazwa typu zmiennej – Long, String,
};
Bool, Double itd. Piąty parametr makra
to zmienna globalna, która ma otrzymać Listing 11. Zmienne konfigurowalne deklarowane z wykorzystaniem makr będą
wartość zmiennej z pliku php.ini. Osta- odczytywane z poziomu php.ini
nie dwa parametry są strukturami opi-
PHP_INI_BEGIN()
sującymi zmienne globalne naszej apli-
STD_PHP_INI_ENTRY("RPN.rpn_stack_size", "50", PHP_INI_PERDIR,
kacji – nie musimy się nimi przejmować, OnUpdateLong, rpn_stack_size, zend_RPN_globals, RPN_globals)
gdyż nawet jeśli chcemy ręcznie dodać STD_PHP_INI_ENTRY("RPN.rpn_queue_size", "150", PHP_INI_PERDIR,
zmienną modyfikowaną z poziomu pliku OnUpdateLong, rpn_queue_size, zend_RPN_globals, RPN_globals)
php.ini, ostatnie dwa parametry pozo- PHP_INI_END()
N
a szczęście mamy kontener IoC dową implementacją zostanie jak w przy-
(ang. Inversion of Control), któ- padku poprzednich artykułów umieszczo-
ry już niejednokrotnie gościł na ny na stronie http://flexi.sf.net/.
łamach PHP Solutions. Czytelnicy, którzy
znają poprzednie artykuły, wiedzą już, co Czym jest kontener IoC?
mniej więcej potrafi IoC: kontener zapew- Kontener IoC to nic innego jak konfigu-
ni nam graf przygotowanych do użycia rowalna fabryka obiektów, która potra-
W SIECI obiektów czy np. umożliwi łatwe konfigu- fi nie tylko powołać obiekty do życia, ale
rowanie dekoratorów. także je skonfigurować tak, aby zaraz po
powołaniu były gotowe do użycia. O tym,
http://en.wikipedia.org/wiki/
Nie dzwoń do nas, my
l
l
wood Principle
http://www.theserverside.
zadzwonimy do Ciebie metodach składania obiektów, można pi-
com/tt/articles/article.tss?l=I Powyższe zdanie to dobrze znane progra- sać książki. Wbrew pozorom jest to pro-
OCBeginners – wprowadze- mistom tzw. prawo Hollywood (ang. Holly- ces dość skomplikowany i jeżeli robiony
nie do Dependency Injection
l http://www.martinfowler.com/
wood Principle). W myśl tego paradygma-
articles/injection.html tu tworzy się oprogramowanie spójne, z
– Inversion of Control
Containers/Dependency In-
luźnymi powiązaniami pomiędzy obiekta- Co należy wiedzieć...
mi, łatwe do testowania i utrzymania. Potrzebna będzie znajomość obiektowe-
jection pattern
http://picocontainer.codeha go programowania w PHP.
l
W obecnym artykule z cyklu Wzorce
us.org/ – implementacja IoC
projektowe i dobre praktyki programistycz-
l
dla Javy
http://flexi.sf.net/ – budowa- ne wspólnie stworzymy prosty kontener
Co obiecujemy...
ny przez nas framework, peł- Z artykułu dowiesz się, jak stworzyć
ne źródła omawiane w arty-
IoC, którego działanie w dużym uprosz- własny kontener IoC w myśl paradyg-
kule czeniu opiera się na wspomnianym prawie matu Hollywood Principle.
Hollywood. Kod kontenera wraz z przykła-
jest niewłaściwie, może spowodować, że cję klasy odpowiadającej za zarządzanie Pamiętajmy, że relacje pomiędzy obiekta-
aplikacja, którą napiszecie będzie bardzo użytkownikami. O tym, jak to zrobić, do- mi pojawiają się dopiero w momencie uru-
trudna w utrzymaniu. Istnieje wiele spraw- wiecie się już za chwilę. chomienia aplikacji. Słabe wiązanie powo-
dzonych wzorców pokazujących, jak po- Należy jeszcze powiedzieć o innej, duje też, że klasy są bardziej elastyczne i
prawnie składać obiekty. Zachęcamy do bardzo ważnej zalecie IoC. Dzięki IoC generyczne, co oznacza, że można je wy-
przeczytania artykułu Obiektowa linia obiekty są słabo ze sobą powiązane, a korzystywać w większej ilość przypadków.
montażowa, czyli przejrzyste i elastyczne przez to łatwiejsze w testowaniu przy po- Wracając teraz do naszego przykładu,
aplikacje w PHP5, który ukazał się w PHP mocy Unit Testów (testów jednostkowych). można byłoby stworzyć klasę do uwierzy-
Solutions nr 2/2006 i jest poświęcony te-
mu zagadnieniu.
Zastosowanie kontenera IoC do skła-
dania obiektów w funkcjonalne grupy może ������� ������� �������
znacznie ułatwić budowanie i testowanie
złożonych aplikacji. Budowanie dlatego,
że obiekty komponujemy w funkcjonalne
grupy dopiero podczas uruchamiania apli-
kacji. Oznacza to, że praktycznie w do-
wolnym momencie życia aplikacji może-
������� �������
my wymieniać klasy, z których składa się
dana aplikacja. Taka wymiana potrafi być
oczywiście bardzo trudna, w szczególno-
ści jeżeli nie stosujemy pisania do inter-
fejsów i silnego typowania. Od pewnego
czasu jednak obie te funkcjonalności do-
stępne są w PHP, dlatego powinniśmy je
�������
stosować.
nie pliku konfiguracyjnego zostanie wy- tami możemy być prawie pewni, że bę- z definicji znajdujących się w pliku konfi-
dzielone do osobnych klas tak, aby każ- dziemy mieli z tym do czynienia. Konte- guracyjnym.
dy mógł łatwo zmienić format i źródło da- ner, który napiszemy, będzie jedynie po- Istnieje jeszcze jedna metoda wiąza-
nych konfiguracyjnych. W szczególno- siadał opcję samego składania obiektów nia obiektów bardzo podobna do autowią-
ści można stworzyć plik konfiguracyjny
w oparciu o XML i Xschema, a do budowy Listing 4. Implementacja klas mapujących plik konfiguracyjny do modelu
plików konfiguracyjnych wykorzystywać obiektowego – klasa DefaultParamMap
jakieś graficzne narzędzie, które dodatko-
wo będzie za nas sprawdzać poprawność <?php
private $className;
class A { private $classFile;
public setB($b){} private $isSingleton;
} private $propertiesParams = array();
private $constructorParams = array();
public function __construct( $className, $classFile, $isSingleton ) {
Przy takiej budowie klasy i zastosowaniu
$this->setName($className);
trzeciej metody składania obiektów kon- $this->setClassFile($classFile);
tener IoC sprawdzi, czy klasa ma jakiś $this->isSingleton = $isSingleton;
setter badając, czy zawiera metody roz- }
poczynające się od słowa set a następ- public function getName() {
return $this->className;
nie sprawdzi, czy ma zarejestrowane w
}
pliku konfiguracyjnym klasy, których na- protected function setName($className) {
zwa pokrywa sie z pozostałą częścią na- $this->className = $className;
zwy settera, w naszym przypadku jest to }
klasa B. Ta metoda również niesie ze so-
public function getClassFile() {
bą pewne niebezpieczeństwo. Musimy
return $this->classFile;
uważać na konwencję nazywania sette- }
rów, gdyż w przypadku pomyłki w nazwie
możemy dostać obiekt, którego wcale protected function setClassFile( $classFile ) {
nie chcieliśmy. if ( !file_exists( $classFile ) ) {
throw new Exception("Plik {$classFile} nie istnieje");
Mając zdefiniowane założenia do bu-
}
dowy kontenera, zdefiniujmy teraz struktu- $this->classFile = $classFile;
rę pliku konfiguracyjnego. }
blice asocjacyjne. Konfiguracja, którą cjacyjnej, każdy klucz tej tablicy jedno- • properties – tablica asocjacyjna, w
będzie zarządzał programista, będzie znacznie identyfikuje obiekt. Na posta- której kluczem jest nazwa atrybutu
znajdować się w specjalnej tablicy, która wie tego identyfikatora z kontenera będą obiektu, a wartością zmienna, któ-
następnie będzie tłumaczona na zestaw pobierane obiekty. Zwróćmy uwagę, że rą należy podstawić pod ten atry-
obiektów przez specjalną klasę parsują- w jednym pliku można zdefiniować wie- but, w przypadku stałych znakowych
cą. Na tych obiektach będzie operował le konfiguracji dla jednej klasy, wystar- lub liczbowych wpisujemy tu ich
nasz kontener. Dzięki takiemu podej- czy, aby były one identyfikowane przez wartość, w przypadku referencji do
ściu łatwo będziemy mogli zmieniać for- inne klucze w tablicy. Pod identyfikato- obiektów wpisujemy znak & i identy-
maty i źródła danych konfiguracyjnych, rem obiektu znajduje się kolejna tablica fikator obiektu zdefiniowany w konte-
a w ekstremalnych sytuacjach będziemy asocjacyjna, która ma jasno zdefiniowa- nerze IoC,
mogli konfigurować kontener nie posia- ny zestaw kluczy: • constructorParams – tablica z pa-
dając w ogóle plików konfiguracyjnych. rametrami przeznaczonymi dla kon-
Listing 1 przedstawia wycinek skryp- • className – nazwa klasy, struktora obiektu, tym razem nie jest
tu index.php. Możemy tu znaleźć dwie • file– położenie pliku z definicją klasy, to tablica asocjacyjna, znaczenie ma
sekcje: jedna bardzo długa, konfiguru- • singleton – flaga mówiąca, czy w niej kolejność umieszczanych war-
jąca obiekty i druga znacznie krótsza, obiekt ma zostać utworzony tyl- tości, będą one w tej samej kolejności
uruchamiająca front kontroler. Teraz ko raz i potem umieszczony w ca- umieszczone w konstruktorze pod-
przyjrzyjmy się Listingowi 2, gdzie znaj- che'u, czy też za każdym razem czas powoływania obiektu do życia,
duje się ten sam skrypt index.php, jed- ma być tworzona kolejna instancja zasady wpisywania parametrów są
nak tym razem konfigurację obiektów i obiektu, takie same jak powyżej.
ich powołanie do życia przejął na sie-
bie kontener IoC. Już na pierwszy rzut
oka widać, że skrypt jest dużo prost- Listing 8. Implementacja klas mapujących plik konfiguracyjny do modelu
obiektowego – klasa ApplicationMap
szy. Warto dodać, że im większe będzie
drzewo obiektów, które musimy utwo- <?php
rzyć, tym większy będzie zysk na czy-
telności kodu. require_once 'ioc/ClassMap.class.php';
Na Listingu 3 znajduje się konfigura-
class ApplicationMap {
cja naszego kontenera IoC, dzięki któ-
rej jesteśmy w stanie odtworzyć drzewo private $classes = array();
obiektów, które powołaliśmy do życia
ręcznie na Listingu 1. I w tym momen- public function __construct() {
cie wielu z Was zapewne złapie się za }
ratora new. Jeżeli korzystacie z wersji Informacja o tym, jakiego settera użyć, Warto jeszcze zwrócić uwagę na
PHP 5.1.3 lub nowszej możecie two- nie jest zapisana w konfiguracji, konte- dwie metody getConstructorParamsR
rzyć obiekty z parametrami do konstruk- ner tworzy ją sam. Poprawna nazwa ecursively i getPropertyValueRecur
tora przy pomocy Reflection API i meto- settera składa się z przedrostka set i sively. Obie są bardzo podobne. Na
dy newInstanceArgs. nazwy propertisa ze zmienioną pierw- podstawie typu parametru, który mo-
Po utworzeniu obiektu jego in- sza literą na wielką. że przyjąć dwie wartości value lub
stancja przekazywana jest do metody Ta konwencja nazywania metod reference, kontener pobiera z kon-
setProperties, gdzie do obiektu przy dostępowych do atrybutów obiektów figuracji stałą lub ponownie urucha-
pomocy setterów dodawane są zmien- nie powinna być Wam obca, jest zgod- mia swoją metodę create, aby utwo-
ne, które w pliku konfiguracyjnym zo- na z konwencją stosowaną w innych rzyć obiekt. Dzięki temu kawałkowi ko-
stały zdefiniowane w sekcji properties. aplikacjach. du kontener może zwracać całe drze-
wa obiektów.
Listing 10b. Pełna implementacja kontenera w podstawowej formie – ciąg dalszy O tym, czy parametr jest typu va-
lue, czy reference, decyduje obecność
& przy definicji wartości parametru w
protected function getConstructorParamsRecursively(ConstructorParamMap pliku konfiguracyjnym.
$constructorParamMap) {
switch ( $constructorParamMap->getType() ) {
case 'value' : $param = $constructorParamMap->getValue(); break; Podsumowanie
case 'reference' : $param = Kontener IoC, którego uczyliśmy się
$this->create( $constructorParamMap->getValue() ); break; tutaj razem zbudować, jest od jakie-
default : throw new Exception( goś czasu wykorzystywany w codzien-
"Niewłaściwy typ parametru {$constructorParamMap->getType()}" );
nej pracy w mojej firmie. Z doświadcze-
}
nia wynika, że jego wdrożenie ułatwiło
return $param; nam pisanie aplikacji.
} Najwięcej zyskaliśmy w kwestii te-
stów i przejrzystości kodu. Dodatkowo
protected function setProperties(ClassMap $classMap, $object) {
spora część klasy po przystosowaniu
$properties = $classMap->getProperties();
do specyfiki kontenera IoC – dostarcza-
foreach($properties as $propertyParamMap) { my obiekty zewnętrzne przez konstruk-
$propertySetterName = $propertyParamMap->getSetterMethodName(); tor i settery – stała się na tyle elastycz-
$object->{$propertySetterName} na, że z powodzeniem bez przepisywa-
( $this->getPropertyValueRecursively($propertyParamMap) );
nia zaczęliśmy wykorzystywać je w kolej-
}
} nych projektach.
Udało się nam też usunąć z podsta-
protected function getPropertyValueRecursively( PropertyParamMap wowego kodu aspekty związanie z auto-
$propertyParamMap ) { ryzacją, logowaniem i walidacją. Jak to
switch ( $propertyParamMap->getType() ) {
zrobiliśmy? O tym przeczytacie w kolej-
case 'value' : $param = $propertyParamMap->getValue(); break;
case 'reference' : $param = $ nych artykułach w magazynie PHP So-
this->create( $propertyParamMap->getValue() ); break; lutions. n
default : throw new Exception(
"Niewłaściwy typ atrybutu {$propertyParamMap->getType()}" );
}
return $param;
}
S
tandard XML, czyli eXtensible DTD czy XML Schema), gdyż w innym
Markup Language został określo- wypadku program odczytujący ten doku-
ny przez World Wide Web Con- ment zgłosi błąd.
sortium (W3C). Obecnie jest przeważnie
wykorzystywany jako format gromadze- Techniki przetwarzania
nia i wymiany danych (np. SXW, ODT, XML-a w PHP
RDF, RSS) oraz tworzenia specjalistycz- Pisząc skrypty w języku PHP możemy
nych języków opartych na znacznikach swobodnie korzystać z dokumentów XML-
– jest więc metajęzykiem. Każdy doku- owych. Do ich przetwarzania służą roz-
ment XML zawiera dane uporządkowa- szerzenia języka PHP o nazwach: SAX,
ne w hierarchii drzewiastej. Spójrzmy na
Listing 1: przedstawiamy na nim przykła- Co należy wiedzieć...
W SIECI dowy kod XML. Jego struktura opiera się Przydatna będzie znajomość podstaw
na znacznikach zawartych w nawiasach programowania obiektowego w PHP5.
trójkątnych (podobnie jak w przypadku
• http://www.w3.org/XML/ HTML-a). Para znaczników, np. <title> Co obiecujemy...
– oficjalna specyfikacja stan- i </title> określa element dokumentu Przedstawimy zasady działania roz-
dardu XML
• http://www.saxproject.org/
XML-owego, który może zawierać tekst szerzeń języka PHP: DOM, SAX oraz
– strona projektu SAX lub kolejne elementy (zwane podrzędny- SimpleXML oraz pokażemy, jak korzy-
• http://www.w3.org/DOM/
mi lub potomnymi). Składnia każdego do- stając z SimpleXML tworzyć i odczyty-
– oficjalna specyfikacja stan-
dardu DOM kumentu XML musi być ściśle przestrze- wać dokumenty XML-owe, w tym pliki
• http://books.evc-cit.info/ gana (nie wolno np. pozostawiać niedo- OpenOffice.org i dane programu Gant-
odbook/book.html – oficjalna
specyfikacja formatu Open- mkniętych znaczników; można też okre- tproject.
Document ślić inne zasady korzystając z plików
SAX
SAX (http://www.saxproject.org/, http://
www.php.net/xml).oznacza Simple API for
XML i umożliwia sekwencyjny odczyt do-
kumentów XML. Pozwala na odczyt prak-
Rysunek 1. Okno programu Ganttproject: po lewej stronie wykres Gantta
tycznie każdego rodzaju dokumentów
XML, nawet tych, które zostały utworzo-
ne niepoprawnie. SAX nie umożliwia nato- Instalacja
miast zapisu ani modyfikacji danych. Aby można było uruchomić przykłady z tego artykułu, zalecane jest posiadanie PHP
Na Listingu 2 przedstawiamy skrypt 5.1.4 lub nowszego. Pod systemem Windows możemy w tym celu skorzystać z ze-
służący do odczytu dokumentu XML-owe- stawu typu AMP (Apache, MySQL, PHP) czy też 3 w 1 o nazwie WampServer (http:
go z użyciem techniki SAX. Zaczynamy od //www.wampserver.com). Jego instalacja jest trywialna i odbywa się przy użyciu pro-
utworzenia parsera ($xml_parser), który stego wizarda.
jest zasobem (ang. resource) tworzonym
przy użyciu funkcji xml_parser_create() i
reprezentującym dokument XML, który bę- Listing 1. Dokument XML Simple (opis książki)
dziemy przetwarzali. Do tego ostatniego w
<document id="12">
technice SAX służą funkcje zwane handle- <author>Guillaume Ponçon</author>
rami (uchwytami), które są wywoływane <title>Best practices PHP 5</title>
przez język PHP podczas odczytu nasze- <chapter>
go dokumentu. Musimy je sami utworzyć, <title>Strumienie XML</title>
<paragraph type="introduction">...</paragraph>
zanim się do nich odwołamy. W naszym
</chapter>
przykładzie zdefiniujemy najpierw dwa </document>
podstawowe uchwyty: początku (startE-
lement()) i końca (endElement()) każdego Listing 2. Przeglądamy dokument XML-owy przy użyciu SAX (wyświetlanie
elementu XML-owego, uruchamiane od- znaczników i zawartości)
powiednio, gdy parser natrafi na znacznik
function startElement($parser, $name, $attrs) { echo $name . "\n"; }
rozpoczynający (np. <author>) i kończący function endElement($parser, $name) { echo $name . "\n"; }
(np. </author>) dany element. W przypad- function dataHandler($parser, $data) { echo '-> ' . trim($data) . "\n"; }
ku napotkania elementu danych pomiędzy
dwoma znacznikami XML wywoływany $xml_parser = xml_parser_create();
$xml='<document id="12"><author>Guillaume Ponçon</author></document>';
jest uchwyt dataHandler. Handlery począt-
ku i końca elementu definiujemy przy po- xml_set_element_handler($xml_parser, "startElement", "endElement");
mocy funkcji xml_set_element_handler(), xml_set_character_data_handler($xml_parser, 'dataHandler');
a uchwyt elementu danych używając xml_ xml_parse($xml_parser, $xml, true);
set_character_data_handler(). Przetwa- xml_parser_free($xml_parser);
Dodajemy zadanie
Aby dodać zadanie do wykresu Gantta,
musimy umieścić nowy element <task> w
pliku XML (Listing 12). W przypadku Sim-
Rysunek 4. Zawartość pliku tekstowego model.odt pleXML służy do tego metoda addChild(),
stępów wykonania projektu, często sto- każdym z nich: datę początkową, czas o której już mówiliśmy. Zaczniemy od za-
sowana w firmach i innych organiza- trwania i tytuł. Potrzebujemy na to około ładowania pliku XML (openoffice.xml).
cjach. Istnieje wiele narzędzi służących dziesięciu linii kodu. Jak widzimy, nasz Aby dodać nowe zadanie, będziemy mu-
do sporządzania takich wykresów; jed- algorytm składa się z funkcji rekurencyj- sieli nadać mu identyfikator będący nu-
nym z nich jest opensourcowy program nej, dzięki której możemy przetwarzać merem większym o jeden od ID ostatnio
Ganttproject, o którym mówimy więcej
w Ramce Czym jest Ganttproject?. Po- Listing 7. Struktura strumienia RSS
nieważ dane programu Ganttproject są
gromadzone w postaci plików XML, więc <rss>
korzystanie z nich w skryptach PHP jest <channel>
<title>
całkiem proste.
Tytuł strumienia wiadomości
Każdemu wykresowi przypisany </title>
jest jeden plik XML, w którym zbierane (...)
są dotyczące go dane, takie jak np. ko- <item>
lor przypisany do każdego zadania. Ko- <title>
Tytuł pierwszej wiadomości
rzeniem (rootem) tego pliku jest element
</title>
o nazwie <project>. Jego atrybuty za- <description>
wierają różne informacje, takie jak da- Opis pierwszej wiadomości
ta ostatniego odczytu czy wersja pliku. </description>
Podrzędne wobec <project> elementy (...)
</item>
pierwszego poziomu stanowią kategorie
<item>
informacyjne: kalendarze, zadania, za- (...)
soby, przypisanie zasobów, zwolnienia, </item>
role i różne kategorie ustawień. Elemen- (...)
ty drugiego i następnych poziomów za- </channel>
</rss>
wierają informacje związane z każdą ka-
tegorią. Listing 8. Odczyt strumienia wiadomości RSS przy użyciu SimpleXML
Korzystamy z
Rysunek 5. Dokument tekstowy OpenOffice.org Writer generowany przez skrypt napi- dokumentów
sany w PHP OpenOffice.org za
zdefiniowanego zadania. Ponieważ kolej- nowego zadania (które umieścimy na tym pomocą SAX
ny identyfikator jest zawsze o 1 większy samym poziomie, co tests) będzie Base. OpenOffice.org to opensourcowy pa-
od poprzedniego, wystarczy znaleźć naj- Teraz dodamy nowe zadanie przy uży- kiet biurowy o ciągle rosnącej popular-
większe ID. W tym celu sporządzimy naj- ciu metody addChild(), która jest dostęp- ności. Korzystają z niego m.in. firmy, in-
pierw listę wszystkich zadań korzystając z na dla każdego węzła drzewa dokumentu stytucje publiczne, organizacje pozarzą-
xpath, a następnie odnajdziemy najwięk- w SimpleXML oraz nadamy mu atrybuty: dowe i osoby prywatne z całego świata.
szy identyfikator używając funkcji max() indentyfikator, nazwę, datę rozpoczęcia, Wszystkie formaty dokumentów OpenOf-
w pętli foreach. Po wykonaniu tych czyn- okres trwania i parametry wyświetlania fice.org (edytora, arkusza kalkulacyjne-
ności musimy wydłużyć czas trwania za- (m.in. kolor). Na koniec zapiszemy nasze go, programu do tworzenia prezentacji i
dania macierzystego, którym dla naszego modyfikacje w pliku korzystając z funk- innych są oparte na XML-u. W wersji 2
tego pakietu wprowadzono format Open-
Listing 9. Zawartość dokumentu XML programu Ganttproject Document, którym się posłużymy w na-
szym artykule.
<?xml version="1.0" encoding="UTF-8"?>
Kompozycja dokumentu
<project name="OpenOfficeManager"
company="Anaska" webLink="http://www.anaska.com" (...)>
OpenOffice.org
<description/> Każdy dokument OpenOffice.org to w rze-
<view zooming-state="default:3"/> czywistości skompresowane archiwum za-
<calendars> wierające pliki XML. Przykładowo, archi-
<!-- właściwości ogólne kalendarza (dni wolne, etc.) --> wum pliku example.odt utworzonego w
</calendars>
OO Writer (edytorze tekstu) będzie za-
<tasks color="#8cb6ce"> wierało tekst oraz style i obrazy osadzo-
<taskproperties> ne w tekście.
<!-- deklaracja typów zadań --> Głównym plikiem tego archiwum, le-
</taskproperties> żącym w jego katalogu głównym jest plik
content.xml, którego przykładową zawar-
<task id="0" name="kernel" (...) >
<task id="1" name="modelisation" (...)> tość (fragment) prezentujemy na Listingu
<depend id="2" type="2" difference="0" hardness="Strong"/> 13. Zawiera on dane naszego dokumen-
</task> tu i kilka deklaracji stylów. Zdefiniowane w
dokumencie style tekstowe są zapisane w
<task id="2" name="development" (...)>
pliku styles.xml.
<depend id="3" type="2" difference="0" hardness="Strong"/>
</task> My pokażemy sposób tworzenia tytu-
<task id="3" (...)/> łu i akapitu.
</task>
</tasks> Odczyt i modyfikacja dokumentu
<resources/>
OpenOffice.org
<allocations/> Zanim będziemy mogli odczytać lub zmo-
<vacations/> dyfikować dokument OpenOffice (test.odt),
musimy wydobyć z archiwum plik con-
<taskdisplaycolumns> tent.xml (Rysunek 3). W tym celu użyjemy
(...)
biblioteki pclzip , którą pobierzemy spod
</taskdisplaycolumns>
adresu http://www.phpconcept.net/pclzip/.
<previous/> Plik content.xml, którego fragment już
<roles roleset-name="Default"/> przedstawiliśmy na Listingu 13 składa się
</project> ze znacznika korzenia office:document
oraz pierwszego poziomu hierarchii XML
przedstawiającego kategorie zawartości. text korzystając ze znanej już nam meto- sję dokumentu XML, którą zapiszemy
W kategorii office:body zawarte są dane dy addChild(). Dla każdego węzła poda- w pliku content.xml przy użyciu funkcji
naszego dokumentu. jemy jego nazwę (text:p), zawartość (No- file_put_contents().
Odczytamy plik content.xml przy uży- wy tytuł i Nowy akapit) i przestrzeń nazw Pozostała nam już tylko czwarta
ciu SAX oraz zmodyfikujemy go korzysta- (text). Po dodaniu obu węzłów dodamy część: usunięcie starego pliku content.xml
jąc z SimpleXML i dodając tytuł i akapit. akapitowi atrybut text:style-name, który z archiwum test.odt przy pomocy pclzip i
Gotowy skrypt przedstawiamy na Listingu określa styl (u nas Standard). zastąpienie go zmodyfikowanym przez
14 – składa się on z 4 części: Przejdźmy teraz do zapisywania pli- nas oraz skasowanie pliku content.xml z
ku. Tak jak poprzednio, użyjemy meto- bieżącego katalogu (unlink()). Oczywi-
• wydobycie pliku content.xml zawiera- dy asXml() aby uzyskać tekstową wer- ście, tę ostatnią funkcję musimy wywołać
jącego zawartość naszego dokumen-
tu z archiwum, Listing 10. Odczyt listy zadań z dokumentu aplikacji Ganttproject
• odczyt pliku content.xml za pomocą
SAX, // Pobieranie pliku do przetwarzania
• dodanie tytułu i akapitu przy użyciu $file = $_SERVER['argv'][1];
// Otwieranie pliku przy użyciu SimpleXML
SimpleXML,
$xml = simplexml_load_file($file);
• zapis pliku na dysk. // Funkcja rekurencyjna odczytująca zadania
function display_tasks(&$xml, $level = 0) {
Zaczniemy od dołączenia biblioteki pcl- $prefix = str_repeat('|', $level).'+-> ';
zip (pclzip.lib.php) i utworzenia obiek- foreach ($xml->task as $task) {
echo $task['start'].' ';
tu $zip klasy PclZip, któremu jako pa-
echo ($task['duration'] > 9 ? '' : '0').$task['duration'];
rametr konstruktora przekazujemy na- echo ' day(s) '.$prefix." ".utf8_decode($task['name'])."\n";
zwę archiwum, które chcemy rozpako- display_tasks($task, $level + 1);
wać (test.odt). Następnie korzystając z }
metody listContent() tego obiektu prze- }
// Wywołanie funkcji rekurencyjnej display_tasks()
szukamy listę plików zawartych w archi-
display_tasks($xml->tasks);
wum, aż natrafimy na content.xml. Je-
go ekstrakcji dokonamy używając metody Listing 11. Zmiana nazwy pierwszego zadania w pliku programu Ganttproject
extractByIndex() obiektu $zip. Mając plik (kernel staje się Base)
content.xml poza archiwum, skorzystamy
$project = simplexml_load_file('openoffice.xml');
z PHP-owej funkcji file_get_contents(),
$project->tasks->task[0]['name'] = 'Base';
aby go załadować. file_put_contents('openoffice.xml', $project->asXml());
Czas na przetwarzanie odczytanego
źródła XML przy pomocy SAX. Dużą za- Listing 12. Dodanie zadania w pliku programu Ganttproject za pomocą
letą tego rozwiązania jest jego szybkość SimpleXML
i prostota, co zdążyliśmy już częściowo $project = simplexml_load_file('openoffice.xml');
poznać. Tworzymy więc parser SAX przy
użyciu xml_parser_create() i przy pomo- // Poszukiwanie identyfikatora największego zadania
cy funkcji rozszerzenia SAX xml_parse_ $xpath = $project->xpath("//task/@id");
$maxId = 0;
into_struct() przekształcimy odczyta-
foreach ($xpath as $item) {
ną zawartość pliku XML-owego w tabli- $maxId = max ((int) $item['id'], $maxId);
cę. Następnie użyjemy na tej tablicy pę- }
tli foreach, aby wyekstrahować z niej ty-
tuły i akapity. // Modyfikacja trwania zadania macierzystego
$project->tasks->task[0]['duration'] = 11;
Teraz utworzymy obiekt $xml, repre-
zentujący ten dokument w SimpleXML. W // Dodanie nowego zadania
tym celu skorzystamy z funkcji simplexml_ $newTask = $project->tasks->task[0]->addChild('task');
load_file() i załadujemy ponownie ten $newTask['id'] = $maxId + 1;
sam plik (content.xml). $newTask['name'] = "preprod_tests";
$newTask['color'] = '#0066ff';
Następnie użyjemy metody xpath()
$newTask['meeting'] = 'false';
obiektu $xml, aby wydobyć węzeł office: $newTask['start'] = '2006-12-03';
text, który obejmuje zawarty w pliku tekst. $newTask['duration'] = '5';
Węzeł ten zawiera ciąg deklaracji akapi- $newTask['complete'] = '0';
tów, a pobierzemy go z pierwszego ele- $newTask['priority'] = '1';
$newTask['expand'] = 'true';
mentu tablicy zwróconej przez xpath() (o
indeksie 0). // Zapisywanie modyfikacji
Dodamy teraz nowy tytuł i akapit. file_put_contents('openoffice.xml', $project->asXml());
W tym celu musimy utworzyć dwa wę-
zły text:p potomne wobec węzła office:
P
ublikacja filmów w Internecie w • część druga – rozbudujemy przykład,
oparciu o technologię Flash spro- który został opisany w pierwszej czę-
wadza się do wykonania trzech ści i pokażemy, jak można zautoma-
czynności: tyzować opisane czynności orazi jak
W SIECI uniezależnić się od systemu opera-
• konwersji filmu do formatu Flash Vi- cyjnego, na którym będzie działać
deo (FLV) obsługiwanego przez Flash galeria,
l http://ffmpeg.mplayerhq.hu/ Playera, • część trzecia – wykorzystamy nabytą
– FFMPEG • stworzenia odtwarzacza (Media Play- w części drugiej wiedzę i kod do stwo-
l http://ffdshow.faireal.net/
mirror/ffmpeg/ – FFMPEG
era), który pobierze z serwera film i rzenia ostatecznej wersji serwisu – w
(windows binary) zaprezentuje go klientowi w przeglą- pełni funkcjonalnej i w 100% uniwer-
http://lame.sourceforge.net/
darce, salnej galerii filmów.
l
– LAME
l http://klaus.geekserver.net/ • publikacji strony internetowej, w której
libflv/ – LIBFLV – program osadzimy odtwarzacz.
do konwersji plików FLV Co należy wiedzieć...
l http://www.geovid.com/ Przydatna będzie podstawowa znajo-
–GEO-VID Video to Flash Aby opisać powyższe zadania, artykuł po- mość PHP.
converter
l http://www.rivavx.com/
dzieliliśmy na trzy części:
?encoder – Riva FVL Enco- Co obiecujemy...
der
• część pierwsza – tzw. szybki start, bez Z artykułu dowiesz się, jak stworzyć
l http://ffmpeg-php.sourcefor-
ge.net/ – PHP-FFMPEG zbędnej teorii pokażemy, jak opubliko- własne Google Video – kompletną gale-
http://www.php.net/ming rię filmów z flashowym Media Playerem
l
wać w internecie pojedynczy film. Bę-
– MING – moduł PHP do na WWW pozwalającą na upload filmów
tworzenia SWF-ów dzie to prosty przykład tylko dla plat- i ich strumieniowe odtwarzanie.
formy Windows,
Szybki start
Mamy do wykonania trzy kroki:
Flashowy wideoodtwarzacz
Macromedia Flash – program, którego
użyjemy do stworzenia pierwszego klipu
flashowego, dysponuje eleganckim Media
Playerem. Macromedia Flash jest odpłat-
ny, ale dla potrzeb prezentacji wykorzy-
stamy go w wersji trial, do ściągnięcia ze
strony: http://www.adobe.com/products/
flash/flashpro/ .
Po zainstalowaniu mamy możliwość
zrobienia efektownego flashowego wide-
oodtwarzacza przy minimalnym nakładzie
pracy. Uruchamiamy Flasha (Rysunek 2),
tworzymy nowy dokument np. o nazwie
testplayer.fla i przenosimy na scenę (2)
(ang. Stage, obszar roboczy dokumentu)
komponent MediaPlayback (1). Następnie
uruchamiamy Component Inspektor (3),
gdzie musimy wpisać adres URL do wcze-
śniej przygotowanego pliku FLV (4). URL
może mięć postać ścieżki względnej lub
bezwzględnej (rozpoczynającej się od fi-
le:// lub http://). My dla uproszczenia ustal-
my, że zarówno Media Player jak i film bę-
Rysunek 1. Riva FLV Encoder – konwerter plików wideo do formatu FLV dą znajdować się w tym samym folderze,
I gotowe!
Tym sposobem szybko kończymy wstęp-
ną prezentację. Wykonana strona widocz-
na będzie we wszystkich przeglądarkach
internetowych posiadających zainstalowa-
ny plugin Flash Player 7 lub nowszy. Jak
widać, wykonana przez nas publikacja pli-
ków wideo, jest zadaniem prostym. Nie-
stety zastosowane rozwiązania nie speł-
niają naszych wymogów. Po pierwsze, są
komercyjne (dodatkowo sporo kosztują) i
są dostępne tylko dla platformy Windows,
a po drugie, wszystkie czynności musieli-
Rysunek 3. Macromedia Flash – Publish Settings śmy wykonać ręcznie. Teraz postaramy
się zautomatyzować proces konwersji fil-
mów, postawimy większy nacisk na uni-
wersalność, uniezależniając się od syste-
mu operacyjnego i do tego skorzystamy
jedynie z darmowego oprogramowania.
Czas na rozbudowę
Jeśli chcemy dać użytkownikom możliwość
uploadu własnych plików wideo, musimy
zadbać o automatyczną konwersję filmów.
Standard Flash Video (FLV) jest formatem
dla plików wideo wymyślonym przez firmę
Macromedia pozwalającym na tzw. stru-
mieniowe pobieranie (ang. streaming) fil-
mów z serwera za pomocą Macromedia
Flash Playera (wersje od 6 w górę). Stru-
mieniowe, czyli takie, które pozwala na po-
kazywanie filmu podczas jego ściągania.
Rysunek 4. Komponent MediaPlayback firmy Macromedia prezentujący film w prze- Flash Player dysponuje również innymi me-
glądarce internetowej todami dostarczania filmów do przeglądarki,
function getButtonShape() {
$img = new SWFBitmap(fopen("image.dbl", "rb")); gdzie:
$w = $img->getWidth();;
$h = $img->getHeight(); • -ar rate – ustawia samplingrate w
Hz,
$shape = new SWFShape();
$shape->setLine(1,255,255,255); • -acodec codec – wymusza uży-
$fill = $shape->addFill($img, SWFFILL_TILED_BITMAP); cie wskazanego typu kodowania dla
$shape->setRightFill($fill); ścieżki audio,
$shape->drawLine($w,0); • -ab bitrate – ustawia bitrate w kbit/s,
$shape->drawLine(0,$h);
• -s size – ustawia rozmiar klatki WxH,
$shape->drawLine(-$w,0);
$shape->drawLine(0,-$h); • -f fmt – wymusza format kodowania
return $shape; pliku wyjściowego,
} • -y – nagranie pliku bez potwierdze-
nia.
Polecenie, które wyciągnie pojedynczą nam metoda nextFrame(). Wynikiem wy- pa. Warto dodać, że wszystko układa-
klatkę z trzeciej sekundy filmu formatu AVI konania kodu z Listingu 1 jest pusty Movie my w obrębie jednego frama, czyli Mo-
i zapisze ją w postaci obrazu w formacje Clip o rozmiarach 200px na 100px i czer- vie Clip tak naprawdę składać się bę-
JPG to: wonym kolorze tła. dzie z jednej klatki. Media Player, któ-
Teraz przechodzimy do ustawia- rego tworzymy, składać się będzie z
ffmpeg -i tmp\test.avi nia elementów na scenie Movie Cli- trzech przycisków (Stop, Play, Pause)
-s 320×240 -vframes 1
-ss 3 -f mjpeg test.jpg
Listing 4. Tworzymy obiekt SWFVideoStream obsługujący video streaming
oraz obszaru, w którym pokazywany To, co udało nam się przed chwilą wy- jego obszaru aktywnego. Do tego słu-
będzie film. konać, oznacza, że w przypadku, gdy ży następująca metoda $button->add
Budowę zaczniemy od stworzenia zostanie naciśnięty button (ustawia- Shape($shape,$flags), która ustala, że
przycisków. Z punktu widzenia użytkowni- liśmy akcje dla zdarzenia SWFBUTTON_ dla buttona $button aktywnym kształ-
ka, przycisk we Flashu to pewien obszar MOUSEDOWN) należy wykonać polecenie: tem dla zdarzeń $flags będzie obiekt
powierzchni o dowolnym kształcie, który myVideoPlayer.pause();. $shape. Dzięki temu, że możemy ustalić
reaguje na zachowanie myszki. Z punk- Polecenie to wykonuje metodę różne kształty obszarów dla wybranych
tu widzenia programisty przycisk to obiekt, pause() na obiekcie myVideoPlayer, zdarzeń, w przyszłości będziemy mogli
który reaguje na pewne zdarzenia wywo- o którym napiszemy za chwilę. Gdy np. zmieniać kolor przycisku, gdy naje-
łane przez kursor myszki nad zdefiniowa- określimy już, jak przycisk ma reago- dziemy na niego myszką. Na razie jed-
nym obszarem sceny. MING pozwala nam wać na dane zdarzenia, musimy okre- nak ustalimy jeden kształt dla wszyst-
zaprogramować dla przycisków następu- ślić kształt, rozmiar, wygląd i pozycję kich zdarzeń:
jące zdarzenia:
$button->addAction($action,
������
SWFBUTTON_MOUSEDOWN).
�����������������
Gdzie $action to akcja, jaka ma zostać ��������������������������
�������������������
wykonana po zdarzeniu. Obiekt $action ���������������
tworzymy w następujący sposób:
���������
$flags = (SWFBUTTON_UP
| SWFBUTTON_HIT Listing 6. Konwersja plików wideo z poziomu PHP
| SWFBUTTON_OVER
<?php
| SWFBUTTON_DOWN); define('FFMPEG_FRAME_SIZE_PARAM','-s 160x120');
//-ar rate – ustawiamy częstotliwość próbkowania (w Hz)
W przypadku $shape mamy duże pole do define('FFMPEG_AUDIO_RATE_PARAM','-ar 22050');
popisu – możemy sobie bowiem naryso- define('MOVIE_SOUND_','160x120');
class VideoFile {
wać np. prostokąt o kolorze czerwonym
private $dbh;
lub inny, ciekawszy obrazek przycisku private $osh;
symbolizującego klawisz pauzy. W tym public function __construct(DatabaseHandler $dbh) {
drugim przypadku przyda się nam do te- $this->osh = PlatformFactory::getPlatformInstance();
go możliwość stworzenia kształtu, którego $this->dbh = $dbh;
}
tłem będzie bitmapa – możemy tu przywo-
public function uploadFile($files_name,$files_tmp_name,$size,$name,$desc) {
łać analogię do HTML-a, gdzie tworzymy $target_path = MY_MEDIA_DATA_DIR . basename($files_name);
tabelkę z tłem jako plik. Wykonanie tego // jeśli plik zostal wgrany, kopiujiemy go do katalogu z mediami
zadania wymaga stworzenia na początku if( move_uploaded_file($files_tmp_name, $target_path)) {
obiektu SWFBitmap:
} else{
throw new Exception("Powstał błąd podczas wgrywania pliku.");
$img = new SWFBitmap(
fopen("image.dbl", "rb"));. }
$this->dbh->addResource($name,$desc,$size);
Przy czym SWFBitmap() pozwala na pobra- $this->convertMovieToFlv(basename($files_name));
$this->convertMovieToImges(basename($files_name));
nie plików graficznych w formacie DBL lub
}
JPG (na stronach projektu MING dostęp-
ne jest narzędzie do konwersji plików GIF private function convertMovieToFlv($fname) {
lub PNG do DBL). Po zainicjowaniu obiek- $flvName = $this->osh->getFileBaseName($fname).'.flv';
tu $img, tworzymy nowy kształt $shape = $command = 'ffmpeg -i "'.MY_MEDIA_DATA_DIR.$fname.'"'.
' -ar 22050 -acodec mp3 -ab 32 -f flv -s 160x120 '.
new SWFShape() i ustawiamy jako jego wy-
'"'.MY_MEDIA_DATA_DIR.$flvName.'"';
pełnienie grafikę: if ($this->osh->exec($command)== 0) {
$this->dbh->addMovie($flvName );
$fill = $shape->addFill( return true;
$img, SWFFILL_TILED_BITMAP); }
else return false;
}
Następnie rysujemy prostokąt, którego
rozmiar pokrywa się z obrazkiem. Do tego private function convertMovieToImges($fname) {
celu wykorzystujemy polecenie:
if ($this->osh->isPhpFfmpegExtensionLoaded()) {
$mov = new ffmpeg_movie(MY_MEDIA_DATA_DIR.$fname);
$shape->setLine(1,255,255,255);
$duration = floatval( $mov->getDuration());
$step1 = $duration/3;
określające parametry linii, którą będzie- $step2 = $step1*2;
my obrysowywać obszar (grubość i skła- $temp = array(0,$step1,$step2);
dowe RGB koloru) oraz:
foreach ($temp as $k=>$v) {
$imgName = $this->osh->getFileBaseName($fname)."0$k.jpg";
$shape->drawLine($x,y); $command ='ffmpeg -i "'.MY_MEDIA_DATA_DIR.$fname.'" -s 160x120
-vframes 1 -f mjpeg -ss '.$v.' "'.MY_MEDIA_DATA_DIR.$imgName.'"';
które rysuje linie do punktu $x,$y, z po-
przedniego punktu, w jakim znajdował if ($this->osh->exec($command) == 0) {
$this->dbh->addImage( $imgName );
się kursor. Listing 3 pokazuje, jak wygląda
}
funkcja tworząca obrys przycisku, którego }
tłem jest obraz image.dbl }
Po wykonaniu tych operacji na sce- else {
nie będziemy już widzieli przyciski. Te- $command ='ffmpeg -i '.MY_MEDIA_DATA_DIR.$fname.' -s 160x120 -vframes 1
-f mjpeg '.MY_MEDIA_DATA_DIR.$this->osh->getFileBaseName($fname).'00.jp
raz skupimy się na odegraniu pliku vi-
g';
deo. Do tego celu wykorzystamy polece- $this->osh->exec($command);
nie $stream = new SWFVideoStream();, }
które inicjuje obiekt obsługujący video }
streaming. Następnie nadajemy obiek- }
?>
towi odpowiednie wymiary $stream-
>setDimension($width, $height); i po-
<?PHP
class PlatformUnix extends PlatformAbstract{ netConn = new NetConnection();
public function exec($command) { netConn.connect(null);
exec($command,$return,$return_value);
return $return_value; Następnie tworzymy strumień, który bę-
}
dzie korzystał z tego połączenia:
}
?> netStream);
Parametryzowanie SWF-a
Przyjrzyjmy się przykładowi, który stwo-
rzyliśmy na samym początku niniejsze-
go artykułu. Warto obejrzeć sobie plik te-
stplayer.html, który po odpowiednim sfor-
matowaniu wygląda mniej więcej jak na
Listingu 5.
Jest to standardowy sposób na wsta-
wienie pliku SWF w ciało strony interne-
towej. Widzimy tu tagi <object> i <embed>
opisujące zmienne środowiskowe dla pu-
blikowanego Movie Clipa, w tym przypad-
ku pliku testplayer.swf.
Zauważmy, że parametry i ich warto-
ści dublują się. Wynika to z braku kom-
patybilności przeglądarek. Tag <embed>
przeznaczony jest dla przeglądarek opar-
tych o engine Gecko (Netscape, Mozilla) i
dla Macintosh Internet Explorer, natomiast
tag <object> przeznaczony jest dla prze-
glądarek wspierających ActiveX. Aby prze-
Rysunek 8. Galeria zdjęć z klatek wyciętych z uploadowanych filmów kazać jakąś wartość do Movie Clipa, mo-
testplayer.swf?
video_path=test.flv
src=
"testplayer.swf?video_path=test.flv"
<param name="movie"
value="testplayer.swf?
video_path=test.flv" />
BEZPIECZEŃSTWO
Kryptografia asymetryczna w PHP
Implementacja RS
PROJEKTY
Wielojęzyczny portal w 5 minut z wykorzystaniem
eZ publish
Nowe możliwości eZ publish 3.8.
DLA ZAAWANSOWANYCH
Więcej o IoC (Inversion of Control)
Zajmiemy się aspektami związanymi z logowaniem,
bezpieczeństwem i walidacją obiektów bizneso-
wych.
TESTY
Co nowego w IDE dla PHP?
Nowe, rewolucyjne możlowości środowisk programi-
stycznych