Professional Documents
Culture Documents
06 AKTUALNOŚCI
Daniel Ancuta
08 OPIS CD
10 TAM BYLIŚMY
Relacja z polskiej premiery C++Buildera 2007
DLA POCZĄTKUJĄCYCH
12 MySQL
Krzysztof Trynkiewicz
Krzysztof opisuje bazę danych – MySQL. Dzięki autorowi poznasz spo-
soby wykonywania większości najpotrzebniejszych operacji na bazie
danych MySQL. Po przeczytaniu tego artykułu dowiesz się wszystkie-
go o instalacji, tworzeniu warstw i tabel, aktualizacji oraz optymaliza-
cji danych MySQL.
22 WordPress
Konrad Gołuchowski
Konrad pokaże w jaki sposób zbudować własną skórkę do systemu
WordPress. W przystępny sposób przedstawia jak zbudowane są sza-
blony oraz jakie możliwości daje nam stworzenie własnej skórki. Za-
prezentuje najczęściej używane funkcje i nauczy Cię wykorzystywać
komentarze.
30 Symfony Framework
Łukasz Klejnberg
Łukasz pokaże Ci w przystępny sposób, jak zainstalować i skonfiguro-
wać Symfony, a na przykładzie prostej strony WWW zapoznasz się z
możliwościami tego frameworka. Między innymi dowiesz się jak wyko-
nać rejestrację nowego użytkownika oraz w jaki sposób można spraw-
dzić dane przesłane z formularza.
4 05/2007
PRAKTYKA NARZĘDZIA
38 Własny system statystyk 56 SciTE
Łukasz Borchmann Robert Zajda
Łukasz przedstawi Ci sposób na szybkie pobieranie informacji doty- Robert pokaże Ci, jak wykorzystać zaawansowane możliwości edy-
czących gościa, jego oprogramowania oraz ustawień. Pokaże Ci, jak tora SciTE oraz jak skonfigurować go do pracy z językiem PHP. Mu-
sprawdzić źródła ruchu, dokonać segregacji ze względu na typ (odno- sisz posiadać podstawową znajomość PHP oraz narzędzi do tworze-
śnik,wyszukiwarka, bezpośredni). Dowiesz się również, jak wyciągać nia kodu.
słowa kluczowe oraz zbadać pozycję w wynikach organicznych wy-
szukiwarek. 60 jQuery
Dariusz Duszyński
Dariusz opisuje bibliotekę javascript, która m.in. tworzy dynamiczne
TECHNIKA efekty graficzne na stronie internetowej oraz daje możliwość wykony-
42 Operacje na tekście wania zapytań asynchronicznych.
Michał Gacki
Michał opisuje podstawy wyświetlania tekstu w PHP oraz funkcje, któ- 66 WordPress i punBB
re umożliwiają zamianę pewnych fragmentów tekstu lub samych kon- Piotr Maliński
kretnych znaków. Pokaże Ci, jak sprawdzić czy w tekście istnieje dany Piotr w pierwszym artykule z serii „Warsztat Programisty” przedsta-
ciąg znaków według podanych kryteriów, zmienić kodowanie tekstu wi Ci sposoby integrowania ze sobą dwóch skryptów na przykładzie
itp. Ponadto znajdziesz tu kilka ciekawostek związanych z tematem. punBB i CMSa WordPress. Zaprezentuje Ci „klasyczny” sposób inte-
gracji oraz integracje za pomocą wtyczki WordPress.
46 Formularz internetowy
Tomasz Roszko
Tomek pomoże Ci w przystępny sposób stworzyć interfejs. Poznasz TESTY KONSUMENCKIE
technologię Ajax w jednym z jej praktycznych zastosowań. Będziesz 70 Statystyki zewnętrzne
wiedział jak wysłać i sprawdzić formularz bez przeładowania strony.
75 Recenzje
50 CakePHP Łukasz Skowroński, Sławomir Zadrożny
Piotr Gapiński
Piotr opisuje różne techniki buforowania stron WWW. Jeśli tylko znasz 78 Felieton
Framework CakePHP, język SQL oraz potrafisz administrować bazę Wojciech Sapiechowski
MySQL. Po przeczytaniu tekstu poznasz możliwości ich praktycznego Witryny internetowe – Tylko dla zarobku?
zastosowania w CakePHP.
Adres korespondencyjny:
Software-Wydawnictwo Sp. z o.o., Redakcja używa systemu automatycznego składu
ul. Bokserska 1, 02-682 Warszawa, Polska
tel. +48 22 887 13 45, fax +48 22 887 10 11 Do tworzenia wykresów i diagramów wykorzystano program firmy
www.phpsolmag.org cooperation@software.com.pl
Wszystkie znaki firmowe zawarte w piśmie są własności odpowiednich firm zostały Pismo ukazuje się w następujących wersjach językowych:
użyte wyłącznie w celach informacyjnych.
polskiej , francuskiej
www.phpsolmag.org 5
Aktualności
Poprawki bezpieczeństwa
WordPress 2.2.1
eZ Componnents 2007.1
e
Została wydana nowa wersja WordPress, Z Componnents to zbiór open sourco- flow. Warto zapoznać się z dokumentacją http://
która to zawiera kilka poprawek błędów wych bibliotek które zna za pewne każ- ez.no/doc/components/overview/latest która poka-
– także tych krytycznych, jak SQL Injection
dy programista PHP. Komponenty zosta- że wam możliwości nowych bibliotek.
czy Shell Injection. Wobec tego zalecamy
aktualizację systemu. ły rozszerzone o dwie nowe biblioteki Authenti-
Źródło: http://wordpress.org/development/ cation który pozwala nam na uwierzytalnianie
2007/06/wordpress-221/ użytkowników na kilka sposobów (poprzez ba- Źródło: http://ez.no/ezcomponents/news/ez_com-
zę danych, LDAP czy też Open ID) oraz Work- ponents_2007_1
J
dzone GtkIconView i GtkNotebook. ak wiemy, największym wrogiem programi-
sty jest użytkownik. Jego nieświadome błę-
Otrzymujemy także oczekiwane przez nie- dy lub też świadome próby ataku mogą nara-
których wsparcie GtkPlug/Socket dla sys-
zić nas na duże kłopoty. Głównym zagrożeniem
temów Win32. Wśród ciekawszych nowo-
ści znajdziemy także wiele najróżniejszych są formularze. Tutaj przychodzi nam z pomocą
widgetów, jak GtkStatusIcon i GtkAssistant. HTML Purifier, który jest biblioteką wartą zainte-
Dodatkowo poprawiono wiele znanych resowania każdego programisty PHP. Umożliwia
błędów oraz dodano kilka pomniejszych ona programiście kontrolowanie wprowadzanego
usprawnień. Rozszerzenie możecie ściągnąć
przez użytkownika kodu HTML. Funkcje biblio-
z strony http://www.gtk.php.net.
Źródło: http:/www.gtk.php.net teki, o których warto wspomnieć, to m.in.:
Rysunek 2. Strona główna, biblioteki
Symfony 1.0.5 • usuwanie kodu XSS; nie jej do swoich potrzeb. Jjeśli mimo to za-
Wydana została nowa wersja jednego z naj- • uzupełnianie niezamkniętych tagów; braknie nam jakiejś funkcjonalności, zawsze
popularniejszych frameworków – Symfony,
• zamienienie przestarzałych elementów na możemy ją zaimplementować, gdyż HTML
w wersji 1.0.5 zawiera ona tylko poprawki
znalezionych błędów. zgodne z XHTML; Purifier jest projektem OpenSource (na li-
Źródło: http://www.symfony-project.com/ • uporządkowanie elementów – nie do- cencji LGPL). Na stronie WWW projektu
weblog/2007/06/25/symfony-1-0-5-rele- puszczenia do nieprawidłowego zagnież- znajdziemy sporą dokumentację, która po-
ased-security-fix.html dżania. zwoli nam w konfortowy sposób korzystać z
biblioteki. Jeśli jesteś użytkownikiem CMS-a
Jak widać, biblioteka ta nie tylko zapewnia Drupal czy też MODx, możesz ściągnąć
nam bezpieczeństwo aplikacji, pozwala także wtyczkę do obsługi tej biblioteki.
na zachowanie czystości kodu, dzięki czemu
nie musimy się już bać, że użytkownik znisz- Demo: http://htmlpurifier.org/demo.php
czy nasz kod XHTML czy też wstrzyknie Download: http://htmlpurifier.org/
nam XSS. Aplikacja posiada rozwinięty sys- download.html
tem konfiguracji, co umożliwiadostosowa- Źródło: http://htmlpurifier.org/
6 05/2007
Aktualności
Z
end już od ponad roku rozwija Swój produkt za najlepszy tego typu na rynku, cóż który nazywa mnie członkiem”, dzisiaj jednak
framework. Spore grono użytkowni- oby im ich pycha nie zaślepiła oczu. każdy z nas ma okazję zostać członkiem zarzą-
du wortalu PHP.pl. Wortal ten znany jest w spo-
ków tej aplikacji doczekało się w koń- łeczności developerów, a istnieje już od wielu
cu wersji stabilnej oznaczonej numerem 1.0.0. lat. Aktualnie serwis poszukuje kandydatów
Wersja ta zawiera sporo poprawek już istnie- Źródło: http://devzone.zend.com/article/2262- do nowo tworzonego zarządu. Do głównych
jących modułów. Sami autorzy uwarzają Swój Zend-Framework-1.0.0-production-release zadań zarządu należeć będzie między innymi:
Agavi RC 5
współpracy z serwisami, firmami;
• nadzorowanie projektów rozwijanych
przez PHP.pl;
• kontrolowanie administratorów;
• organizacja konkursów;
• pomoc w realizacjach podejmowanych
przez członków grupy PHP.pl.
W
ydana została kolejna wersja Rele- Odbyła się tam konferencja poświęcona roz-
ase Candidate o numerze 5, jed- wojowi języka PHP na świecie. Kilka z tema-
tów poruszanych na konferencji to m.in.:
nego z najlepszych frameworków
PHP, jakim jest Agavi. Jest to ostatnia wersja • Zend Framework – przedstawienie funk-
przed wydaniem finalnym, które ukaże się w lip- cjonalności oraz pokazanie przykłado-
cu. Każda z wersji Agavi utwierdza nas w prze- wych aplikacji;
konaniu, że w PHP także powstają aplikacje w • PHP i Oracle;
• PDO – metody bardziej efektywnej,
pełnym tego słowa znaczeniu. Wraz z kolejny-
przenośnej i bezpiecznej implementacji;
mi wersjami dostajemy dawkę kodu, który zde- • CodeGear Delphi dla PHP;
cydowanie ułatwia nam pracę z tym framewor- • Symfony Framework.
Rysunek 2. Strona www Agavi
kiem lub też dodaje nowe funkcjonalności. Tak
samo jest tym razem, developerzy przygotowa- Jak widzimy, teraz obsługa SOAP staje się dzie- Więcej informacji na temat konferencji można
znależć na stronie: http://devzone.zend.com/
li nam kilka nowych narzędzi oraz usprawnień. cinnie prosta. Wersja ta została wzbogacona:
article/2217-Dutch-PHP-Conference-2007-
Pierwszą rzeczą, o której na pewno warto wspo- Wrap-Up
mnieć, jest dodanie obsługi SOAP. Stworzenie • wsparcie dla przestrzeni nazw w XML; Źródło: http://devzone.zend.com/article/
akcji dostępnej przez SOAP jest naprawdę pro- • wsparcie dla UTF-8 w StringValidator; 2217-Dutch-PHP-Conference-2007-Wrap-Up,
ste, a opiera się na kilku czynnościach: • wsparcie dla XSL stylesheets w plikach kon- http://www.phpconference.nl/
figuracyjnych;
• Dodajemy nowy router zawierający elemen- • parser konfiguracji został przepisany.
ty <wsdl:input> (dla wejścia) oraz <wsdl:out-
put> (dla wyjścia) – z definicją parametrów; Jest to tylko kilka z nowości, po więcej infor-
• Jeśli zdefiniujemy nagłówki w WSDL, macji odsyłam do changeloga.
Agavi doda je automatycznie;
• Z danych ustawionych w routerze Agavi Agavi w Ohloh: http://www.ohloh.net/projects/5907
automatycznie wygeneruje WSDL, który Changelog: http://trac.agavi.org/browser/
może być wykorzystywany przez innych branches/0.11/CHANGELOG
klientów obsługujących protokół. Źródło: http://agavi.org/
www.phpsolmag.org 7
Opis CD
• Pierwszy rozdział to informacje na temat użytkowników; Rysunek 2. Po zalogowaniu do systemu należy przejść do ustawień
• Podsumowanie ogólne zawierające zestawienie wybranych
danych z ostatnich 7 dni;
• Szczegółowe informacje na temat użytkowników, wizyt i odsłon.
Ponadto widoczna jest również opcja wybierania zakresu czasu;
• Podział użytkowników wg ilości powrotów;
• Podział użytkowników wg czasu ostatniego powrotu.
• Serwisy linkujące;
• Ścieżki;
• Szczegóły odsłon dla danej strony;
• Słowa kluczowe.
8 05/2007
Jeśli nie możesz odczytać zawartości płyty CD, a nie jest
ona uszkodzona mechanicznie, sprawdź ją na co najmniej
dwóch napędach CD. W razie problemów z płytą, prosimy
pisać pod adres: cd@software.com.pl
O
prócz premierowych pokazów nowego C++Builder® 2007 pozwala tworzyć aplikacje resowanie wśród programistów Delphi. Code-
narzędzia IDE dla programistów C++ Web 2.0 wykorzystujące technologię AJAX Gear nie zamierza poprzestać na pierwszej edy-
zaprezentowano także dostępne na (ang. Asynchronous JavaScript and XML). Nowy cji oprogramowania. Delphi dla PHP wpisze się
rynku od kilku miesięcy środowiska Delphi 2007 zestaw komponentów INDY 10 Internet Proto- na stałe do gamy oferowanych produktów. Pod-
i Delphi for PHP 2007 oraz serwer bazodano- col dostarcza nowe możliwości programistom czas ostatniej części konferencji Bogdan Polak za-
wy InterBase 2007. W pierwszej części konferen- aplikacji internetowych. W kolejnej części kon- prezentował możliwości serwera bazodanowego
cji konsultant techniczny BSC Polska – Bogdan ferencji przedstawiono nowe możliwości środo- InterBase 2007. Nowy InterBase zapewnia wie-
Polak – przedstawił ogólne perspektywy rozwo- wiska Delphi 2007 for Win32, a w szczególno- le korzyści związanych z architekturą wielowąt-
ju produktów firmy CodeGear oraz zaprezento- ści wsparcie dla platformy Microsoft Windows kową. Zastosowanie systemu rejestracji zdarzeń
wał nowe możliwości środowiska C++Builder® Vista®, nową architekturę dostępu do baz da- i procedur przywracania do pracy po awa-
2007. Pod koniec każdego bloku tematycznego nych DBX4, możliwości zarządzania buildami rii gwarantuje wysoki stopień bezpieczeństwa.
przewidziano czas na sesje pytań i odpowiedzi. w oparciu o MSBuild oraz ulepszoną technolo- InterBase jest jednocześnie jedną z najszybszych
C++Builderc 2007 jest jedynym natywnym śro- gię instalacyjną. Delphi 2007 for Win32 wspie- baz danych, która dzięki obsłudze SMP może
dowiskiem typu RAD do programowania w ję- ra wykorzystanie technologii AJAX, pozwalając pracować z wieloma procesorami, w tym wie-
zyku C++ dla systemu Windows. Oferuje pełne na szybkie i wizualne tworzenie interaktywnych lordzeniowymi. InterBase uzyskał certyfikację
wsparcie dla Windows Vista® oraz pozwala pro- aplikacji internetowych. Po raz kolejny duże za- do pracy na systemach Windows, Linux i Solaris.
gramistom na łatwe dostosowanie istniejących już interesowanie uczestników wzbudziło narzę- Pożegnanie z uczestnikami uwieńczyło loso-
aplikacji C++ do wymogów tego systemu. Umoż- dzie Delphi dla PHP – pierwsze narzędzie RAD wanie nagród. Po konferencji każdy z uczestni-
liwia tworzenie nowych aplikacji Windows do programowania aplikacji w języku PHP. Pod- ków mógł skorzystać z unikalnej oferty ceno-
wykorzystujących możliwości interfejsu Vista czas wykładu słuchacze mogli zapoznać się mię- wej przygotowanej specjalnie na tą okazję. Wiele
Aero. Nowa edycja komponentów bazodano- dzy innymi z możliwościami nowego edytora, osób skorzystało także z zaproszenia na bezpłat-
wych dbExpress (DBX4) umożliwia łączenie debuggera oraz zintegrowanej biblioteki VCL ne seminaria on-line dotyczące programowania
się z najnowszymi wersjami serwerów SQL. dla PHP. Nowy produkt wzbudził duże zainte- w Delphi dla PHP.
10 05/2007
Dla początkujących
MySQL
Bazy danych od podstaw
P
ierwszym nasuwającym się pytaniem Podobnie jak w przypadku PHP, MySQL zo- nie w powłoce:
jest: dlaczego właśnie MySQL? Ta baza stał zaprojektowany do działania zdalnego, na
danych oferuje wysoką wydajność, po- serwerze. Do działania nie potrzebuje jednak rpm -i MySQL-server-WERSJA.i386.rpm
twierdzoną licznymi testami – jest to jeden z serwera HTTP, bowiem sam sobie jest serwe- MySQL-client-WERSJA.i386.rpm
najszybciej działających produktów na rynku. rem. Oznacza to, że instalując MySQL, insta-
Jego licencję (GPL) można streścić następują- lujemy aplikację, która działa w tle i oczeku- Nie zapomnijmy zastąpić słowa WERSJA od-
co: jeśli pobieramy opłaty za używanie pro- je na połączenia przez jej protokół. Łączyć z powiednim numerem. MySQL zostanie za-
duktu korzystającego z MySQL, musimy wy- serwerem MySQL możemy się na wiele spo- instalowane, uruchomiony zostanie ser-
kupić płatną licencję. Oznacza to, że do zasto- sobów (przez PHP, phpMyAdmin, czy konso- wer „mysqld” oraz dodany zostanie wpis w /
sowań niekomercyjnych można stosować My- lę kliencką dostarczaną z pakietem instalacyj- etc/init.d/ uruchamiający serwer przy każ-
SQL bez ograniczeń. Już same te dwa argu- nym), niezależnie, czy serwer działa na kom- dym rozruchu komputera. Procedura instala-
menty przemawiają zdecydowanie za używa- puterze lokalnym, czy zdalnym. Mamy więc cji MySQL bez udziału plików RPM jest bar-
niem MySQL. Oczywiście, jest to baza stabil- ponownie do wyboru dwie możliwości: ko- dziej skomplikowana, jednak dobrze opisana
na i łatwa w użyciu (obsługuje składnię poda- rzystać z usług hosting providera (w Interne- w manualu.
ną w standardzie SQL 92, dzięki czemu ucząc cie można znaleźć darmowe i płatne oferty) W przypadku instalacji MySQL na Win-
się jej obsługi, uczymy się także obsługi więk- lub zainstalować MySQL u siebie. W pierw- dowsie, logujemy się jako administrator i po-
szości innych baz danych), posiadająca wie- szym przypadku, będziemy tworzyć użyt- bieramy pakiet. Do wyboru mamy samoin-
le funkcjonalności, która jest cały czas w roz- kownika (dane do logowania) przy pomo- stalujący się plik *.exe lub spakowane archi-
woju. Konkurencja nie pozostaje daleko w ty- cy interfejsu dostarczanego przez provide- wum. Oczywiście, najłatwiej wybrać pierw-
le, jednak praktycznie każdy produkt ma ja- ra (najczęściej przez panel WWW). Otrzy- szą możliwość – przez proces instalacji zo-
kąś wadę: mamy także zapewne zainstalowany system staniemy przeprowadzeni szybko i sprawnie,
phpMyAdmin (dostęp do bazy danych przez wszystkie ustawienia zaaplikuje nam instala-
• PostgreSQL – szybkość; stronę WWW), co znacznie ułatwi sprawdza- tor. W drugim przypadku, możemy wypako-
• SQLite – brak dostępu przez protokół nie wyników wykonywania zapytań. Jeśli ma- wać archiwum i własnoręcznie umieścić my-
zdalny (operuje na plikach lokalnych); my taką możliwość, najprościej będzie z niej sqld-max.exe w autostarcie (to nasz serwer).
• Access – cenę i niską ekonomię. skorzystać – możemy przejść do kolejnej czę- Możemy także zainstalować MySQL jako
ści artykułu. usługę przechodząc przy pomocy wiersza po-
Niemniej nie należy się martwić – systemy W przypadku instalacji MySQL na wła- lecenia do katalogu instalacji, a potem katalo-
baz danych podlegają w większości standar- snym komputerze, niezbędnych będzie kil- gu bin i wydając polecenie mysql-max –stan-
dom, dzięki czemu ucząc się składni MySQL, ka działań. Najpierw musimy zainstalować dalone a następnie mysql-max –install. Pro-
będziemy znać podstawy składni innych serwer MySQL (tzw. daemon). Dla syste- cedura ta mogła jednak zmienić się od czasu
12 05/2007
MySQL od podstaw
napisania artykułu, dlatego zalecam zajrze- blic wielowymiarowych, zmiennych itd.), trze- my wtedy możliwości modyfikacji danych w
nie do manuala w przypadku instalacji z ar- ba więc wiedzieć, jakich komend użyć, by je wy- przypadku przejęcia przez intruza danych do
chiwum. świetlić. Dwie pierwsze możliwości zapewnia- cześciej używanego konta, służącego do odczy-
Manual MySQL zawiera dokładne instruk- ją interfejs, który automatycznie formatuje i tu. Ustanawianie przywilejów jest jednak kwe-
cje instalacji dla wielu systemów (Solaris, wyświetla wyniki zapytań (komend). Narazie stią „dmuchania na zimne” i ma sens jedynie
MacOS itp.) i jest bardzo przystępnie na- więc polecam korzystanie z aplikacji klienckiej w przypadku ważnych danych, nie jest więc w
pisany, dlatego warto się do niego odwoły- (konsoli), ewentualnie panelu phpMyAdmin. gestii tego artykułu – odsyłam do świetnego
wać. Manuale stanowią ogromny atut PHP Po zapoznaniu się z podstawowymi zapytania- opisu polecenia GRANT na http://dev.mysql.com/
i MySQL – są to niewątpliwie jedne z najle- mi, przejdziemy do opisu ich implementacji w doc/refman/5.0/en/grant.html. Dodajmy jesz-
piej opisanych produktów służących do two- PHP. Warto jednak już teraz wspomnieć, że do cze, że w MySQL nie są rozróżniane wielkości
rzenia oprogramowania. W przeciwieństwie niektórych zapytań PHP się po prostu nie nada- liter w poleceniach, jednak w niektórych sys-
do manuali innych języków, czytając je, nie je (właśnie z racji konieczności własnoręcznego temach operacyjnych rozróżniane są wielkości
czujemy, że czytamy encyklopedię lub słow- formatowania wyników). Takie operacje to na liter w nazwach baz danych i tabelach. War-
nik, lecz normalną książkę. przykład: tworzenie bazy danych wraz z tabe- to więc przyjąć stałą konwencję w przypadku
Po instalacji MySQL sprawdzamy jego działa- lami (czynność jednokrotna – nie warto dla niej nazw. Często stosowanym pomysłem jest wy-
nie komendą wpisaną do konsoli (w Windowsie budować skryptu PHP, o ile nie tworzymy in- dawanie poleceń pisanych wielkimi literami
Start -> Uruchom): stalatora do naszego skryptu), wyświetlanie do- z nazwami własnymi pisanymi małymi. Czas
stępnych tabel, zmiana ustawień bazy lub ta- już przejść do praktyki. Bazę danych tworzy-
mysql -u root beli. Do debuggowania (w tym wypadku np. my poleceniem:
W przypadku systemu Windows podamy także sprawdzania, czy w tabelach znajdują się po-
ścieżke do katalogu z MySQL, np. prawne wartości) lepiej skorzystać z konsoli lub CREATE DATABASE test;
phpMyAdmin. Jeśli używamy porządnego edy-
c:\mysql\bin mysql -u root tora PHP (np. polecany w artykule „Wstęp do Gdy stworzymy bazę danych (nasz „katalog”
PHP” Zend Developer Environment), mamy do dla tabel), przed stworzeniem tabel, musimy
Powinniśmy zobaczyć powitanie w Monitorze dyspozycji wbudowanego klienta SQL, który zdeklarować, że właśnie jej chcemy użyć po-
MySQL, w którym możemy wydawać komen- także formatuje wyniki zapytań. leceniem:
dy. Opuścić go można przy pomocy komendy
\q. Jeśli napotkamy error can't connect to Tworzenie baz i tabel USE test;
MySQL server, oznacza to, że serwer nie został Zapytania w MySQL kończymy znakiem śred-
uruchomiony. Możemy ponownie uruchomić nika. Jest to ważne, ponieważ możemy dzię- Jeśli chcemy usunąć bazę danych (wraz z jej ta-
system lub uruchomić serwer wpisując: ki temu formatować zapytania. W systemie belami i danymi w nich zawartymi!), używa-
MySQL możemy stworzyć wiele baz danych, my komendy:
mysqld –standalone a w nich – wiele tabel. To w tabelach zawarte
Przy logowaniu do mysql użyliśmy nazwy użyt- są dane, natomiast bazy danych służą do kata- DROP DATABASE test;
kownika root. Ze względów bezpieczeństwa, logowania tabel. Dobrze jest przyjąć konwen-
powinniśmy ustanowić hasło w Monitorze ko- cję tworzenia jednej bazy danych dla każdego W MySQL można używać przydatnych opcjo-
mendą: projektu, a także dwóch kont użytkowników nalnych if exists i if not exists. Oznacza
o ograniczonych prawach – za pomocą jed- to, że np. zapytanie:
set password for root@localhost=password( nego konta możliwy byłby jedynie odczyt da-
'hasło'); nych, za pomocą drugiego – zapis. Ogranicza- CREATE DATABASE IF NOT EXISTS test;
mysql -u root -p
Używanie MySQL
Jak wspomniałem, komendy MySQL można
wydawać na kilka sposobów. Możemy w tym
celu użyć aplikacji phpMyAdmin (jeśli mamy ją
zainstalowaną), jak widać na Rysunku 1. Może-
my także wydać komendę bezpośrednio w Mo-
nitorze MySQL (plik mysql.exe w Windowsie i
mysql w Linuxie) – przestawia to Rysunek 2.
W końcu, mamy dostęp do MySQL z pozio-
mu PHP. Teoretycznym minusem ostatniego
rozwiązania, w przypadku nauki, jest fakt, że
wyniki otrzymujemy w różnych formach (ta- Rysunek 1. PhpMyAdmin w akcji
www.phpsolmag.org 13
Dla początkujących
nie będzie próbowało utworzyć bazy o nazwie tuje, że każdy kolejny wiersz będzie miał która przyspiesza wyszukiwanie po tym
test, jeśli już taka istnieje. Szczególnie przydat- w tej kolumnie wartość o jeden większą polu). Znakomita większość tabel po-
ne jest if not exists w przypadku tworze- niż poprzedni (to pole będzie więc nu- siada takie pole jako pierwsze – w celu
nia tabel. Tworzymy tabelę „tabela” (jeśli jesz- merem wiersza, który w przypadku baz identyfikacji wierszy;
cze nie istnieje) z polami: danych nazywamy rekordem); primary • nazwa: wartości tej kolumny będą składać
key oznacza, że będzie to klucz główny się z maksymalnie 30 znaków;
• id_produktu: wartości tej kolumny bę- naszej tabeli (klucz główny oznacza, że • opis: pole podobne do powyższego, jed-
dą liczbami całkowitymi (int), wartość wartości w tej kolumnie nigdy się nie nak może zawierać do 65 535 znaków (są
tej kolumny nie może być pusta (not powtarzają, są więc unikalne; jednocze- też większe i mniejsze typy łańcuchowe
null) – inaczej próba dodania nie po- śnie, klucz główny implikuje indeksowa- pól, jednak te są najczęściej wykorzysty-
wiedzie się; auto _ increment gwaran- nie, czyli tworzenie tabeli pomocniczej, wane);
14 05/2007
MySQL od podstaw
• data_dodania: kolumna ta posiada for- konkretnej wartości głosu w drugiej tabeli. Uwaga: polecenie ALTER modyfikuje jedy-
mat datetime, będzie domyślnie wypeł- Podobnie, nie możemy dodać wartości głosu nie definicję tabeli, a nie wartości w niej
niana aktualnym czasem, a zapytania bę- nie zwiększając sumy – prowadziłoby to do zapisane. Powyższe polecenie nie zmieni
dą zwracać datę w formacie RRRR-MM- zamieszania i sfałszowania wyników. Trans- wartości wierszy – do tego służy polece-
DD GG:MM:SS. Istnieją także inne typy akcja gwarantuje, że zajdą obydwie możliwo- nie UPDATE, które omówimy w dalszej czę-
dat (np. datetime, date, time, year). ści, lub żadna. Wspomnieć należy, że typ ta- ści artykułu.
beli można zmienić – jeśli więc zauważymy, MySQL oferuje wiele typów pól. Warto po-
W końcu, po zdefiniowaniu pól (kolumn), że jeden typ okazuje się niewydajny, może- znać te mniej popularne, by nie „strzelać z ar-
jakie mają znaleźć się w tablicy, określamy my zastosować inny. maty do muchy”, co często dzieje się, gdy pro-
(nieobowiązkowo) typ tworzonej tabeli. Możemy zobaczyć dostępne bazy danych i jektant użyje TEXT zamiast VARCHAR dla samej
MySQL obsługuje kilka typów tabel, z któ- tabele (po wybraniu bazy danych przy pomocy nazwy produktu. Oczywiście, jedyną różni-
rych zdecydowanie najpopularniejszymi są USE) wykonując odpowiednio komendy: cą będzie czas wykonania zapytania, a więc
MyISAM i InnoDB. Nie wdając się w szcze- kluczowa sprawa, jeśli idzie o bazy danych.
góły, różnica między nimi polega na struk- SHOW DATABASES; Wspomniane polecenia mają wiele dodatko-
turze przechowywania danych i funkcjo- SHOW TABLES; wych opcji, którym warto się przyjrzeć, my
nalności. MyISAM stosuje się, jeśli tabe- jednak na pewno chcemy już operować na da-
la zawiera dane, do których potrzebny jest Jeśli chcemy obejrzeć zapytanie, które utwo- nych.
szybki dostęp i nie są często modyfikowane rzy tabelę już istniejącą, wydajemy polecenie:
(jest to domyślne ustawienie – jeśli usunie- Wstawianie, usuwanie
my TYPE= MyISAM z powyższego zapytania, SHOW CREATE TABLE tabela; i aktualizacja danych
efekt będzie taki sam). Z kolei wolniejsze Operacje określone powyżej należą raczej do
InnoDB zawiera niewątpliwą zaletę w posta- Rezultat powinien dać polecenie zbliżone wolnych. Bazy danych nastawione są na szyb-
ci blokowania na poziomie wierszy (a nie ta- do tego, którym stworzyliśmy tabelę. Moż- kość wyszukiwania i zwracania informacji,
beli – jak MyISAM), obsługuje także trans- na spodziewać się kilku detalicznych zmian, dlatego musimy oszczędnie i rozmyślnie pro-
akcje. Wyjaśnię to na przykładzie: mamy które są automatycznie dodawane, więc za- jektować struktury baz danych, by ograniczyć
tabelę z tysiącami rekordów. Jeśli tabela zwyczaj pomijane, np. rozmiar pola int bę- ilość zapytań odpowiednio: INSERT, DELETE
jest typu MyISAM, przy dodawaniu nowe- dzie wynosił 11, kodowanie znaków zosta- i UPDATE.
go wiersza, zablokowane na ten czas zosta- nie dodane po definicji typu tabeli (w za- Polecenie INSERT występuje w różnych od-
nie jakiekolwiek inne działanie na tej tabeli leżności od ustawień domyślnych systemu mianach: możemy dodawać jeden lub kilka
(a więc także odczyt). bazodanowego) oraz nazwy tabel i kolumn wierszy, dodawać pewne warunki lub okre-
Przyjmijmy, że nasza witryna odczytuje zostaną ujęte w znaki `. Jeśli chcemy usunąć ślać jedynie wartości niektórych pól tabe-
z tabeli rekordy przy każdorazowym przeła- tabelę, stosujemy: li (ma to sens np. w przypadku, gdy więk-
dowaniu, zaś użytkowników mamy co naj- szość pól ma ustawione opcje not null oraz
mniej setki. Jako administratorzy, dodajemy DROP TABLE tabela; default – wtedy zostaną automatycznie uzu-
wiersz do tabeli (np. z nowym towarem). W pełnione). Dodajmy pierwsze wiersze do na-
czasie wykonania takiego zapytania (ułam- Natomiast do modyfikacji tabeli służy polece- szej tabeli:
ki sekundy, choć niekiedy nawet sekundy nie ALTER . W przypadku graficznych interfej- W tej formie zapytania podajemy wartości
– zależnie od wprowadzanych danych) po- sów, jak np. phpMyAdmin, nie musimy znać wszystkich pól oddzielone przecinkiem (tekst
bieranie danych przez użytkowników zosta- tego polecenia, jednak sposób tworzenia ta- musi być zawarty w apostrofach), zaś kolejne
nie wstrzymane – załadowanie naszej witry- beli będzie miał wpływ na to, jak zbudujemy wiersze oddzielone są przecinkami i ujęte w na-
ny będzie przedłużone o ten czas oczekiwa- zapytanie dodające, czy wyszukujące rekordy wiasy. W pierwszym wierszu dla pola id_pro-
nia. Jeśli rzadko dodajemy do tabeli nowe da- – warto więc znać tekstowe wersje poleceń. duktu podajemy wartość NULL. Jego deklaracja
ne, problem będzie niezauważony (dodatko- Dla przykładu, aby dodać kolumnę na końcu zakłada, że taka wartość nie może wystąpić, więc
wo MyISAM oferuje kompresje i działa szyb- tabeli, używamy: MySQL automatycznie przypisze temu polu ko-
ciej niż InnoDB). lejną wartość z auto_increment (będzie to 1).
Jeśli jednak dodawanie wiersza będzie od- ALTER TABLE tabela ADD COLUMN kolumna Podobnie sprawa ma się z ostatnim polem
bywało się automatycznie i często, różnica varchar(20); – zostanie mu przypisana wartość CURRENT_
może być zauważalna. W tym celu stosuje
się tabele InnoDB – choć wolniejsze, bloku-
ją przed odczytem nie całą tabelę, lecz jedy-
nie aktualnie modyfikowany wiersz. W tym
czasie inne rekordy z tabeli mogą być pobra-
ne przez użytkowników. InnoDB obsługuje
także transakcje.
Transakcje można najogólniej objaśnić jako
zbiory kilku dowolnych poleceń, które albo
wykonają się wszystkie poprawnie, albo ba-
za danych wróci do stanu sprzed wykonania
pierwszego polecenia.
Jest to szczególnie przydatne przy do-
dawaniu danych do wielu tabel – jeśli np.
w jednej przechowujemy wartości głosów,
a w drugiej ich sumę, nie możemy pozwolić,
by suma głosów zwiększyła się bez dodania Rysunek 2. Klient tekstowy mysql
www.phpsolmag.org 15
Dla początkujących
TIMESTAMP, czyli aktualny znacznik czasu. Operacja SELECT jest najważniejszą w ca- Jak widać, zmieniamy wartość pola opis.
W drugim wierszu robimy coś, czego raczej łym systemie bazodanowym i omówimy ją Kluczowym wyrażeniem jest tu WHERE
nie powinno się robić w przypadku pól auto_ szerzej później. Polecenie UPDATE jest szcze- – określone są po nim warunki, jakie mu-
increment – podajemy jego wartość. Nie jest to gólnie przydatne w przypadku przechowy- si spełniać wiersz, by do niego została za-
zabronione, jest więc możliwe, ale ma sens jedy- wania danych statystycznych wewnątrz ta- stosowana zmiana. W naszym przypadku
nie, gdy usuniemy rekord ze „środka” tablicy i bę- bel. Zmieńmy lekko treść rekordu numer określamy id_produktu (które jest unikalne
dziemy chcieli ponownie zająć jego numer. Efekt dwa: z założenia tabeli), zmiana będzie więc do-
możemy zobaczyć, wykonując zapytanie: tyczyła jednego wiersza. Jeśli usuniemy wa-
UPDATE tabela SET opis='Napoj gazowany o runek, zmiana będzie dotyczyć wszystkich
SELECT * FROM tabela; smaku coli' WHERE id_produktu='3'; rekordów:
16 05/2007
MySQL od podstaw
www.phpsolmag.org 17
Dla początkujących
Jeśli założymy, że w tabeli tabela ma- Powyższe zapytanie zwróci tabelę, której ko- ilość zwróconych wyników. Klauzula LIMIT
my zamówienia produktów wraz z kolum- lumna nie będzie miała nazwy nazwa, lecz może jednak przyjmować także dwa parame-
ną id _ zamawiającego posiadającą numer pole1. Zmieniliśmy więc nazwę wynikowej try. W takim wypadku, pierwszy parametr
klienta, do którego są przypisane dane (np. kolumny. Będzie to miało znaczenie w połą- określa punkt startowy, od którego należy li-
nazwa) klienta w tabeli kontrahenci, takie czeniu z PHP, bowiem nazwy kolumn zwra- czyć ilość maksymalnych wyników określoną
zapytanie zwróci nam nazwę i cenę zamó- canych przez zapytanie są zamieniane na in- przez drugi parametr. Ma to sens, gdy stroni-
wienia numer 15 wraz z nazwą kontrahen- deksy tablic z wynikami w PHP. Przykład cujemy dane, np. po 50 na wyników na stro-
ta, który zamówienia dokonał. Takie po- możemy jednak podać także bez użycia PHP. nie. Dla trzeciej strony wyników, wykonamy
wiązanie dwóch lub więcej tabel nazywa MySQL posiada wiele wbudowanych funkcji, zapytanie:
się relacją. których często nie używa się, chociaż są szyb-
MySQL posiada tak że użyteczną funkcjo- sze i równie sprawne, jak te zaimplemento- SELECT * FROM tabela ORDER BY cena
nalność zwaną aliasami. Jeśli nie podoba nam wane w PHP: DESC LIMIT 2*50, 50;
się nazwa tabeli, np. z powodu jej długości, mo-
żemy na czas wykonania zapytania przypisać jej SELECT count(*) AS rekordow FROM tabela; Takie zapytanie posortuje tabelę względem
inną nazwę: ceny (malejąco), a następnie zwróci pozycje
Zapytanie takie zwróci wartość funkcji od 100 do 150, a więc maksymalnie 50 wyni-
SELECT t1.nazwa FROM tabela AS t1; count(*), która to z kolei zwraca ilość rekor- ków, lecz odpowiednich dla trzeciej strony.
dów w tablicy. Posługiwanie się jednak na- Jeśli za drugi parametr podamy -1, otrzy-
Tabeli tabela nadaliśmy alias t1, którego na- stępnie wynikami takiego zapytania z ko- mamy wszystkie wyniki począwszy od punktu
stępnie używamy w zapytaniu SELECT. Efekt lumną o nazwie count(*) byłoby co najmniej określonego przez pierwszy parametr.
jest taki sam, jak zapytania: niewygodne. Dlatego, przypisujemy jej alias Zanim przejdziemy do przykładu z ży-
rekordow. Wynikiem będzie jeden rekord z cia, nauczmy się jeszcze trochę teorii – cho-
SELECT tabela.nazwa FROM tabela; liczbą wierszy tabeli tabela. Funkcji count() ciaż może niezbyt ciekawej, jednak niezwy-
za argument możemy podać także nazwę ta- kle istotnej. Jeśli nie opanujemy zagadnienia
W tym konkretnym przypadku, skrót nie ma beli lub pewne zapytanie. Na przykład, je- normalizacji bazy danych, już przy pierw-
sensu, jednak przydaje się, jeśli używamy za- śli poprzedzimy nazwę kolumny słowem szym projekcie będziemy zmuszeni ponow-
pytań zagnieżdżonych. Po klauzuli WHERE distinct, wszystkie duplikaty zostaną zre- nie projektować bazę danych, ponieważ zapy-
możemy bowiem umieścić nie tylko nazwy dukowane do jednej pozycji: tania będą wykonywać się zbyt długo i będą
istniejących tabel, ale także kolejne zapyta- zbyt skomplikowane.
nie SELECT (w nawiasie). Wynikiem tego po- SELECT count(distinct nazwa) FROM tabela;
dzapytania będzie oczywiście tabela, do któ- Optymalizacja bazy danych
rej pól możemy odwoływać się przypisując Jeśli w tabeli tabela będziemy mieć kilka re- W przypadku używania bazy danych, istot-
jej wcześniej alias. Zapytania zagnieżdżone są kordów o tej samej wartości w polu nazwa, ny jest czas wykonywania zapytań. Jest on
niezwykle istotne przy większych projektach zwrócona zostanie ilość tylko rekordów uni- w większości przypadków zależny od pro-
i zademonstrujemy je później na przykładzie kalnych. Wszelkie duplikaty nie zostaną doli- jektu (architektury) bazy danych – rozkładu
z życia wziętym. Wróćmy jednak do aliasów. czone do wyniku. danych między tabelami (czy nawet całymi
Możemy je przypisać nie tylko tabelom, ale tak- Kolejną przydatną klauzulą jest LIMIT. Jak bazami danych na różnych serwerach). Klu-
że wierszom: już pokazaliśmy, określa, ilu maksymalnie re- czowe są więc dwa składniki: dobrze zapro-
kordów ma dotyczyć zapytanie. Jeśli użyje- jektowana baza oraz dobrze skonstruowane
SELECT tabela.nazwa AS pole1 FROM tabela; my jej w SELECT, będzie określać maksymalną zapytania. Jakkolwiek to drugie użytkownik
musi sam zagwarantować (MySQL umożli-
wia podgląd wolnych zapytań w dzienniku),
tak przy projektowaniu bazy warto trzymać
się pewnych zasad. Jeśli baza jest z nimi zgod-
na, zwie się ją znormalizowaną. Zanim wyja-
śnię to znaczenie, dodam, że prędkość dzia-
łania bazy danych można zwiększyć przy po-
mocy polecenia:
18 05/2007
MySQL od podstaw
rekordu Jana Kowalskiego wartość tego po- nym i wykraczającym poza granice tego arty- rozdzielone na dwie tabele, by przyspie-
la będzie miała postać Angielski, Niemiecki, kułu. Jeśli chcemy projektować bazy danych szyć wyszukiwanie. Przy większym obcią-
Polski. Taka baza danych jest nieznormalizo- używane często, powinniśmy zaznajomić się żeniu, można bardziej rozszerzyć podział.
wana – jeśli bowiem będziemy chcieli póź- z tymi terminami. Występuje tu tzw. „klucz obcy” – poster_
niej wyszukać pracowników znających an- id. Jest to numer konta osoby, która umie-
gielski, będziemy musieli wykonać skompli- Baza filmów na przykładzie ściła komentarz (jej nick pobierany jest z
kowane i długie czasowo zapytanie. Aby ta- http://www.eldoras.com tabeli accounts);
ka baza (w tym wypadku tabela) była zgodna Przeanalizujmy teraz strukturę bazy da- • links – zawiera odnośniki do miniatur
z pierwszą postacią normalną, musimy roz- nych serwisu skupiającego filmy – http:// i filmów dla każdego rekordu będącego
dzielić języki – po jeden, dla każdego rekor- www.eldoras.com. Dobra architektura pozwoli- osobnym filmem;
du. Oznacza to, że po znormalizowaniu bę- ła w tym wypadku na generowanie bardzo róż- • performers – zawiera nazwę wykonawcy,
dziemy mieć trzy wpisy (dla każdego z języ- norodnych statystyk przy ogromnych możliwo- wraz z jego identyfikatorem (NIE jest to
ków) dla Jana Kowalskiego! Pozostałe warto- ściach wyszukiwania. Oczywiście, każda baza identyfikator konta, bowiem serwis zakła-
ści pól będą więc się powtarzać dla każdego danych da się bardziej zoptymalizować, jed- da, że wykonawca nie musi być zarejestro-
wpisu – uzyskaliśmy znormalizowanie, ale nak ta struktura okazuje się bardzo wydajna na- wanym użytkownikiem);
kosztem zwiększenia ilości danych. Opty- wet w przypadku 3000 unikalnych odwiedzin • songs – zawiera nazwy piosenek oraz ich
malniej będzie więc, jeśli utworzymy osob- dziennie. Kod odpowiedzialny za stworzenie wykonawców wraz z ich identyfikatora-
ną tabelę jezyki, a w niej pola id_pracownika tabel widać na Listingu 1. mi. Podział na wykonawców i tytuły po-
oraz jezyk. Będziemy więc mieć trzy wpi- Listing został wygenerowany przez phpMy- zwala na generowanie statystyk według
sy dla Jana Kowalskiego w tej tabeli, jednak Admin, ma więc trochę inną strukturę od tej, wykonawców, natomiast identyfikator
jej zawartość będzie niewielka – pierwsze której się uczyliśmy (np. klucz podstawowy jest jednoznacznie określa jedną piosenkę.
pole będzie zawierało zawsze jego identyfi- definiowany dopiero po kolumnach) – efekt Przyspiesza to także wyszukiwanie sa-
kator (taki sam, jak w macierzystej tabeli), jest jednak taki sam. Przeanalizujmy po kolei mych wykonawców lub samych tytu-
natomiast drugie – pojedynczy język. Warto za- wszystkie tabele: łów;
znaczyć, że ponieważ wartość id_pracownika • stats – zawiera dane statystyczne dla każ-
będzie mogła być powielana, nie może on • accounts – zawiera dane użytkowników, dego filmu: ilość oglądnięć, ocenę, ilość
być kluczem głównym tabeli. W macierzystej odpowiednio zakodowane; głosów oraz ich sumę (przydatne w gene-
tabeli pozostanie natomiast jeden wiersz dla • added – posiada id filmu oraz datę jego rowaniu nowej oceny);
Jana Kowalskiego, z którego całkowicie usu- dodania do serwisu; • videos – jest kluczową tabelą, określają-
niemy kolumnę języki. Od teraz, by znaleźć • comments_en_0 oraz comments_pl_0 – ko- cą pewne relacje. Dla każdego rekordu
jego umiejętności językowe, wykonywać bę- mentarze w różnych językach zostały, (filmu), przypisana jest piosenka (a więc
dziemy zapytanie:
Listing 4. Tworzenie tabeli o nazwie tabela
SELECT jezyki.jezyk FROM jezyki,
pracownicyWHERE pracownicy. CREATE TABLE IF NOT EXISTS tabela (
id_pracownika=13 AND jezyki.id id_produktu int not null auto_increment primary key,
pracownika=pracownicy.id_pracownika; nazwa varchar(30),
opis text,
Oczywiście, moglibyśmy od razu zapisać data_dodania timestamp not null default CURRENT_TIMESTAMP
... AND jezyki.id _ pracownika=13, jed- ) TYPE=MyISAM;
nak jeśli zapytanie będzie bardziej rozbu-
dowane, zmiana numeru będzie konieczna Listing 5. Dodanie pierwszych wierszy w tabeli
we wszystkich miejscach, warto więc od ra- INSERT INTO tabela VALUES
zu posłużyć się relacją. W klauzuli FROM wy- (
mieniliśmy tabelę pracownicy, chociaż z niej NULL,
nie pobieramy bezpośrednio danych. Słu- 'Cola',
ży nam ona jednak do wykonania zapytania 'Napoj gazowany',
przy budowie relacji, musimy więc ją wy- NULL
mienić. Tym sposobem znormalizowaliśmy ),
względem pierwszej zasady bazę danych. (
Dla przykładu, jeśli teraz będziemy szukać 3,
anglojęzycznych pracowników, wykonamy 'Pepsi',
zapytanie: 'Napoj gazowany',
NULL
SELECT pracownicy.imie, pracownicy.nazwisko );
FROM pracownicy, jezyki WHERE
jezyki.jezyk='angielski' AND Listing 6. Tworzenie tabeli o nazwie ceny
jezyki.id_pracownika=pracownicy. CREATE TABLE IF NOT EXISTS ceny (
id_pracownika; id int not null auto_increment primary key,
id_produktu int not null,
Postaci normalnych jest kilka, z należy znać cena int not null,
pierwszą, a warto – trzy pierwsze. Kolejne data_dodania timestamp not null default CURRENT_TIMESTAMP
postacie są jednak związane z kluczami tabel, ) TYPE=MyISAM;
są więc zagadnieniem bardziej skomplikowa-
www.phpsolmag.org 19
Dla początkujących
tytuł i artysta), wykonawca oraz konto wspólne powiązania dla wszystkich danych sji językowej serwisu, wczytywane są róż-
użytkownika, który film dodał. z tabel wymienionych w FROM – video_id ne dane. Następnie napotykamy instrukcję
musi być wspólny, zaś tabela videos zawiera warunkową, która określa, że jeśli jesteśmy
Jak widzimy, zastosowany został silnik InnoDB id odpowiadające id piosenek i wykonawców na pierwszej lub ostatniej stronie wyników,
w celu blokowania na poziomie wierszy w tabelach z ich danymi tekstowymi, więc nie pojawią się napisy Dalej i Wstecz.
– MyISAM wyraźnie nie zdawał egzaminu. głównie z nią tworzymy powiązania. Powią- Dalej, deklarujemy zmienną $i , która bę-
zanie pierwsze (z lastadded.video_id) gwa- dzie oznaczać ilość filmów wyświetlonych
PHP i MySQL rantuje, że pod uwagę bierzemy tylko osiem w jednym wierszu (cztery) na stronie z wy-
PHP w wersji 5 oferuje kilka sposobów po- ostatnich rekordów i dane z nimi związane. nikami. Używamy pętli while, która przej-
łączenia się z bazą danych MySQL. Najko- Na końcu, ponownie sortujemy dane wzglę- dzie przez każdy rekord wyniku. Jest to
rzystniejszymi rozwiązaniami wydają się dem daty dodania. Wynik tego zapytania typowa konstrukcja w połączeniu z mysql_
PDO i mysqli, które jednak wymagają zna- przechowywany jest w $query_videos. fetch_assoc() , która zawiera wielowymia-
jomości zagadnienia programowania zo- Kolejne zapytanie zwraca łączną ilość fil- rową tablicę (osiem rekordów z filmami,
rientowanego obiektowo (opartego na kla- mów w serwisie. Dalszy kod służy do okre- każdy z nich ma swoje dane – tablica więc
sach), które z kolei jest techniką dosyć za- ślenia, jaka liczba ma być przypisana do wy- jest dwuwymiarowa).
awansowaną i nieprzydatną w przypadku rażenia na stronie Strona X z Y – X jest zdefi- Każde wywołanie pętli while przypisze
małych projektów. Po opanowaniu najważ- niowane w odfiltrowanym $page, natomiast zmiennej $video wartość rekordu z jednym
niejszych funkcji PHP jest to jednak nie- Y jest właśnie określane w zmiennej $total_ filmem. Dalej znajduje się kod odpowiedzial-
zbędny przystanek na drodze do zostania pages – jest to ilość wyników podzielona ny za wyświetlenie danych w odpowiednich
poważnym deweloperem. Kod serwisu http:// przez osiem. Intval() służy do zaokrągle- znacznikach (które są potem formatowane
www.eldoras.com został jednak napisany nia wartości – jeśli reszta z dzielenia równa pod kątem wyglądu za pomocą arkuszy sty-
pod PHP 4 (działa także pod PHP 5) i z tego się 0, to przypisanie Y jest łatwe. W innym li CSS). Jeśli pętla while przechodzi czwarty
względu używa wciąż przydatnych i ułatwiają- przypadku filmów jest mniej niż wielokrot- raz, oznacza to, że należy przejść do kolejnego
cych naukę funkcji. ność 8, więc stosujemy widoczne obliczenie wiersza – kończymy więc listę UL i rozpoczy-
Przypatrzmy się, jak wygląda obsługa serwi- by określić prawidłową ilość stron. Użyliśmy namy nową. Na końcu inkrementujemy $i.
su z poziomu PHP. Na Listingu 2. widać kod funkcji mysql_fetch_assoc() z argumentem Nie jest jednak powiedziane, że zostanie
odpowiedzialny za wyświetlanie najnowszych będącym wynikiem zapytania MySQL – wy- zwróconych dokładnie 8 wyników – jeśli
filmów na stronie głównej serwisu. nikiem tego jest z kolei tablica o indeksach bowiem jesteśmy na ostatniej stronie, mo-
Jak widać, najpierw jest inicjowane połącze- będących nazwami kolumn w MySQL (lub że ich być np. 6. Wtedy pętla while zakoń-
nie z bazą danych znajdującą się pod adresem ich aliasów, jeśli zostały przypisane). czy się z $i równym 6. Dlatego definiuje-
localhost (czyli na komputerze, na którym uru- Jeśli ktoś próbował być sprytny i podał w my kolejną pętlę while – jeśli zostało wy-
chomiony jest serwer HTTP). Nazwa i hasło do- adresie strony podstronę z wynikami, która świetlonych mniej niż 8 miniatur z przypi-
stępu do bazy zostały wycięte z oczywistych nie ma prawa istnieć z racji braku filmów, sami, zapełniamy pozostałe miejsca obraz-
względów. Następnie, wybieramy bazę danych skrypt kończy działanie. Kolejne zapytania kami „Brak grafiki”. Efekt tego kodu widać
(nasz katalog tabel) przy pomocy kolejnej wbu- odpowiedzialne są za zliczenie ilości zareje- na Rysunku 3.
dowanej funkcji. strowanych użytkowników dodanie jednego
Wykonanie zapytania MySQL zlecamy wyświetlenia do statystyk oraz pobranie ilo- Podsumowanie
funkcji mysql_query, która zwraca wyniki ści wyświetleń. Czas na zaprezentowanie wy- MySQL oferuje ogromne możliwości, które
do zmiennej $query_videos (i kilku innych ników zapytań. Odpowiedzialny za to kod połączone z PHP tworzą to, co widzimy każ-
w dalszych poleceniach). Kod wygląda na nie- widać na Listingu nr 3. dego dnia w Internecie – Wikipedię, Yahoo
zmiernie skomplikowany, jest jednak bardzo Widzimy tu niezbyt estetyczny, pomiesza- itd... Trudno o lepsze argumenty przema-
intuicyjny. Po SELECT określamy, co chce- ny kod PHP i xHTML. Wprawdzie wygląda wiające za nauką tworzenia stron w ramach
my otrzymać. Do wyświetlenia miniatur fil- to fatalnie, jednak przy odpowiednim forma- pakietu AMP (Apache + MySQL + PHP).
mów, niezbędne będą: linki do miniatury towaniu i podświetlaniu składni jest całkiem Tak PHP, jak MySQL zawiera jeszcze mnó-
i filmu, nazwa wykonawcy, tytuł piosenki czytelne. stwo przydatnych funkcjonalności, jednak
i nazwa artysty (przypisywane są od razu alia- Trzeba jednak zaznaczyć, że pisząc kod w już informacje zawarte w tych dwóch arty-
sy, by mieć wygodniejsze nazwy indeksów projekcie kilkuosobowym, należy podzielić kułach mogą wystarczyć do stworzenia wła-
tablic w PHP) oraz id danego filmu – do stwo- aplikację na kilka „warstw". Na przykład, sche- snej wideogralerii, jak na http://eldoras.com.
rzenia linka do obejrzenia filmu. mat MVC (ang. Model – View – Controller) za- Zachęcamy do nauki i realizowania swoich
Dalej mamy klauzulę FROM – musimy kłada podział na warstwę biznesową, wyglądu pomysłów!
zawrzeć w niej wszystkie tabele, z których ko- i kontrolną. Dzięki takiemu podziałowi, kod
rzystamy do pobrania powyższych danych. odpowiedzialny za obliczenia nie jest zmiesza-
Sprawdzamy więc, gdzie leżą powyższe da- ny z kodem odpowiedzialnym za wygląd itd...
ne i dopisujemy je. Jedną z tabel jest wy- Przydatne w tym celu jest także opanowanie
nik podzapytania, któremu dajemy nazwę użycia szablonów, jest to jednak przydatne w
lastadded. większych, zespołowych projektach. Najpierw
Jest ono odpowiedzialne za pobranie iden- napotykamy na dziwny zlepek: KRZYSZTOF TRYNKIEWICZ
tyfikatorów ośmiu ostatnio dodanych fil- Studiuje Informatykę na Uniwersytecie Jagielloń-
mów (stronicowanie realizowane jest co 8 <?=$lang_latest_videos?> skim. Od wielu lat zajmuje się tworzeniem witryn
filmów, więc zmienna $page określa, na której w technologii PHP oraz Flash. Obecnie rozwija kil-
stronie wyników jesteśmy; jest ona wcześniej Jest to skrócony odpowiednik <? print ka równoległych projektów autorskich dostęp-
odpowiednio filtrowana – domyślnie jest to $lang _ latest _ videos; ?>. Zmienne o nych na witrynach http://eldoras.com i http://
zmienna $_GET['page']). Dalej, określone przedrostku $lang oznaczają tekst zależny ajax.eldoras.com
są relacje w klauzuli WHERE. Ustalamy więc od języka – w zależności od wybranej wer- Kontakt z autorem: chris.trynkiewicz@gmail.com
20 05/2007
Dla początkujących
WordPress
Tworzymy skórkę
T
worząc szablon dla nowego bloga, zo- wając /*, a kończymy używając */. Metadane inna podstrona. Później WordPress wyszuku-
baczymy, że WordPress oferuje bar- określamy, używając formatu: nazwa: wartość. je kolejno szablony, które może wykorzystać.
dzo wiele funkcji. Nasze szablony Do określenia nazwy skórki używamy identy- Jeżeli szablon o zadanej nazwie istnieje, to on
mogą mieć nie tylko inny wygląd niż domyśl- fikatora: Theme Name. Jeżeli chcemy nazwać zostaje wybrany.
ne, ale także większą funkcjonalność. W ni- naszą skórkę „Moja pierwsza skórka”, odpo- Dla strony głównej naszego bloga Word-
niejszym artykule będziemy wykorzystywać wiednia linia w pliku style.css będzie wyglą- Press w pierwszej kolejności użyje pliku
wersję 2.2, która w chwili pisania artykułu dała jak poniżej. home.php. Jeżeli taki plik nie istnieje, poszuka
była najnowszą wersją. index.php. Pojedynczy post w pierwszej kolej-
Theme name: Moja pierwsza skórka ności będzie szukał pliku single.php, a jeśli ta-
Jak działa system szablonów Używając podobnych identyfikatorów, może- kiego nie ma, zostanie użyty index.php. Stro-
System skórek w WordPressie oparty jest o my dodać następujące informacje: ny (Page) dają nam większe możliwości kon-
szablony i style CSS. Każda skórka posiada figuracji. W pierwszej kolejności WordPress
własny podkatalog w katalogu wp-content/ • adres strony domowej skórki – (Theme URI); będzie szukał pliku szablonu wybranego w pa-
themes/, w którym znajdują się wszyst- • opis skórki – (Description); nelu administratora. Abyśmy mogli wybrać
kie pliki skórki. Gdy wchodzimy na stronę, • wersje – (Version) – opcjonalnie; szablon z panelu administratora, musimy na
skrypt wybiera odpowiedni plik, a następnie • autora – (Author); początku pliku szablonu (np custom.php) w ko-
go wyświetla. Obrazki, style i inne dodatko- • adres strony autora – (Author URI); mentarzu po identyfikatorze Template Name:
we pliki także powinny być zawarte w tym • skórka nadrzędna – (Template) – opcjo- umieścić nazwę naszego szablonu, np.:
katalogu. nalnie.
Pliki szablonów są zwykłymi plikami PHP, /*
w których wymieszany jest kod xHTML Przypatrzmy się uważniej identyfikato- Template Name: My custom template
z kodem PHP. Dzięki licznym funkcjom udo- rowi Template. Jeżeli chcemy, aby nasza */
stępnianym przed WordPress możemy w skórka dziedziczyła szablony z określo-
bardzo prosty sposób wyświetlać różne ele- nej skórki, jako wartość po identyfikato- Jeżeli taki plik nie zostanie znaleziony,
menty na stronie. Nasza skórka musi posia- rze umieszczamy nazwę katalogu wybra- WordPress będzie szukał pliku page.php,
dać przynajmniej 2 pliki: index.php i style.css. nej skórki. Określenie skórki nadrzędnej a na końcu index.php. Dla każdej katego-
Pierwszy posłuży jako szablon domyśl- spowoduje użycie wszystkich szablonów rii możemy użyć osobnego pliku szablonu.
ny wszystkich podstron, a drugi oprócz te- wybranego schematu, co oznacza, że sza- Jeżeli WordPress znajdzie plik o nazwie
22 05/2007
WordPress
category-numer_kat.php, gdzie numer_kat jest szablon, który jest używany, gdy nie znaleziono kod możemy zobaczyć na Listingu 1. Szablon
numerem ID kategorii (np category-3.php), bardziej szczegółowego szablonu. Wiemy już, ten jest bardzo wybrakowany. Brakuje w nim
to ten plik zostanie wykorzystany. Jeżeli jak wyświetlić nagłówek i stopkę. Wykorzysta- nawigacji między poszczególnymi strona-
nie utworzyliśmy takiego pliku, WordPress my do tego funkcje get_header i get_footer. mi, nawigacji między postami ijakiejkolwiek
będzie sprawdzał kolejno pliki: category.php, W tym momencie domyślne pliki są wystar- obsługi komentarzy. Odpowiednie funkcje
archive.php, a na końcu index.php. Do wyświe- czająco dobre. Domyślny plik z nagłówkiem do wykonania tych zadań poznamy w dalszej
tlenia strony o autorze WordPress kolejno wyświetli nam oprócz odpowiednich tagów części artykułu.
sprawdza szablony: author.php, archive.php oraz meta tytuł i opis bloga. Domyślna stopka wy-
index.php. Do wyświetlenia postów z okre- świetli nam oprócz informacji niezbędnych w Przydatne funkcje
ślonej daty WordPress będzie sprawdzał pli- stopce liczbę zapytań oraz czas generowania Poznamy teraz wybrane funkcje, które po-
ki date.php, archive.php i na końcu index.php. strony. zwolą nam tworzyć szablony. Pierwszą będzie
W przypadku wyszukiwania zostanie użyty WordPress przed wyświetleniem szablonu wy- bloginfo. Wyświetla ona opcje ustawione
plik search.php. Jeśli takiego pliku nie znale- wołuje zapytanie do bazy, pobierając odpowied- w panelu admina. Jako argument przyjmu-
ziono, WordPress użyje domyślnego szablonu nie dane za bazy danych. Sam analizuje infor- je nazwę opcji, której wartość ma wyświetlić.
index.php. Jeżeli dana podstrona nie została zna- macje przesłane do skryptu i tworzy odpowied- Jako parametr możemy podać:
leziona, zostanie wykorzystany plik 404.php, nie zapytanie. Aby sprawdzić, czy dostępne są ja-
a jeśli takiego nie ma – index.php. kieś posty, używamy funkcji have_posts. Jeżeli • name – funkcja wyświetli nazwy blogu;
Umiejętne wykorzystanie hierarchii sza- są dostępne do wyświetlenia posty, zwraca true, • description– funkcja wyświetli opisu
blonów pozwala na budowę zaawansowa- jeśli nie ma zwraca false. Używając tej funkcji blogu;
nych i bardzo zróżnicowanych stron. W ram- w pętli while jako warunku, sprawdzamy, czy • url – funkcja wyświetli URL do strony
ce Linki znajduje się adres strony, na której dostępne są kolejne posty do wyświetlenia, a na- bloga;
znajdziemy diagram ilustrujący tę hierarchię. stępnie używając funkcji the_post, „pobieramy” • rdf _ url – funkcja wyświetli URL do
Oprócz hierarchii szablonów WordPress ofe- post. Automatycznie aktualizuje ona niezbęd- RDF/RSS 1.0;
ruje także specjalne funkcje, które pozwa- ne dane, tak abyśmy mogli wykorzystywać funk- • rss _ url – funkcja wyświetli URL do
lają na poziomie konkretnego pliku szablo- cje takie jak the_title czy the_ID. Tytuł posta RSS 0.92;
nu sprawdzić, która strona jest wyświetlana. wyświetlamy, używając funkcji the_post, a aby • rss2 _ url – funkcja wyświetli URL do
Z tymi funkcjami zapoznamy się w dalszej wyświetlić treść, używamy funkcję the_content. RSS 2.0;
części artykułu. Więcej przydatnych funkcji poznamy w dalszej • atom _ url – funkcja wyświetli URL do
części artykułu. Atom feed?;
Struktura strony Zbierzmy teraz wszystkie poznane infor- • comments _ rss2 _ url – funkcja wyświe-
Zastanówmy się nad tym, jak wygląda struk- macje i stwórzmy nasz pierwszy szablon. Jego tli URL do RSS 2.0 feed dla komentarzy;
tura pojedynczej podstrony bloga. Najprost-
sza strona zawiera takie elementy jak nagłó-
Listing 1. Pierwszy szablon
wek, treść i stopka strony. Na początku każ-
dego pliku musi znaleźć się wywołanie funk- <?php
cji get_header, która wyświetli nam odpo- //Wyświetlamy nagłówek
wiedni nagłówek. Jeżeli w katalogu skór- get_header();
ki znajduje się plik header.php, zostanie on ?>
wczytany. Jeżeli go nie stworzyliśmy, zosta- <?php
nie dołączony domyślny plik. Podobnie jak w //Sprawdzamy, czy są dostępne jakiekolwiek posty
przypadku nagłówka – jeżeli stworzyliśmy if (have_posts()) :
plik footer.php zostanie on dołączony zamiast //Wyświetlamy posty w pętli
domyślnej stopki. while (have_posts()) : the_post();
Większość stron zawiera także panel boczny. ?>
Jego kod znajduje się w pliku sidebar.php. Jeże- //Wyświetlamy tytuł i treść
li takiego pliku nie umieścimy w katalogu skór- <div class="post" id="post-<?php the_ID(); ?>">
ki, to ponownie zostanie użyty domyślny plik. <h3 class="title"><?php the_title(); ?></h3>
Aby dołączyć panel boczny, używamy funkcji <div class="content">
get_sidebar. <?php the_content(); ?>
Strona może zawierać także inne elemen- </div>
ty. Do ich dołączania stosujemy na przykład </div>
funkcję include. Gdybyśmy – dajmy na to <?php endwhile; else: ?>
– chcieli dołączyć formularz wyszukiwania <p>
zawarty w pliku searchform.php, musielibyśmy <?php
wywołać funkcję w następujący sposób: //Wyświetlamy informację o braku postów
echo 'Brak postów spełniających twoje kryteria';
include( TEMPLATEPATH .'/searchform.php' ); ?>
</p>
Stała TEMPLATEPATH zawiera ścieżkę do katalo- <?php endif; ?>
gu naszej skórki. <?php
//Wyświetlamy stopkę
Plik szablonu get_footer();
Stworzymy teraz nasz pierwszy plik szablonu. ?>
Index.php w katalogu naszej skórki to domyślny
www.phpsolmag.org 23
Dla początkujących
• pingback _ url – funkcja wyświetli URL • html _ type– funkcja wyświetli zawar- • stylesheet _ url – funkcja wyświetli
dla Pingback; tość „Content-type”; adres URL do pliku style.css w twoim
• – funkcja wyświetli adres
admin _ email • wpurl – funkcja wyświetli URL dla insta- szablonie;
e-mail administratora; lacji WordPressa; • stylesheet _ directory – funkcja wy-
• charset – funkcja wyświetli nazwę kodo- • template _ url – funkcja wyświetli URL świetli URL do katalogu ze stylami.
wania znaków; do używanego szablonu;
• version – funkcja wyświetli wersję • template _ directory – funkcja wyświetli Jeżeli zamiast wyświetlenia powyższych
WordPressa; URL do katalogu szablonu; informacji chcemy je pobrać do zmiennej, po-
winniśmy użyć funkcji get _ bloginfo.
Gdy będziemy chcieli wyświetlić tytuł
Listing 2. Plik sidebar.php. Kod panelu bocznego
bloga, zastosujemy wp_title. Jako pierwszy
<div id="sidebar"> argument możemy podać separator między
<ul> poszczególnymi fragmentami tytułu. Drugi
<li><h2>Archiwa</h2> parametr określa, czy chcemy wyświetlić ty-
<ul> tuł (true, wartość domyślna), czy też wolimy,
<?php aby funkcja zwróciła tytuł jako wynik działania
//Wyświetlamy archiwa funkcji (wartość false).
wp_get_archives('type=monthly'); ?> Poznamy teraz kilka funkcji, które są szcze-
</ul> gólnie przydatne przy budowie własnego
</li> panelu bocznego. Bardzo często pierwszym
<li><h2>Kategorie</h2> elementem, który zauważamy na panelu
<ul> bocznym, jest kalendarz. WordPress oferuje
<?php nam funkcję get_calendar, która pozwala
//Wyświetlamy kategorie go wyświetlić. Przyjmuje ona jeden parametr,
wp_list_categories('sort_column=name&optioncount=1&hierarchical=0'); ?> który określa, czy WordPress ma użyć tyl-
</ul> ko pierwszej litery nazwy tygodnia (wartość
</li> true, np. S zamiast Sun), czy skrótu (wartość
<?php false, np. Sun w niedziele). Przy wyświetla-
//Wyświetlamy linki niu dni tygodnia WordPress opiera się o wy-
get_links_list(); ?> brany język.
<li><h2>Meta</h2> Jeżeli zechcemy wyświetlić łącza do archi-
<ul> wum, najprawdopodobniej wykorzystamy do
<?php tego funkcję wp_get_archives. Domyślnie
//Wyświetlamy link do rejestracji (domyslnie wyświetla link pomiędzy <li> i </li> wyświetli ona łącza do archiwum danego mie-
wp_register(); ?> siąca, używając listy HTML (znaczniki <li>).
<li><?php Funkcja ta przyjmuje jednak parametry, uży-
//Wyświetlamy link logowania/wylogowania wając formatu query string, czyli podobnego
wp_loginout(); ?> do tego, w jakim przekazywane są zmien-
</li> ne w adresie URL metodą GET. Poszczególne
</ul> parametry rozdzielone są znakiem &, a wartość
</li> poprzedzona jest nazwą parametru i znakiem =.
</ul> Jeżeli chcemy wyświetlić linki określonego
</div> rodzaju, używamy identyfikatora type. War-
tościami, które możemy użyć dla tego argu-
Listing 3. Fragment kodu, który pozwala wyeksponować posty z kategorii 3 mentu. są:
<?php
if (have_posts()) : • yearly – wyświetla łącza do archiwum
while (have_posts()) : the_post(); grupowanego po latach;
//Sprawdzamy, czy post należy do kategorii 3. i wyświetlamy odpowiedni tekst • monthly – wyświetla łącza do archiwum
if( in_category(3) ) grupowanego po miesiącach (wartość
echo '<div class=”featured”>'; domyślna);
else • daily – wyświetla łącza do archiwum
echo '<div class=”post”>'; dziennego;
//Wyświetlamy post • weekly – wyświetla łącza do archiwum
?> tygodniowego;
<h1><?php the_title();?></h1> • postbypost – wyświetla łącza do postów.
<div class=”content”><?php the_content(); ?></div>
</div> Możemy także ograniczyć liczbę wyświetla-
<?php nych linków. W tym celu używamy identyfi-
endwhile; katora limit. Do wyświetlenia ostatnich 12
endif; miesięcy możemy użyć poniższego wywoła-
?> nia funkcji.
wp_get_archives('type=monthly&limit=12');
24 05/2007
WordPress
Kolejnym parametrem, który możemy podać, Identyfikator depth określa pokazywaną głę- katora order, podając jako wartość ASC (ko-
jest format. Identyfikator format może przyj- bokość drzewa strony. Ustawienie wartości lejność rosnąca) lub DESC (kolejność maleją-
mować następujące wartości: na 1 pokaże tylko strony najwyższego rzędu, ca). Aby pokazać puste kategorie, ustawiamy
wartości 2 – strony najwyższego rzędu i ich wartość hide_empty na 0 (domyślnie Word-
• html – domyślna wartość, używa listy podstrony. Domyślnie ustawiona jest wartość Press używa wartości 1). Do wyświetle-
HTML do wyświetlenia linków (znacznik 0, co sprawia, że wyświetlane jest pełne drze- nia podkategorii wybranej kategorii uży-
<li>); wo wraz z wcięciami. Ustawienie wartości na wamy identyfikatora child_of, który jako
• option – używany jest do budowania pól -1 powoduje wyświetlenie wszystkich stron wartość przyjmuje numer ID kategorii nad-
SELECT (znacznik <option>); bez wcięć. rzędnej. Podobnie jak w przypadku funkcji
• link – używa znacznika <link>; Gdy chcemy wyświetlić tylko podstrony wp_list_pages – możemy użyć identyfikato-
• custom – używa wartości podanych dla konkretnej strony, używamy identyfikatora rów title_li, include oraz exclude. Mamy
parametrów before i after. child_of. Jako wartość możemy podać nu- również możliwość ograniczenia liczby wy-
mer ID strony, której podstrony chcemy po- świetlanych kategorii, używając identyfikato-
Ostatnim identyfikatorem jest show _ post _ kazać. Kolejnym ważnym atrybutem jest echo, ra number i podając jako wartość maksymalną
count, który odpowiada za wyświetlenie licz- które określa, czy lista ma zostać wyświetlo- liczbę wyświetlanych kategorii.
by postów w archiwach. Działa ze wszyst- na (domyślnie wartość 1) czy zwrócona przez Aby wyświetlić listę autorów, używamy
kimi wartościami type oprócz postbypost. funkcję, (wartość 0). Funkcja ta jest odpowie- funkcji wp_list_authors. Przyjmuje ona jeden
Jeżeli wartość show _ post _ count wynosi 1, dzialna za jeszcze kilka innych atrybutów, np. parametr, który określa różne opcje. Format
WordPress wyświetli liczbę postów. Jeżeli nie wyświetlanie daty, obsługę pól Custom Field tego ciągu znaków jest identyczny jak w przy-
chcemy wyświetlenia tej informacji, podaje- Key i Custom Field Value. padku funkcji wp_list_pages. Najważniejszy-
my wartość zero. Wartość zero jest domyśl- Aby wyświetlić listę kategorii, powinni- mi parametrami, które możemy ustawić, są:
ną wartością, więc jeśli nie podamy tego para- śmy użyć wp_list_categories. Podobnie optioncount (wartości 1 lub 0) – umożliwiają-
metru, to WordPress domyślnie nie wyświetli jak przy kilku poprzednich funkcjach tu- ca pokazanie listy postów, oraz show_fullname
liczby postów. taj także przekazujemy argumenty, używa- (wartości 1 lub 0) – nakazująca wypisanie imie-
Gdy chcemy wyświetlić listę stron (Pages), jąc odpowiednio sformatowanego ciągu zna- nia i nazwiska autora zamiast nicka.
powinniśmy użyć funkcji wp_list_pages. ków. Do określenia kolejności wyświetlania Do zakończenia budowy naszego panelu bocz-
Funkcja ta przyjmuje parametry w sposób kategorii służy identyfikator orderby, który nego brakuje nam jeszcze tylko listy linków. Do
identyczny jak wp_get_archives, używając pozwala sortować według numeru ID (war- ich wyświetlenia służy funkcja get_links_list.
tak formatu zapytania (ang. query string). tość id), nazwy kategorii (wartość name) oraz Jako jedyny parametr możemy przekazać to, we-
Aby określić wyświetlany tytuł listy, usta- liczby postów (wartość count). Aby określić dług jakiej kolumny zostaną uporządkowane
wiamy odpowiednią wartość dla identyfika- kolejność wyświetlania, używamy identyfi- linki. Poprawnymi ergumentami są wartości:
tora title_li. Możemy także posortować
strony, używając identyfikatora sort_column
Listing 4. Dwie pętle z postami z użyciem rewind_post
oraz odpowiednich wartości:
<?php
• post _ title – domyślne, sortowanie if (have_posts()) :
według tytułu strony; while (have_posts()) : the_post();
• menu _ order – sortowanie według tzw. if( in_category(3) )
Page Order ustawianego w panelu admini- echo '<div class=”featured” >'.the_content().'</div>;
stratora; endwhile;
• post _ date – sortowanie według daty endif;
utworzenia; rewind_posts();
• post _ modified – sortowanie według daty if (have_posts()) :
ostatniej modyfikacji; while (have_posts()) : the_post();
• ID – sortowanie według numeru ID; if( !in_category(3) )
• post _ author – sortowanie według nu- echo '<div class=”post” >'.the_content().'</div>;
meru ID autora; endwhile;
• post _ name – sortowanie według tzw. endif;
Post slug. ?>
www.phpsolmag.org 25
Dla początkujących
id (numer ID linku) oraz name (tytuł linku). Do- W poprzedniej części poznaliśmy kilka ta- tor kategorii, jako drugi sposób wyświetla-
myślnie linki zostaną wyświetlone w kolejności kich funkcji. Były to funkcje umożliwiające nia linków podkategorii);
rosnącej. Aby wyświetlić je w kolejności maleją- wyświetlenie ID posta (the_ID), tytuł posta • the _ permalink – adres trwałego adresu
cej, musimy poprzedzić nazwę kolumny znakiem (the_title) czy treść (the_title). WordPress do postu;
_ (np _id lub _name). Na Listingu 2. możemy zo- oferuje wiele podobnych funkcji. Do najważ- • the _ excerpt – wyświetla fragment tre-
baczyć przykładowy kod panelu bocznego. niejszych należą: ści posta;
Wśród licznych funkcji szablonów możemy • the _ autor – autor posta (warto poznać
znaleźć takie, które działają tylko w pętli z po- • the _ category – wyświetlenie kategorii także inne funkcje, jak np.: the _ author _
stami (w szczególności po użyciu the_post). (jako pierwszy parametr podajemy separa- firstname, the _ author _ lastname, the _
author _ ID, itd.);
• oraz the _ time – czas dodania posta
Listing 6. Przykład pliku szablonu komentarzy
(jako argument przyjmuje format czasu i
<h2 id="comments"><?php comments_number(__('Brak komentarzy'), __('1 komentarz'), daty zgodny z funkcją date).
__('% komentarzy')); ?>
<?php Większość tych funkcji ma także odpowied-
//Sprawdzamy, czy są komentarze niki, które zwracają dane zamiast je wyświe-
<?php if ( $comments ) : ?> tlać np. get _ the _ content, get _ the _
<ol id="comments"> title, itd. WordPress oferuje także funk-
<?php cje pozwalające na nawigację miedzy posta-
//Przechodzimy pętlą po komentarzach i wyświetlamy komentarze mi. Next _ post _ link wyświetla następny
foreach ($comments as $comment) : ?> post, a _ post _ link – poprzedni. Pierwszy
<li id="comment-<?php comment_ID() ?>"> parametr to format wyświetlania linku, a
<?php comment_text() ?> miejsce wstawienia znacznika <a> oznacza-
<p><cite>przez <?php comment_author_link() ?>, <?php comment_date() ?> my tekstem %link. Jeżeli podamy wartość
<?php comment_time() ?></cite> <?php edit_comment_link('Edytuj', ' |'); ?></p> Przejdź do %link, to WordPress wygeneruje
</li> kod Przejdź do <a href=”...”>...</a>. Do-
<?php endforeach; ?> myślnie skrypt przyjmuje format »
</ol> %link. Jako drugi parametr podajemy for-
<?php else : // Jeżeli nie ma jeszcze komentarzy ?> mat tytułu linku. Miejsce wstawienia
<p>Brak komentarzy</p> tytułu posta oznaczamy tekstem %title.
<?php endif; ?> Domyślnie wyświetlany jest tylko tytuł
<?php posta. Trzeci argument określa, czy na-
//Jeżeli można komentować stępny post ma być tylko z tej samej kate-
if ( comments_open() ) : ?> gorii (wartość true), czy także z innych
<h2 id="postcomment">Komentuj</h2> (wartość false). Domyślnie WordPress
<form action="<?php echo get_option('siteurl'); ?>/wp-comments-post.php" method="post" przyjmuje wartość false, jeżeli nie podamy
id="commentform"> wartości tego parametru. Ostatni parametr,
<?php jaki możemy przekazać, to numery ID kate-
//Jeżeli użytkownik jest zalogowany gorii, jakie chcemy wykluczyć. W wersji 2.2
if ( $user_ID ) : ?> numery ID powinny być rozdzielone prze-
<p>Zalogowany jako <a href="<?php echo get_option('siteurl'); ?>/wp-admin/ cinkiem (np. '4, 5, 6'). We wcześniejszych
profile.php"><?php echo $user_identity; ?></a>.</p> wersjach separatorem był tekst and (np.
<?php else : ?> '4 and 5 and 6').
<p><input type="text" name="author" id="author" value="<?php echo $comment_author; ?>" WordPress udostępnia jeszcze szereg innych
/> funkcji. Dodatkowo pewne rozszerzenia doda-
<label for="author"><small>Autor</small></label></p> ją własne funkcje, których możemy używać w
<p><input type="text" name="email" id="email" value="<?php echo $comment_author_email; szablonach. W tej części artykułu poznaliśmy
?>" /> te najczęściej wykorzystywane. W dalszej czę-
<label for="email"><small>Adres e-mail (nie zostanie opublikowany) </small></label></ ści artykułu pojawią się jeszcze inne przydat-
p> ne funkcje.
<p><input type="text" name="url" id="url" value="<?php echo $comment_author_url; ?>"
/> Pętla z postami i własne zapytania
<label for="url"><small>Strona WWW</small></label></p> Pętla z postami jest najważniejszym elemen-
<?php endif; ?> tem treści niemal każdej strony WordPressu.
<p><textarea name="comment" id="comment"></textarea></p> Wcześniej poznaliśmy kilka przydatnych funk-
<p><input name="submit" type="submit" id="submit" value="Komentuj" /> cji, które możemy wykorzystywać tylko w pętli.
<input type="hidden" name="comment_post_ID" value="<?php echo $id; ?>" /> Kluczowymi funkcjami dla pętli są have_posts
</p> i the_post, które zostały opisane już wcześniej.
<?php do_action('comment_form', $post->ID); ?> Teraz nauczymy się rozwiązywać przy pomocy
</form> wybranych funkcji różne problemy.
<?php else : // Komentowanie nie jest dozwolone ?> Załóżmy, że na stronie głównej nasze-
<p>Nie można komentować tego postu</p> go bloga chcielibyśmy wyeksponować w
<?php endif; ?> szczególny sposób posty z jednej kategorii.
26 05/2007
WordPress
W jaki sposób możemy to osiągnąć? Każ- query_posts('cat=3,5,7'); spowoduje pobranie posta o uproszczonej na-
dy post może znajdować się w kilku kate- zwie first-name. Możemy także chcieć pobrać
goriach. Wyobraźmy sobie, że dysponujemy Jeżeli chcemy wykluczyć pewną kategorię, wybraną stronę. W tym celu wykorzystamy
kategorią „Featured”, której posty chcemy dodajemy znak – przed numerem kategorii. page _ id.
wyeksponować. Załóżmy też, że kategoria ta Używając poniższego wywołania, wyświetlimy
ma ID równe 3. Do sprawdzenia, czy dany posty z wszystkich kategorii z wyjątkiem 3. query_posts('page_id=2');
post jest w naszej kategorii, użyjemy funk-
cji in_category. Przyjmuje ona jako para- query_posts('cat=-3'); Przy pomocy query _ posts możemy tak-
metr numer ID kategorii i sprawdza, czy że podać, ile postów chcemy pobrać (np.
aktualnie przetwarzany post w pętli należy Jeżeli chcemy zamiast ID kategorii podać showposts=3) oraz ile najnowszych postów
do tej kategorii. Na Listingu 3. możemy zoba- jej nazwę, musimy zamiast cat zastosować ma zostać pominiętych (offset=5). Wszyst-
czyć, jak wygląda odpowiedni fragment ko- category _ name. Poniższe wywołanie funkcji kie powyższe części możemy łączyć, używa-
du. Wszelkie elementy nawigacyjne zostały wyświetli posty z kategorii „Featured clips”. jąc znaku &. Aby pobrać np. 5 najnowszych
celowo pominięte. postów z kategorii 3., wywołamy funkcję
Warto wspomnieć jeszcze, że gdybyśmy query_posts('category_name=Featured clips') query _ posts w następujący sposób.
używali tego pliku jako szablonu nie tyl-
ko dla strony głównej, ale także dla innych Możemy także wyświetlić posty konkretne- query_posts('cat=3&showpost=5');
podstron, musimy sprawdzić, czy jesteśmy go autora. Używając author i podając ID au-
na stronie głównej. Aby to uczynić, używa- tora lub używając author _ name i podając Możemy także posortować posty względem
my funkcji is_home. Gdybyśmy o tym za- wartość z kolumny user _ nicename w tabeli innego parametru niż data dodania. Służą
pomnieli, nie moglibyśmy wyświetlić listy użytkowników. do tego orderby do określenia kolumny sor-
postów z kategorii „Featured”. Odpowiedni towania oraz order do określenia porządku
warunek powinien wyglądać tak: query_posts('author=3'); sortowania. Funkcja query _ posts ma jesz-
query_posts('author_name=Kodie'); cze kilka przydatnych opcji, z którymi war-
if( is _ home() && in _ category(3) ) to się zapoznać.
Możemy także pobrać pojedynczy post uży- Są to między innymi wyświetlenie po-
Wyobraźmy sobie, że chcielibyśmy wy- wając p i jako argument podając numer ID stów z wybranego roku ( year=2005), miesią-
świetlić najpierw najnowsze posty z kate- posta lub używając name i podając tzw. post ca (monthnum=6), dnia (day=15) oraz kilka in-
gorii „Featured”, a dopiero potem pozosta- slug, czyli uproszczoną tytuł posta. Poniższe nych. Wymienione zostały te najważniejsze
łe. Wykorzystamy tutaj ponownie funk- wywołanie funkcji spowoduje pobranie posta parametry, z tymi rzadziej wykorzystywa-
cję in _ category. Aby „przewinąć” posty o numerze ID równym 3. nymi możemy zapoznać się w Internecie na
i rozpocząć pętlę od nowa, musimy wyko- stronie: http://codex.wordpress.org/Template_
rzystać funkcję rewind _ posts. Dzięki te- query_posts('p=3') Tags/query_posts.
mu znowu będziemy mogli w taki sam spo- Wiemy już, w jaki sposób pobrać no-
sób jak w pierwszym przypadku wykorzy- Natomiast wywołanie we posty. Teraz zostaje tylko ponownie
stać funkcje have _ posts i the _ post. Na wykorzystać znane nam już dobrze funk-
Listingu 4. możemy zobaczyć kod wykonu- query_posts('name=first-post'); cje have_posts i the_post. Na Listingu 5.
jący dwie pętle.
Może się zdarzyć jednak tak, że oprócz naj-
Listing 7. Plik functions.php
nowszych postów będziemy chcieli wyświetlić
dokładnie 5 najnowszych postów z jednej wy- <?php
branej kategorii. Wtedy będziemy musieli – po- function my_get_the_image($content){
dobnie jak wcześniej – wykonać pętlę dwa razy. //Szukamy znacznika <img
Musimy jednak wywołać nowe zapytanie. W $img = strpos( $content, '<img');
tym celu wykorzystamy funkcję query_posts. //Jeżeli takiego nie ma, zwracamy pusty ciąg znaków
Jako jedyny parametr przyjmuje ona ciąg zna- if( $img === false ) return '';
ków określający, co ma zostać pobrane, ile po- //Szukamy ciąg src=”
stów i jak mają zostać uszeregowane ponow- $srcpos = strpos( $content. 'src=”', $img ) + 5; /* = strlen('src=”') */
nie, wykorzystując format query string. Z tych //Pobieramy adres obrazka
informacji WordPress sam tworzy zapytanie $path = substr($content, $srcpos, strpos($content, '”', $srcpos) - $srcpos);
SQL. Jakie zatem informacje możemy przeka- //Zwracamy nową wartość
zać tej funkcji? return '<img src=”'.$path.'” class=”thumb”/>';
Rozpoczniemy od podania kategorii, z któ- }
rej chcemy pobrać posty. Do tego służy identy- ?>
fikator cat. Odpowiednie wywołanie tej funk-
cji, aby pobrać tylko posty z kategorii 3., wyglą- Listing 8 Komentarze WordPress
dałoby następująco. $query = new WP_Query();
$query->query('cat=3');
query_posts('cat=3'); if( $query->have_posts() )
while( $query->have_posts() ){
Jeśli chcielibyśmy pobrać posty z kilku katego- $query->the_post();
rii, musimy oddzielić je przecinkami. Poniż- /* ... */
szy kod pozwala nam wyświetlić posty z kate- }
gorii 3., 5. oraz 7.
www.phpsolmag.org 27
Dla początkujących
możemy zobaczyć kod wykorzystujący funk- z nadpisywaniem wyników i używaniem wty- funkcję comment_author_link. Jeżeli nie
cję query_posts. czek, teraz zajmijmy się komentarzami. chcemy wyświetlać linku, a tylko samego au-
Co jednak stanie się, jeżeli zapragniemy tora, możemy posłużyć się funkcją comment_
wykorzystać query_post przed wywołaniem Komentarze author. Sam adres URL możemy wyświe-
pierwszej pętli? Nie będziemy mogli już wy- Nieodłączną częścią każdego bloga są komenta- tlić, używając funkcji comment_author_url,
korzystać wyniku pierwszego zapytania, gdyż rze. WordPress oferuje gotowe funkcje i rozwią- a cały link – comment_author_url_link.
zostanie nadpisany drugim. Jak wybrnąć z tej zania do wykorzystania. Szablon komentarzy Do wyświetlenia kolejno adresu e-mail i łącza
sytuacji? Są dwa rozwiązania. Musimy wie- znajduje się w pliku comments.php, jeśli jednak do niego używamy odpowiednio comment_
dzieć, że funkcje query_posts, have_posts i go nie stworzymy, WordPress użyje domyślne- author_email i comment_author_email_link.
the_post zapisu wykorzystują wyniki zapisa- go szablonu ze skórki default. Nie powinniśmy jednak wyświetlać adresu
ne w zmiennej $wp_query. Możemy zatem za- Aby dołączyć komentarze do naszej stro- e-mail autora komentarzy ze względu na
pisać kopię zmiennej $wp_query w zmiennej ny, musimy posłużyć się funkcją comments_ ochronę naszych użytkowników przed spa-
tymczasowej, wywołać zapytanie, a potem template. Jako jedyny parametr możemy po- mem. Możemy jeszcze pokazać link do edycji
przywrócić oryginalną zawartość $wp_query. dać jej nazwę naszego szablonu. Jeśli jej nie po- komentarza. W tym celu wykorzystamy funk-
W PHP 4 wystarczy przypisać zmienną damy, WordPress automatycznie uzna, że sza- cję edit_comment_link. Przyjmuje ona trzy
$wp_query do innej zmiennej. W ten sposób blon nazwaliśmy comments.php. Funkcja ta za- argumenty: tekst łącza, tekst wyświetlany
zostanie stworzona jej kopia: działa tylko, jeżeli nasza strona wyświetla stro- przed znacznikiem <a> oraz jako trzeci tekst
nę, post lub zmienna $withcomments ustawio- wyświetlany po znaczniku </a>. Funkcję tę
$temp_query = $wp_query; na jest na true. możemy wywołać w następujący sposób:
Rozpocznijmy tworzenie szablonu z ko-
Jednak w PHP 5 operator = przypisuje referen- mentarzami. Przechowywane są one w zmien- edit_comment_link('edycja komentarza',
cje, a nie kopie obiektu. Musimy zastosować nej $comments. Musimy także wiedzieć, że '<p>', '</p>');
nowy operator klonowania obiektu: clone. większość funkcji pobierająca lub wyświetla-
jąca dane wybranego komentarza pobiera je Najważnieszją funkcją jest wyświetlenie tre-
$temp_query = clone $wp_query; ze zmiennej $comment. W takim razie nasza ści komentarza. W tym celu posłużymy się
pętla wyświetlająca komentarze powinna wy- comment _ text. To są najważniejsze funk-
Następnie wystarczy po pętli przypisać do glądać tak: cje obsługi pojedynczego komentarza, warto
$wp _ query zawartość $temp _ query. Na początku tego kodu sprawdzamy, czy są też zapoznać się z tymi rzadziej używanymi.
Niestety, używając tej metody, musimy albo jakieś komentarze, a następnie w pętli wyświe- Informacje o nich możemy znaleźć w pliku
znać wersję PHP, na której będzie umieszczo- tlamy je. Teraz poznamy funkcje pozwalające wp-includes/comment_template.php oraz w doku-
na strona, albo sprawdzać wersję przed stworze- wyświetlić poszczególne elementy komenta- mentacji na stronie http://codex.wordpress.org/
niem kopii. Jest jednak inne rozwiązanie. Funk- rza. Są one bardzo podobne do funkcji wyświe- Template_Tags#Comment_tags.
cje query_posts, have_posts oraz the_post tlającej posty. Comment_ID wyświetla numer ID Wyświetlając posty, musimy także spraw-
są tylko funkcjami ułatwiającymi działanie na komentarza. Comment_date wyświetla datę do- dzić, czy dany post nie czeka w kolejce do
obiekcie WP_Query przechowywanym w zmien- dania komentarza. Jako jedyny parametr po- moderacji. Aby to uczynić, sprawdzamy
nej $wp_query. Zamiast używać tych funk- dajemy format daty zgodnie z formatem funk- wartość pola $comment->comment_approved.
cji możemy samodzielnie stworzyć obiekt WP_ cji date. Jeśli nie podamy formatu, WordPress Jeżeli wynosi ona zero, oznacza to, że komen-
Query i zamiast funkcji query_post wykorzy- pobierze format z ustawień bloga. Podobną tarz nie przeszedł jeszcze procesu moderacji.
stać metodę query. Zamiast funkcji have_posts funkcją jest comment_time, która wyświetla W tym wypadku powinniśmy wyświetlić sto-
i the_post używamy metod tego obiektu o tej sa- czas dodania posta. Jeżeli nie podamy żadne- sowną informację.
mej nazwie. Zatem wywołanie funkcji wraz z pę- go parametru lub przekażemy pusty ciąg zna- Zajmijmy się teraz innymi funkcjami.
tlą powinno wyglądać następująco: ków, WordPress ponownie pobierze formato- Funkcja comments_number oferuje nam moż-
Niektóre wtyczki mają problemy z radze- wanie czasu z ustawień bloga. Jako drugi para- liwość wyświetlenia liczmy komentarzy.
niem sobie z wieloma zapytaniami. Aby temu metr możemy podać, czy chcemy wyświetlić Przyjmuje ona dokładnie trzy argumenty:
zaradzić, powinniśmy wywołać update_post_ czas lokalny (wartość false), czy czas GMT tekst do wyświetlenia w przypadku braku
caches($posts) po wywołaniu metody lub (wartość true). Domyślnie wyświetlany jest komentarzy, tekst do wyświetlenia w przy-
funkcji the_post. czas lokalny. padku jednego komentarza oraz tekst do wy-
Wiemy już, jak wykonać osobne zapytania i Aby wyświetlić autora wraz z podanym świetlenia w przypadku wielu komentarzy.
jak poradzić sobie z problemami związanymi przez niego adresem URL, wykorzystujemy W tym ostatnim przypadku, aby wskazać
miejsce wystąpienia liczby, używamy znaku
% . Zatem wywołanie funkcji:
Listing 9. Wywoływanie metody the_post
28 05/2007
WordPress
tytuł łącza, jako drugi możemy podać skrypt wanych w szablonach albo do dodania strony akcji wp_head, która wywołana jest tuż przed
generujący plik RSS. Jeżeli nie podamy te- w panelu administratora. Kiedy możemy wy- zamknięciem znacznika head. Przyjmijmy,
go pliku, WordPress użyje domyślnego pliku korzystywać taki plik? Możliwości jest wiele. że nazwiemy naszą funkcję my_custom_head.
wp-commentsrss2.php. Przed wyświetleniem My wykorzystamy tę funkcjonalność, aby wy- Przykładowe wywołanie funkcji add_action
formularza dodającego komentarze musi- świetlić miniaturkę pierwszego obrazka postu może wyglądać tak jak kod poniżej.
my sprawdzić, czy możemy dodawać ko- (o ile istnieje) przed fragmentem tekstu.
mentarze. Jeśli tak, to wartość pola $post-> Zastanówmy się, w jaki sposób może dzia- add_action('wp_head', 'my_custom_head');
comment_status będzie wynosić “open”. łać taka funkcja? Przede wszystkim pobierze-
Jeśli można dodawać komentarze, to wyświe- my adres pierwszego obrazka z treści. Aby Nasza funkcja my _ custom _ head będzie wy-
tlamy formularz. Jako parametr action formu- pobrać treść, wykorzystamy funkcję get_the_ pisywała treść, używając funkcji echo. Jej kod
larza ustawiamy plik wp-comments-post.php. content. Należy pamiętać, że większość wty- możemy zobaczyć na Listingu 6. Warto wspo-
Aby podać dokładny adres, używamy funk- czek, które modyfikują treść posta, nie zadzia- mnieć, że do jednej akcji możemy przypisać
cji get_option podając jako parametr tekst ła, gdy używamy get_the_content. Gdy za- wiele funkcji, które mają zostać uruchomio-
siteurl. Znacznik otwierający formularz mo- leży nam na zadziałaniu wtyczek (np. wtycz- ne. Oprócz akcji możemy używać także fil-
że wyglądać następująco: ki galerii), to najłatwiejszym wyjściem będzie trów, które pozwalają nam zmodyfikować da-
użycie funkcji ob_start, wywołanie the_ ne przed wyświetleniem. Przykładem takie-
<form action="<?php echo get_option(' content, później zapisanie treści do zmien- go zastosowania może być na przykład filtr
siteurl'); ?>/wp-comments-post.php" nej używając funkcji ob_get_contents oraz zmieniający w treści posta emotikony na ob-
method="post" id="commentform"> użycie ob_end_clean do wyczyszczenia bufo- razki przed wyświetleniem. Najważniejszą
ra. Skupmy się teraz na odnalezieniu obrazka. różnicą między filtrami a akcjami jest to, że
Dalej wyświetlamy pola formularza. Pamię- Mając treść strony, wystarczy odnaleźć znacz- filtry przyjmują wartość do zmiany jako pa-
tajmy, że dla zalogowanych użytkowników nik <img> a w nim atrybut src. Dla uprosz- rametr i zwracają ją używając return. Akcje
nie musimy wyświetlać pól: autor, e-mail czenia przyjmijmy, że dokument jest sforma- natomiast nie przyjmują argumentów i wy-
i strona WWW. Aby to sprawdzić, spraw- towany poprawnie i wartość atrybutu znaj- świetlają wynik swojego działania bezpośred-
dzamy, czy $user _ ID nie jest fałszem lub duje się w cudzysłowie po znaku równości. nio na stronie (np. przez funkcję echo). Pełną
nie jest pusty. Pola formularza mają ściśle Takie zadanie można wykonać na wiele spo- listę filtrów i akcji znajdziemy pod adresami
określone nazwy. Zatem pole autor ma na- sobów. My wykorzystamy najprostszy z uży- podanymi w ramce. Filtry i akcje są przydat-
zwę author, pole e-mail nazwę email, pole ciem funkcji strpos i substr. Nazwiemy ne, lecz częściej niż w szablonach wykorzystu-
strony WWW nazwę url, a pole treści ko- naszą funkcję my_get_the_image i zapiszemy je się je przy budowie wtyczek. Pozostaje pyta-
mentarza nazwę comment. Musimy jeszcze ją w pliku functions.php. Jej kod możemy zoba- nie, kiedy używać wtyczek, a kiedy pliku func-
dodać ukryte pole o nazwie comment _ czyć na Listingu 7. tions.php. Używając obu rozwiązań, możemy
post _ ID o wartości $id . Jeśli chcemy wy- W kodzie pliku home.php w miejscu, gdzie stworzyć rozwiązania o podobnej funkcjonal-
świetlić listę znaczników, które mogą zostać powinien pojawić się adres obrazka, wstawia- ności. Musimy pamiętać jednak o tym, że plik
użyte w komentarzach, używamy funkcji my poniższą linię functions.php działa tylko dla określonego sza-
allowed _ tags. Przed znacznikiem zamy- blonu, a nie dla wszystkich, jak ma to miej-
kającym formularz powinniśmy jeszcze dać echo my_get_the_image( get_the_content() ); sce z wtyczkami. Plik functions.php jest tylko
wywołanie funkcji do _ action, co umożli- formą pomocy szablonom w wyświetlaniu
wi wtyczkom modyfikacje naszego formula- Oczywiście obrazek należy przeskalować. danych czy też stworzeniu pewnych opcji kon-
rza. Wywołanie tej funkcji powinno wyglą- Można w tym momencie skorzystać np. ze figuracji szablonu. Jednak do modyfikacji da-
dać następująco: skryptu phpThumb lub samodzielnie utworzyć nych powinniśmy raczej używać wtyczek.
miniaturkę i zapisać ją na dysku i zwrócić do
do_action('comment_form', $post->ID); niej ścieżkę. Zachęcam do samodzielnego wy- Podsumowanie
konania takiej funkcji. Dla naszych potrzeb W artykule starałem się pokazać, że tworzenie
Na Listingu 6. możemy zobaczyć przykłado- zadowolimy się przeskalowaniem za pomo- szablonów w WordPressie daje znacznie więk-
wy plik wyświetlający komentarze. Gdy pro- cą stylów CSS. Trzeba jednak pamiętać, że to sze możliwości niż tylko zmiana wyglądu. Od-
jektujemy własną skórkę, zwykle łatwiej jest rozwiązanie ma swoje wady. powiednio wykorzystana wiedza pozwala prze-
skopiować plik comments.php ze skórki default Używając pliku functions.php, możemy rów- kształcić nasz blog nie do poznania. Niniejszy
i zmodyfikować ten plik niż tworzyć całość od nież dodać własne funkcje do akcji. Służy do artykuł jest tylko wprowadzeniem w tematy-
początku. tego funkcja add_action. Dzięki niej mamy kę tworzenia skórek. Zapoznanie się ze strona-
ogromne możliwości modyfikacji wyświetla- mi podanymi w ramce na pewno pomoże jesz-
Functions.php nych elementów zarówno na stronie bloga, cze rozszerzyć wiedzę i zobaczyć więcej intere-
Poznaliśmy już, jak tworzyć pliki szablo- jak i w panelu administratora. Nasza funkcja sujących przykładów oraz rozwiązań.
nów. WordPress oferuje nam także dodatko- zostanie wywołana w odpowiednim momen-
wy plik functions.php, który jest wczytywany cie, tak że będziemy mogli dodać własne dane.
przed szablonami. Może on posłużyć np. do Zobaczymy, jak moglibyśmy dodać do sekcji
zdefiniowania własnych funkcji wykorzysty- HEAD naszej strony kod JS lub CSS. Użyjemy
KONRAD GOŁUCHOWSKI
W Sieci Autor od wielu lat zajmuje się programowaniem
w języku PHP. Jest administratorem i redaktorem
• http://codex.wordpress.org/ – strona dla administratorów i deweloperów WordPressa serwisów CompZone.Org i TryCMS.org. Progra-
• http://codex.wordpress.org/Template_Hierarchy – hierarchia szablonów
muje także w językach Java i C++.
• http://codex.wordpress.org/Plugin_API/Filter_Reference – filtry w WordPressie
• http://codex.wordpress.org/Plugin_API/Action_Reference – akcje w WordPressie Kontakt z autorem:
kodie@compzone.org, kodie@trycms.org
www.phpsolmag.org 29
Dla początkujących
Symfony Framework
Część pierwsza – Moduł Użytkownika
S
ymfony jest frameworkiem typu RAD, wer i uruchomić w przeglądarce internetowej. pomocy następujących poleceń:
dzięki któremu można tworzyć w bardzo W tym celu:
szybki i przyjemny sposób aplikacje bazo- pear channel-discover pear.
danowe. Pozwala na łączenie się z ważniejszymi • Pobieramy sf_sandbox.tgz z http://www. symfony-project.com
typami bazy danych. Proces tworzenia przyszłej symfony-project.com/get/sf_sandbox.tgz, rozpa- pear install symfony/symfony
aplikacji polega na utworzeniu aplikacji frontend, kowujemy i kopiujemy do katalogu, z które- pear install http://phing.info/pear/
a następnie modułów użytkownik, posty, osym- go będzie miał dostęp Apache; phing-current.tgz
fony, kontakt. Podczas tworzenia modułu gene- • Konfigurujemy wirtualny host w pliku
rowana jest podstawowa klasa akcji, którą w póź- konfiguracyjnym serwera Apache, jak wi- (instalujemy pakiet, jeśli nie był wcześniej
niejszej fazie programowania będziemy systema- dać na Listingu 1; zainstalowany). Po wykonaniu polecenia
tycznie uzupełniać. Będziemy projektowali pro- • Przeładowujemy serwer Apache. symfony – V powinien pojawić się napis z
sty system rejestracji nowego użytkownika, logo- wersją Symfony, w moim przypadku Symfony
wania oraz dodawania przez niego postu z moż- Jest to bardzo dobre rozwiązanie do testów, nie version 1.0.4
liwością edycji, jak widać na Rysunku 1. Struk- jest jednak zalecane do aplikacji końcowych, Konfigurację wirtualnego hosta wykonu-
tura naszego projektu będzie składała się z nastę- które mają być dostępne szerszemu gronu użyt- jemy tak samo jak w przypadku sf_sandbox.
pujących katalogów apps, batch, cache, config, da- kowników. W tym celu lepiej zainstalować Jeśli wszystko przebiegło prawidłowo i instala-
ta, doc, lib, log, plugins, test, web. W tym artyku- symfony ręcznie, jak jest to opisane poniżej. cja Symfony zakończyła się sukcesem, to po wy-
le będziemy głównie zajmować się katalogiem wołaniu strony ukaże się nam informacja jak na
apps, który z kolei będzie składał się na katalog Instalacja pod Linuksem Rysunku 2.
frontend a w nim będą zawarte config, i18n, lib, Aby zainstalować poprawnie działające Sym-
modules, templates. Następnie katalog modules bę- fony z biblioteką Propel i Creole, należy wyko- Uwaga
dzie zawierał wygenerowane moduły m.in. uzyt- nać następujące czynności z poziomu shella z Bardzo ważne jest, aby serwer Apache miał
kownik. W module tym będą katalogi actions, uprawnieniami roota: możliwość zapisywania w katalogu cache i log.
config, lib, templates i validate. W actions zawar-
ta będzie klasa actions.class.php odpowiedzialna • instalujemy PEAR::Log poleceniem cffff; Konfigurujemy Symfony
za główną funkcjonalność modułu uzytkownik. • następnie przy pomocy PEARA instaluje- i bazę danych
Z kolei templates będzie zawierał szablony, które my Propel poleceniami: Tworzymy bazę danych tak jak na Listingu 2,
będą wykorzystywane w metodach klasy actions. • pear install http://propel.phpdb.org/ a następnie konfigurujemy pliki database.yml
Katalog validate służy do umieszczania plików, pear/propel_generator-current.tgz; i propel.ini, jak to widać na Listingu 3. i 4.
30 05/2007
Symfony Framework
Uwaga
Przy konfiguracji plików z rozszerzeniem yml Listing 1. Konfiguracja wirtualnego hosta w pliku httpd.conf Apache'a
należy używać wyłącznie spacji, nie można
używać tabulatora, w przeciwnym razie będzie <VirtualHost 127.0.0.1:80>
zgłaszany błąd. W przyszłości więc jeśli będzie- # nazwa hosta, po którym będzie wywołanie strony w przeglądarce internetowej
my edytować pliki register.yml i login.yml spraw- # http://symfony
dzanie formularza nie zadziała prawidłowo, ServerName symfony
należy najpierw sprawdzić plik yml, czy czasa- # w tym miejscu podajemy ścieżkę dostępu do katalogu symfony i podkatalogu web
mi nie ma gdzieś tabulatora. Następnie musimy DocumentRoot „/var/www/html/symfony/web”
założyć kilka tabel w bazie danych, które będą # definiujemy, że jako pierwszy ma być przeczytany index.php
niezbędne w naszym projekcie. Przede wszyst- DirectoryIndex index.php
kim należy przeanalizować problem. Ogólna # definiujemy alias do katalogu sf znajdującego się w katalogu web
funkcjonalność aplikacji będzie następująca: Alias /sf /var/www/html/symfony/web/sf
# umożliwiamy dostęp do katalogu web
• rejestracja nowego konta; <Directory „/var/www/html/symfony/web”>
• panel logowanie; AllowOvveride All
</Directory>
</VirtualHost>
www.phpsolmag.org 31
Dla początkujących
• edycja profilu;
Listing 5. Zapisanie kolumn w znacznikach <column /> • przypomnienie hasła (wygenerowanie no-
<column name=”id” type=”integer” required=”true” wego i przesłanie e-mailem);
primaryKey=”true” autoIncrement=”true” /> • pisanie nowych postów;
<column name=”created_at” type=”timestamp” /> • walidacja formularzy;
<column name=”sha1_password” type=”varchar” size=”40” /> • wysyłanie e-maila z potwierdzeniem zało-
<column name=”salt” type=”varchar” size=”32” /> żenia konta;
<column name=”nick” type=”varchar” size=”20” /> • edycja podstron serwisu przy pomocy apli-
<column name=”strona_www” type=”varchar” size=”100” /> kacji backend.
<column name=”email” type=”varchar” size=”100” />
<column name=”podpis” type=”varchar” size=”255” /> Będą zatem potrzebne cztery tabele: użytkow-
<column name=”potwierdzenie” type=”integer” size=”5” /> nik, posty, osymfony i kontakt. Wobec tego edy-
<column name=”status” type=”integer” size=”1” default=”0” /> tujemy plik schema.xml, który znajduje się w
katalogu config.
Listing 6. Metoda executeRegister(). Odpowiedzialna za wyświetlanie formularza rejestracji i
zapisywania nowego użytkownika do bazy danych Uwaga
public function executeRegister() { Jeśli w katalogu istnieje plik schema.yml, nale-
// jeśli został wysłany formularz, zapisujemy nowego użytkownika do bazy danych, ży go usunąć, gdyż będziemy korzystać z pli-
// jeśli nie to formularz rejestracji ku zapisanego w XML-u. Jeśli plik schema.xml
if ($this->getRequest()->getMethod() == sfRequest::POST) { nie istnieje, tworzymy go. Na początku musi-
// generowanie liczby z podanego przedziału, wymagane przy potwierdzeniu konta my zdefiniować typ dokumentu xml. Ustawia-
$potwierdzenie = mt_rand(10000,99999); my również odpowiednie kodowanie znaków:
// zapisywanie danych do tabeli uzytkownik <?xml version=”1.0” encoding=”ISO-8859-2”?>
// tworzymy nowy obiekt klasy Uzytkownik Strukturę bazy danych zawieramy w znaczni-
$uzytkownik = new Uzytkownik(); ku <database></database>:
$uzytkownik->setNick($this->getRequestParameter('nick'));
$uzytkownik->setStronaWww($this->getRequestParameter('strona_www')); <database package=”lib.model” name=”propel”
$uzytkownik->setEmail($this->getRequestParameter('email')); defaultIdMethod=”native” noxsd=”true”>
$uzytkownik->setPodpis($this->getRequestParameter('podpis')); </database>
$uzytkownik->setPotwierdzenie($potwierdzenie);
// zapisujemy dane do tabeli użytkownika Następnie dodajemy tabelę użytkownik
$uzytkownik->save(); między znacznikami <database></database>.
// wysyłanie e-maila z potwierdzeniem tworzymy nowy obiekt klasy sfMail Poszczególne kolumny będą zawarte w znacz-
$mail = new sfMail(); niku <table></table>, gdzie phpName oznacza
$mail->initialize(); nazwę, do której będziemy się odwoływać
// ustawiamy sendmail jako główny program do wysyłania poczty, w systemach Linux w języku PROPEL. Dla wygody phpName
// sendmail może być aliasem do np. Postfixa ustawiamy na nazwę tabeli z tą różnicą, że
$mail->setMailer('sendmail'); pierwsza litera jest duża. Dzięki temu nazew-
// ustawiamy kodowanie nictwu unikniemy wielu problemów, któ-
$mail->setCharset('iso-8859-2'); re w późniejszym okresie tworzenia aplika-
// ustawiamy nadawcę cji mogą okazać się trudne do zlokalizowania
$mail->setSender('lukasz@helionet.com.pl','Redaktor'); i naprawienia.
$mail->setFrom('lukasz@helionet.com.pl','Redaktor');
// dodajemy adres e-mail rejestrowanego użytkownika <table name=”uzytkownik”
$mail->addAddress($this->getRequestParameter('email')); phpName=”Uzytkownik”>
// ustawiamy temat e-maila </table>
$mail->setSubject('Rejestracja konta i potwierdzenie');
// ustawiamy treść e-maila Do tabeli dodajemy kolumny id, created_at,
$mail->setBody(' sha1_password, salt, nick, strona_www, email, pod-
Witamy w testowym projekcie opartym na frameworku Symfony,\n\n pis, potwierdzenie i status. Każda kolumna będzie
Prosimy o potwierdzenie konta. W tym celu kliknij w poniższy link:\n zapisana w znaczniku <column /> – Listing 5,
http://symfony/uzytkownik/potwierdzenie/kod/'.$potwierdzenie.'\n\n W podobny sposób dodajemy pozostałe tabele sto-
Pozdrawiamy,\n sując się do podanych wytycznych: tabela posty:
Redakcja projektu Symfony w akcji ');
// wysyłamy e-mail • kolumna id typu integer z zaznaczoną
$email->send(); opcją required, podstawowym kluczem
// ustawiamy nowy szablon z komunikatem dla użytkownika tuż po pomyślnym primaryKey oraz automatyczną numera-
wysłaniu formularza cją autoIncrement;
$this->setTemplate('nowy_uzytkownik');; • kolumna id_uzytkownika typu integer
} else { z zaznaczoną opcją required;
// wyświetlanie formularza z szablonu registerSuccess.php • kolumna created_at typu timestamp;
return sfView::SUCCESS; • kolumna tytul typu varchar o rozmiarze
} size równym 255 znakom;
• kolumna tresc typu longvarchar.
32 05/2007
Symfony Framework
Moduł użytkownik
– klasa actions.class.php
Nasza pierwsza metoda executeRegister()
będzie umożliwiała wyświetlanie formula-
rza rejestracji oraz zapisanie nowego użyt-
kownika do tabeli uzytkownik. Metoda za-
mieszczona jest na Listingu 6. Z chwilą do-
dania użytkownika do bazy danych zo-
stanie wysłany e-mail z prośbą potwier-
dzenia konta. Wyświetlanie formularza
odbywa się za pomocą szablonu register-
Success.php, który należy utworzyć w katalo-
gu templates modułu użytkownik. Następnie
poddajemy go edycji. W pierwszej kolejno-
ści definiujemy możliwość sprawdzania for-
mularza poprzez plik register.yml umieszczo-
ny w katalogu validate. W tym celu plik ten
rozpoczynamy linią:
www.phpsolmag.org 33
Dla początkujących
<?php echo form_error('email') ?>, methods: Następnie określamy wymogi dla zmiennej nick:
<?php echo input_tag('email') post: [nick, email, haslo, powtorz_haslo,
strona_www, podpis] names:
Pole haslo: nick:
Wszystkie definicje pól będą występować po sło- required: true
<?php echo form_error('haslo') ?>, wie kluczowym names (wpisujemy tylko raz). required_msg: to pole jest wymagane,
<?php echo
input_password_tag('haslo')
Listing 7. Dodanie nickValidator i checkdbnickValidator
<?php echo form_error('podpis') ?>, Listing 8. Komunikaty zawarte w dyrektywach min_error i max_error
<?php echo input_tag('podpis') ?> strona_wwwValidator:
class: sfStringValidator
Następnie dodajemy ukryte pole referer funkcją: param:
min: 4
<?php echo input_tag('referer') ?>. max: 255
min_error: adres internetowy musi składać się przynajmniej z 4 znaków
Musimy również dodać przycisk umożliwia- max_error: adres internetowy nie może mieć więcej niż 255 znaków
jący wysłanie formularza. Użyjemy funkcji: podpisValidator:
<?php echo submit _ tag('zarejestruj') ?> class: sfStringValidator
i na samym końcu dodajemy oczywiście znacz- param:
nik </form>. W trakcie pracy nad różnymi for- min: 4
mularzami odkryjemy, że wbudowane funk- max: 255
cje w szablony Symfony są bardzo pomocne min_error: podpis musi składać się przynajmniej z 4 znaków
i często skracają czas pracy. W tabeli 1 przed- max_error: podpis nie może mieć więcej niż 255 znaków
stawiamy tagi html wykorzystywane przy
tworzeniu formularzy. Proszę zwrócić uwa- Listing 9. Zazwartość pliku myRegisternickValidator.class.php. Proszę zwrócić uwagę na proste
gę jak czytelne i krótkie są tagi Symfony. odwołania SQL w postaci języka PROPEL
W pierwszej kolumnie są przedstawione funk- <?php
cje umożliwiające tworzenie formularzy a w class myRegisternickValidator extends sfValidator {
drugiej zwracane wartości przez nie w posta- public function initialize($context, $parameter = null) {
ci kodu html. parent::initialize($context);
Mamy już formularz rejestracji. Teraz przy- $this->setParameter('nick_error', 'Invalid input');
dałaby się możliwość jego sprawdzania przy $this->getParameterHolder()->add($parameters);
wysyłaniu. Zatem tworzymy wcześniej wspo- return true;
mniany plik register.yml w katalogu validate. }
Zaczynamy od definicji zmiennych, które mają public function execute(&$value, &$error) {
być przekazywane z formularza nick, email, haslo, $nick = $value
powtorz_haslo, strona_www i podpis: // szukanie takiego samego nicka w tabeli uzytkownik, zapytanie w języku PROPEL
$c = new Criteria();
// odwołanie do tabeli uzytkownik do pola nick
$c->add(UzytkownikPeer::NICK, $nick);
$uzytkownik = UzytkownikPeer::doSelectOne($c);
// jeśli istnieje taki nick, to zostanie wywołany błąd
if ($uzytkownik) {
$error = $this->getParameter('nick_error');
return false;
}
return true;
}
Rysunek 5. Widok niewypełnionego formularza ?>
po przesłaniu
34 05/2007
Symfony Framework
haslo:
Listing 10. Zawartość pliku myRegisteremailValidator.class.php. Proszę zwrócić uwagę na proste
odwołania SQL w języku PROPEL required: true
required_msg: twoje hasło jest wymagane
<?php powtorz_haslo:
class myRegisteremailValidator extends sfValidator { required: true
public function initialize($context, $parameter = null) { required_msg: ponowienie twojego hasła jest
parent::initialize($context); wymagane
$this->setParameter('email_error', 'Invalid input'); validators: [checkhasloValidator]
$this->getParameterHolder()->add($parameters);
return true; Definicja dla zmiennej haslo jest troszkę in-
} na w porównaniu do powtorz_haslo dlate-
public function execute(&$value, &$error) { go, że validator checkhasloValidator będzie
$email = $value sprawdzał zgodność tych dwóch zmiennych.
// szukanie takiego samego e-maila w tabeli uzytkownik, W momencie gdy hasła nie będą się zgadza-
// zapytanie w języku PROPEL ły zostanie zwrócona informacja o błędzie
$c = new Criteria(); z właśnie tego validatora.
// odwołanie do tabeli uzytkownik do pola email Następne zmienne strona_www i podpis rzą-
$c->add(UzytkownikPeer::EMAIL, $email); dzą się tymi samymi wymaganiami, z tą różni-
$uzytkownik = UzytkownikPeer::doSelectOne($c); cą, że używają innych nazw validatorów ale o
// jeśli istnieje taki e-mail, to zostanie wywołany błąd tych samych właściwościach zmienna strona:
if ($uzytkownik) {
$error = $this->getParameter('email_error'); strona_www:
return false; required: false
} validators: [strona_wwwValidator]
return true;
} zmienna podpis:
?>
podpis:
Listing 11. Metoda setPassword() odpowiedzialna jest za kodowanie hasła. Nową funkcjonalność required: false
dodajemy w pliku Uzytkownik.php, który znajduje się w katalogu symfony/lib/model validators: [podpisValidator]
public function setPassword($password) {
$salt = md5(rand(100000, 999999).$this->getNick().$this->getEmail()); W przypadku tych dwóch zmiennych dyrekty-
$this->setSalt($salt); wy required zaznaczone są na false. Dzięki temu
$this->setSha1Password(sha1($salt.$password)); ustawieniu sprawdzane są tylko i wyłącznie w
} momencie gdy zostaną wypełnione a validatory
będą zwracać stosowne informacje w przypad-
Listing 12. Metoda executePotwierdzenie(), dzięki której nowe konto użytkownika jest ku nie spełnienia ich zależności. Następnym
akceptowane lub nie
krokiem jest tworzenie odpowiednich validato-
public function executePotwierdzenie() { rów, i tak dla sprawdzania hasła wpisujemy:
// tworzenie nowego obiektu klasy Uzytkownik
$uzytkownik = new Uzytkownik(); checkhasloValidator:
$uzytkownik = UzytkownikPeer::retrieveByKod($this->getRequestParameter('kod')); class: sfCompareValidator
// gdy zostanie znaleziony użytkownik o podanym kodzie, jego status będzie param:
// zamieniony z 0 na 1 check: haslo
if($uzytkownik) { compare_error: hasła nie zgadzają się
$uzytkownik->setStatus(1);
$uzytkownik->save(); Prawda, że proste. W wymaganiach do zmien-
// ustawiamy szablon nowy_uzytkownik_okSuccess.php nej powtorz_haslo utworzyliśmy powyższy
$this->setTemplate('nowy_uzytkownik_okSuccess.php'); validator i przekazaliśmy do niego zmienną
} else { haslo, dzięki temu zostały porównane dwie
// w przeciwnym razie zostanie wyświetlony komunikat o błędzie zmienne. Dodajemy kolejne dwa validatory nick-
// ustawiamy szablon nowy_uzytkownik_errorSuccess.php Validator i checkdbnickValidator odpowiedzial-
$this->setTemplate('nowy_uzytkownik_errorSuccess.php'); ne za sprawdzanie zmiennej nick – Listing 7.
} Validator checkdbnickValidator używa kla-
} sy, która jeszcze nie istnieje. Będzie to nasze
pierwsze rozszerzenie, w którym zdefiniu-
www.phpsolmag.org 35
Dla początkujących
36 05/2007
Symfony Framework
Metoda setPassword() aktywacji. Nową metodę dodajemy na końcu uzytkownik_errorSuccess.php (są to pliki in-
Musimy jeszcze dodać jedną metodę set- klasy actions.class.php (Listing 12). formacyjne, na razie zostawiamy je puste) w ka-
Password(), gdyż została ona użyta podczas za- talogu templates oraz register.yml w katalo-
pisywania hasła nowego użytkownika. Metoda ta Metoda executePotwierdzenie() gu validate modułu uzytkownik. Gdy zaloguje-
ma na celu zapisanie hasła w kodowaniu MD5 Aby nasza nowa metoda działała po- my się poprawnie, zostanie wyświetlony szablon
(Listing 11). Jeśli chcemy użyć naszych metod w prawnie musimy, dodać kolejną o nazwie login_uzytkownik_okSuccess.php. Jest to dla
klasie akcji, należy umieścić je w odpowiednim retrieveByKod(), która będzie umieszczona nas potwierdzenie, że się udało. Jeśli chcielibyśmy
miejscu, w naszym przypadku jest to główny_ w pliku UzytkownikPeer.php znajdującym zobaczyć, czy rzeczywiście została utworzona sesja,
katalog_symfony/lib/model/Uzytkownik.php. się w katalogu /katalog_główny_projektu/ możemy to sprawdzić dzięki frontend_dev.php,
Sprawdzamy nasz formularz rejestracji. Aby wpro- lib/model/ (Listing 13.). gdzie dev jest skrótem od deweloper. Wybieramy
wadzone zmiany były aktywne, ponownie wyko- zakładkę vars&config (Rysunek 6.), następnie glo-
nujemy polecenie w głównym katalogu projektu Metoda retrieveByKod() bals i na samym dole odszukujemy linijkę zaczyna-
./symfony clear-cache. Wciśnijmy najpierw Teraz zatem sprawdźmy, jak działa akceptacja jącą się od session. Powinno wyglądać to tak:
button zarejestruj i zobaczmy, jakie komunikaty nowego konta. Patrzymy do bazy danych (ta-
się pojawią – Rysunek 5. Teraz dodajemy nowe- bela Uzytkownik -> pole Potwierdzenie) lub do e- session:
go użytkownika. Klikamy zarejestruj. Jeśli nie zo- maila, na którego został wysłany link z potwier- symfony/user/sfUser/attributes:
stały zgłoszone błędy, zostanie wywołany szablon dzeniem, i w oknie przeglądarki internetowej symfony/user/sfUser/authenticated: 1
nowy_uzytkownikSuccess.php, w którym będzie wklejamy link: http://symfony/uzytkownik/ symfony/user/sfUser/credentials:
informacja o przesłanym e-mailu z linkiem do po- potwierdzenie/kod/87286 Jeśli kod okazał się subscriber
twierdzenia konta. Jest to swego rodzaju zabez- poprawny, to konto zostało aktywowane i od tej
pieczenie przed spamerami. Dodaliśmy nowego pory użytkownik może się logować do systemu. Podsumowanie
użytkownika, sprawdźmy teraz, jak zachowa To już wszystko. Gratuluję, jeśli dotąd dotarłeś.
się formularz rejestracji w przypadku podania Metoda executeLogin() Dowiedzieliśmy się wiele z tego artykułu. Pozna-
tego samego e-maila i nicka. Zostaną wyświetlo- Skoro mamy już działający poprawnie formularz re- liśmy proste zastosowanie praw. W następnej czę-
ne ostrzeżenia o istniejącej nazwie i e-mailu w jestracji, który potrafi analizować pola poprzez plik ści zajmiemy się pozostałymi modułami oraz do-
bazie danych. Nasz formularz jest już gotowy. register.yml, oraz poprawnie działającą aktywa- damy możliwość wylogowania się i przypomnie-
Ale utworzone konto nie jest jeszcze aktywne. cję konta, to teraz czas najwyższy zająć się nową me- nia hasła. Dowiemy się również, jak należy przypi-
W liście wysłanym do użytkownika został za- todą odpowiedzialną za logowanie użytkownika i sać prawa do konkretnych modułów i metod.
warty link potwierdzający rejestrację, który był przypisanie mu prawa subscriber, aby miał do-
przedstawiony na Listingu 5.: http://symfony/ stęp do swojego menu i zamieszczonego w nim lin-
uzytkownik/potwierdzenie/kod/'.$potwierdzenie.' ku do profilu, który będzie mógł edytować. Użyt- ŁUKASZ KLEJNBERG
Musimy do klasy akcji dodać nową metodę kownik zalogowany będzie mógł również pisać no- Autor jest studentem informatyki w Wyż szej Szko-
executePotwierdzenie(), która będzie pobie- we komentarze. Na końcu plik actions.class.php le Informatyki i Zarządzania w Rzeszowie. Pracuje
rała unikalny dla każdego użytkownika kod dodajemy metodą executeLogin(), która przed- jako projektant stron WWW w firmie Helionet.pl.
z linku. Następnie po poprawnym zatwier- stawiona jest na Listingu 14. Następnie należy Kontakt z autorem: lukasz@helionet.com.pl
dzeniu zostanie wyświetlony szablon nowy_ utworzyć pliki loginSuccess.php (Listing 15.), Na potrzeby artykułu został opracowany layout
uzytkownik_okSuccess.php, w którym będzie loginError.php (kopia pliku loginSuccess.php), graficzny przez Bartłomieja Kina, który również
informacja o poprawnym dodaniu konta i o jego login_uzytkownik_okSuccess.php i login_ pracuje w firmie Helionet.pl.
www.phpsolmag.org 37
Praktyka
P
rzy poszukiwaniu – adekwatnych do • $ _ SERVER['HTTP _ ACCEPT _ LANGUAGE'] widłowego działania niezbędne jest istnienie
realizacji postawionych sobie zadań – preferencje użytkownika dotyczące do- pliku browscap.ini po stronie serwera. W nie-
– narzędzi, może okazać się, że te do- myślnego języka strony; których przypadkach jest to trudne do zre-
stępne na rynku, nie odpowiadają stawianym • $ _ SERVER['HTTP _ REFERER'] – adres alizowania, dlatego w dalszej części artykułu,
wobec nich oczekiwaniom, a ich budowa jest strony, za pośrednictwem której nastąpiło przyjęliśmy, iż nie istnieje możliwość zastoso-
zbyt skomplikowana do samodzielnej modyfi- odwołanie do naszej (np. poprzez kliknię- wania funkcji.
kacji. Może zdarzyć się, że zależy nam na śle- cie odnośnika);
dzeniu ruchu robotów sieciowych (wyszukiwa- • $ _ SERVER['HTTP _ USER _ AGENT'] – ciąg Funkcje rozszerzające możliwości
rek internetowych czy spambotów), który nie znaków identyfikujący przeglądarkę i sys- Przykładem oryginalnej i niewystępującej w ty-
zostanie zarejestrowany z poziomu JavaScript tem użytkownika; powych systemach statystyk opcji jest niewąt-
(a więc przez zewnętrzne serwisy, vide Google • $ _ SERVER['HTTP _ X _ FORWARDED _ FOR'] pliwie sprawdzanie aktualnej pozycji w wy-
Analytics). – jeżeli użytkownik łączy się za pośred- szukiwarkach pod hasła, na które pozycjo-
W takich sytuacjach jedyną alterna- nictwem proxy, a ustawienia serwera na nujemy naszą witrynę. Dzięki zestawieniu
tywą jest stworzenie własnego systemu to pozwalają, zawiera właściwe IP; tych statystyk ze zgromadzonymi do tej pory
statystyk, którego głównymi zaletami są • $ _ SERVER['REMOTE _ ADDR'] – adres IP możemy łatwo stwierdzić, w jaki sposób są
prostota, możliwość bezproblemowej rozbu- użykownika wyświetlającego stronę lub one ze sobą powiązane i czy faktycznie opła-
dowy i dostosowania do konkretnej strony proxy. ca się zabiegać o jak najwyższą lokatę pod da-
internetowej. ne słowo kluczowe w wynikach organicznych
PHP jako przedstawiciel języków server-side po- wyszukiwarek. Listing 1. przedstawia przykła-
Co należy wiedzieć? siada ograniczoną wiedzę o komputerze klien- dową implementację funkcji zwracającej pozycje
PHP daje możliwość dostępu do szeregu pre- ta, dlatego nie ma bezpośredniej możliwości w Google, która jest zachętą do dalszych prac
definiowanych zmiennych, wśród nich znaj- pobrania rozdzielczości ekranu przy jego uży- nad budowaniem naszego autorskiego systemu.
dują się superglobalne, wchodzące w skład ta- ciu. Jeśli taka informacja jest nam potrzebna, Analogicznie do podanego przykładu z ła-
blicy $_SERVER (zawierającej m. in. nagłówki pobieramy ją z poziomu JavaScriptu i przekazu- twością wykonamy podobne funkcje dla
HTTP), która dostarcza nam garść informacji jemy poprzez COOKIE, którego odczytanie nie innych wyszukiwarek. Niekiedy z jakiegoś po-
dotyczących odwiedzającego witrynę interne- sprawia problemów. Zwracamy szczególną uwa- wodu pragniemy zamaskować informacje
38 05/2007
Statystyki
o tym, że dane pobierane są z poziomu skryp- tu spełniającego zależność, z uwagi na przyję- get_all() tablicy budowane jest wyrażenie
tu przez parsowanie strony z wynikami. Może- te w bazie nazewnictwo (Rysunek 1.) domyślą regularne (odpowiadające strukturze lin-
my tego dokonać, zastępując funkcję file_get_ wartością jest „P99”. Taka operacja będzie wy- ków) w celu wyciągnięcia słowa kluczowe-
contents() naszą własną, bazującą na CURL-u, konywana niejednokrotnie, np. podczas przy- go, zaś samo ID wyszukiwarki zapisane zosta-
który daje możliwość ustawienia User Agenta porządkowywania typowi preglądarki czy wy- je jako kolejny z parametrów. W celu zabez-
(Listing 2.). szukiwarki nazwy odpowiedniego do uaktual- pieczenia przed atakami XSS zastosowaliśmy
nienia pola. funkcję strip_tags().
Przykładowy system statystyk
Zwracamy uwagę przede wszystkim na wyni- Pobieranie danych Zapis danych
ki organiczne wyszukiwarek (Google, Onet, To na pozór łatwe zadanie zrealizują trzy me- Na Listingu 5 widoczna jest przykładowa
Wirtualna Polska, MSN oraz Yahoo!) i anali- tody klasy userinfo. Pierwsza z nich – Listing 3 implementacja metody db(), odpowiedzial-
zę stron polecających. Prowadzenie pozosta- – odpowiedzialna jest za pobranie adresu IP lub nej za zapis pobranych wcześniej danych.
łych statystyk dotyczących przeglądarek czy wyciągnięcie go zza proxy, jeśli zajdzie taka ko- W przypadku konieczności utworzenia ko-
systemów operacyjnych na potrzeby niniej- nieczność. Ważnym elementem jest walidacja lejnych rekordów, równoznacznej z odwie-
szego artykułu zostanie zredukowane do mi- poprawności, której pominięcie nie jest rozsąd- dzinami pierwszego w ciągu danej doby
nimum. Skupiamy się na źródłach ruchu, nie ne ze względu na to, że dane te mogą zostać z ła- użytkownika, czyszczony jest rejestr adre-
badamy natomiast popularności poszczegól- twością zmanipulowane przez złośliwego użyt- sów IP.
nych podstron naszej witryny. Kod systemu kownika. Alternatywą jest automatyczne utworzenie
statystyk umieszczamy w czterech plikach we- Na potrzeby metody unique(), zwraca- niezbędnych wpisów za pośrednictwem unik-
dług schematu: jącej wartość typu bool, utworzyliśmy już sowego daemona cron. Ogranicza się to do usu-
tabelę „today”, zawierającą adresy IP osób zli- nięcia pierwszej instrukcji if z metody, utwo-
• functions.inc.php; czonych w danym dniu, co pozwala na branie rzenia odrębnego pliku cron.php oraz dodania
• class.inc.php; pod uwagę jedynie unikalnych wizyt. W celu do rejestru crontab:
• stats.inc.php; zmniejszenia liczby zapytań – jeśli ustawie-
• display.php. nia przeglądarki na to pozwalają – wysyłamy 0 0 * * * wget -q http://www.nasza-
plik COOKIE o ważności do północy trwają- strona.pl/sciezka/cron.php > /dev/null
Dysponujemy serwerem cego dnia.
bez wsparcia dla funkcji W przypadku zwrócenia wartości true Co zostanie umożliwone, poprzez wydanie
get_browser() przechodzimy do pobrania kolejnej daw- w lini poleceń, komendy:
Dane przechowujemy w bazie utworzonej ki informacji, a więc kolejno: detekcji ty-
zapytaniem przedstawionym na dołączonym pu przeglądarki, systemu operacyjnego oraz /usr/bin/crontab -e
do gazety nośniku. W zależności od ilości od- przeparsowania nagłówka HTTP_REFERER,
wiedzających witrynę przyjmujemy adekwat- zawierającego adres URL strony, za pośred- W celu przeglądu już istniejących wpisów
ne wartości maksymalne pól. nictwem której internauta trafił na naszą. użytkownika wystarczy:
Warto wspomnieć o budowie pierwszego z Jeśli jego zawartość sugeruje przejście z wy-
plików – functions.inc.php. Posiada on, oprócz szukiwarki, na podstawie znajdującej się w /usr/bin/crontab -l
podstawowych funkcji regulujących opera-
cje na bazie danych, inną nazwaną check().
Listing 1. Funkcja sprawdzająca pozycję strony w Google pod dane słowo kluczowe
Jej zadaniem jest zwrócenie nazwy pola tabe-
li na podstawie badania zawartości elementów function get_links ($url, $q) {
tablicy $array w ciągu $string. Zwracana jest // Budowanie prawidłowego URL-a (zamiana spacji na “+”)
wartość „PX”, gdzie „X” jest indeksem elemen- $q=str_replace(' ', '+', $q);
// Pobieranie 100 pierwszych witryn z wyników organicznych
www.phpsolmag.org 39
Praktyka
40 05/2007
Statystyki
www.phpsolmag.org 41
Technika
Operacje na tekście
Wprowadzenie
P
o pierwsze, musimy wiedzieć, jak wyglą- tla więc tekst „kot”). Ostatnie linijki pokazują, że w if (strlen($news) > 200) {
da wyświetlanie tekstu w PHP. Wszelkie przypadku użycia podwójnego cudzysłowia zmien- echo substr($news, 0, 200).'[...]';
operacje na tekście będziemy wykonywać ne w nim zawarte są parsowane, jednak rozwiąza- }
za pomocą funkcji na zmiennej, zawierający da- nie to nie jest zalecane, gdyż wszystkie benchmar- else
ny tekst. Powinno być oczywiste, że do wyświetla- ki PHP pokazują, że jest to sposób najwolniejszy. {echo $news;
nia tekstu w PHP służą funkcje echo i print. Są to W tekście wyświetlanym z pojedynczym cudzysło- }
identyczne funkcje, więc dlaczego nie mogłaby być wem możemy bez problemu wstawić cudzysłów
tylko jedna? Dlatego, że w PHP wiele funkcji wystę- podwójny, jednak aby wstawić pojedynczy, musi- Jeśli news będzie dłuższy niż 200 znaków, zosta-
puje np. pod dwoma nazwami, aby upodobnić się my poprzedzić go znakiem backslash ( \ ). Analo- nie skrócony właśnie do 200 znaków, a na jego
do wielu języków programowania, by programi- gicznie wygląda sytuacja z użyciem wyświetlania końcu zostanie dodany kwadratowy nawias z wie-
stom było po prostu wygodniej nauczyć się PHP. tekstu w podwójnym cudzysłowie, tyle że odwrot- lokropkiem. Możemy także z tekstu wyciągnąć je-
Mniejsza o to. Wyświetlmy testowo tekst „Ala ma nie. Przykład:– Listing 3.Jak widać sytuacja ta nie den interesujący nas znak. Przydaje się to w róż-
kota, a kot ma Alę” na kilka możliwości – Listing.1. występuje, gdy wyświetlamy tekst bezpośrednio w nych sytuacjach, np. jeśli chcemy zakodować jakąś
Wszystkie te zapisy są poprawne, a dla wyświetla- dokumencie. Zajmijmy się podstawową „obróbką” informację i wplatamy interesujące nas znaki po-
nia tekstu nie zawierającego żadnych zmiennych tekstu. Najlepiej jest pracować z użyciem zmien- między znaki „śmieci", a nasz skrypt PHP będzie
najlepszym zapisem będzie ostatni – z użyciem za- nych. Zapisujemy więc nasze zdanie do zmiennej te znaki wyciągał i układał w logiczną całość. Uży-
mknięcia i ponownego otwarcia kodu PHP między $tekst. Jeśli nie mamy takiej możliwości (np. tekst wamy w tym przypadku klamr przy zmiennej, a
tekstem. W tym przypadku nie jest używana żadna strony jest generowany przez PHP, a chcemy prze- między nimi podajemy konkretny indeks znaku.
funkcja PHP, gdyż tekst stanowi wtedy część doku- robić cały tekst wynikowy), możemy użyć bufora. Przykład takiego zastosowania:
mentu. Jest to zatem zapis najbardziej optymalny. Wygląda to tak – Listing 4. Pierwsza funkcja, która
Oczywiście, do tekstu możemy także wprowadzić może nam się przydać, to substr. Pozwala ona na $kod = 'fksmajso3jr0lf0es3a32fsgc';
zmienne. Dodajmy zmienną $cat z tekstem „kot” i skrócenie tekstu do określonej liczby liter. Ponadto $klucz = $kod{4}.$kod{12}.$kod{18};
użyjmy ją w naszym kodzie. Dodajmy także zapis z pozwala obciąć tekst nie tylko z jednej strony, ale i z echo $klucz;
podwójnym cudzysłowiem ( “” ) – Listing 2. Przy- dwóch. Składnia funkcji wygląda tak:
kład ten pokazuje, że w przypadku użycia pojedyn- Powyższy przykład wyświetli imię „ala”. Jak
czego cudzysłowia ( ' ' ) zmienne nie są parsowane substr(tekst, start, [długość]); widać, wszystko jest małymi literami – co
42 05/2007
Operacje na tekście
teraz zrobić, aby daną literę bądź całe sło- $n; $i++) { je się dopóki warunek, iż $i jest mniejsze
wo zamienić na wersaliki? Z pomocą przy- echo $tekst{$i}.'<br />'; od $n jest spełniony. Za każdym przebie-
chodzi nam funkcja strtoupper oraz jej sio- } giem pętli zmienna $i zwiększana jest o 1.
stra strtolower, która zamienia litery na ma- } Zastosować funkcję można bardzo łatwo
łe. Przykład zastosowania – Listing 6. Klam- – ustaw _ tekst _ pionowo($zmienna) ub
ry możemy też wykorzystać do wyświetla- Jak widać zmienna-index $i jest ustawia- bezpośrednio, np.
nia tekstu pionowo. W tym celu najlepiej na na 0, a zmienna $n przyjmuje wartość
napisać własną funkcję. Nazwijmy ją po pro- długości zmiennej $tekst. Pętla wykonu- ustaw_tekst_pionowo('Mój tekst').
stu “ustaw_tekst_pionowo”. Głównym środ-
kiem użytym w naszej funkcji będzie pętla.
Listing 5. Zastosowanie funkcji substr
Funkcja najpierw policzy ile podany tekst
ma znaków, aby pętla mogła tyle razy prze- <?
biec i wyświetlać każdy znak z tagiem <br /> $tekst = 'Ala ma kota, a kot ma Alę';
(przejście do następnej linii w HTML). // Wyświetli “ ma kota, a kot ma “ - gdy obcinamy tekst z obu stron, należy
// w parametrze długość użyć znaku minus
function ustaw_tekst_pionowo($tekst) echo substr($tekst, 3, -3);
{ ?>
for ($i = 0, $n = strlen($tekst); $i <
Listing 6. Przykład zastosowania funkcji strtoupper oraz strtolower
<?
Listing 1. Kilka możliwości wyświetlenia
danego tekstu $kod = 'fksmajso3jr0lf0es3a32fsgc';
$klucz = $kod{4}.$kod{12}.$kod{18};
<? echo strtoupper($klucz); // Wyświetli ALA
echo 'Ala ma kota, a kot ma Alę'; echo strtoupper($kod{4}).$kod{12}.$kod{18}; // Wyświetli Ala
print 'Ala ma kota, a kot ma Alę'; echo strtolower(strtoupper($klucz)); // Wyświetli ala
?>Ala ma kota, a kot ma Alę<? ?>
?>
Listing 7. Przykład zastosowania funkcji strstr oraz stristr
Listing 2. Dodanie zmiennej $cat oraz <?
podwójnego cudzysłowia $tekst = 'Ala ma kota, a kot ma Alę';
<? // Zwróci “Wyraz 'ala' znajduje się w podanym tekście”
$cat = 'kot'; if (stristr($tekst, 'ala')) {
echo 'Ala ma kota, a '.$cat.' ma Alę'; ?>Wyraz 'ala' znajduje się w podanym tekście <?
print 'Ala ma kota, a '.$cat.' ma Alę'; } else {
?>Ala ma kota, a <?=$cat?> ma Alę<? ?>Wyraz 'ala' nie znajduje się w podanym tekście <?
echo “Ala ma kota, a $cat ma Alę”; }
print “Ala ma kota, a $cat ma Alę”; // Zwróci “Wyraz 'ala' nie znajduje się w podanym tekście” (małe litery)
?> if (strstr($tekst, 'ala')) {
?>Wyraz 'ala' znajduje się w podanym tekście<?
Listing 3. Wyświetlanie tekstu w } else {
podwójnym cudzysłowie ?>Wyraz 'ala' nie znajduje się w podanym tekście <?
<? }
echo 'Ala ma \'kota\', a “kot” ma Alę'; // Zwróci “Wyraz 'Ala' znajduje się w podanym tekście”
echo “Ala ma 'kota', a \“kot\” ma Alę”; if (strstr($tekst, 'Ala')) {
?>Ala ma 'kota', a “kot” ma Alę<? ?>Wyraz 'Ala' znajduje się w podanym tekście<?
?> } else {
?>Wyraz 'Ala' nie znajduje się w podanym tekście <?
Listing 4. Możemy użyć bufora }
<? ?>
// funkcja rozpoczynająca buforowanie // Przykład użycia funkcji eregi i ereg
ob_start(); <?
$tekst = 'Ala ma kota, a kot ma Alę';
/* if (ereg('ala', $tekst)) { // Wyświetli "Nie znaleziono 'ala'"
tutaj wszystkie funkcje wyświetlające ?>Znaleziono 'ala'<?
tekst wynikowy } else {
*/ ?>Nie znaleziono 'ala'<?
}
// pobieranie już sparsowanego wyniku if (eregi('ala', $tekst)) { // Wyświetli "Znaleziono 'ala'”
// powyższych operacji do zmiennej ?>Znaleziono 'ala'<?
$tekst = ob_get_contents(); } else {
// zamykanie i czyszczenie bufora ?>Nie znaleziono 'ala'<?
ob_end_clean(); }
?> ?>
www.phpsolmag.org 43
Technika
Warunki na podstawie danego rzeczy, np. do sprawdzania poprawności adre- nych nie będę się tu rozpisywał – jest to temat
tekstu sów e-mail podczas rejestracji użytkowników. rozległy i został opisany w numerze 6/2006 PHP
Jak sprawdzić, czy dany tekst zawiera podany W artykule nie będziemy podawać przykładów, Solutions w artykule „Przyjazne URLe w PHP" .
ciąg znaków? Możemy posłużyć się funkcjami które wymagają użycia dużo bardziej zaawanso- Dlatego też w przykładzie zostało zapisane tylko
stristr i strstr. Funkcje robią to samo z tym wanych wyrażeń regularnych. Funkcje te są zwy- jedne potrzebne nam wyrażenie – Listing 8.
wyjątkiem, że stristr nie zwraca uwagi na kłymi funkcjami pozwalającymi na sprawdzenie
wielkość liter. Odpowiednikami tych funkcji są tylko „na sztywno” podanego ciągu znaku. Co Przeszukiwanie i zamiana tekstu
także eregi i ereg z takim wyjątkiem, że funk- jednak, jeśli chcemy sprawdzić, czy w tekście PHP umożliwia także zamienianie pewnych
cje mogą, aczkolwiek nie muszą, zostać uży- znajduje się jakikolwiek wyraz zaczynający się fragmentów tekstu na inne. Najczęściej uży-
te z wyrażeniami regularnymi ( np. aby okre- np. na literę g, a kończący na literę a? Przykład wane, a zarazem najprostsze umożliwiające to
ślić konkretny zakres sprawdzania w danym – nie znamy treści tekstu, chcemy wiedzieć, czy funkcje to str_replace i preg_replace. Skład-
tekście, zamiast sprawdzać w całości). Funckja zawiera słowo według podanych kryteriów, mo- nia tych funkcji jest identyczna z tą różnicą, że
eregi nie zwraca uwagi na wielkość liter. że to być np. gitara czy glazura. Z pomocą przyj- preg_replace używa wyrażeń regularnych,
Funkcji możemy użyć zatem tak – Listing 7. dzie nam funkcja preg_match korzystająca z wy- dzięki czemu możemy tą funkcją zrobić wię-
Funkcje te można użyć także do wielu innych rażeń regularnych. Na temat wyrażeń regular- cej. Jednakże to ma też swoją wadę – funkcja
ta jest wolniejsza. Do zamiany stałych fragmen-
tów tekstu dużo lepsza jest str_replace. Oto
Listing 8. Przykład użycia funkcji preg_match
jej składnia: str_replace(szukaj, zamień,
<? tekst);Funkcje te są bardzo proste w użyciu i
$tekst = 'Gitarzysta gra na gitarze. Jego gitara jest stara'; pozwalają na podanie im tablic do przeszuka-
if (preg_match(“/\sg(.*?)a\s/s”, $tekst)) { nia i zamiany, co wpływa pozytywnie na wydaj-
?>W podanym tekście występują wyrazy ność (lepiej użyć raz funkcji z tablicą niż dzie-
zaczynające się na g i kończące na a<? sięć razy osobno).Przykład – Listing 9. Funkcję
} str_replace często wykorzystuje się także do
else { wycięcia danego fragmentu tekstu. Wtedy, jako
?>W podanym tekście nie występują wyrazy pierwszy parametr podajemy szukany ciąg, a ja-
zaczynające się na g i kończące na a<? ko drugi tylko pusty cudzysłów (''), np.
}
?> str_replace('Ala ma kota', '', $tekst)
Listing 9. Przykłady użycia funkcji str_replace spowoduje usunięcie wszystkich ciągów "Ala
<? ma kota" w zmiennej $tekst. Teraz bardziej
$szukaj = 'kot'; praktycznie rozwiązanie – przykładowo chce-
$zamien = 'kocur'; my do wszystkich linków w danym tekście do-
$tekst = 'Ala ma kota, a kot ma Alę'; dać klasę link, tak aby każdy link wyglądający
/* tak <a href=”...”>...</a> przyjął postać
Stosujemy funkcję str_replace bezpośrednio na zmiennej $tekst. Równie dobrze nie
musimy tego robić – wystarczy od razu wyświetlić funkcję (echo str_replace($szukaj, <a href=”...” class=”link”>...</a>
$zamien, $tekst); ) – Listing 10.
*/
$tekst = str_replace($szukaj, $zamien, $tekst); W szablonie wyrażenia regularnego przy prze-
echo $tekst; // Wyświetli "Ala ma kocura, a kocur ma Alę" szukiwaniu każdy odnaleziony ciąg znaków
?> (wyrażenie (.*?) ) odpowiada kolejnej cyfrze po
<? dwóch znakach slash w zamianie (np. \1, \2).
// Przykład z użyciem tablic
$szukaj = array('kota', 'kot '); Zmiana kodowania tekstu
$zamien = array('koteczka', 'kocur '); za pomocą funkcji
$tekst = 'Ala ma kota, a kot ma Alę'; Często bywa tak, że mamy problem z kodowa-
$tekst = str_replace($szukaj, $zamien, $tekst); niem znaków narodowych na naszych dynamicz-
echo $tekst; // Wyświetli “Ala ma koteczka, a kocur ma Alę” nych stronach. Na poprawne wyświetlanie takich
?> znaków na stronie wyświetlającej tekst z bazy
danych wpływa kodowanie bazy danych, kodo-
Listing 10. Dodanie klasy link do wszyskich linków w tekście wanie danej tabeli bazy danych, kodowanie pliku
<? wyświetlającego tekst oraz kodowanie samego
$linki = '<a href=”index.php”>Strona główna</a> <a href=”index.php?p=firma”>O firmie</a> dokumentu HTML. Gdy jeden wariant jest niepo-
| <a href=”index.php?p=kontakt”>Kontakt</a>'; prawny, znaki nie zawsze wyświetlają się popraw-
$linki = preg_replace(“#<a(.*?)href=\”(.*?)\”>(.*?)</a>#si”, ' nie (lub ich część). Ratować możemy się sami,
<a\\1 href=”\\2” class=”link”>\\3</a>', $linki); pisząc odpowiednią funkcję. Funkcja change_
echo $linki; encoding będzie zmieniała kodowanie danego
// Przykład wyświetli “<a href=”index.php” class=”link”>Strona główna</a> tekstu na podstawie znaków zawartych w tabli-
// | <a href=”index.php?p=firma” class=”link”>O firmie</a> <a href= cach (każdy znak ma swój kod, dlatego też funkcja
// ”index.php?p=kontakt” class=”link”>Kontakt</a>” działa w każdym kodowaniu – Listing 11.
?> Funcja działa na prostej zasadzie – jako
pierwszy parametr podajemy tekst do przeko-
44 05/2007
Operacje na tekście
Listing 11. Tworzenie funkcji change_encoding Listing 13. Użycie składni heredoc
<? <?
function change_encoding($string, $type) $a = 5;
{ $b = 'Ala ma kota';
$win2utf = array( $c = 'a kot ma Alę';
"\xb9" => "\xc4\x85", "\xa5" => "\xc4\x84", "\xe6" => "\xc4\x87", "\xc6" => "\ $d = array('test1', 'test2');
xc4\x86", "\xea" => "\xc4\x99", "\xca" => "\xc4\x98", echo <<<EOT
"\xb3" => "\xc5\x82", "\xa3" => "\xc5\x81", "\xf3" => "\xc3\xb3", "\xd3" => "\ “Witamy panie i panowie”
xc3\x93", "\x9c" => "\xc5\x9b", "\x8c" => "\xc5\x9a", 'To jest nasz test składni heredoc',
"\xbf" => "\xc5\xbc", "\x8f" => "\xc5\xbb", "\x9f" => "\xc5\xba", "\xaf" => "\ Teoretycznie nie ma tu ograniczeń.
xc5\xb9", "\xf1" => "\xc5\x84", "\xd1" => "\xc5\x83", 3 + $a = 8.
); $b,$cMożemy także wyświetlać zawartości
$iso2utf = array( tablic, np. $d[0] EOT;
"\xb1" => "\xc4\x85", "\xa1" => "\xc4\x84", "\xe6" => "\xc4\x87", "\xc6" => "\ ?>
xc4\x86", "\xea" => "\xc4\x99", "\xca" => "\xc4\x98",
"\xb3" => "\xc5\x82", "\xa3" => "\xc5\x81", "\xf3" => "\xc3\xb3", "\xd3" => "\ Listing 14. Przykład zastosowania znaków
xc3\x93", "\xb6" => "\xc5\x9b", "\xa6" => "\xc5\x9a", specjalnych
"\xbc" => "\xc5\xba", "\xac" => "\xc5\xb9", "\xbf" => "\xc5\xbc", "\xaf" => "\ <?
xc5\xbb", "\xf1" => "\xc5\x84", "\xd1" => "\xc5\x83" $tekst = “Ten tekst\n przechodzi
); do\n nowej linii. Mam dużo
if ($type == 'ISO-8859-2->UTF-8') { \$becho $tekst;
return strtr($string, $iso2utf); /*
} Przykład wyświetli:
else if ($type == 'UTF-8->ISO-8859-2') { Ten tekst
return strtr($string, array_flip($iso2utf)); przechodzi do
} nowej linii
else if ($type == 'WINDOWS-1250->UTF-8') { Mam dużo $
return strtr($string, $win2utf); */
} ?>
else if ($type == 'UTF-8->WINDOWS-1250') {
return strtr($string, array_flip($win2utf));
} Oto lista najczęściej używanych znaków spe-
else if ($type == 'ISO-8859-2->WINDOWS-1250') { cjalnych:
return strtr($string, "\xa1\xa6\xac\xb1\xb6\xbc", "\xa5\x8c\x8f\xb9\x9c\x9f");
} • \n — nowa linia;
else if ($type == 'WINDOWS-1250->ISO-8859-2') { • \r — powrót karetki;
return strtr($string, "\xa5\x8c\x8f\xb9\x9c\x9f", "\xa1\xa6\xac\xb1\xb6\xbc"); • \t — tabulacja pozioma;
} • \\ — odwrotny ukośnik;
} • \$ — znak dolara.
?>
Jak widać, znaki te zapisuje się poprzedzając
Listing 12. Zmiana kodowania je backslashem. Przykład zastosowania – Li-
<? sting 14.
$tekst = 'Tekst z polskimi znakami ęóąśłżźćń zapisany w ISO-8859-2';
$tekst = change_encoding($tekst, 'ISO-88592->WINDOWS-1250'); Podsumowanie
echo $tekst; Przedstawione tu informacje o operacjach na tek-
?> ście to tylko podstawy. Przy pomocy bardziej za-
awansowanych funkcji oraz wyrażeń regularnych
możemy z tekstem robić dużo więcej. Mamy
dowania, a jako drugi typ kodowania. W za- otwieramy operator <<< po którym umieszcza- nadzieję, że artykuł naprowadzi Cię na dalsze kro-
leżności od tego jak kodowany jest tekst i jaki my identyfikator składni (tym samym identy- ki w tej dziedzinie, która jest bardzo przydatna
chcemy otrzymać wynik, podajemy odpowied- fikatorem należy zamknąć tekst). W przypad- w większości skryptów PHP.
ni parametr. Do dyspozycji mamy zamianę ku prostszego tekstu posłuży nam identyfika-
ISO-8859-2 na UTF-8 i odwrotnie, WINDOWS- tor EOT. Przykład zastosowania – Listing 13.
1250 na UTF-8 i odwrotnie oraz ISO-8859-2 na Możemy także wyświetlać zawartości tablic.
WINDOWS-1250 i odwrotnie. Przykład użycia Pamiętajmy o tym, że identyfikator kończący MICHAŁ GACKI
funkcji – Listing 12. tekst musi zaczynać się w pierwszej kolumnie Jest programistą-samoukiem. Od najmłodszych
nowej linii, by nie spowodował błędu składni, lat interesuje się informatyką, a najbardziej
Ciekawostki a po nim może znajdować się tylko średnik. programowaniem, które jest jego pasją. Pracu-
Do zapisywania większej ilości tekstu wraz ze Warto wiedzieć, że wyświetlanie tekstu w je w założonej przez siebie grupie (obecnie nie
zmiennymi i znakami specjalnymi bez obaw podwójnym cudzysłowie pozwala na używa- tylko programistycznej) pod nazwą Bil Software
o cudzysłowy możemy użyć składni heredoc. nie znaków specjalnych (cytowanych). Może- (www.bilsoftware.com).
Po funkcji echo lub print zamiast cudzysłowu my zapisać przejście do nowej linii, akapit itp. Kontakt z autorem: michal@bilsoftware.com
www.phpsolmag.org 45
Technika
Formularz internetowy
Walidacja z wykorzystaniem AJAX
O
dpowiednie połączenie tych techno- JavaScript i XML kodu: xmlHttp = new ActiveXObject("Mic
logii, które potrafi asynchronicznie, Nadszedł długo oczekiwany moment. Stworzy- rosoft.XMLHTTP"); Oczywiście, powinniśmy
czyli niewidocznie dla użytkownika, my główną część naszej aplikacji, której zada- także sprawdzić, czy nasze działania zostały
wywoływać skrypty umieszczone na serwerze, niem będzie niewidoczne dla użytkownika wy- wykonane w poprawny sposób. Na Listingu 2.
nazywamy AJAX-em. Aby przybliżyć Ci za- wołanie skryptów PHP umieszczonych na ser- przedstawiliśmy, jak powinna wyglądać funk-
lety i tajniki AJAX-u, wykonamy formularz, werze. Na starcie stwórzmy zmienną przecho- cja createXmlHttpRequestObject();
w którym wprowadzone dane sprawdzimy już wującą obiekt XMLHttpRequest. Robimy to Następnym krokiem jest utworzenie funk-
w momencie jego wypełniania. w pliku index.html – dokładnie tym, w którym cji check. Na samym początku pamięta-
umieściliśmy nasz formularz. W tym momencie my oczywiście, aby dodać nowo wprowadzo-
Przygotowanie formularza HTML używać będziemy języka JavaScript, zatem waż- ne przez użytkownika dane do pamięci pod-
Załóżmy, że nasz formularz ma posłużyć ne jest, aby prawidłowo umieścić go w struktu- ręcznej. Robimy to, używając polecenia push:
do wysyłania wiadomości e-mail. Będziemy rze dokumentu HTML. JavaScript wstawiamy memory.push("inputValue="+inputValue
potrzebować pola: Imię i Nazwisko, Twój adres w sekcji HEAD pomiędzy znaczniki: +"&fieldID="+fieldID);. Po tym zabiegu
e-mail i Wiadomość. Na samym początku zaj- sprawdzamy już tylko, czy obiekt XMLHttp-
mijmy się podstawowym przygotowaniem for- <script language="javascript" Request jest wolny i czy nasza pamięć podręcz-
mularza przy wykorzystaniu tagów HTML-a. type="text/javascript">/* na nie jest pusta, gdyż w przeciwnym wypad-
Kod naszej propozycji formularza zaprezento- <![CDATA[ */ TU TU TU będzie nasz ku nie mielibyśmy czego sprawdzać. Teraz wy-
wany jest w Listingu 1. Oczywiście istnieje do- skrypt JavaScript /* ]]> */</script> starczy już pobrać dane oczekujące w kolejce i
wolność w formatowaniu wyglądu, należy jed- wykonać żądanie. Jak wykonać funkcję check,
nak zwrócić uwagę na pewne istotne punkty. Jeżeli istnieje taka potrzeba możemy również przedstawiliśmy na Listingu 3.
Kluczowymi elementami formularza są wczytać kod z innego pliku, właśnie tak: Tak naprawdę wykonaliśmy właśnie ser-
wywołania funkcji check w momencie, gdy ce aplikacji AJAX. Winni jesteśmy pań-
użytkownik opuści dane pole, i funkcja send_ <script type="text/javascript" stwu jeszcze jedno wyjaśnienie. Użyta meto-
message() w momencie, gdy wyśle wiado- src="nazwa_pliku.js"></script> da readyState zwraca status żądania, gdzie
mość. Założenie zatem jest dość proste: w mo- również w sekcji HEAD 0 oznacza, że nie zainicjalizowano żądania,
mencie, gdy użytkownik wpisze dane, spraw- 1 – trwa ładowanie, 2 – załadowano, 3 – in-
dzimy je i w razie potrzeby wyrazimy naszą Wracając jednak do deklaracji zmiennej prze- teraktywne, 4 – zakończono żądanie. Teraz
dezaprobatę. Tutaj jednak napotykamy na pe- chowującej obiekt XMLHttpRequest, wykonu- należy stworzyć skrypt, który odbierze przy-
wien problem. Cóż bowiem się stanie, jeżeli jemy to w następujący sposób: var xmlHttp = chodzące informacje. Wykona to funkcja han
internauta jest niebywałym mistrzem klawia- createXmlHttpRequestObject();. dleRequestStateChange. Nieocenioną umie-
tury i bardzo szybko przechodzi z jednego po- Potrzebna będzie także zmienna przecho- jętnością w tym przypadku jest poprawne po-
la do drugiego? Wtedy istnieje możliwość, że wująca adres wywoływanego skryptu var sługiwanie się strukturą XML. Spójrzcie, jak
46 05/2007
Formularz internetowy
<FORM id="form_kontakt"><!--Nie musimy podawać argumentu dla action, gdyż wywołamy odpowiednie pliki asynchronicznie (czyli w tle),
wtedy też podamy, jaki plik wywołujemy i jakiej metody użyjemy do przekazania danych-->
<div style="float:left; display:inline; padding-right:10px;"><!--diplasy:inline użyte tylko po to, aby naprawić błędne
wyświetlanie elementów float przez Internet Explorera-->
<label style="padding-bottom:2px;" for="nazwa_klienta">Imię i nazwisko:</label>
<label style="padding-bottom:2px;" for="adres_email">Adres e-mail:</label>
<label style="padding-bottom:2px;" for="wiadomosc">Wiadomość:</label>
</div>
<div style="float:right: display:inline; ">
<input style="padding-bottom:2px;" id="nazwa_klienta" name="nazwa_klienta" type="text" value="" onblur="check(this.va
lue,this.id)"/><!--wywołanie funkcji check spowoduje połączenie z odpowiednim skryptem na serwerze, który
sprawdzi dane i prześle odpowiedź-->
<input style="padding-bottom:2px;" id="adres_email" name="adres_email" type="text" value="" onblur="check(this.value,thi
s.id"/>
<textarea style="padding-bottom:2px;" name="wiadomosc" cols="19" rows="10" id="wiadomosc"></textarea>
</div>
<div style="padding-top:5px;padding-bottom:5px; font-size:14px;">
<div id="comunication"><!--Tutaj wyświetlimy komunikaty nadesłane z serwera--></div></div>
<div style="clear:both; padding-left:209px;">
var xmlHttp;
if (window.ActiveXObject)
{
try
{
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); //w ten sposób robimy to specjalnie dla IE
}
catch (e)
{
xmlHttp = false; //jeżeli nie udało się stworzyć – z reguły znaczy to, że ktoś nie używa IE
}
}
else
{
try
{
xmlHttp = new XMLHttpRequest(); //tu powołujemy obiekt XMLHttpRequest dla wszystkich innych przeglądarek poza IE
}
catch (e)
{
xmlHttp = false;
}
}
if (!xmlHttp)
{
alert("Bе┌д┘d podczas tworzenia obiektu XMLHttpRequest.");
}
else
{
return xmlHttp;
}
www.phpsolmag.org 47
Technika
// wcześniej sprawdzamy, czy dane już zostały dostarczone, robimy to dzięki xmlHttp.status, którego wartość powinna wynosić 200,
// i xmlHttp.readyState, którego wartość powinna wynosić 4
var hellomessage,myDiv;
//zwraca odpowiedź serwera w postaci dokumentu XML, możemy również użyć responseText, a jako zwrot otrzymay łańcuch znaków
xmlResponse = xmlHttp.responseXML;
xmlDocumentElement = xmlResponse.documentElement;
hellomessage = xmlDocumentElement.firstChild.data;
myDiv = document.getElementById("comunication");
//wstawiamy otrzymaną wiadomość do bloku opatrzonego id comunication
myDiv.innerHTML = hellomessage;
setTimeout(”check();”,500) //ponowne wywołanie funkcji check, żeby obsłużyła kolejne żądania oczekujące w kolejce
header('Content-Type: text/xml');
echo '<?xml version="1.0" encoding="utf-8" standalone="yes"?>';
echo '<response>';
48 05/2007
Formularz internetowy
www.phpsolmag.org 49
Technika
CakePHP
Buforowanie stron
W
ielokrotne generowanie stron, Cache przeglądarki internetowej malny czas, w którym dane są traktowa-
których zawartość nie zmienia Zamiast za każdym razem generować tę sa- ne jako aktualne (liczony względem da-
się, powoduje zbędne obciążenie mą zawartość strony wystarczy przy pierw- ty określonej przez znacznik Last-Modi-
serwera WWW i bazy danych. Każde żąda- szym wyświetleniu zapamiętać ją i używać fied);
nie od użytkownika musi zostać przetworzo- przy kolejnych wywołaniach – Rysunek 1. • public – wymusza buforowane (przy-
ne, a wynik skierowany do przeglądarki in- Właściwie w każdej nowoczesnej przeglą- datne dla stron, które w normalnych
ternetowej, jednak za każdym razem serwer darce internetowej znajdują się ustawienia warunkach nie są umieszczane w ca-
pobiera te same dane. Nie stanowi to proble- związane z cache. Najczęściej jest to para- che);
mu, gdy strony przegląda kilku użytkowni- metr określający miejsce zarezerwowane
ków, ale kłopoty mogą się pojawić wraz ze na pliki tymczasowe przeglądanych stron Listing 1. Przykładowe żądanie i odpowiedź
wzrostem popularności serwisu. Im więcej WWW. Zasady aktualizacji cache są proste. serwera WWW
użytkowników, tym bardziej serwer będzie Przeglądarka za pomocą znaczników HTTP
obciążony wykonywaniem zadań, które pro- sprawdza, czy przechowywane dane są aktu- HEAD / HTTP/1.1
wadzą do wyświetlenia stron nieróżniących alne – Listing 1. i w miarę możliwości korzy- HOST: localhost
się od siebie wcale lub różniących się tylko sta z nich zamiast pobierać dane z Internetu. HTTP/1.1 200 OK
w niewielkim stopniu. Naturalnym rozwią- Dzięki temu powrót do poprzednio wyświe- Date: Mon, 02 Jul 2007 21:24:12 GMT
zaniem problemu spadku wydajności jest tlanej strony WWW w przeglądarce (przy- Server: Apache
zapisywanie „na boku” generowanych stron cisk „wstecz”) powoduje szybkie wyświetle- Accept-Ranges: bytes
i udostępnianie ich innym użytkownikom. nie informacji, najczęściej bez konieczności X-Powered-By: PHP/4.2.2
Zamiast za każdym razem generować tą samą pobierania danych z sieci. Set-Cookie: PHPSESSID=
zawartość strony wystarczy przy pierwszym Kontrola aktualności cache odbywa się ac35d9b842215f4fb23ca419337af4b8;
wyświetleniu zapamiętać ją i używać przy za pomocą znaczników: Cache - Control, path=/
kolejnych wywołaniach. Technika ta nazywa Expires, Last-Modified oraz ETag przesyła- Expires: Thu, 19 Nov 1981 08:52:00 GMT
się page caching (pol. buforowanie stron) i jest nych w nagłówku stron WWW: Cache-Control: no-store, no-cache,
najprostszą metodą przyspieszania działania Expires: DATA_GMT – Znacznik określa ter- must-revalidate
serwisu. Przy pierwszym wyświetleniu stro- min możliwej zmiany lub wygaśnięcia ważno- Pragma: no-cache
na zostaje zapisana do pliku HTML. Każde ści dokumentu. Po upływie określonego cza- Connection: close
następne odwołanie do tej samej strony po- su (liczonego względem GMT) dokument mo- Content-Type: text/html
woduje, iż do przeglądarki użytkownika zo- że ulec zmianie lub zostać usunięty. Najprost- Content-Language: pl
stanie wysłana zawartość bezpośrednio z ca- szym sposobem wymuszenia, by plik nie zo-
50 05/2007
CakePHP
• no-cache – wymusza pominięcie cache nerowany, co przy częstych zmianach sta- nić na TRUE wartość stałej CACHE_CHECK w
(przeglądarki i serwerów proxy) i pobiera- wia pod znakiem zapytania sens używania pliku /app/config/core.php. define ('CACHE_
nie danych bezpośrednio z Internetu; tej technologii. W praktyce jednak strony CHECK', true); W kontrolerze powiązanym
• no-store – wymusza usunięcie danych z WWW można podzielić na fragmenty, które z widokiem, dla którego włączamy cache, mu-
cache zaraz po przesłaniu ich do użytkow- są statyczne, oraz na takie, które zmieniają się simy dodać CacheHelper przez umieszczenie
nika; często, i poddać buforowaniu tylko te ostat- kodu: var $helpers = array('Cache');
• must-revalidate – wymusza sprawdzanie nie. Wynikowa strona jest wtedy „składana” Następnie należy określić, co chcemy umie-
stanu przedawnionych dokumentów znaj- z mniejszych bloków, z których część będzie ścić w cache. Do zmiennej $cacheAction mu-
dujących się w cache. znajdowała się w cache. Jest to bardzo intu- simy przypisać tablicę zawierającą akcje, któ-
icyjne – w przypadku sklepu internetowego re mają być buforowane, oraz czas (w sekun-
Last-Modified: DATA _ GMT– Znacznik okre- lista produktów jest fragmentem, który naj- dach), przez który cache ma być aktualny
śla datę ostatniej modyfikacji dokumentu – rzadziej ulega zmianom, a z kolei koszyk za- (można używać liczb lub zapisów „1 day” czy
Listing 1. ETag: ZNACZNIK – Znacznik jest kupów klienta może zmieniać się dynamicz- „60 seconds”) – Listing 3.
unikalnym identyfikatorem strony genero- nie. Wykorzystanie page cache w CakePHP W praktyce zdarza się, że pewne fragmen-
wanym przez serwer WWW, który zmie- zaczniemy od zapoznania się konfiguracją ty strony są wypełniane dynamicznymi dany-
nia się za każdym razem, gdy przesyłane da- serwera. Domyślnie cache widoków jest za- mi i nie mogą znaleźć się w cache ze względu
ne ulegną modyfikacji. Znaczniki możemy blokowane. By je aktywować, musimy zmie- na wyświetlane dane. Wystarczy wówczas, że
wysyłać do przeglądarki za pomocą funkcji
header() – Listing 2.
Listing 2. Przykładowe znaczniki wysyłane do przeglądarki za pomocą funkcji header()
QUERY-CACHE �����������������������������������������
Nowoczesne bazy danych są najczęściej wy-
posażone w mechanizm QUERY-CACHE po-
wodujący zapamiętanie zapytań kierowa-
nych do bazy oraz skojarzonych z nimi wyni- ����������������������������������
ków. Takie samo zapytanie SQL do bazy da-
nych spowoduje przekazanie wyników prze- �����������
chowanych w QUERY-CACHE bez koniecz-
ności odczytu informacji z plików bazoda- ����������
nowych. Cache jest czyszczony w przypad-
ku zmian w tabelach do których zapytania
się odwołują. MySQL4 posiada błąd, któ-
ry powoduje czyszczenie całego QUERY-CA-
CHE w przypadku zmian w dowolnej tablicy, �����
co niekorzystnie wpływa na czas odpowiedzi
serwera na te same zapytania.
www.phpsolmag.org 51
Technika
fragment kodu, który nie powinien być bu- zentowane błędne nieaktualne dane. W naj- tlać dane z różnych modeli danych). Zmia-
forowany, określimy za pomocą znaczników prostszym przypadku w reakcji na zmiany na danych dowolnego modelu spowoduje
<cake:nocache> oraz </cake:nocache> – Li- możemy usunąć wszystkie pliki cache. Roz- więc automatyczne usunięcie cache dla całe-
sting 4. wiązanie to ma jednak tę wadę, że nawet nie- go widoku. CakePHP automatycznie usuwa
wielka zmiana spowoduje konieczność czaso- cache, gdy nastąpi zmiana w stanie aplikacji.
Czyszczenie cache chłonnego generowania cache na nowo. Zde- Jeżeli użytkownik spowoduje działanie, któ-
Przy korzystaniu z cache kluczowym momen- cydowanie lepiej jest usuwać tylko te pliki ca- re będzie skutkowało zmianami w bazie da-
tem w funkcjonowaniu serwisu jest sposób che, które prezentują dane, które uległy zmia- nych (INSERT, UPDATE, DELETE), zosta-
reakcji na zmiany w prezentowanych danych. nie. CakePHP wykorzystuje fakt, że prezen- nie usunięte cache dla widoku powiązane-
Jeżeli nie będzie sprawnego mechanizmu in- towane na stronach WWW dane są powią- go z kontrolerem odwołującym się do mode-
formowania aplikacji, które pliki cache nale- zane z modelem danych, a cache jest związa- li danych, które uległy zmianie. Istnieje moż-
ży usunąć, to użytkownikowi zostaną zapre- ny z widokiem (który z kolei może wyświe- liwość ręcznego sterowania cache i usuwania
nieaktualnych danych za pomocą funkcji cle-
arCache(). Jako parametr przekazujemy na-
Listing 4. Przykład wyłączenia buforowania fragmentu kodu widoku
zwę kontrolera, kontrolera i akcji lub kontro-
<h1> Ostatnie 10 wiadomości! </h1> lera, akcji i parametrów identyfikujących plik
<cake:nocache> cache – Listing 5.
<ul> W prosty sposób można zaimplemento-
<?php foreach($recentMessages as $message): ?> wać dodatkowy scenariusz czyszczenia cache
<li>$message['title']</li> sprawdzający się w sytuacjach, gdy nie może-
<?endforeach;?> my zapobiec cyklicznemu tworzeniu się no-
</ul> wych plików cache, ale jednocześnie chcemy
</cake:nocache> uniknąć ciągłego usuwania plików. Zamiast
spowalniać działanie aplikacji ciągłym testo-
Listing 5. Funkcja clearCache() usuwająca nieaktualne pliki cache waniem aktualności cache możemy urucho-
// Usuń wszystkie strony z cache, bazując na nazwie kontrolera mić dodatkowy proces działający w tle. Pro-
clearCache('controller'); ces ten będzie odpowiedzialny za cykliczne
czyszczenie cache co określony (konfiguro-
// Usuń wszystkie strony z cache, bazując na nazwie kontrolera i nazwie akcji walny) przedział czasowy niezależnie od ob-
ciążenia aplikacji.
clearCache('controller_action/');
Składowanie danych
// Usuń wszystkie strony z cache, bazując na nazwie kontrolera, nazwie akcji Najprostszym sposobem przechowywania
// i parametrze cache są pliki umieszczone bezpośrednio w
systemie operacyjnym (jest to jedyny sposób
// Do funkcji clearCache() można przekazywać wiele parametrów przechowywania cache obsługiwany automa-
tycznie przez CakePHP w wersji 1.1.xx). Wy-
clearCache(array('controller_action_params','controller2_action_params)); generowana strona HTML zostanie umiesz-
czona w publicznie dostępnym obszarze ser-
wera (w miejscu określonym ścieżką dostępu
wskazywaną przez stałą $CACHE) – każde od-
Memcached wołanie do tej samej strony będzie wówczas
System cache przechowujący dane w pamięci RAM, umożliwiający zapisywanie danych i obiek-
przekierowywane na plik cache. Rozwiąza-
tów. Wysoce wydajny i skalowalny umożliwia łączenie serwerów działających w oparciu o różne
architektury systemowe. Stosowany m.in. w serwisach LiveJournal i Wikipedia. System memca- nie takie oprócz oczywistych zalet, takich jak
ched jest dostępny w repozytoriach wielu dystrybucji Linuksa (kod źródłowy można pobrać z ad- prostota implementacji czy dobra wydajność,
resu http://www.danga.com/memcached). Obsługę memcached w PHP zapewnia binarne rozsze- ma podstawową wadę: nie jest rozwiązaniem
rzenie, dostępne na pecl.php.net. skalowalnym. Jeżeli nasz serwis będzie się
Krótki przegląd metod API:
rozwijał i zajdzie konieczność uruchomie-
• Memcache::add – dodaje element do serwera. nia dodatkowego serwera WWW, to stanie-
• Memcache::addServer – dDodaje serwer memcached do listy wykorzystywanych serwerów. my przed problemem związanym z dystry-
• Memcache::close – zamyka połączenie. bucją plików cache i ich synchronizacją. Za-
• Memcache::decrement – zmniejsza wartość elementu. pytania od użytkowników mogą być kierowa-
• Memcache::delete – usuwa element z serwera. ne do dowolnego serwera, każdy będzie więc
• Memcache::flush – usuwa wszystkie elementy z serwera.
• Memcache::get – zwraca element z serwera.
z nich tworzył pliki cache niezależnie. Poza
• Memcache::getExtendedStats – statystyki wszystkich serwerów memcached. tym usunięcie cache z jednego serwera nie
• Memcache::getServerStatus – zwraca stan serwerów memcached. spowoduje usunięcia plików z pozostałych
• Memcache::getStats – statystyki serwerów. serwerów. Można co prawda utworzyć jeden
• Memcache::getVersion – zwraca wersję serwera memcached. wspólny sieciowy filesystem na potrzeby ca-
• Memcache::increment – inkrementuje wartość elementu.
che wszystkich serwerów, ale rozwiązanie
• Memcache::pconnect – otwiera stałe połączenie.
• Memcache::replace – zmienia wartość podanego elementu. traci wtedy swoją prostotę. Innym rozwiąza-
• Memcache::set – zapisuje dane na serwerze. niem jest umieszczanie danych cache w bazie
• Memcache::setCompressThreshold – włącza automatyczną kompresję dużych wartości. danych. Jest to elastyczniejsze od plików ca-
• Memcache::setServerParams – zmienia parametry i stan serwera. che w systemie operacyjnym – głównie kosz-
tem dodatkowego obciążenia zasobów serwe-
52 05/2007
CakePHP
// metoda usuwająca przechowywane dane na podstawie klucza // usuń temat dyskusji wraz ze wszystkimi wiadomościami
// wyszukiwania // usuń zbędne pliki z cache
www.phpsolmag.org 53
Technika
54 05/2007
Narzędzia
SciTE
„Lekki” edytor o dużych możliwościach
P
HP jest bardzo popularnym językiem nel wyjścia). su. W najprostszej konfiguracji SciTE przy-
programowania, co przekłada się rów- pomina program Notatnik z systemu Win-
nież na liczbę dostępnych dla niego na- SciTE może pracować zarówno w środowisku dows. Nie dajmy się jednak zwieźć pozorom.
rzędzi programistycznych. Niestety, szeroka Windows, jak i pod kontrolą większości syste- Przy odrobinie wytrwałości to z pozoru ubo-
gama aplikacji tak naprawdę utrudnia wybór, mów unixowych (w tym Linuksa), co dla wie- gie narzędzie, może zmienić się w funkcjonal-
ponieważ sama znajomość funkcji progra-
mu nie wystarczy aby stwierdzić czy to ten
„właściwy”. W praktyce edytor można uznać
za sprawdzony dopiero po napisaniu kliku
skryptów podczas codziennej pracy.
SciTE to prosty, szybki i konfigurowalny edy-
tor tekstu wyposażony w wiele funkcji przydat-
nych programistom przy tworzeniu kodu. Po-
czątkowo był on tylko programem demonstru-
jącym możliwości komponentu Scintilla (na
którym bazuje), z czasem jednak rozrósł się tak,
że obecnie konkuruje z wieloma narzędziami
programistycznymi.
Edytor ten został wyposażony w wie-
le funkcji ułatwiających programowanie.
Trudno byłoby wymienić je wszystkie, dla-
tego poniżej znajdują się tylko ważniejsze
z nich:
56 05/2007
SciTE
ny i wygodny edytor kodu tak jak to przedsta- ków (np. nie posiadamy uprawnień zapisu) konfiguracyjnym użytkownika mógłby wyglą-
wia Rysunek 1. w katalogu instalacyjnym możemy utworzyć dać następująco:
plik z konfiguracją języka w innej lokalizacji.
Konfiguracja Na przykład w systemach uniksowych może- import .SciTE/html
Konfiguracja edytora SciTE nie należy do naj- my stworzyć w katalogu domowym folder o
prostszych, ponieważ polega na edycji plików nazwie .SciTE i w nim umieszczać pliki z wła- lub
tekstowych, a to z kolei wymaga studiowania snymi ustawieniami. Aby wczytać konfigura-
dokumentacji. Warto jednak poświęcić na te cję dla danego języka z innej lokalizacji niż ka- import /home/nazwauzytkownika/.SciTE/html
czynności trochę czasu, ponieważ efekt mo- talog instalacyjny należy skorzystać z opcji im-
że być imponujący. Podstawowa konfigu- port podając pełną ścieżkę do wczytywanego W domyślnej instalacji SciTE nie posiada
racja SciTE zawiera się w pliku SciTEGlo- pliku pomijając rozszerzenie .properties. Od- osobnego pliku konfiguracyjnego dla języka
bal.properties znajdującym się przeważnie powiedni wpis (np. dla języka HTML) w pliku PHP. Oczywiście można go utworzyć, jednak
w katalogu instalacyjnym aplikacji. Aby go
nie szukać możemy otworzyć plik wybiera-
jąc z menu programu Options | Open Glo-
bal Options File. Tutaj dokonujemy odpo-
wiednich poprawek zgodnie z dokumentacją
dostępną na stronie http://scintilla.sourceforg
e.net/SciTEDoc.html. SciTE oferuje również
możliwość stworzenia własnej konfiguracji
bez wprowadzania modyfikacji w pliku glo-
balnym. Dokonujemy tego poprzez utworze-
nie pliku użytkownika SciTEUser.properties
wybierając z menu programu opcję Options
| Open User Options File. Plik ten będzie pu-
sty, tak więc najlepszym rozwiązaniem bę-
dzie skopiowanie do niego ustawień global-
nych a następnie wykonanie potrzebnych
zmian. Wybrane opcje konfiguracyjne zosta-
ły przedstawione na Listingu 1.
Dwa panele
Edytor SciTE umożliwia korzystanie z dwóch
paneli: panelu edycji – w którym tworzony jest
kod, oraz panelu wyjścia – gdzie można obser-
wować komunikaty programów zewnętrznych
oraz uruchamiać polecenia systemowe. Jest to
bardzo przydatne gdy korzystamy z debugge- Rysunek 2. Uzupełnianie składni
ra lub programu sprawdzającego poprawność
składni. W dalszej części artykułu dowiemy
się jak skonfigurować sprawdzanie składni dla
języka PHP.
command.name.13.*=example
command.mode.13.*=subsystem:lua,
savebefore:no,groupundo
command.shortcut.13.*=Ctrl+E
command.13.*=example
Rysunek 3. API PHP i podpowiedzi w edytorze SciTE
www.phpsolmag.org 57
Narzędzia
58 05/2007
Powyższy przykład spowoduje umieszczenie
w menu Tools pozycji o nazwie example, która
będzie odpowiedzialna za uruchomienie funk-
cji example z pliku rozszerzeń lua.
Szczególnie przydatna może okazać się moż-
liwość reakcji na zdarzenie onSave (podczas za-
pisywania pliku). Tworząc odpowiedni skrypt
możemy np. automatycznie wysyłać pliki na
zdalny serwer poprzez protokół FTP używając
zewnętrznych programów.
Pod adresem http://lua-users.org/wiki/SciteScripts
można znaleźć kilka gotowych do użycia skryp-
tów. Zachęcam również do zapoznania się z do-
kumentacją tworzenia rozszerzeń z użyciem
LUA pod adresem http://scintilla.sourceforge.net/
SciTELua.html.
Podsumowanie
Jak widać edytor SciTE jest bardzo zaawan-
sowanym narzędziem w swojej klasie. Choć
niektórym programistom będzie tu brakować
funkcji takich jak zarządzanie projektami czy
klient FTP. Można te braki oczywiście obejść
stosując dodatkowe oprogramowanie, bądź
pisząc rozszerzenia w języku LUA.
Niewątpliwie największą zaletą tej aplikacji
jest konfigurowalność, pozwalająca na dosto-
sowanie jej do własnych potrzeb programisty i
chyba właśnie to docenia większość użytkow-
ników najbardziej. Należy również wspomnieć
o stabilności programu i niskim zapotrzebowa-
niu na zasoby systemowe.
Poza stroną domową http://scintilla.sour-
ceforge.net/SciTE.html w sieci nie znajdzie-
my zbyt wiele na temat opisywanego edy-
tora – najprawdopodobniej początkujących
użytkowników odstrasza konfiguracja tego
narzędzia. Warto również zajrzeć na grupę
dyskusyjną http://mailman.lyra.org/mailman/
listinfo/scite-interest – można tu odnaleźć wie-
le odpowiedzi na pytania nurtujące nie tylko
początkujących użytkowników tego imponu-
jącego narzędzia.
ROBERT ZAJDA
Autor artykułu jest właścicielem firmy APISOFT
zajmującej się bezpieczeństwem systemów in-
formatycznych i wdrażaniem oprogramowania
open-source oraz nauczycielem przedmiotów in-
formatycznych w Zakładzie Doskonalenia Zawo-
dowego w Radomiu.
Kontakt z autorem: robert.zajda@gmail.com
www.phpsolmag.org
Narzędzia
jQuery
Pisz mniej, rób więcej
D
odatkowo bardzo intuicyjne two- „name”. Kod w jQuery napisać można w na-
rzy grupy obiektów i kolekcje, dając z tą różnicą, że jeden wpis odnosi się automa- stępującej postaci:
możliwość iteracji po wybranych ele- tycznie do wszystkich linków na tworzonej
mentach grupy. Wyposażenie jQuery w możli- przez nas stronie. $("a[@name]").css("background", "#eee"
wość wykonywania zapytań asynchronicznych );
w połączeniu z łatwością manipulacji dowolny- Selektory HTML i CSS
mi obiektami lub grupami obiektów wewnątrz Pełne wsparcie dla CSS (1, 2, 3) oraz wszystkich Łatwo się domyślić, że wykonanie tego frag-
strony HTML daje silne i łatwe w użyciu narzę- selektorów HTML stanowi podstawę dobrego mentu kodu spowoduje zmianę koloru tła
dzie do tworzenia atrakcyjnych wizualnie stron imienia omawianej biblioteki. Możliwość defini- wyselekcjonowanych elementów. Bardziej
w technologii AJAX. cji kolekcji selektorów i iteracji po dowolnej z nich użytecznym selektorem jednak wydać się
jest dużym ułatwieniem w tworzeniu logiki apli- może taki, który wybiera linki zawierają-
Instalacja i konfiguracja kacji webowej po stronie klienta. Przypuśćmy że ce w swym adresie wskazanie do np. kata-
Instalacja jest bardzo prosta, a właściwie nie chcemy odwołać się do elementu o ID „ordere- logu „galery”.
ma jej wcale. Wystarczy ściągnąć plik jqu- dlist”. W klasycznym skrypcie JavaScript musie-
ery.js i włączyć go jako skrypt do własnej stro- libyśmy użyć konstrukcji: document.getElement $("a[@href*=/gallery]").click(function() {
ny. Od tego momentu można zacząć używać ById("orderedlist") by wydobyć interesujący // do something with all links that
funkcjonalności, jaką daje nam ta bibliote- nas element. Przy wsparciu jQuery mamy do dys- // point somewhere to /gallery
ka. Pobieramy plik jQuery.js z adresu: http:// pozycji konstrukcję: });
code.jquery.com/jquery-latest.js i umieszcza-
my go w katalogu roboczym razem z plikiem $("#orderedlist").addClass("red"); Można długo opisywać różne ciekawe kom-
tworzonej przez nas strony. Następnie włą- binacje metod selekcji elementów strony, za-
czamy w kod strony zawartość ściągniętego Przy czym możemy na wybranym obiekcie mieszczone tutaj przykłady zostały wybra-
pliku, deklarując w części nagłówkowej na- wywołać dowolne funkcje dostarczane z oma- ne, by pokazać spektrum możliwości, jakie na
szej strony: wianą biblioteką, w tym konkretnym przykła- tym polu daje nam jQuery.
dzie została wywołana funkcja
<script src="jquery-latest.js" type="text/ Walidacja formularzy
javascript"></script> addClass("red"); Częstym i bardzo eleganckim rozwiązaniem
stosowanym na różnego rodzaju stronach
Tworzymy kod powodujący, iż po kliknięciu Funkcja ta, jak łatwo się domyślić, doda jest walidacja formularzy. Nie trzeba chyba
na dowolny link w obrębie strony HTML po- klasę „red” do elementu o ID „orderedlist”. nikogo przekonywać, że duże formularze na
60 05/2007
jQuery
witrynach pełnych elementów graficznych działania danego zapytania. Pierwszą użytecz- załadowaniu danych ze skryptu PHP, załaduje
lepiej walidować bez kosztownego przełado- ną funkcją, związaną z dziedziną „ajax”, jest je do znacznika HTML o ID =”wynik” (<div
wywania całej strony, gdyż słabe łącze mo- funkcja get. Parametrami jej wywołania są: id=”wynik”><div>)
że spowodować, że wypełniający formularz .get(url, params, callback), gdzie url to W pliku test.php przetwarzamy zapyta-
zirytuje się długim oczekiwaniem na odpo- URL, params określa parametry przekazywa- nie oraz przekazane parametry – Listing 11.
wiedź serwera z informacją, że wpisana war- ne w zwykłym URL-u za znakiem zapytania, u Oczywiście, taki prosty przykład jest dobry,
tość jest niewłaściwa. Zacznijmy od przykła- nas będą w postaci: ale dla nas dobry to za mało, potrzebne nam
du, w którym będziemy walidować numer są zapytania, które odpowiednio zareagują w
PESEL, a w przypadku wpisania niewłaści- { name: "PHPSolution", id: "3/2007" } przypadku niepowodzenia zapytania, a tak-
wej wartości ostrzeżemy użytkownika, ale że – co być może ważniejsze – zrealizują od-
pozwolimy mu wypełniać dalej formularz Ostatnim parametrem może być nazwa funk- powiednie czynności po pełnym wykonaniu
i ostatecznie zaakceptujemy wadliwy nu- cji, którą chcemy wywołać po wykonaniu za- zapytania, czyli wtedy, kiedy „spłyną” już
mer PESEL. Najpierw przygotujemy funk- pytania, może być to funkcja formatująca wszystkie dane od serwera. Jest to potrzeb-
cję, która dokona sprawdzenia, czy przeka- treść stronę w zależności od uzyskanej odpo- ne w przypadku przetwarzania przez serwer
zana jako argument wartość jest poprawnym wiedzi. Dla przykładu podamy kod, który po skomplikowanych operacji bazodanowych.
numerem PESEL.
Część funkcji zmieniona w komen-
Listing 1. Funkcja sprawdzająca poprawność numeru PESEL
tarz umożliwia w szybki sposób rozszerze-
nie funkcjonalność testu o sprawdzenie po- function validPESEL(pesel)
prawności podanej w innym polu formula- {
rza płci, w tym celu należy dodać kolejny if(pesel == 0)return true;
argument funkcji o nazwie „plec” (dozwolo- if (pesel.length > 11) return false;
ne wartości to M lub K) i usunąć znaki ko- var rePesel = /(\d{11})/;
mentarza z odpowiedniego fragmentu kodu.
Mając tak przygotowaną funkcję, możemy if (rePesel.test(pesel)) pesel = RegExp.$1;
sprawić, by została wywołana przy wysłaniu else return false;
formularza. Aby na nasze żądanie mimo pesel = pesel.split("");
błędnego wpisu dane zostały wysłane, zasto-
sujemy jeszcze jedną funkcję pomocniczą. //if(plec)
Teraz szybie powiązanie funkcji do zdarzenia //{
wysłania formularza przy pomocy jQuery. // if(pesel[9]%2 && plec.search("K")!=-1) return false;
// else if (!pesel[9]%2 && plec.search("M")) return false;
$('#frmDaneOsobowe').ajaxForm( { //}
beforeSubmit: validate } );
var wagi = new Array(1,3,7,9,1,3,7,9,1,3);
Czegóż wybredny programista chciał- var suma=0;
by mieć więcej w tej sytuacji? Możliwość
sprawdzenia, czy dany numer PESEL istnie- for(i=0;i<=9;i++) suma += pesel[i]*wagi[i];
je w naszej lokalnej bazie danych? Wywoła- suma %= 10;
nie asynchronicznego zapytania get i uzy- var sumaKontrolna = (10-suma) % 10;
skanie odpowiedzi od przygotowanego od-
powiednio skryptu PHP wydaje się właści- if (pesel[10]==sumaKontrolna) return true;
we. W podobny sposób można sprawdzić else return false;
adres e-mail i w czasie, gdy użytkownik wy- }
pełnia resztę formularza, możemy przesłać
e-mail do przygotowanego skryptu PHP, Listing 2. Formularz HTML z logowaniem asynchronicznym
który nie tylko sprawdzi poprawność adre- <form method="get" class="cmxform" id="form" action="form.php">
su pod względem budowy (ciąg znaków, li- <fieldset>
terka at, kolejny ciąg znaków), lecz także <p>
odpyta serwery DNS o rekordy MX czy na- <label for="login">Twój login</label>
wet system pocztowy o poprawność adresu <input id="user" name="user" title="Podaj login, przynajmniej trzy znaki"
e-mail. Aby jednak to zrobić, zapoznajmy się class="{required:true,minLength:3}" />
z funkcjonalnością zapytań asynchronicz- </p>
nych oferowaną przez jQuery. <p>
<label for="pass">Hasło</label>
GET I POST asynchronicznie <input type="password" name="password" id="password" class="{
To, co czyni z omawianej biblioteki uniwersal- required:true,minLength:5}" />
ną do różnych zastosowań, to możliwość wy- </p>
syłania asynchronicznych zapytań. Biblioteka <p>
ta ma gotowy zbiór funkcji wspierających za- <input class="submit" type="submit" value="Login"/>
pytania asynchroniczne i – co bardzo użytecz- </p>
ne – funkcje te jako jeden z parametrów przyj- </fieldset>
mują tzw. callback, a dokładnie nazwę funk- </form>
cji, która ma być wywołana na zakończenie
www.phpsolmag.org 61
Narzędzia
62 05/2007
jQuery
z gotowych funkcji i tego, co już zostało napi- chronicznie do przetestowania poprawności da- Akcją wykonywaną przy wysłaniu formula-
sane, znacznie przyśpiesza tworzenie własnej nych. Kod formularza zawarty jest w Listingu 2. rza jest asynchroniczne wywołanie skryptu
aplikacji. Z tego właśnie powodu sięgniemy Kodem zawarty w Listingu 3. oprogramuje- PHP form.php, w którym możemy umieścić
po gotowe funkcje przygotowane do walida- my elementy formularza, wykorzystując funk- uwierzytelnienie użytkownika, i włączenie
cji formularzy, a dostarczone jako plugin jQu- cje dostarczane przez jQuery. sesji, tak by dalsze wędrowanie po stronie
ery o nazwie: validation. Pobieramy plik z ad- odbywało się w spersonalizowany sposób.
resu: http://jquery.bassistance.de/validate/jqu- Współpraca jQuery zPHP Dla potrzeb testów ograniczymy się do pro-
ery.validate.zip Po rozpakowaniu włączamy Umieszczamy w kodzie HTML potrzebne ele- stej symulacji prawdziwego logowania. Kod
w kod naszej strony następujące pliki: menty, takie jak: pliku form.php zawiera Listing 4.To, co wy-
W katalogu “js” umieszczamy następujące pli- różnia jQuery od innych podobnych biblio-
ki pomocnicze: cmxforms.js, jquery.js, form.js, <button id="reset">Programowy reset formy tek, to fakt, że wokół jQuery nabudowało
test.js, testrunner.js. Zaczniemy od przygotowa- </button> się wiele ciekawych i darmowych bibliotek,
nia formularza logowania, który wyślemy asyn- <div id="result">Oczekiwany rezultat</div> które rozszerzają i wzbogacają jego funkcjo-
nalność. Jednym z takich przykładów jest
jQPie, który:
Listing 5. Strona z „jQuery callendar”
www.phpsolmag.org 63
Narzędzia
); $('.callendarFocus').calendar();
A w kodzie HTML umieszczamy formularz z
Listing 11. Przykładowy plik php, generujący odpowiedź dla zapytania asynchronicznego elementem
<?php <input type=”text” class=”callendarFocus” §
name=”testData”>
If(isset($_GET[‘name’] && $_GET[‘name’] === „PHPSolution” ) echo $_GET[‘name’].
” To dobry magazyn”; Do pełnego zadowolenia brakuje nam jeszcze
konfiguracji kalendarza, tak by domyślna war-
If(isset($_GET[‘id’] && $_GET[‘id’] === „3/2007”) echo $_GET[‘id’]. tość była tą, którą chcemy widzieć w danym
” To ciekawy numer”; miejscu, i format też był odpowiedni.
JQuery ma zaimplementowanych wiele róż-
?> nych funkcji odpowiedzialnych za wizualne
efekty i animacje elementów strony. Prostym
Listing 12. Przykładowe zapytanie ajax przykładem może być tutaj stopniowe nada-
$.ajax( wanie przezroczystości dowolnemu elemento-
{ wi strony. Kod w Listingu 6. pokazuje, jak po
url: „test.php”, ustawieniu kursora w polu tekstowym formu-
data: „name=PHPSolution&id=3/2007”, larza sprawić, by pole to zniknęło.
type: „GET”,
success: function(data){ Podsumowanie
$("#wynik").html(data); jQuery daje możliwość zarówno budowania szyb-
}, kich i sprawnych efektów graficznych, jak i łatwe-
go generowania zapytań asynchronicznych i mo-
complete: callback_complete, dyfikacji treści strony po stronie przeglądarki.
}); Przytoczone tu przykłady stanowią cząstkę
możliwości jakie daje ta biblioteka. Celem te-
Listing 13. Włączenie potrzebnych plików js dla validatora jQuery go artykułu było jednak zapoznanie czytelni-
<script src="js/jquery.js" type="text/javascript"></script> ka z funkcjonowaniem i sposobem użycia tej bi-
<script src="js/cmxforms.js" type="text/javascript"></script> blioteki na własnej stronie i mamy nadzieję, że
<script src="jquery.metadata.js" type="text/javascript"></script> cel ten został osiągnięty. Mocną stroną bibliote-
<script src="jquery.validate.js" type="text/javascript"></script> ki jest mnogość pluginów i szeroka rzesza pro-
gramistów gotowa wesprzeć technicznie kiedy
mamy jakiś problem, tak więc warto wypróbo-
Po stworzeniu instancji klasy $pquery = new Podaj tekst : wać to co nam ta biblioteka oferuje.
PQuery(); możemy używać własności jQuery
w skrypcie php. <input type="text" name="field" /><br />
<input type="submit" /> </form> DARIUSZ DUSZYŃSKI
<?=$pquery->form_remote_tag( array Autor jest programistą w toruńskiej firmie JADE
('url'=>'index.php?task=ajax', Wartość wpisana do pola tekstowego zostanie Sp. z o.o.
'update'=>'#idtoupdate'));?> przekazana zapytaniem asynchronicznym do Kontakt z autorem: dduszynski@jade.pl
64 05/2007
Narzędzia
WordPress i punBB
Integrowanie
W
ordpress to znany system CMS/ oferuje swój mechanizm do integracji, lecz na tworzyć jedynie przy logowaniu, gdy API
Blog, a punBB to popularne i bar- idealny nie jest i próba zastosowania go z wtyczek Wordpressa przekazuje do wtyczki
dzo funkcjonalne forum dysku- WordPressem skończyłaby się kolizją kodu hasło a nie jego hasz.
syjne. WordPress jest stosowany we wszyst- i błędnym działaniem CMS-a. Musimy więc
kich serwisach grupy jakilinux.org (jakili- niezależnym od punBB kodem zintegrować Integracja – wersja II
nux.org, polishlinux.org, wolnakultura.info i oba skrypty, modyfikując kod Wordpressa W katalogu WordPressu /wp-content/plugins/
inne), natomiast punBB jest wykorzystywa- (jednostronna integracja) – Listing 1. stwórz katalog jl-punbb, a w nim plik
ne jako forum dyskusyjne na jakilinux.org (w jl-punbb.php o kodzie przedstawionym na Li-
przyszłości także w innych serwisach). Ce- Integracja – wersja I stingu 2.
lem jest zintegrowanie systemu użytkowni- Dla tabeli użytkowników punBB dodajemy no- Teraz w Panelu Admina WordPressu
ków obu skryptów, tak by czynności jak lo- wą kolumnę „wp_id”, która przechowuje nu- w zakładce Plugins włącz wtyczkę i goto-
gowanie, rejestracja, wylogowanie, zmiana ha- mer ID danego użytkownika z tabeli użytkow- we. Dodatkowo nie wymaga ona edycji
sła i przypomnienie hasła wpływały na oba ników WordPressa. Kod SQL wygląda nastę- tabeli punBB.
skrypty. Integracje tego typu możemy prze- pująco:
prowadzać na kilka sposobów: Synchronizacja użytkowników
ALTER TABLE `pun_users` ADD `wp_id` Powyższa wtyczka zajmuje się rejestracją,
• zastąpić system użytkowników i upraw- INT UNSIGNED NOT NULL DEFAULT 0; logowaniem, wylogowaniem i zmianą has-
nień jednego skryptu systemem z dru- ła dla użytkowników, którzy zarejestrowa-
giego; Oczywiście prefiks „pun _ ” do tabel punBB li się w WP po jej zainstalowaniu. W punBB
• dokonać krzyżowej integracji (czynności może być inny i w takim przypadku edytu- nie będziemy mieć dostępu do istniejące-
jak logowanie wykonuje identyczną czyn- jemy nazwy tabel w zapytaniach z prezento- go konta admina. Musimy zsynchronizo-
ność dla drugiego skryptu); wanych w tym artykule fragmentów kodu. wać tabelę użytkowników punBB z tabelą
• dokonać jednostronnej integracji (jeden Zaprezentowane na listingu 1 zmiany skut- użytkowników WordPressu. Usuwamy ist-
skrypt przy np. logowaniu loguje również kują tym, że rejestracja, logowanie, wylogo- niejących użytkowników (poza „Gościem”
do drugiego skryptu). wanie, resetowanie hasła i zmiana hasła w DELETE FROM pun_users WHERE id > 1; Te-
WordPressie spowoduje dokładnie to samo raz musimy pobrać wszystkich użytkowni-
Pierwszy przypadek jest dość trudny do w punBB. Integracja jest skończona, chociaż ków z tabeli Wordpressu i w pętli dodać je
realizacji jeżeli system użytkowników i ma jedną wadę – wprowadziliśmy modyfi- do tabeli punBB według zapytania z funk-
uprawnień jest rozbudowany. JPortal ma od- kacje do kodu WordPressu, co utrudni jego cji wtyczki punbb_user_register. W tabe-
dzielonych zwykłych użytkowników od ad- aktualizację. Skrypt ten jednak posiada sys- li użytkowników punBB kolumna group_id
minów, przez co łatwo dla tego skryptu do- tem wtyczek – „plugins”. API tego systemu określa przynależność do grupy. Dla admi-
konać integracji typu pierwszego (istnieją- jest na tyle rozbudowane, że możemy prze- nistratora Wordpressu nadajemy wartość 1,
66 05/2007
WordPress i punBB
include '../punbb/config.php'; /* */
setcookie($cookie_name, NULL, time()-3600, '/', '', '0'); // Następnie znajdź:
www.phpsolmag.org 67
Narzędzia
czyli prawa admina forum. A co jeśli inte- le. Do kodu wtyczki wystarczy dodać kod Nie tylko punBB
grujemy forum zawierające już wielu użyt- z Listingu 3. Zaprezentowane rozwiązanie nie ogranicza się do
kowników i tematy/posty? Powyższy sposób Ostatni etap integracji to usunięcie odno- punBB. Taką samą metodę możemy zastosować
synchronizacji spowoduje sporo zamieszania śników w punBB do logowania i rejestracji do integrowania skryptów innego typu. W niektó-
w przynależności wiadomości do określonego lub ustawienie przekierowań na odpowied- rych przypadkach, gdy skrypt udostępnia API do
autora. Musimy zastosować nieco inne podej- nie strony w WordPressie: Na początku pliku integracji zadanie będziemy mieć ułatwione. Dla
ście. Nie usuwamy użytkowników. Ci, którzy register.php forum wstaw: header('Location: przykładu dla forum Invision Power Board istnie-
mieli odmienne loginy, stracą dotychczasowe http://www.url/do/wordpress/wp-login. je projekt IPB SDK umożliwiający szeroką integra-
konta na punBB. Dodajemy do tabeli punBB php?action=register'); Dla pliku login.php cję a także wykorzystywanie komponentów forum.
tych użytkowników WP, których nie ma na na początku wstaw: IPB SDK możemy pobrać ze strony http://www.ipb
forum. By pobrać takich użytkowników, wy- sdk.sourceforge.net. Dzięki tej klasie w prosty sposób
starczy zapytanie: header('Location: http://www.url/do/ otrzymamy dostęp do systemu logowania i użyt-
wordpress/wp-login.php'); kowników, właściwości forum takich jak BBco-
SELECT * FROM wp_users WHERE user_login de, ankiety, szukanie, posty, tematy i wiele wię-
NOT IN (SELECT username W profilu musimy wyłączyć zmianę hasła cej. By używać IPB SDK musimy mieć odpowied-
FROM pun_users) – edytuj profile.php i znajdź: nią wersję forum jak i klasy SDK – 1.6 dla IPB 2.1.*
lub 1.5 dla IPB 2.0.*. Gdy już wszystko gotowe nale-
Dodajemy według zapytania z funk- if ($action == 'change_pass') ży ustawić ścieżkę do katalogu z forum IPB w pliku
cji wtyczki punbb_user_register, a następ- { ipbsdk_conf.inc.php ( $root_path i $board_url).
nie nadajemy prawa admina na forum ad- Teraz możemy korzystać z IPB SDK. Zaczynamy
minowi z WP. Cały ten bałagan migracji Poniżej dodaj: od stworzenia obiektu klasy:
rozwiąże nasza wtyczka do Wordpressu.
Możemy dodać kod, który zostanie wykona- header('Location: http://www.url/do/ require_once 'ipbsdk_class.inc.php';
ny przy jej aktywacji i zsynchronizuje tabe- wordpress/wp-admin/profile.php'); $SDK =& new IPBSDK();
68 05/2007
WordPress i punBB
// copy users from WP to punBB that doesn't have account on punBB By zalogować użytkownika wystarczy użyć
metody login:
$q = $wpdb->get_results("SELECT * FROM wp2_users WHERE user_login NOT IN (
SELECT username FROM pun_users)"); $sdk->login($LOGIN. $HASŁO);
}
PIOTR MALIŃSKI
Autor jest studentem Politechniki Warszawskiej
na kierunku technologia chemiczna, a także pro-
gramistą PHP i Python.
Kontakt z autorem: riklaunim@gmail.com
www.phpsolmag.org
Testy konsumenckie
Testy konsumenckie
Statystyki zewnętrzne
70 05/2007
Statystyki zewnętrzne
w systemie funkcji oraz tabelaryczne zestawienie cji poszukiwali oraz skąd pochodzili. Zebrane
możliwych opcji dla każdego pakietu. w ten sposób dane pozwalają odpowiedzieć na
Z usługi 7point korzystamy od kilku miesię- pytanie, w jakim stopniu przygotowana przez
cy i stale utwierdzamy się w przekonaniu, że nas oferta jest dobrana do ich potrzeb.
był to najlepszy wybór. Opinię podzielają rów- Wiedzę tę poszerzają wykresy wyświetlają-
nież nasi partnerzy, którym polecamy produkt ce informacje o odbiciach, nowych i powraca-
i wdrażamy w realizowanych projektach. jących użytkownikach, stronach wejściowych
Statystyki stosujemy głównie do oceny po- i wyjściowych. Natomiast informacje technicz-
pularności serwisu oraz analizy skuteczności ne, takie jak stosowane przeglądarki, ustawie-
prowadzonych działań marketingowych. Wy- nia rozdzielczości ekranów, pomagają nam
soka precyzja prezentacji wyników pomaga w definiowaniu standardów, wykorzystywa-
w określeniu zachowań i preferencji użytkowni- nych przez internautów.
ków odwiedzających naszą stronę. Dzięki temu Dodatkowym atutem są tygodniowe rapor-
szybciej docieramy do ich potrzeb i pod tym ką- ty przesyłane na podany adres e-mailowy, na pod-
tem optymalizujemy witrynę, jej zawartość me- stawie których możemy analizować zmiany w za-
rytoryczną, ofertę, a także użyteczność. chowaniach internautów i tworzyć archiwum.
Emilia Adamczyk
Ze względu na to, że prowadzimy intensyw- Przyjemnym dla oka dodatkiem są wykresy
właściciel, specjalista ds. e–biznesu
ne kampanie promocyjne w wyszukiwarkach, 3D, a miły kontakt z pracownikami firmy, na
e–solution agencja interaktywna najbardziej istotnymi danymi prezentowanymi których pomoc zawsze można liczyć, jest waż-
w systemie są odsłony serwisu według słów klu- nym uzupełnieniem całej usługi. Firma 7point
czowych, które użytkownicy wpisują w wyszu- otwarta jest na nowe pomysły i propozycje part-
O statystykach 7point dowiedzieliśmy się z prze- kiwarki internetowe. Dają nam one pełen obraz nerów, które są rozważane i wdrażane do syste-
słanej do nas propozycji współpracy. Przeanalizo- w określeniu ich trafności. mu. Dzięki temu jest on stale rozwijany, oferu-
waliśmy wszystkie dostępne na rynku oferty i zde- Dużą zaletą jest również gromadzenie infor- jąc nowe funkcje przydatne użytkownikom.
cydowaliśmy się na korzystanie z tego właśnie pro- macji na temat kolejności wyświetlania pod- Statystyki 7point posiadają dużo więcej opcji
duktu. Przekonała nas przede wszystkim bogata stron serwisu, czyli ścieżek, po których wędro- przydatnych właścicielom witryn, specjalistom ds.
funkcjonalność oraz intuicyjna nawigacja, której wali internauci, a także szczegóły ich wizyt. Sta- marketingu, programistom, dlatego powinny być
brakowało konkurencyjnym rozwiązaniom. Po- tystyki 7point pokazują, w jaki sposób użyt- nieodłącznym elementem każdej strony WWW,
zytywne wrażenie zrobiła na nas również szybka kownicy wchodzą na stronę (bezpośrednio, która ma przynosić korzyści, a nie tylko być.
i profesjonalna pomoc administratora, a także czy- z wyszukiwarki, z katalogu czy innego adresu),
telny, szczegółowy opis wszystkich dostępnych ile czasu na niej spędzili, jakiego typu informa- Ocena: «««««
Problem zaczyna się w momencie, kiedy to Dzisiaj trzeba rozwijać swoją ofertę i pamiętać,
nie sam użytkownik, ale jego klient oczeku- że nie wszędzie Internet dostarczany jest z pręd-
je jasnych, rzetelnych i dobrze zaprezentowa- kością powyżej 1 Mbit/s. Nieatrakcyjny wygląd
nych informacji dotyczących jego strony inter- bądź ciągnące się w nieskończoność oczekiwanie
netowej (w przypadku sklepów temat jest jesz- na otwarcie strony na słabym EDGE-u (w Bielsku-
cze poważniejszy). Białej nie brakuje takich miejsc) odbiera chęć dal-
Nasza firma tworzy m.in. serwisy i sklepy in- szych poszukiwań.
ternetowe, a zatem to, co w końcowym efekcie Moja opinia przypomina tekst sponsorowany,
zobaczy nasz klient i jakie korzyści będzie czer- ale od momentu rozpoczęcia współpracy z 7point
pał ze współpracy z nami, staje się sprawą najważ- nasi klienci nie zgłosili praktycznie żadnych uwag
niejszą. Po wpisaniu w wyszukiwarce hasła „sta- co do jakości oraz rzetelności przedstawianych
Paweł Puzoń tystyki WWW” zwróciłem uwagę na kilka adre- danych. To komfort, który bardzo doceniam!
sów. Wśród nich był link sponsorowany statystyk Dodatkwe plusy? Oto kilka z nich: usługa
Statystyki internetowe. Niektórzy się zastana- 7point. Link sponsorowany w potocznej opinii umożliwia określenie dowolnego zakresu czasu
wiają: czy ktoś z tego jeszcze korzysta? Oczy- oznacza „są drodzy, bo ich stać”. Sam nie wiem, podczas odczytu, a prezentacja danych jest bar-
wiście tak! Łatwo sobie wyobrazić firmę, któ- dlaczego, ale tak jest. Początkowo poświęciłem im dzo przejrzysta. Ponadto 7point oferuje szeroki
ra wydaje miesięcznie kilkaset złotych (czasami trochę czasu tylko dlatego, że firma znajduje się w wybór miesięcznych limitów odsłon (łatwo do-
kilka tysięcy!) na pozycjonowanie swojej witry- moim mieście – Bielsku-Białej. Po analizie i omó- stosować do potrzeby konkretnej witryny). Wy-
ny w Google. Jak najprościej wykazać, że wyda- wieniu strony ze znajomymi doszedłem do wnio- kresy też są nieźle wykonane.
wane środki dają efekty, a zwiększająca się licz- sku, że warto. Kilka przykładów: 7point oferuje Ostatnia sprawa to promocje – ważne w na-
ba telefonów w firmie to nie efekt dobrej ko- dosyć duży wybór parametrów (ma też dobrze szym przypadku (firma proponuje upusty dla
niunktury, ale cierpliwej i skutecznej pracy in- wykonany podział na kategorie). W porównaniu z stałych klientów oraz program partnerski).
formatyka? konkurencją cena za ich usługi jest atrakcyjna. Co Żeby nie było zbyt słodko są i minusy. Przy-
Nasza firma często spotyka się z tego typu ważne, system nie ogranicza ilości zbieranych da- kład? Ostatnio firma zmieniła swoją nazwę
problemami i poniżej podzielę się swoimi spo- nych, a do jednego konta można „podpiąć” kilka i przebudowała główny układ witryny. Ponieważ
strzeżeniami. domen. Na początek wystarczy. istnieją od niedawna, takie zmiany wprowadza-
Na polskim rynku odnaleźć można jedynie Oczywiście na rynku są inne firmy i warto ją zamieszanie. Dla stałych bywalców to norma,
kilka ciekawych rozwiązać spośród firm ofe- o nich pamiętać. Wystarczy wspomnieć moc- ale ciekawscy dyrektorzy marketingu lub preze-
rujących profesjonalne statystyki WWW. Wy- no reklamowany stat24 oraz zapomniany już si firm nie przepadają za takimi zmianami.
bór jest więc mocno zawężony a co za tym idzie przeze mnie (kiedyś właściwie jedyny dostęp-
– łatwiejszy. ny, teraz wyglądający nieco archaicznie) MyStat. Ocena: «««««
www.phpsolmag.org 71
Testy konsumenckie
ną ilość subkont, aby móc udostępnić statystyki rolę odgrywają dane dotyczące ścieżek jakimi po-
swojej witryny innym osobom. Może także two- ruszają się po stronie użytkownicy – dzięki takim
rzyć określoną ilość niezależnych stref, by przeglą- informacjom właściciel witryny może prześle-
dać statystyki stron swojego serwisu w prostszy dzić zestawienie najbardziej typowych schema-
i wygodniejszy sposób. Dodatkowo system 7point tów poruszania się użytkowników po serwisie.
umożliwia monitorowanie większej liczby domen Ponadto istotną funkcjonalnością jest możliwość
Ustosunkowanie prezesa w ramach jednego konta. Warto również zwrócić wyboru dowolnego zakresu czasu prezentowa-
Rafał Wawak uwagę na fakt, że nasz system liczy również aliasy/ nych statystyk – dzięki tej funkcji użytkownik
mirrory domen bez konieczności ich rejestrowa- może przeglądać dane z dowolnego dnia, miesią-
W 2005 roku firma Lege Artis rozpoczęła prace nia (o ile zawartość ich stron nie różni się od za- ca lub roku. System 7point dostarcza również in-
nad nowym systemem statystyk internetowych. wartości stron zarejestrowanej domeny głównej). formacji technicznych o komputerze internau-
Zespół naszych programistów przez rok przygo- Kolejną, jedną z najistotniejszych dla nas ty (system, przeglądarka, rozdzielczość ekra-
towywał mechanizmy nowego systemu. W mar- kwestii, było stworzenie systemu, który dostar- nu itp.). Dodatkowo warto wspomnieć o jednej
cu 2006 roku uruchomiony został system staty- czałby kompleksowych informacji o serwisie je- z istotnych funkcji naszego serwisu jaką jest, cie-
styk internetowych pod domeną NeoStat.pl, któ- go użytkownikowi, tak aby w efekcie informa- sząca się dużym zainteresowaniem wśród na-
ry był zarazem projektem pilotażowym. Od maja cje te znajdowały swoje zastosowanie w prak- szych klientów, możliwość otrzymywania bez-
tego roku możemy już zaoferować naszym klien- tycznych działaniach naszych klientów. Sta- płatnych tygodniowych raportów, które zawie-
tom właściwą wersję statystyk – system 7point. raliśmy się, aby gama dostępnych danych by- rają zestawienie najistotniejszych statystyk wraz
Mamy nadzieję, że cały czas i praca, które zostały ła jak największa. Dzięki dostarczanym przez z tendencjami.
włożone w stworzenie systemu, przyniosą przede nas statystykom klient może więc zbadać lojal- Już od początku tworzenia systemu wiedzie-
wszystkim satysfakcję klientom, a nam pewność, ność użytkowników wobec swojego serwisu, je- liśmy, że nasi klienci powinni być w pełni usa-
że dostarczamy w pełni profesjonalnych usług. go jakość i atrakcyjność oraz sprawdzić jak jego tysfakcjonowani nie tylko oferowanym przez
Przy opracowywaniu systemu kierowaliśmy się serwis funkcjonuje. Ponadto klient ma dostęp nas produktem, lecz także całością świadczo-
kilkoma, istotnymi według nas względami – pro- do informacji na temat pozycji swojego serwisu nych przez nas usług. Dlatego mogą oni liczyć
stotą obsługi, z czym ściśle wiązała się również es- w wyszukiwarkach oraz lokalizacji i zachowania na pomoc techniczną zarówno na etapie insta-
tetyka i klarowność prezentowanych widoków. użytkowników. lacji statystyk, jak i w trakcie ich użytkowania.
Dołożyliśmy więc wszelkich starań, by interfejs Dane, jakie liczy 7point, dotyczą wielu istot- Poza tym staramy się być w stałym kontakcie
był przyjazny i łatwy w odbiorze, a co za tym nych dla właścicieli serwisów kwestii związa- z klientami , aby znać ich sugestie i opinie na te-
idzie, odczytanie danych nie stanowiło problemu nych ze statystykami. Są to między innymi szcze- mat użytkowania statystyk. Dzięki temu może-
nawet dla osób, które nie mają na co dzień do czy- gółowe informacje na temat użytkowników, wi- my na bieżąco rozwijać nasz produkt.
nienia ze statystykami internetowymi. zyt i odsłon. Mogą być one przeglądane w róż- Mimo że system 7point jest nową propozy-
Ponadto zależało nam, by klienci mogli korzy- nych kontekstach: słów kluczowych, ilości i czę- cją na rynku statystyk internetowych, do dziś
stać ze statystyk za rozsądną cenę oraz by płacili stotliwości powrotów, odbić czy też stron starto- miało okazję korzystać z niego aż kilkaset ser-
tylko za to, czego naprawdę potrzebują. Dlatego w wych i końcowych wizyt. Kolejne kategorie, pre- wisów. Już wersja pilotażowa odznaczała się
ramach naszego systemu klient może wybrać trzy zentowane przez system 7point, to niezbędne w szybkością oraz stabilnością działania. W efek-
rodzaje usług – Echo, Monitor lub Horizon. Każ- planowaniu kampanii w sieci zestawienia słów cie z naszych statystyk korzystają do dziś klien-
da z nich jest pomyślana w ten sposób, aby użyt- kluczowych i wyszukiwarek. Ogromną wagę ma- ci zarejestrowani wkrótce po uruchomieniu
kownik mógł wybrać optymalną wersję dla po- ją również informacje dotyczące genezy ruchu na wersji pilotażowej. Wśród monitorowanych
trzeb i charakteru swojej witryny. Usługi zróżni- stronie – dzięki statystykom 7point użytkownik przez nasz system serwisów można znaleźć za-
cowane są pod względem miesięcznego limitu od- ma dostęp do przeglądania zestawień na temat równo te, których miesięczną liczbę odsłon li-
słon, ilości prezentowanych parametrów oraz ce- wyszukiwarek, wejść ze stron, katalogów stron, czy się w milionach, jak i małe serwisy gene-
ny. W ramach poszczególnych wersji użytkow- poczty WWW, jak również zestawień dotyczą- rujące w miesiącu od kilku do kilkudziesięciu
nik może utworzyć w swoim serwisie określo- cych geolokalizacji użytkowników. Niebagatelną tysięcy odsłon.
72 05/2007
Statystyki zewnętrzne
R E K L A M A
www.phpsolmag.org 73
Testy konsumenckie
stat24 świadczy bezpłatne oraz płatne usłu- rencyjnej cenie lub całkowicie bezpłatnie. Po-
gi monitorowania serwisów WWW. Są to pro- nadto największymi zaletami stat24 są spraw-
dukty o unikalnej jakości i użyteczności, któ- dzona metodologia wykonywania badań oraz
rych wykorzystanie przyczynia się do rozwo- fakt, że dane udostępniane przez stat24 są
ju działalności biznesowej w Internecie i słu- w pełni akceptowalne przez agencje reklamo-
ży do zwiększania wartości posiadanych zaso- we oraz uznawane za wiarygodne źródło wie-
bów medialnych. Przestrzeń serwisów, które dzy o serwisie.
są monitorowane bezpłatnie, jest wykorzysty- W pełni zgadzam się z opinią home.pl. Ofer-
wana do wykonywania badań ankietowych In- ta stat24 uzupełnia ofertę produktową firmy
ternetu. Stat24 nigdy nie emitował reklam ko- gwarantując jej i jej klientom dostęp do profesjo-
mercyjnych. nalnego narzędzia badawczego.
Poza statystykami stat24 udostępnia każde- Współpraca z MTV układa się bardzo po-
mu klientowi bezpłatny licznik internetowy myślnie. Cieszy mnie, że MTV w przyszłości
oraz możliwość korzystania z rankingu. Dzię- planuje objąć monitoringiem inne swoje wi-
ki rankingowi stat24 każdy właściciel staty- tryny. Ustosunkowując się do punktu, w któ-
styk WWW może porównać oglądalność swo- rym jest mowa o małej ilości skryptów udo-
Ustosunkowanie jej witryny z innymi serwisami w danej katego- stępnianych za pośrednictwem stat24, chciała-
Dyrektor Zarządzający stat24 rii oraz klasyfikacji generalnej. Ponadto stat24 bym zaznaczyć, że stat24 jest produktem stwo-
Żaneta Tarnowska udostępnia raporty badawcze, które podsu- rzonym z myślą o małych i średnich przedsię-
mowują miesięczną oglądalność monitorowa- biorstwach – stąd ograniczona ilość skryptów.
stat24 tworzy grupa młodych ludzi, połączo- nych serwisów WWW. Raporty tworzone są Zgodnie z polityką firmy klientom, dla których
nych wspólną pasją, jaką jest Internet. Dziś, na podstawie danych zbieranych poprzez sta- udostępniana ilość skryptów zliczających jest
po 3 latach dynamicznego rozwoju, stat24 to tystyki stat24. niewystarczająca, proponujemy statystyki ge-
uznana marka w zakresie statystyk dla małych stat24 cały czas unowocześnia oferowaną miusTraffic.
i średnich serwisów internetowych. Monito- usługę. Na początku 2007 roku została wpro- Zgadzam się z wypowiedzią – jesteśmy part-
rujemy ponad 900 000 witryn, odnotowując wadzona nowa geolokalizacja, która graficznie nerem Ceneo, jednocześnie porównywarka ko-
miesięcznie ponad 3 mld odsłon, a dzięki in- obrazuje oglądalność w poszczególnych kra- rzysta z naszego narzędzia badawczego. Cie-
tegracji z platformą technologiczną firmy Ge- jach. Ponadto powstała szczegółowa mapa Pol- szy mnie, że Ceneo jest zadowolone z naszych
mius SA – lidera w dziedzinie badań Interne- ski, która dzięki mechanizmowi wyszukiwaw- usług.
tu – nasze statystyki są rzetelne, wiarygodne czemu pozwala na znalezienie użytkowników 4 gwiazdki to świetna ocena – mobilizu-
i spełniają wymogi europejskich standardów pochodzących nawet z niewielkich miejscowo- je nas do pracy, wprowadzania na rynek no-
badawczych. ści w kraju. wych rozwiązań oraz ulepszania dotychczaso-
Powstanie stat24 było decyzją Gemius SA Aktualnie stat24 prowadzi prace nad nowym wej usługi.
i wiązało się z umożliwieniem oferowania ma- produktem, który zostanie wprowadzony na ry-
łym i średnim przedsiębiorstwom profesjonal- nek w drugiej połowie 2007 roku.
nego narzędzia badawczego, jakim miał być stat24 jest w Polsce symbolem wiarygodno-
stat24. Główną misją stat24 jest poszerzanie za- ści, niezawodności i łatwego dostępu do przy-
sięgu badawczego, zarówno w Polsce, jak i w Eu- datnych informacji dotyczących witryny po-
ropie Środkowo-Wschodniej. przez czytelny interfejs po korzystnej i konku-
74 05/2007
Recenzja
Wydawnictwo: Helion
Autor: Jeffrey Bardzell
Stron: 472
Cena: 69 zł
ISBN: 83-246-0309-3
Dzisiaj, gdy zapotrzebowanie na strony WWW rośnie z dnia na Przechodząc przez kolejne lekcje, nauczymy się: tworzyć formu-
dzień, coraz więcej osób chce zająć się ich tworzeniem. Jednak larze służące do wysyłania maili, zbudujemy kalkulator cen wycie-
obecnie odchodzi się od prostych, statycznych witryn, standardem czek, pracować z bazą danych, budowania interfejsów wyszukiwa-
są strony dynamiczne. nia, tworzyć prosty CMS do aktualizacji stron, ponadto instalować
Materiał składa się z 15 lekcji, które nie są oddzielnymi zagadnie- środowiska ASP, PHP oraz ColdFusion. Każdy rozdział w sposób
niami, a składają się na jeden duży projekt. I tak na wstępie poznamy charakterystyczny dla serii Oficjalny Podręcznik, poprzedzony jest
charakterystykę fikcyjnej firmy turystycznej Newland Tours. Firma informacją co zrobimy podczas danej lekcji, przewidywany czas na
co prawda posiada już własną stronę WWW, jednak nie jest z niej jej ukończenie, oraz jakie pliki potrzebne będą do jej wykonania.
zadowolona. Wynika to z tego że informacje na stronie są nieaktu- Książka nie wyczerpuje całej problematyki a jest jedynie wstę-
alne, a wszelkie zmiany na witrynie wymagają skorzystania z usług pem do tematyki związanej z tworzeniem dynamicznych stron
webmastera, co nie jest ani tanie, ani praktyczne. Dlatego Newland WWW. Podsumowując ten podręcznik jest bardzo dobrą pozycją,
Tours zleca przebudowę strony na dynamiczną, z prostym CMSem który w przystępny sposób, opisuje przebudowę witryny. Małym
za pomocą którego jej pracownicy będą mogli w prosty sposób uak- niedopatrzeniem jest to, że na płycie CD pliki źródłowe są w wer-
tualniać ofertę. I to jest zadanie dla Ciebie drogi Czytelniku. Dzięki sji angielskiej, a książka opisuje polską wersję witryny. Jednak na
takiemu podejściu, mamy możliwość zapoznać się z potencjalnymi szczęście, polskie pliki źródłowe są do pobrania na strony wydaw-
problemami webmastera. nictwa Helion, pod adresem http://helion.pl/ksiazki/d8apof.htm.
Wydawnictwo: Helion
Autorzy: Tom Green, Jordan L. Chilcott
Stron: 480
Cena: 59 zł
ISBN: 83-246-0313-1
Książka Macromedia Flash 8 Professinal Oficialny Podręcznik to brany, że poziom trudności rośnie wraz z kolejnymi przerabianymi
obowiązkowa lektura, przeznaczona szczególnie dla osób które za- lekcjami. Przystępny język, wprowadzenia do lekcji, podsumowa-
wodowo zamierzają zajmować się projektowaniem i przygotowy- nia każdej lekcji, a także przybliżony czas potrzebny na wykonanie
waniem materiałów na potrzeby Internetu oraz coraz dynamicz- ćwiczenia sprawia że nauka jest przyjemna i wiemy czego się na-
niej rozwijającego się rynku aplikacji mobilnych. uczymy przerabiając kolejną lekcję.
Po podręcznik powinny sięgnąć osoby, posiadające przynajm- Zostały wyjaśnione tutaj takie tematy jak: praca z tekstem, grafi-
niej podstawową wiedzę na temat obsługi programu Flash 8 lub ze- ką, wideo, podstawy Action Script 2.0 oraz ich praktyczne zastoso-
tknęły się w swojej pracy z wcześniejszą wersją programu. Dzięki wanie np. do prezentacji slajdów, tworzenia animacji, przygotowy-
tej książce będą mogły rozwinąć swoje dotychczasowe umiejętno- waniem aplikacji na urządzenia przenośne itp.
ści, a tworzone projekty wzbogacić zarówno o elementy audio, wi- Na uwagę zasługuje to, że większość kolejnych lekcji, wyma-
deo lub dynamicznie uaktualniać zawartość stron przygotowywa- ga od czytelnika wykorzystania umiejętności zdobytych przy
nych we Flashu. Osobom rozpoczynającym swoją przygodę z Fla- wcześniejszych ćwiczeniach. Bardzo przydatne są również
shem polecam do lekturę książki „Macromedia Flash 8 Oficialny wskazówki oraz komentarze, dotyczące standardów oraz za-
Podręcznik”, który wprowadza i wyjaśnia podstawowe zagadnienia sad projektowych przyjętych przez osoby zajmujące się zawodo-
związane z programem Flash 8. wo Flashem. Sprawia to, że wykonując kolejne ćwiczenia szyb-
Materiał podręcznika został podzielony na 13 ciekawych lekcji ko i coraz lepiej opanowujemy obsługę praktycznego wykorzy-
(materiały źródłowe są dołączone na CD). Materiał zostały tak do- stania Flasha.
75
Recenzja
Instalacja
i pierwsze spostrzeżenia
Po włożeniu nośnika z oprogramowaniem ma-
my wybór składników instalacji – Delphi for PHP
oraz InterBase 2007. To dobre rozwiązanie, gdyż
nie każdy jest zainteresowany InterBase'em, a jed-
nocześnie ci, którzy chcą, mogą go sobie doinsta-
lować i mieć w pełni sprawną aplikację opartą o
profesjonalną bazę danych. Instalacja przebiega
bezproblemowo, ale jak zdążyłem zauważyć, w
razie próby reinstalacji programu pojawia się kło-
pot. Z rejestru systemu nie są usuwane informa-
cje o bibliotekach standardowych, przez co przy
ponownej instalacji są pomijane przez instalator i
program nie może działać właściwie. Warto więc
pamiętać o czyszczeniu rejestru przed ponow-
nym zainstalowaniem.
Po pomyślnej instalacji możemy uruchomić
nasze oprogramowanie. Jako pierwszy zobaczy-
my widok okienka na wzór borlandowskiego
Buildera, od którego przecież wywodzi się fir-
ma CodeGear (Rysunek 1.).
Rysunek 1. Główne okno Delphi for PHP
Po lewej stronie mamy okienka, w których
możemy obserwować wykorzystywane elemen-
ty umieszczone na formie oraz właściwości po-
szczególnych elementów. Po prawej stronie na-
tomiast znajduje się widok komponentów, baz
danych oraz elementów do wykorzystania w
aplikacji. W centralnym okienku natomiast
możemy zobaczyć kilka podstawowych infor-
macji o ostatnio edytowanych projektach, parę
nowinek na temat produktu oraz kilka najczę-
ściej wykorzystywanych funkcji programu, np.
otwarcie nowego pliku.
Pierwsze próby
Jak to zwykle bywa, zanim zaczniemy pracę z
nowym oprogramowaniem, należy zapoznać się
z dokumentacją. Tutaj natrafiamy na pierwszy
zawód. Dokumentacja jest całkiem spora, ma-
my opisane poszczególne klasy, metody i bi-
blioteki, ale liczbę przykładów można policzyć
na palcach obu rąk. A przecież, jak wiadomo,
człowiek najlepiej uczy się na przykładach. Aby
więc rozpocząć pracę z tym programem, warto
jest znać chociaż ogólne zasady działania aplika- Rysunek 2. Przykładowo dodane komponenty
76 05/2007
Delphi for PHP
baczymy tylko w IE. Jest to niedopuszczalne nie kodu dla metody podwójnego kliknięcia,
przy realizacji stron WWW, ponieważ straci- w której będziemy mogli oprogramować żąda-
libyśmy możliwość nawigacji. Po dodaniu ele- ne zadanie. Do poszczególnych elementów od-
mentów możemy je oprogramować, przecho- wołujemy się poprzez następujący schemat:
dząc do widoku kodu widocznego na Rysun-
ku 3. Pierwsze, co dostrzeżmy w tym wido- $this->nazwa_elementu;
ku, to liczba dołączanych plików. Jest ich cał-
kiem sporo jak na stronę, która tak naprawdę Gdy chcemy zmienić lub ustawić jakąś war-
nic jeszcze nie robi. Przechodząc dalej, mamy tość dla elementu, po prostu rozszerzamy po- Rysunek 5. Logowanie do panelu administratora
zadeklarowane zmienne reprezentujące doda- przedni kod do postaci:
ne elementy. Aby dodać jakąś akcję, musimy Przykładowy projekt
w trybie Design wybrać element i np. kliknąć $this->nazwa_elementu-> Firma CodeGear udostępniła przykładowy pro-
na niego dwa razy, co spowoduje wygenerowa- nazwa_parametru=wartość parametru; jekt e-commerce wykonany w Delphi for PHP
oparty o bazę InterBase. Może pobrać go każdy,
warunkiem jest tylko zarejestrowanie się na ich
stronie. Po utworzeniu bazy oraz umieszczeniu
plików strony na naszym serwerze Apache, któ-
ry został automatycznie zainstalowany z Delphi
for PHP, możemy zobaczyć pobraną aplikację.
Jedyne słowa, które się nasuwają po zobaczeniu
tej strony, to „żart” albo „porażka marketingo-
wa”. Stronę pokazano na Rysunkach 4. i 5.
Strony są nader proste i zrobienie takich wi-
tryn w PHP również nie powinno zająć du-
żo czasu, choć tę stronę zapewne wykonano
w znacznie krótszym czasie niż normalnie, ale
nie wygląda ona interesująco i na pewno nie po-
kazuje możliwości, którymi tak przecież chwa-
li się CodeGear. Strona ma funkcjonalność ni-
by–sklepu internetowego pozbawionego rze-
czywistych funkcji. Pliki tej aplikacji mają obję-
tość 1 MB (nie wliczając obrazków), co samo w
sobie może zaszokować każdego. O ile wygląd
łatwo zmienić, bo witryna wykorzystuje szablo-
ny, o tyle zdecydowanie nie można pochwalić
Rysunek 3. Widok kodu takiego rozmiaru strony WWW. Niestety tak
duży rozmiar jest odczuwalny podczas korzy-
stania z tej strony, jej wygenerowanie nawet na
localhoście trwa parę chwil. Edycja projektu nie
sprawia żadnych problemów, o ile znamy PHP,
natomiast całkowite przebudowanie takiej stro-
ny może okazać się dość skomplikowanym za-
daniem.
Podsumowanie
Możemy stwierdzić, że program Delphi for PHP
jest na pewno ciekawym rozwiązaniem, któ-
re w przyszłości może znaleźć swoje miejsce
na rynku. Niestety, w tym momencie sprawia
wrażenie oprogramowania robionego w pośpie-
chu, a jak wiadomo nawet przemyślany projekt
z braku czasu może wiele stracić na swojej funk-
cjonalności. Poza tym brakuje źródeł, z których
można czerpać wiedzę na temat tworzenia apli-
kacji w tym programie – dokumentacja pozba-
Rysunek 4. Strona dla zwykłego użytkownika wiona przykładów, dwa krótkie filmy oraz nie-
wielka strona to zdecydowanie za mało.
W sieci
• http://www.codegear.com/products/delphi/php – strona producenta, można z niej dowie-
ŁUKASZ SKOWROŃSKI
dzieć się paru rzeczy o produkcie oraz zobaczyć dwa filmy z przykładami wykorzystania pro- Autor jest studentem informatyki na Uniwersyte-
gramu. cie w Białymstoku oraz pracuje jako programista
• http://dn.codegear.com/article/36362 – strona producenta z przykładową stroną WWW. PHP w firmie E–Studio.
Kontak z autorem: lukas.skowronski@gmail.com
www.phpsolmag.org 77
Felieton
Witryny internetowe
– tylko dla zarobku?
W
szyscy zapewne wiemy, że na two- Ile straconych nerwów przy nauce programowa- a fakt, że informatyk to całkiem opłacalny za-
rzeniu witryn internetowych moż- nia? Sam zajmuje się tworzeniem witryn inter- wód, czerpiemy spore zarobki. Ale tak napraw-
na całkiem nieźle zarobić. Ale czy netowych i wiem, co to wszystko znaczy. dę, dlaczego? Może to chciwość... jedna z gor-
kiedykolwiek zastanawialiście się, czy istnieją oso- W „interesie” siedzę już około 5 lat i do tej szych z ludzkich cech. Zazwyczaj informatycy
by, które zrobią to dla nas „for free”? Surfując po pory pamiętam początki. Spotkałem tylko ma- nie mają czasu i chęci, aby zajmować się osoba-
Internecie, spotkałem wiele ogłoszeń „Zrobię stronę łą garstkę ludzi, którzy byli mi w stanie pomóc mi początkującymi. Idąc dalej, ludzi dziwi to, że
internetową za...”, „Profesjonalna firma stworzy stro- całkowicie za darmo. Reszta oferowała mi swo- zakładamy portale dla internautów, nie dla zarob-
nę internetową za...”. Dziwnie się poczułem... Oso- ją pomoc za 50, 100, 200, a nawet 1000 zł. ku. Mówię w tej chwili, o osobach które siedzą w
by, które chcą w jakiś sposób zaistnieć w cyber- Skąd nastolatek miał wziąć choćby 100 zł? tym wszystkim „po uszy”. Moi przyjaciele twier-
świecie, muszą za to płacić? Nie mogą sami stwo- Dzięki właśnie tej grupie osób prowadzę jed- dzą, że nie opłaca mi się prowadzić serwisu, bo
rzyć strony w jakimś darmowym oprogramowa- nak poważny portal internetowy... i za to im nie przynosi praktycznie żadnych zysków i pyta-
niu? Programów jest sporo, trzeba tylko umieć je dziękuję. Tak naprawdę powyższy wstęp nie ją, dlaczego to robią. Zgadnijcie, co odpowiadam...
znaleźć. Ale czy taka strona będzie chętnie ogląda- jest głównym tematem tego felietonu. Pragnę Dla satysfakcji, że ktoś może się dowiedzieć
na? Wydaje się, że nie bardzo... Zazwyczaj nie wy- pokazać, że czasami to 500 zł jest mniej warte tego, czego szukał. Daje mi to, można powiedzieć,
gląda ona najlepiej. A co z wyszukiwarkami? Sami od satysfakcji za podziękowania od osób, któ- ogromną satysfakcję, że ktoś, komu pomogłem,
wiecie, jak to wszystko jest zbudowane... rym pomogliśmy. Być może dzięki naszej po- przysyła mi zwyczajne „dziękuję za pomoc” lub
Wracając do tworzenia witryn, czy ktoś mocy ktoś zostanie sławnym programistą, bo inne miłe słowa. Myślę, że czasami warto...
będzie się uczył HTML-a, PHP, JS, obsługi go to wszystko zainteresuje. A może zostanie
Photoshopa czy Gimpa tylko po to, aby stwo- sławnym fotografem, bo stworzy prostą gale-
rzyć sobie własną stronę, gdzie np. umieści gale- rię zdjęć. WOJCIECH SAPIECHOWSKI
rię zdjęć? To byłoby zbyt pracochłonne. Ile cza- Przejdźmy dalej, dlaczego nie chcemy robić Od kilku lat zajmuje się tworzeniem witryn interneto-
su musimy poświęcićna to, aby w jakimś stop- stron „for free”? Zapewne, jak wiemy, pieniądze wych. Jest jednym z administratorów portalu WebHat.
niu pojąć możliwości programów graficznych? szybko „uciekają”, więc musimy jakoś zarabiać, Kontakt z autorem: sapcik@webhat.pl
78 05/2007
Prenumerata PRO
Więcej informacji: patrycja.wadolowska@software.com.pl tel.: 022 887-13-45
v
www.buyitpress.com
Prosimy wypełnić czytelnie i przesłać faksem na numer: (22) 887 10 11 lub listownie na adres: Software-Wydawnictwo Sp. z o.o.,
Bokserska 1, 02-682 Warszawa, e-mail: pren@software.com.pl. Przyjmujemy też zamówienia telefoniczne: (22) 887 14 44
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
W sprzedaży od października