Zacznij tam, gdzie inni kończą! PHP jest obecnie najpopularniejszym językiem programowania aplikacji internetowych, a je
1,299 168 6MB
Polish Pages [355] Year 2012
Table of contents :
Spis treści
O autorach
O korektorze merytorycznym
Przedmowa
Wprowadzenie do PHP
Geneza PHP
Czym jest PHP?
Szczegółowy przegląd treści książki
Rozdział 1. Obiektowość
Rozdział 2. Wyjątki i referencje
Rozdział 3. Mobilne PHP
Rozdział 4. Media społecznościowe
Rozdział 5. Nowości technologiczne
Rozdział 6. Tworzenie formularzy i zarządzanie nimi
Rozdziały 7. i 8. Integracja z bazami danych. Część I i II
Rozdział 9. Integracja z bazami danych. Część III
Rozdział 10. Biblioteki
Rozdział 11. Bezpieczeństwo
Rozdział 12. Programowanie zwinne z wykorzystaniem Zend Studio dla Eclipse, Bugzilli, Mylyn i Subversion
Rozdział 13. Refaktoryzacja, testy jednostkowe i ciągła integracja
Rozdział 14. XML
Rozdział 15. JSON i Ajax
Rozdział 16. Konkluzja
Przyszłość PHP
Rozdział 1. Obiektowość
Klasy
Dziedziczenie i przeciążanie
„Magiczne” funkcje
Metody __get i __set
Metoda __isset
Metoda __call
Metoda __toString()
Kopiowanie, klonowanie oraz porównywanie obiektów
Interfejsy, iteratory i klasy abstrakcyjne
Kontekst klasy i elementy statyczne
Podsumowanie
Rozdział 2. Wyjątki i referencje
Wyjątki
Referencje
Podsumowanie
Rozdział 3. Mobilne PHP
Różnorodność urządzeń
Rozpoznanie urządzenia
Aplikacja kliencka
Wbudowane funkcje PHP
Rozpoznawanie możliwości urządzenia
WURFL
Tera-WURFL
Narzędzia renderujące
WALL
Reagujący CSS
Emulatory i SDK
Tworzenie dla systemu Android
Adobe Flash Builder dla PHP
Kody QR
Podsumowanie
Rozdział 4. Media społecznościowe
OAuth
Twitter
API publicznego wyszukiwania
Prywatne REST API
Wykorzystanie mechanizmu OAuth w celu powiązania strony z systemem logowania
Dodatkowe metody API i przykłady jego wykorzystania
Facebook
Dodanie linku wylogowania z Facebooka
Żądanie dodatkowych uprawnień
Graph API
Podsumowanie
Rozdział 5. Nowości technologiczne
Przestrzenie nazw
Przestrzenie nazw i autoładowanie
Przestrzenie nazw — podsumowanie
Funkcje anonimowe
Nowdoc
Lokalne instrukcje goto
Standardowa biblioteka PHP — SPL
SPL — podsumowanie
Rozszerzenie phar
Podsumowanie
Rozdział 6. Tworzenie formularzy i zarządzanie nimi
Walidacja danych
Wczytywanie plików i obrazów
Konwersja obrazów i miniatury
Wyrażenia regularne
Integracja języków
Podsumowanie
Rozdział 7. Integracja z bazami danych. Część I
Wprowadzenie do MongoDB
Zapytania w MongoDB
Modyfikowanie dokumentów w MongoDB
Agregacje w MongoDB
Podsumowanie MongoDB
Wprowadzenie do CouchDB
Wykorzystanie interfejsu Futon
Podsumowanie CouchDB
Wprowadzenie do SQLite
Podsumowanie SQLite
Podsumowanie
Rozdział 8. Integracja z bazami danych. Część II
Wprowadzenie do rozszerzenia MySQLi
Podsumowanie rozszerzenia MySQLi
Wprowadzenie do PDO
Podsumowanie PDO
Wprowadzenie do ADOdb
Podsumowanie ADOdb
Wyszukiwanie pełnotekstowe przy wykorzystaniu Sphinksa
Podsumowanie
Rozdział 9. Integracja z bazami danych. Część III
Wprowadzenie do Oracle
Podstawy. Połączenie i wykonywanie zapytań
Interfejs tablicowy
Procedury i kursory w PL/SQL
Praca z typami LOB
Inne podejście do połączeń — pule połączeń
Zestawy znaków w bazie danych i PHP
Podsumowanie
Rozdział 10. Biblioteki
SimplePie
TCPDF
Pobieranie danych ze stron internetowych
Integracja z Mapami Google
Wiadomości e-mail i SMS
gChartPHP — biblioteka wykorzystująca Google Chart API
Podsumowanie
Rozdział 11. Bezpieczeństwo
Nigdy nie ufaj danym
register_globals
Białe i czarne listy
Dane formularzy
$_COOKIES, $_SESSION i $_SERVER
Żądania Ajax
Powszechne ataki
Polityka tego samego pochodzenia
XSS (Cross Site Scripting)
CSRF (Cross-Site Request Forgery)
Sesje
Zapobieganie atakom typu SQL injection
Wyrażenia filtrujące
Plik php.ini i ustawienia serwera
Środowisko serwerowe
Zabezpieczanie pliku php.ini
Algorytmy haseł
Podsumowanie
Rozdział 12. Programowanie zwinne z wykorzystaniem Zend Studio dla Eclipse, Bugzilli, Mylyn i Subversion
Zasady programowania zwinnego
Rajd programowania zwinnego
Wprowadzenie do programu Bugzilla
Mylyn dla Eclipse
Bugzilla i Mylyn w połączeniu z Eclipse
Maksymalizowanie korzyści
Podsumowanie
Rozdział 13. Refaktoryzacja, testy jednostkowe i ciągła integracja
Refaktoryzacja
Niewielka refaktoryzacja
Większy przykład
Testy jednostkowe
Ciągła integracja
Serwer ciągłej integracji
System kontroli wersji
Analiza statyczna
Budowanie automatyzacji
Uruchomienie serwera Jenkins
Podsumowanie
Rozdział 14. XML
Podstawy XML
Schematy
SimpleXML
Parsowanie XML z tekstu
Parsowanie XML z pliku
Przestrzenie nazw
RSS
Generowanie dokumentów XML za pomocą SimpleXML
DOMDocument
XMLReader i XMLWriter
Podsumowanie
Rozdział 15. JSON i Ajax
JSON
PHP i JSON
Ajax
Tradycyjny model WWW
Model Ajax
Zdarzenia synchroniczne kontra asynchroniczne
Obiekt XMLHttpRequest
Wykorzystanie obiektu XMLHttpRequest
API JavaScript wyższego poziomu
Przykłady jQuery
Przesyłanie danych z Ajaksa do skryptu PHP
Prosty program graficzny
Utrzymanie stanu
Podsumowanie
Rozdział 16. Konkluzja
Zasoby
www.php.net
www.zend.com
devzone.zend.pl
www.phparch.com
Konferencje
Certyfikacja PHP
Podsumowanie
Dodatek. Wyrażenia regularne
Składnia wyrażeń regularnych
Przykłady wyrażeń regularnych
Opcje wewnętrzne
Chciwość
Funkcje wykorzystujące wyrażenia regularne
Zamiana ciągów — preg_replace
Inne funkcje
Skorowidz
Spis treści
O autorach ...................................................................................................................................11 O korektorze merytorycznym .......................................................................................................13 Przedmowa ..................................................................................................................................15 Wprowadzenie do PHP ................................................................................................................17 Rozdział 1.
Obiektowość ..........................................................................................................21 Klasy ....................................................................................................................................................... 21 Dziedziczenie i przeciążanie ............................................................................................................... 23 „Magiczne” funkcje ............................................................................................................................. 27 Metody __get i __set .................................................................................................................... 27 Metoda __isset ............................................................................................................................... 28 Metoda __call ................................................................................................................................ 28 Metoda __toString() ..................................................................................................................... 29 Kopiowanie, klonowanie oraz porównywanie obiektów ............................................................... 29 Interfejsy, iteratory i klasy abstrakcyjne ........................................................................................... 31 Kontekst klasy i elementy statyczne .................................................................................................. 35 Podsumowanie ..................................................................................................................................... 36
Rozdział 2.
Wyjątki i referencje ................................................................................................37 Wyjątki .................................................................................................................................................. 37 Referencje .............................................................................................................................................. 41 Podsumowanie ..................................................................................................................................... 45
Rozdział 3.
Mobilne PHP ..........................................................................................................47 Różnorodność urządzeń ..................................................................................................................... 47 Rozpoznanie urządzenia ..................................................................................................................... 48 Aplikacja kliencka ......................................................................................................................... 48 Wbudowane funkcje PHP ........................................................................................................... 48 Rozpoznawanie możliwości urządzenia ........................................................................................... 51 WURFL .......................................................................................................................................... 51 Tera-WURFL ................................................................................................................................. 57
PHP. ZAAWANSOWANE PROGRAMOWANIE
Narzędzia renderujące ........................................................................................................................ 60 WALL ............................................................................................................................................. 60 Reagujący CSS ............................................................................................................................... 62 Emulatory i SDK .................................................................................................................................. 62 Tworzenie dla systemu Android ................................................................................................ 62 Adobe Flash Builder dla PHP ..................................................................................................... 62 Kody QR ................................................................................................................................................ 63 Podsumowanie ..................................................................................................................................... 64
Rozdział 4.
Media społecznościowe .........................................................................................65 OAuth .................................................................................................................................................... 65 Twitter ................................................................................................................................................... 66 API publicznego wyszukiwania .................................................................................................. 66 Prywatne REST API ..................................................................................................................... 67 Wykorzystanie mechanizmu OAuth w celu powiązania strony z systemem logowania ........77 Dodatkowe metody API i przykłady jego wykorzystania ....................................................... 80 Facebook ............................................................................................................................................... 83 Dodanie linku wylogowania z Facebooka ................................................................................. 88 Żądanie dodatkowych uprawnień .............................................................................................. 89 Graph API ...................................................................................................................................... 89 Podsumowanie ..................................................................................................................................... 91
Rozdział 5.
Nowości technologiczne ........................................................................................93 Przestrzenie nazw ................................................................................................................................ 93 Przestrzenie nazw i autoładowanie ............................................................................................ 96 Przestrzenie nazw — podsumowanie ........................................................................................ 96 Funkcje anonimowe ............................................................................................................................ 96 Nowdoc ................................................................................................................................................. 97 Lokalne instrukcje goto ..................................................................................................................... 100 Standardowa biblioteka PHP — SPL .............................................................................................. 100 SPL — podsumowanie ............................................................................................................... 103 Rozszerzenie phar .............................................................................................................................. 103 Podsumowanie ................................................................................................................................... 106
Rozdział 6.
Tworzenie formularzy i zarządzanie nimi ............................................................107 Walidacja danych ............................................................................................................................... 107 Wczytywanie plików i obrazów ....................................................................................................... 113 Konwersja obrazów i miniatury ...................................................................................................... 114 Wyrażenia regularne ......................................................................................................................... 115 Integracja języków ............................................................................................................................. 118 Podsumowanie ................................................................................................................................... 119
Rozdział 7.
Integracja z bazami danych. Część I ....................................................................121 Wprowadzenie do MongoDB .......................................................................................................... 122 Zapytania w MongoDB .............................................................................................................. 126 Modyfikowanie dokumentów w MongoDB ........................................................................... 130 Agregacje w MongoDB .............................................................................................................. 132 Podsumowanie MongoDB ........................................................................................................ 134
6
SPIS TREŚCI
Wprowadzenie do CouchDB ........................................................................................................... 134 Wykorzystanie interfejsu Futon ............................................................................................... 135 Podsumowanie CouchDB ......................................................................................................... 140 Wprowadzenie do SQLite ................................................................................................................. 141 Podsumowanie SQLite ............................................................................................................... 149 Podsumowanie ................................................................................................................................... 149
Rozdział 8.
Integracja z bazami danych. Część II ...................................................................151 Wprowadzenie do rozszerzenia MySQLi ....................................................................................... 151 Podsumowanie rozszerzenia MySQLi ..................................................................................... 158 Wprowadzenie do PDO .................................................................................................................... 158 Podsumowanie PDO .................................................................................................................. 161 Wprowadzenie do ADOdb ............................................................................................................... 161 Podsumowanie ADOdb ............................................................................................................. 165 Wyszukiwanie pełnotekstowe przy wykorzystaniu Sphinksa ..................................................... 165 Podsumowanie ................................................................................................................................... 173
Rozdział 9.
Integracja z bazami danych. Część III ..................................................................175 Wprowadzenie do Oracle ................................................................................................................. 175 Podstawy. Połączenie i wykonywanie zapytań .............................................................................. 177 Interfejs tablicowy .............................................................................................................................. 180 Procedury i kursory w PL/SQL ........................................................................................................ 183 Praca z typami LOB ........................................................................................................................... 186 Inne podejście do połączeń — pule połączeń ................................................................................ 190 Zestawy znaków w bazie danych i PHP .......................................................................................... 192 Podsumowanie ................................................................................................................................... 193
Rozdział 10. Biblioteki .............................................................................................................195 SimplePie ............................................................................................................................................. 196 TCPDF ................................................................................................................................................. 199 Pobieranie danych ze stron internetowych ............................................................................. 204 Integracja z Mapami Google ............................................................................................................ 209 Wiadomości e-mail i SMS ................................................................................................................ 211 gChartPHP — biblioteka wykorzystująca Google Chart API ..................................................... 215 Podsumowanie ................................................................................................................................... 219
Rozdział 11. Bezpieczeństwo ...................................................................................................221 Nigdy nie ufaj danym ........................................................................................................................ 221 register_globals ........................................................................................................................... 222 Białe i czarne listy ....................................................................................................................... 222 Dane formularzy ......................................................................................................................... 223 $_COOKIES, $_SESSION i $_SERVER .................................................................................. 224 Żądania Ajax ................................................................................................................................ 224 Powszechne ataki ............................................................................................................................... 225 Polityka tego samego pochodzenia .......................................................................................... 225 XSS (Cross Site Scripting) .......................................................................................................... 225 CSRF (Cross-Site Request Forgery) ......................................................................................... 228 Sesje ...................................................................................................................................................... 229 Zapobieganie atakom typu SQL injection ...................................................................................... 229
7
PHP. ZAAWANSOWANE PROGRAMOWANIE
Wyrażenia filtrujące .......................................................................................................................... 230 Plik php.ini i ustawienia serwera ..................................................................................................... 233 Środowisko serwerowe ............................................................................................................... 233 Zabezpieczanie pliku php.ini .................................................................................................... 234 Algorytmy haseł ................................................................................................................................. 235 Podsumowanie ................................................................................................................................... 236
Rozdział 12. Programowanie zwinne z wykorzystaniem Zend Studio dla Eclipse, Bugzilli, Mylyn i Subversion ..............................................................................................237 Zasady programowania zwinnego .................................................................................................. 237 Rajd programowania zwinnego ....................................................................................................... 238 Wprowadzenie do programu Bugzilla ............................................................................................ 239 Mylyn dla Eclipse ............................................................................................................................... 240 Bugzilla i Mylyn w połączeniu z Eclipse ......................................................................................... 242 Maksymalizowanie korzyści ............................................................................................................. 245 Podsumowanie ................................................................................................................................... 246
Rozdział 13. Refaktoryzacja, testy jednostkowe i ciągła integracja .........................................249 Refaktoryzacja .................................................................................................................................... 249 Niewielka refaktoryzacja ............................................................................................................ 250 Większy przykład ........................................................................................................................ 253 Testy jednostkowe ............................................................................................................................. 265 Ciągła integracja ................................................................................................................................. 279 Serwer ciągłej integracji ............................................................................................................. 280 System kontroli wersji ................................................................................................................ 280 Analiza statyczna ........................................................................................................................ 281 Budowanie automatyzacji .......................................................................................................... 282 Uruchomienie serwera Jenkins ................................................................................................. 282 Podsumowanie ................................................................................................................................... 285
Rozdział 14. XML .....................................................................................................................287 Podstawy XML ................................................................................................................................... 287 Schematy ............................................................................................................................................. 288 SimpleXML ......................................................................................................................................... 289 Parsowanie XML z tekstu .......................................................................................................... 289 Parsowanie XML z pliku ............................................................................................................ 290 Przestrzenie nazw ....................................................................................................................... 294 RSS ................................................................................................................................................ 296 Generowanie dokumentów XML za pomocą SimpleXML .................................................. 298 DOMDocument ................................................................................................................................. 303 XMLReader i XMLWriter ................................................................................................................ 305 Podsumowanie ................................................................................................................................... 306
Rozdział 15. JSON i Ajax ..........................................................................................................307 JSON .................................................................................................................................................... 308 PHP i JSON .................................................................................................................................. 309 Ajax ...................................................................................................................................................... 312 Tradycyjny model WWW ......................................................................................................... 313 Model Ajax ................................................................................................................................... 313 Zdarzenia synchroniczne kontra asynchroniczne ................................................................. 315 8
SPIS TREŚCI
Obiekt XMLHttpRequest ........................................................................................................... 316 Wykorzystanie obiektu XMLHttpRequest .............................................................................. 317 API JavaScript wyższego poziomu ........................................................................................... 322 Przykłady jQuery ........................................................................................................................ 322 Przesyłanie danych z Ajaksa do skryptu PHP ........................................................................ 327 Prosty program graficzny ................................................................................................................. 328 Utrzymanie stanu ....................................................................................................................... 330 Podsumowanie ................................................................................................................................... 335
Rozdział 16. Konkluzja .............................................................................................................337 Zasoby .................................................................................................................................................. 337 www.php.net ................................................................................................................................ 337 www.zend.com ............................................................................................................................ 338 devzone.zend.pl ........................................................................................................................... 338 www.phparch.com ...................................................................................................................... 338 Konferencje ......................................................................................................................................... 339 Certyfikacja PHP ................................................................................................................................ 340 Podsumowanie ................................................................................................................................... 341
Dodatek
Wyrażenia regularne ...........................................................................................343 Składnia wyrażeń regularnych ......................................................................................................... 343 Przykłady wyrażeń regularnych ....................................................................................................... 344 Opcje wewnętrzne ...................................................................................................................... 347 Chciwość ...................................................................................................................................... 347 Funkcje wykorzystujące wyrażenia regularne ............................................................................... 348 Zamiana ciągów — preg_replace ............................................................................................. 348 Inne funkcje ........................................................................................................................................ 350
Skorowidz ..................................................................................................................................353
9
PHP. ZAAWANSOWANE PROGRAMOWANIE
10
O autorach
Peter MacIntyre ma ponaddwudziestoletnie doświadczenie w przemyśle IT, głównie w obszarze tworzenia oprogramowania. Posiada certyfikat Zend (ZCE). Opublikował wiele prac związanych z IT, między innymi: Using Visual Objects (Que 1995), Using PowerBuilder 5 (Que 1996), ASP.NET Bible (Wiley 2001), Zend Studio for Eclipse Developer’s Guide (Sams 2008), PHP5. Programowanie (Helion 2007) i PHP: The Good Parts (O’Reilly Media 2010). Był prelegentem na międzynarodowych konferencjach, włączając w to CA-World w Nowym Orleanie, CA-TechniCon w Kolonii i CA-Expo w Melbourne. Mieszka na Wyspie Świętego Edwarda w Kanadzie, gdzie piastuje stanowisko starszego konsultanta w firmie OSSCube (www.osscube.com), będącej liderem w dziedzinie tworzenia oprogramowania open source. Pomaga w prowadzeniu Centrum Doskonalenia Zend. Można się z nim skontaktować mailowo pod adresem [email protected]. Brian Danchilla jest certyfikowanym inżynierem Zend i okazjonalnym programistą Java. Posiada licencjat w dziedzinie informatyki i matematyki. Programy komputerowe pisze już ponad połowę swojego życia, włączając w to aplikacje internetowe, analizy numeryczne oraz programy VOIP (voice over IP). Szybko wdraża się w nowe technologie i API. Jest zagorzałym czytelnikiem publikacji technicznych. Pracując jako asystent na uniwersytecie, prywatny nauczyciel i kierownik zespołów PHP Danchilla, nauczył się przekazywać swoją wiedzę. Udziela się także w ramach społeczności Stack Overflow. Kiedy nie programuje, lubi spędzać czas na świeżym powietrzu albo grać na gitarze. Mladen Gogala jest bardzo doświadczonym specjalistą w dziedzinie baz danych. Może się pochwalić długą i udaną karierą. Był administratorem bazy Oracle oraz systemów Linux i Unix, administratorem VAX/VMS, a ostatnio architektem wydajności baz danych. Od roku 1990 pracował z bazami zawierającymi terabajty danych — głównie z bazami Oracle. Zna Linuksa, Perl i PHP. PHP stało się jego ulubionym językiem na początku roku 2000. Jest autorem książki Easy Oracle PHP: Create Dynamic Web Pages with Oracle Data (Rampant TechPress, 2006). Napisał także kilka artykułów dotyczących PHP, Oracle i Symfony. Urodził się w roku 1961 w chorwackim Zagrzebiu.
PHP. ZAAWANSOWANE PROGRAMOWANIE
12
O korektorze merytorycznym
Thomas Myer jest autorem, konsultantem i programistą. Większość czasu spędza, pracując nad projektami PHP (głównie nad programami CodeIgniter, ExpressionEngine, WordPress i MojoMotor), jednak zdarza mu się także pracować z Pythonem, Perlem i Objective-C. Możesz subskrybować jego kanał na Twitterze (jeśli się odważysz): @myerman. Nie zapomnij także odwiedzić strony www.tripledogs.com, aby dowiedzieć się więcej na temat założonej przez niego firmy Triple Dog Dare Media. Aktualnie mieszka w Austin (Teksas) z żoną Hope i psami Kafką i Marlowe’em.
PHP. ZAAWANSOWANE PROGRAMOWANIE
14
Przedmowa
Ponieważ PHP rozpoczynało swój żywot jako projekt hakerów — próba opracowania łatwego i przyjemnego języka pozwalającego na tworzenie stron internetowych — nikt nie przypuszczał, że zyska ono popularność, jaką cieszy się dzisiaj. Przez lata próbowano badać powodzenie PHP różnymi metodami, sprawdzając, ile stron używa tego języka, liczbę sprzedanych książek o nim w sklepie Amazon, liczbę znaczących firm, które go wykorzystują, liczbę związanych z nim projektów, wielkość społeczności itd. Wtedy pojawił się nowy, o wiele mniej naukowy sposób. W 2008 roku, kiedy byłem w podróży poślubnej z żoną Any, mieszkaliśmy w małym hotelu o nazwie Noster Bayres, w Buenos Aires. Przybyliśmy po długim locie do zupełnie nowego miejsca, pełnego twarzy, których nigdy nie widzieliśmy. Wyobraź sobie moje zdziwienie, kiedy po wypełnieniu przez nas dokumentów recepcjonista zapytał mnie, czy to ja jestem Suraski, „ten gość od PHP”. Okazało się, że tworzył w PHP sieć społecznościową dla San Telmo. Wszystkie wskaźniki udowadniały wprawdzie duży zasięg i popularność PHP, ale to zdarzenie, mające miejsce w małym hotelu po drugiej stronie globu, przekonało mnie ostatecznie. Skoro ten recepcjonista tworzył oprogramowanie w PHP, zdecydowanie byliśmy w głównym nurcie. Obecnie, prawie trzy lata później, zaawansowana znajomość PHP jest kluczowa dla twórców aplikacji internetowych i dla wszystkich innych — w związku z ogromnym wzrostem popularności usług HTTP. PHP. Zaawansowane programowanie prezentuje kilka ważnych aspektów współczesnego programowania PHP, włączając w to obiektowość, tworzenie aplikacji mobilnych oraz skalowalne źródła danych, które mogą mieć istotny wpływ na przydatność aplikacji do pracy w chmurze. Jestem pewien, że wiedza, którą zdobędziesz, będzie dla Ciebie ważnym narzędziem i pomoże Ci wykorzystać wszystkie możliwości PHP 5.3. Szczęśliwego „pehapowania”! Zeev Suraski, CTO, Zend
PHP. ZAAWANSOWANE PROGRAMOWANIE
16
Wprowadzenie do PHP
To kolejna książka dotycząca języka PHP. Jest ona unikalna, ponieważ skupia się na zaawansowanych zagadnieniach i na nowościach. Staraliśmy się, aby była tak nowoczesna, jak to tylko możliwe w szybko zmieniającym się świecie internetu. Przeprowadzamy Czytelnika z poziomu średnio zaawansowanego do wysoko zaawansowanego użytkownika języka PHP.
Geneza PHP PHP rozpoczęło swój żywot jako projekt prowadzony przez Rasmusa Lerdorfa. W czerwcu 1995 r. Lerdorf opublikował wersję 1.0 osobistych narzędzi do tworzenia stron (ang. Personal Home Page Tools — stąd nazwa „PHP”). Była to kolekcja funkcji pozwalająca na automatyzację tworzenia i utrzymywania małych stron internetowych. Od tamtej pory PHP znacznie się rozwinęło, ewoluując do aktualnej wersji 5.3.4 (gdy powstawała książka). PHP był jednym z pierwszych języków pozwalających na tworzenie stron internetowych typu open source. Lerdorf okazał się wizjonerem, który zauważył potencjał języka, który mógłby rozwijać się razem ze społecznością internetową.
Czym jest PHP? Czym dokładnie jest PHP? Jak wygląda w aktualnej wersji? Najprościej mówiąc, PHP jest generatorem kodu HTML. Jeśli spojrzysz na kod źródłowy strony wygenerowanej za pomocą PHP, zobaczysz tylko znaczniki HTML; może jeszcze trochę skryptów JavaScript, jednak żadnego kodu PHP. Oczywiście, jest to zbytnie uproszczenie definicji języka, którego udział w rynku języków wykorzystywanych do tworzenia stron internetowych obejmuje od 39 do 59% (według różnych źródeł). Bez względu na to, którą liczbę uznasz za prawdziwą, PHP jest aktualnie najpopularniejszym językiem tworzenia i utrzymywania stron internetowych. Należy także zauważyć, że PHP jest darmowe. Tak, darmowe! Jest projektem open source. A więc jak na produkt, który nie jest monitorowany ani prowadzony przez żadną instytucję, PHP poradziło sobie świetnie, jeżeli chodzi o popularność. UWAGA. Więcej informacji dotyczących oprogramowania open source znajduje się w publikacji The Cathedral and the Bazaar Erica S. Raymonda, dostępnej pod adresem http://www.catb.org/~esr/writings/cathedral-bazaar/. Jest tam porównanie produktów tradycyjnych i open source.
PHP. ZAAWANSOWANE PROGRAMOWANIE
Aktualnie Zend Corporation jest prawdopodobnie światowym liderem PHP. Firma opracowała wiele dodatkowych produktów wspierających PHP i rozszerzających jego możliwości. Jest także głównym graczem, jeżeli chodzi o rozwój tego języka, odkąd założyciele firmy — Zeev Suraski i Andi Gutmans — podnieśli rękawicę (od PHP3). PHP jest bardzo otwartym i wyrozumiałym językiem między innymi dlatego, że jest słabo typowany. Oznacza to, że zmienne nie muszą być deklarowane z typem danych, jaki będzie w nich przechowywany — co jest konieczne w niektórych innych językach programowania. PHP próbuje raczej „wywnioskować” typ danych zapisanych w zmiennej z kontekstu i jej zawartości. Oznacza to na przykład, że zmienna o nazwie $informacje może podczas wykonywania programu przechowywać wiele różnych wartości. W niektórych przypadkach może to być wadą, ponieważ dane mogą ulegać modyfikacjom, powodując błędy w liniach, które np. oczekują liczby całkowitej, a otrzymują tekst. Programy PHP można także tworzyć w modelu zorientowanym obiektowo (OOP). Klasy, właściwości, metody, dziedziczenie, polimorfizm i enkapsulacja są częściami języka. To zwiększa możliwości powtórnego użycia kodu tworzonego w PHP oraz ułatwia korzystanie z niego. Oczywiście podejście obiektowe istnieje od długiego czasu, a PHP adaptuje i rozszerza możliwości obiektowe od kilku lat. Kolejną cenną cechą PHP jest możliwość wykonywania skryptów z poziomu wiersza poleceń (w systemach Linux i Windows), dzięki czemu język ten może być wykorzystywany w zadaniach CRON; nie musisz uczyć się innego języka programowania w celu realizacji innych zadań w środowisku serwerowym. Możesz tworzyć strony internetowe w tym samym języku, z którego korzystasz przy manipulowaniu plikami (jeżeli będziesz chciał). PHP ma także wiele punktów integracyjnych. Jest bardzo otwartym językiem. PHP służy nie tylko do tworzenia stron internetowych — może mieć wiele innych zastosowań. Połącz go z bazą danych poprzez odpowiednie rozszerzenie, a otrzymasz interfejs webowy lub nawet aplikację webową. Wykorzystaj dodatkową bibliotekę (np. tcpdf), a będziesz mógł w locie generować dokumenty PDF. Są to tylko dwa przykłady; w książce omówimy znacznie więcej dodatkowych bibliotek.
Szczegółowy przegląd treści książki Co w takim razie znajdziesz w tej książce? Staraliśmy się, aby zawierała najświeższe informacje dotyczące PHP, tak abyś umiał korzystać z najnowszych możliwości i rozszerzeń tego języka. Nie poświęcaliśmy miejsca na proste zagadnienia związane z językiem, takie jak to, czym jest zmienna lub w jaki sposób tworzyć pętle. Chcemy, abyś stał się wysoko zaawansowanym programistą oraz aby ten materiał pomógł Ci się przygotować do egzaminu certyfikacyjnego pozwalającego uzyskać tytuł ZCE (ang. Zend Certified Engineer). Poniżej znajdziesz krótkie omówienie tematyki poszczególnych rozdziałów.
Rozdział 1. Obiektowość Celem pierwszego rozdziału jest przygotowanie Cię do tego, byś mógł zrozumieć informacje i przykłady kodu, które będą prezentowane w dalszej części książki. Przedstawiamy podstawy modelu obiektowego oraz jego implementacji w PHP, następnie od razu przechodzimy do zaawansowanych zagadnień. Ważne jest, abyś dobrze zrozumiał ten rozdział, zanim przejdziesz do kolejnych.
Rozdział 2. Wyjątki i referencje W tym rozdziale omawiamy zagadnienia związane z programowaniem obiektowym i prezentujemy sposoby obsługi błędów za pomocą bloków try i catch. Jest to elegancki sposób zarządzania błędami w aplikacjach PHP — jego opanowanie daje ogromne możliwości. Następnie omawiane są referencje i ich znaczenie w odniesieniu do klas i funkcji, z których będziesz korzystał.
Rozdział 3. Mobilne PHP Urządzenia mobilne są coraz popularniejsze, stają się coraz mniejsze i wydajniejsze. W tym powiększającym się rynku swoje udziały zdobywają firmy takie jak Apple, RIM czy HTC. Do urządzeń tych są jednak potrzebne aplikacje — pokażemy w tym rozdziale, w jaki sposób PHP może przydać się w ich tworzeniu. 18
WPROWADZENIE DO PHP
Rozdział 4. Media społecznościowe Podobnie prężnie rozwijają się media społecznościowe, a PHP znacznie się do tego rozwoju przyczynia. Wiele aplikacji dostępnych na Facebooku jest napisanych właśnie w PHP. Liczne inne strony, np. Flickr, częściowo Yahoo!, a nawet aplikacje blogowe, są zależne od PHP. W tym rozdziale omówimy niektóre z interfejsów dostępnych dla integracji z portalami społecznościowymi.
Rozdział 5. Nowości technologiczne W aktualnej (gdy powstawała ta książka) wersji 5.3.4 PHP udostępnia nowe funkcje. Wiele z nich pochodzi z długo oczekiwanej wersji 6.0, ale ponieważ niektóre funkcje zostały ukończone przed innymi, początkowa kolekcja została wydana jako wersja 5.3. W tym rozdziale przeanalizujemy najlepsze nowe funkcje oraz wyjaśnimy, w jaki sposób możesz z nich skorzystać w swoich projektach.
Rozdział 6. Tworzenie formularzy i zarządzanie nimi W tym rozdziale poświęcimy trochę miejsca na omówienie funkcjonalności i technik, które mogą zostać wykorzystane przy tworzeniu formularzy. Ponadto przybliżymy kontrolowanie wpisywanych danych, reagowanie na błędnie wpisane dane (np. błędny format daty) oraz sposób przekazywania danych do aplikacji.
Rozdziały 7. i 8. Integracja z bazami danych. Część I i II Oczywiście jednym z głównych aspektów tworzenia współczesnych stron internetowych jest możliwość przechowywania i wyświetlania danych pochodzących ze źródeł danych. W tych dwóch rozdziałach pokażemy wiele sposobów manipulowania danymi. Omówimy systemy zarządzania bazami — od mniejszych baz danych, takich jak bazy NoSQL, do dużych silników bazodanowych, takich jak MySQLi. Wyjaśnimy także, jak można skorzystać z dodatkowych narzędzi, np. PDO i Sphinx.
Rozdział 9. Integracja z bazami danych. Część III PHP i Oracle łączy wyjątkowa więź, jeżeli w grę wchodzą duże kolekcje danych. W tym rozdziale omówimy sprawy dotyczące tego związku oraz podpowiemy, jak go wykorzystać.
Rozdział 10. Biblioteki Jak już wspomniano, PHP jest bardzo otwarte na inne biblioteki. W rozdziale 10. przybliżymy niektóre z nich, te najpopularniejsze i najbardziej zaawansowane. Oprócz tego zostaną poruszone między innymi: możliwość generowania dokumentów PDF, przeglądanie kanałów RSS, tworzenie profesjonalnych wiadomości e-mail, integracja z mapami Google.
Rozdział 11. Bezpieczeństwo Książka nie byłaby kompletna, gdybyśmy nie przeanalizowali najnowszych technik z dziedziny bezpieczeństwa. Na ten obszerny temat przeznaczyliśmy rozdział 11. Omawiamy w nim najbezpieczniejszy (obecnie) algorytm szyfrujący, SHA1, oraz zagadnienia związane z ochroną danych wprowadzanych w formularzach i danych udostępnianych przez system.
19
PHP. ZAAWANSOWANE PROGRAMOWANIE
Rozdział 12. Programowanie zwinne z wykorzystaniem Zend Studio dla Eclipse, Bugzilli, Mylyn i Subversion Rozdział ten nie jest ściśle związany z PHP. Wyjaśniamy w nim, jak korzystać z jednego z najpopularniejszych środowisk programistycznych (IDE) dla PHP — Zend Studio for Eclipse. Zobaczymy, w jaki sposób może współpracować zespół programistów opierający swoje działanie na koncepcji programowania zwinnego (słyszałeś o programowaniu ekstremalnym?). Omówimy używanie narzędzi SVN, Bugzilla i Mylyn oraz ich współpracę mającą na celu zwiększenie produktywności zespołu.
Rozdział 13. Refaktoryzacja, testy jednostkowe i ciągła integracja Jest to rozszerzenie poprzedniego rozdziału. Nacisk został tu położony na zagadnienia związane z poprawianiem jakości programów PHP, aczkolwiek głównym tematem rozdziału są refaktoryzacja i testy jednostkowe. Dowiesz się ponadto, jak poprawnie z nich korzystać w swojej codziennej pracy.
Rozdział 14. XML W ostatnich latach popularność XML znacznie wzrosła. W tym rozdziale wyjaśnimy, w jaki sposób wykorzystać SimpleXML do obsługi dokumentu XML pochodzącego ze źródła zewnętrznego. Powiemy także o możliwości tworzenia dokumentów XML wewnątrz systemu.
Rozdział 15. JSON i Ajax Ponownie oddalamy się nieco od czystego PHP. Tym razem przybliżymy bibliotekę JSON. Wyjaśnimy, jak używać jej z Ajaksem, by strony były przyjazne dla użytkowników.
Rozdział 16. Konkluzja W tym rozdziale prezentujemy dodatkowe źródła wiedzy dotyczącej PHP. Wymieniamy strony internetowe, magazyny oraz konferencje, dzięki którym możesz pogłębić swoje wiadomości i lepiej zrozumieć język PHP i związaną z nim społeczność.
Przyszłość PHP Ponieważ PHP jest produktem open source, trudno przewidzieć kierunek, w którym będzie rozwijane w bliskiej i dalekiej przyszłości. Bardzo wierzę jednak w społeczność. Odkąd jestem programistą PHP, nie widziałem jeszcze błędnego kroku w wykonaniu tego kolektywu. Wiem, że urządzenia mobilne będą się rozwijały. PHP już podejmuje działania, aby nadążyć za tym rozwojem. Co jeszcze stanie się w niedalekiej przyszłości? Może zostanie poprawiona integracja z telefonią, jeśli chodzi o smartfony, i kompatybilność danych. Być może rozwinie się rozpoznawanie mowy. Kto wie? Na podstawie swojego dotychczasowego doświadczenia w programowaniu w języku PHP sądzę, że społeczność będzie trzymała rękę na pulsie i że nas nie zawiedzie. Patrzenie w przyszłość PHP jest bardzo pocieszające; jest jak patrzenie na piękny wschód słońca z przekonaniem, że kolejny dzień może być tylko lepszy.
20
ROZDZIAŁ 1
Obiektowość
Rozdział ten jest wprowadzeniem do podstawowych zagadnień obiektowości. Co właściwie oznacza stwierdzenie, że PHP jest zorientowane obiektowo? Najprościej mówiąc, PHP pozwala tworzyć i porządkować hierarchicznie typy tworzone przez użytkownika. Książka ta dotyczy PHP 5.3, które wprowadza nowe elementy do repertuaru narzędzi obiektowych. PHP przeszło radykalne zmiany od wersji 4., która także zawierała podstawowe mechanizmy obiektowości. W wersji 4. nie można było na przykład definiować widoczności metod i właściwości. W PHP 5.3 zostały dodane przestrzenie nazw. Omówimy tu klasy, dziedziczenie, tworzenie obiektów oraz definiowanie interfejsów. Przedstawimy również zaawansowane pojęcia, takie jak iteratory. Zaczynajmy.
Klasy Klasy są po prostu typami definiowanymi przez użytkownika. W językach obiektowych klasa wykorzystywana jest jako szablon do tworzenia obiektu lub instancji (kopii funkcjonalnej) tej klasy. Klasa zawiera opis standardowych właściwości wszystkich należących do niej elementów. Celem klas jest enkapsulacja definicji obiektu, jego zachowanie oraz ukrycie jego implementacji przed użytkownikiem końcowym, a także pozwolenie temu użytkownikowi na wykorzystanie obiektów klas w sposób udokumentowany i oczekiwany. Enkapsulacja zmniejsza rozmiary programów i czyni je łatwiejszymi w zarządzaniu, ponieważ obiekty zawierają potrzebną do tego logikę. Istnieje także mechanizm autoładowania, który pozwala rozbić skrypty na mniejsze, łatwiejsze w zarządzaniu części. Zanim przeanalizujemy prosty przykład klasy, zapoznaj się z terminologią. • Element klasy lub właściwość — zmienna, część danych klasy. • Metoda — funkcja zdefiniowana wewnątrz klasy. Teraz zdefiniujemy klasę dla punktu na dwuwymiarowej przestrzeni, określonego przy użyciu współrzędnych kartezjańskich (listing 1.1). Omawiana klasa została zaprojektowana wyłącznie do celów demonstracyjnych i ma poważne wady. Zalecamy, abyś nie wykorzystywał jej jako podstawy do tworzenia własnego kodu. Listing 1.1. Przestrzeń dwuwymiarowa
Przedstawiona klasa zawiera sporo elementów wartych przeanalizowania i poprawienia. Jak już wcześniej stwierdziliśmy, opisuje ona punkt na płaszczyźnie, określony współrzędnymi kartezjańskimi $x i $y. Przy zmiennych jest umieszczone słowo kluczowe public, do którego wrócimy później. Zaimplementowana została także metoda konstruktora __construct, wywoływana w momencie tworzenia w pamięci nowego obiektu (lub instancji) klasy Punkt poprzez wywołanie operatora new. Innymi słowy, kiedy wywoływana jest linia $p1=new Punkt(2,3), metoda __construct jest wywoływana automatycznie, a argumenty w nawiasach po nazwie klasy są przekazywane do metody __construct i mogą być w niej wykorzystane. Metoda __construct odwołuje się do zmiennej $this. Zmienna $this umożliwia w językach obiektowych odwołanie się do instancji klasy. Odnosi się zawsze do aktualnie obsługiwanego obiektu. Jest obiektowym odpowiednikiem „ja”. Różne odmiany tej zmiennej wykorzystywane są w niemal wszystkich językach obiektowych; w niektórych jest nazywana „self”. Konstruktor klasy jest metodą inicjalizującą (tworzącą instancje) obiekty danej klasy. W tym przypadku przypisuje koordynaty. Koordynaty (zmienne $x i $y) są właściwościami klasy. Zdefiniowane są także inne metody, dwie metody get oraz metoda odleglosc, która oblicza odległość między dwoma punktami. Kolejną rzeczą wartą zauważenia jest słowo kluczowe public. Oznaczanie elementów klasy jako „publiczne” pozwala na uzyskanie do nich pełnego dostępu. W naszym skrypcie znajduje się linia: $p2->x=5; — koordynat x jest w niej modyfikowany bezpośrednio. Taki dostęp nie pozwala na kontrolowanie go i we wszystkich przypadkach, poza najprostszymi, nie powinien mieć miejsca. Dobrą praktyką jest tworzenie akcesorów (metod get i set), które będą odczytywały i zapisywały właściwości w sposób kontrolowany. Innymi słowy, za pośrednictwem metod get i set można kontrolować wartości właściwości. Dla właściwości publicznych metody get i set są nadmiarowe, ponieważ możliwy jest bezpośredni dostęp do nich, tak jak w przypadku $p2->x=5;. Jednakże właściwości publiczne nie pozwalają kontrolować wartości właściwości. Metody get i set mogą być pisane ręcznie dla każdej właściwości, jednak PHP umożliwia wykorzystanie tak zwanych „magicznych” metod, które mogą być stosowane zamiast metod tworzonych ręcznie. Możliwe jest lepsze chronienie elementów klasy poprzez użycie słów kluczowych private i protected. Dokładne znaczenie tych dwóch słów kluczowych będzie wyjaśnione w następnym podrozdziale. Należy także zauważyć, że public jest domyślną widocznością. Jeżeli widoczność dla elementu klasy nie będzie wyszczególniona — zostanie ustawiona na public. Kod: class C { $member; function method() {...} …. }
jest równoznaczny z kodem: class C { public $member;
22
ROZDZIAŁ 1. OBIEKTOWOŚĆ
pubic function method() {…} …. }
W przeciwieństwie do elementów publicznych prywatne właściwości i metody klasy są widoczne tylko dla metod tej klasy. Metody, które nie są częścią klasy, nie mają dostępu do prywatnych właściwości, nie mogą także wywoływać żadnych prywatnych metod. Jeżeli dla właściwości $x i $y słowo kluczowe public zostanie zamienione na protected i nastąpi próba uzyskania dostępu, wyświetli się informacja o błędzie: PHP Fatal error: Cannot access private property Point::$x in script2.1 on line 25
Innymi słowy, nasza mała sztuczka w linii 25., czyli $p2->x=5, przestanie działać. Metoda konstruktora, podobnie jak metody get_x() i get_y(), nie będzie miała żadnego problemu z dostępem do właściwości tak długo, jak długo będzie częścią klasy. Jest to poprawna sytuacja, ponieważ nie będzie możliwości modyfikowania wartości właściwości bezpośrednio z potencjalnym zmodyfikowaniem zachowania klasy w sposób, jaki nie powinien mieć miejsca. W skrócie — klasa jest bardziej hermetyczna, podobnie jak autostrada, na której jest określona liczba wjazdów i zjazdów. Właściwości publiczne i prywatne zostały już opisane. Czym jednak są właściwości i metody oznaczone jako protected? Do takich właściwości i metod dostęp może uzyskać metoda klasy, do której one należą, oraz metoda klasy dziedzicząca po klasie bazowej, do której one należą. Przyjrzymy się temu bliżej w kolejnym podrozdziale.
Dziedziczenie i przeciążanie Zgodnie ze stwierdzeniem z początku tego rozdziału klasy mogą być organizowane hierarchicznie. Hierarchia osiągana jest poprzez dziedziczenie. W celu zademonstrowania dziedziczenia utworzymy kolejną klasę, nazwaną pracownik. Część pracowników firmy to menedżerowie — klasa menedzer będzie klasą dziedziczącą po ogólniejszej klasie pracownik. Dziedziczenie bywa także nazywane specjalizacją. Przyjrzyj się klasie z listingu 1.2. Listing 1.2. Przykład klasy pracownik
Klasa ta została utworzona do celów demonstracyjnych i nie powinna być wykorzystywana jako szablon. Warto zauważyć, że konstruktory obu klas są publiczne. Gdyby były prywatne, utworzenie nowego obiektu klasy byłoby niemożliwe. Po uruchomieniu skrypt zwróci następujący wynik: Pracownik Kowalski otrzymał podwyżkę w kwocie 50 złotych Nowa pensja wynosi 350 złotych Ten pracownik jest menedżerem Pracownik Nowak otrzymał podwyżkę w kwocie 50 złotych Nowa pensja wynosi 150 złotych Żegnaj okrutny świecie: PRACOWNIK:Nowak Żegnaj okrutny świecie: MENEDŻER:Kowalski Żegnaj okrutny świecie: PRACOWNIK:Kowalski
Na powyższym przykładzie doskonale można wytłumaczyć pojęcie dziedziczenia. Każdy menedżer jest pracownikiem. Słowo „jest” jest charakterystyczne dla dziedziczenia. W tym przypadku klasa pracownik jest klasą nadrzędną dla klasy menedzer. W przeciwieństwie do prawdziwych relacji pokrewieństwa klasa w PHP może mieć tylko jednego rodzica, wielokrotne dziedziczenie nie jest dozwolone. Ponadto metody klasy nadrzędnej mogą być wywoływane poprzez wykorzystanie konstrukcji parent::, pokazanej w klasie menedzer. Kiedy tworzony jest obiekt klasy dziedziczącej, konstruktor klasy nadrzędnej nie jest wywoływany automatycznie. Wywołanie konstruktora klasy nadrzędnej w klasie podrzędnej należy do zadań programisty. To samo dotyczy metody destruktora. Jest ona dokładnym przeciwieństwem klasy konstruktora. Konstruktor jest wywoływany w momencie tworzenia obiektu w pamięci; destruktor jest wywoływany, gdy obiekt nie jest już potrzebny lub kiedy dla obiektu zostanie wywołana funkcja unset. Jawne wywoływanie funkcji unset nie jest powszechne, zazwyczaj jest wykorzystywane w celu oszczędzania pamięci. To oznacza, że destruktor jest automatycznie wywoływany dla wszystkich obiektów w momencie zakończenia działania skryptu. Metody destruktorów są używane przeważnie do zwolnienia zasobów, na przykład zamknięcia otwartych plików lub połączeń z bazą danych. Zauważ także, że metoda destruktora w klasie klasy menedzer ma pełny dostęp do właściwości nazwisko, pomimo że jest ona właściwością klasy nadrzędnej pracownik. Jest to właściwy cel wykorzystania modyfikatora dostępu protected. Gdyby nazwisko było właściwością prywatną klasy pracownik, powyższy przykład by nie działał. Metoda daj_podwyzke istnieje w obu klasach. PHP „wie”, która metoda powinna zostać wykorzystana dla danej klasy; jest to jeden z aspektów fundamentalnej zasady obiektowości — enkapsulacja. Obiekt $x jest typu menedzer, a metoda daj_podwyzke wyświetliła tekst „Ten pracownik jest menedżerem” po wyświetleniu standardowych informacji wyjściowych. Inaczej mówiąc, metoda daj_podwyzke w klasie menedzer przeciąża lub zastępuje metodę daj_podwyzke w klasie pracownik. Zauważ, że pojęcie przeciążania w PHP jest rozumiane inaczej niż w językach C++ lub Python, w których oznacza ono funkcję (nie metodę klasy) o takiej samej nazwie, ale innych argumentach. Wracając do PHP — jeżeli metoda zostanie oznaczona słowem kluczowym final, nie będzie mogła być przeciążona. Gdyby metoda daj_podwyzke została zadeklarowana w ten sposób: final function daj_podwyzke($wartosc) { …. }
24
ROZDZIAŁ 1. OBIEKTOWOŚĆ
to przeciążenie w klasie menedzer nie byłoby możliwe. Polecamy poćwiczyć podstawowe zagadnienia obiektowości na małym skrypcie oraz poeksperymentować z ustawianiem dla różnych elementów klas modyfikatorów dostępu: public, protected i private, aby zaznajomić się z efektami. Mówiąc o dziedziczeniu, nie można pominąć klas abstrakcyjnych. Dla klas abstrakcyjnych nie można tworzyć instancji — nie można tworzyć żadnych obiektów tej klasy. Klasy te są wykorzystywane głównie jako szablony w celu wymuszenia na klasach dziedziczących określonej struktury. Klasa jest abstrakcyjna, jeżeli zostanie oznaczona słowem kluczowym abstract w następujący sposób: abstract class A { …. }
Żaden obiekt tej klasy nie może być utworzony. PHP zwróci błąd czasu wywoływania i zatrzyma wykonywanie skryptu. Możliwe jest także tworzenie metod abstrakcyjnych wewnątrz klasy abstrakcyjnej: abstract class A { abstract protected metoda(...); }
Metody abstrakcyjne wykorzystywane są do wymuszania implementacji metody w klasach dziedziczących. Klasy abstrakcyjne są z reguły używane jako szablony dla klas dziedziczących po nich. Dobry przykład klasy abstrakcyjnej można znaleźć w standardowej bibliotece PHP (SPL — Standard PHP Library). Klasy dla sterty sortowanej (SplMinHeap, SplMaxHeap) dziedziczą po klasie abstrakcyjnej SplHeap i implementują metodę compare w inny sposób. SplMinHeap posortuje elementy od najmniejszego do największego, natomiast SplMaxHeap posortuje je odwrotnie. Wspólne cechy obu klas są zawarte w klasie abstrakcyjnej SplHeap, której dokumentację można znaleźć pod adresem http://ca2.php.net/manual/en/class.splheap.php. Zamiast tworzyć sztuczne przykłady klas abstrakcyjnych, zobaczmy, w jaki sposób są używane w SPL. Oto proste zastosowanie klasy SplMinHeap:
Wykonanie tego kodu zwróci następujący wynik: Adam Marcin Piotr
Imiona zostały posortowane alfabetycznie — ich kolejność jest inna, niż była przy wstawianiu. W dalszej części wyjaśnimy, w jaki sposób można wykorzystać obiekt klasy SplMaxHeap w pętli; potraktujemy go jak tablicę. Zwróćmy teraz uwagę na praktyczne techniki programowania obiektowego. Być może zastanawiasz się, jak sprawić, aby klasa była dostępna dla skryptu PHP. Klasy są z reguły pisane tak, aby mogły być wykorzystywane wielokrotnie. Oczywistą odpowiedzią jest utworzenie odrębnego pliku, który następnie może zostać dołączony do skryptu za pomocą dyrektywy require lub include, jednak ten sposób może szybko stać się kłopotliwy, kiedy liczba plików zacznie rosnąć. Okazuje się, że PHP wyposażone jest w narzędzie mające pomóc w rozwiązaniu tego problemu — jest to funkcja __autoload. Przyjmuje ona jako parametr nazwę klasy i będzie wywołana, kiedy PHP nie będzie mogło znaleźć odpowiedniej klasy w aktualnie wykonywanym skrypcie. Zasadniczo __autoload jest funkcją obsługującą przy wystąpieniu wyjątku „klasa nie została odnaleziona”. Do wyjątku tego wrócimy później. Przykład z listingu 1.2 może być przepisany w dwóch plikach (listing 1.3).
25
ROZDZIAŁ 1. OBIEKTOWOŚĆ
Listing 1.3. Listing 1.2 przepisany w dwóch plikach Plik listing1_3.php
Plik ACMEmanager.php: , ponieważ mogą być załadowane lub załączone w nagłówku pliku, zanim strona zostanie złożona. Wszystkie białe znaki pomiędzy znakami ?> a znakiem końca pliku będą wstawione na początku wynikowego kodu HTML strony. PHP radzi sobie z brakiem końcowych znaków ?>, więc dobrą praktyką jest pomijanie ich na końcu pliku. Jest to prawdopodobnie najczęstszy powód błędów typu „przesyłanie już się rozpoczęło”, występujących podczas stosowania funkcji header() przy przesyłaniu nagłówka HTTP do przeglądarki.
„Magiczne” funkcje Większość metod nazywanych zazwyczaj „magicznymi” funkcjami odnosi się do brakujących właściwości i metod niezdefiniowanych w klasie. Powodem tego jest szeroko stosowane definiowanie właściwości jako tabeli asocjacyjnej zamiast jako odrębnych zmiennych. Takie podejście jest proste w realizacji, łatwo rozszerzalne oraz wygodne w zarządzaniu, co przełożyło się na popularność definiowania właściwości jako tablicy. Bez „magicznych” funkcji nie byłoby łatwego dostępu do takich właściwości. Pierwsza para tych specjalnych metod warta wspomnienia to metody __get i __set.
Metody __get i __set Metoda __set jest wywoływana w momencie przypisania wartości do nieistniejącej właściwości. Metoda __get jest wywoływana w momencie odczytu wartości nieistniejącej właściwości (listing 1.4). Listing 1.4. Przykład wykorzystania funkcji __get i __set # Przykład wykorzystania funkcji __get i __set # Nieistniejąca właściwość "limit_predkosci" jest zapisywana i odczytywana.
27
ROZDZIAŁ 1. OBIEKTOWOŚĆ
W wyniku działania powyższego skryptu otrzymamy: Brak właściwości! Ograniczenie prędkości wynosi 100 km/h Metoda __isset() została wywołana.
Właściwość limit_predkosci nie jest zdefiniowana, jednak odwołanie do niej nie kończy się błędem, ponieważ w momencie odwołania wykonana została metoda __get. Metoda __set została natomiast wywołana w momencie przypisania wartości do nieistniejącej właściwości. Definiowanie wszystkich właściwości klasy jako tabeli asocjacyjnej i odwoływanie się do nich jak do odrębnych właściwości jest częstą praktyką. Taki sposób definiowania właściwości pozwala na łatwe rozwijanie klasy.
Metoda __isset Poza metodami __get i __set na listingu 1.4 zademonstrowano wykorzystanie funkcji __isset, która jest stosowana do sprawdzania, czy nieistniejąca właściwość, zazwyczaj definiowana jako tablica, została ustawiona (ma przypisaną wartość). Oczywiście dostępna jest także funkcja __unset. Jest ona wywoływana w momencie wywołania unset dla niezdefiniowanej właściwości. Metoda __isset jest także wywoływana podczas sprawdzania, czy zmienna nie jest pusta, za pomocą funkcji empty(). Funkcja empty() sprawdza, czy argument jest ustawiony oraz czy jego długość jest większa od 0. Zwraca prawdę, jeżeli argument nie jest ustawiony lub jego długość jest równa 0, w przeciwnym wypadku zwraca fałsz. Jeżeli argument zostanie ustawiony na pusty ciąg znaków, funkcja empty() zwróci prawdę.
Metoda __call Dla nieistniejących właściwości funkcja __call wywoływana jest w momencie odwołania się do nieistniejącej metody. Jak pokazuje doświadczenie, funkcja wykorzystywana jest raczej rzadko. Listing 1.5 przedstawia krótki przykład, obrazujący to w pełni. Listing 1.5. Funkcja __call jest wykonywana w momencie odwołania się do nieistniejącej metody
Wykonanie skryptu zwróci następujący wynik: nazwa:nieistniejaca_metoda 1 2 3
Metoda nieistniejaca_metoda oczywiście nie została zdefiniowana, jednak mimo to wywołanie jest poprawne.
28
ROZDZIAŁ 1. OBIEKTOWOŚĆ
Metoda __toString() Ostatnia opisywana tutaj „magiczna” funkcja, __toString(), jako jedyna nie ma nic wspólnego z nieistniejącymi elementami klasy. Wykorzystywana jest w momencie, kiedy obiekt jest konwertowany na ciąg znaków poprzez bezpośrednie rzutowanie lub pośrednio, poprzez przekazanie go jako parametru funkcji, która oczekuje argumentów łańcuchowych, np. print (listing 1.6). Listing 1.6. Przykład wykorzystania metody __toString
Wykonanie skryptu zwróci następujący wynik: element test2.
Wypisywana jest wartość zwracana przez metodę __toString. Funkcja jest wywoływana w momencie wykorzystania obiektu jak zmiennej łańcuchowej. Funkcja ta jest bardzo pożyteczna, gdy konieczne jest wyświetlenie złożonych obiektów zawierających nietypowe elementy, takie jak połączenia sieciowe lub bazodanowe albo inne obiekty binarne.
Kopiowanie, klonowanie oraz porównywanie obiektów Na początku tego rozdziału wyjaśniono, czym są klasy i w jaki sposób tworzyć i wykorzystywać złożone obiekty. Teraz przyszedł czas na przedstawienie niektórych aspektów wewnętrznej obsługi obiektów. Kiedy tworzony jest obiekt przy zastosowaniu dyrektywy w rodzaju $x=new class(....), zmienna $x jest referencją na obiekt. Co się stanie, kiedy wywołamy polecenie $x=$y? To bardzo proste — obiekt, na który dotychczas wskazywała zmienna $x, jest usuwany, wywoływany jest jego destruktor, a zmienna $x od tej chwili wskazuje na obiekt $y. Listing 1.7 przedstawia skrypt demonstrujący powyższe zachowanie. Listing 1.7. Wykonanie $x=$y
Wykonanie skryptu zwróci następujący wynik: Przypisywanie zmiennej: Usuwanie obiektu obiekt 1... Koniec skryptu Usuwanie obiektu obiekt 2...
Obiekt 1 jest usuwany z pamięci podczas przypisywania $x=$y. Dlaczego usunięty został obiekt 2? Odpowiedź na to pytanie jest bardzo prosta — destruktor wywoływany jest zawsze, gdy obiekt przestaje być potrzebny. Kiedy skrypt się kończy, wszystkie obiekty przestają być potrzebne i dla każdego z nich jest wywoływany jego destruktor. To powód umieszczenia przypisania pomiędzy dwoma poleceniami print. Ponadto zauważ, że destruktor wywoływany jest tylko raz, pomimo że do obiektu istnieją dwie referencje, $x i $y. Destruktor wywoływany jest raz dla obiektu, nie dla każdej referencji do niego. Ten sposób kopiowania obiektów jest nazywany płytkim kopiowaniem, ponieważ nie jest tworzona prawdziwa kopia obiektu, zmieniane są tylko referencje. Oprócz płytkiego kopiowania istnieje także kopiowanie głębokie, tworzące nowy obiekt. Głębokie kopiowanie wykonywane jest przy użyciu operatora clone. Przykład takiego kopiowania pokazano na listingu 1.8. Listing 1.8. Głębokie kopiowanie przy wykorzystaniu operatora clone
Głębokie kopiowanie ma miejsce w linii $x = clone $y. W momencie wykonywania tej linii tworzona jest nowa kopia obiektu $y i wywoływana jest funkcja __clone w celu ustawienia nowej kopii obiektu w sposób wymagany przez skrypt. Wynik działania skryptu wygląda następująco:
30
ROZDZIAŁ 1. OBIEKTOWOŚĆ
Obiekt obiekt 1 ma 0 kopii. Usuwanie obiektu obiekt 1... Obiekt obiekt 2:KLON ma 1 kopii. Obiekt obiekt 2 ma 0 kopii. Koniec skryptu, uruchamianie destruktorów. Usuwanie obiektu obiekt 2... Usuwanie obiektu obiekt 2:KLON...
Nowo utworzona kopia zapisana w zmiennej $x ma wartość właściwości obiekt 2:KLON i liczbę kopii ustawioną na 1 w rezultacie czynności, które zostały wykonane wewnątrz metody __clone. Zauważ także, że konstruktor został wywołany dwukrotnie — raz dla obiektu oryginalnego i raz dla kopii. Klonowanie nie jest używane tak często jak przypisanie przez referencję, jednak dobrze jest mieć taką możliwość. W jaki sposób porównywane są obiekty? Należy rozważyć kilka przypadków, zależnie od kryteriów porównania. Kiedy dokładnie nazwiemy dwie zmienne obiektowe $x i $y „równymi”? Są następujące trzy poprawne logicznie możliwości: • Obiekty tej samej klasy mają równe wartości dla wszystkich właściwości. • Obiekty są referencją do tego samego obiektu tej samej klasy. • Wykorzystywanych jest kilka innych niestandardowych kryteriów. Standardowy operator porównania == testuje pierwszy wariant. Wyrażenie $x==$y jest prawdziwe wtedy i tylko wtedy, gdy odpowiednie właściwości obu obiektów są sobie równe. Druga możliwość — czyli $x i $y są referencjami na ten sam obiekt — sprawdzana jest za pomocą specjalnego operatora === (trzy znaki równości pisane łącznie). Wyrażenie $x===$y jest prawdziwe wtedy i tylko wtedy, gdy obie zmienne są referencją na ten sam obiekt. Zwróć uwagę, że zwyczajowe przypisanie $x=$y spowoduje, że wyrażenie $x===$y będzie prawdziwe, klonowanie natomiast sprawi, że wyrażenie będzie fałszywe. Jeżeli nie została zdefiniowana niestandardowa metoda __clone, oryginalny obiekt i klon będą równe dla wyrażenia z wykorzystaniem operatora ==. Co możemy zrobić w trzecim przypadku, niestandardowej definicji równości? Musimy utworzyć niestandardową funkcję porównującą i porównać zwracane wartości. Podczas pisania funkcji przyjmujących argumenty konkretnych klas możliwe jest egzekwowanie typu zmiennej przekazywanej do funkcji poprzez podanie nazwy klasy przed formalną nazwą argumentu. Wygląda to w ten sposób: function funkcja_testowa(test3a $a) {….}
Wymagane jest tutaj, aby argument $a był typu test3a. Jest to możliwe wyłącznie dla typów obiektowych i tablicowych poprzez wstawienie słowa array zamiast nazwy klasy. PHP5 nadal jest słabo typowanym językiem i wymuszenie typów argumentów dla standardowych typów takich jak int nadal nie jest wspierane.
Interfejsy, iteratory i klasy abstrakcyjne Kolejnym standardowym typem w programowaniu obiektowym jest interfejs. Interfejs jest obiektem opisującym zestaw metod, które klasa może zaimplementować. Interfejs wygląda następująco: interface interf { public function f1($x,$y,...,); public function f2(....); …. public function fn(...); }
Zauważ, że kod metody nie jest wyspecyfikowany, wyszczególnione są tylko jej nazwa i argumenty. Klasa może zaimplementować interfejs w następujący sposób: class c extends klasaNadrzedna implements interf { (wszystkie funkcje wyszczególnione w interfejsie muszą zostać zaimplementowane) … )
31
ROZDZIAŁ 1. OBIEKTOWOŚĆ
Interfejsy mogą po sobie dziedziczyć jak klasy. Składnia jest identyczna: interface interf2 extends interf1 { function f1(...); }
Nowy interfejs interf2 będzie zawierał wszystkie funkcje z interfejsu interf1 oraz nowe, zdefiniowane w interf2 (listing 1.9). Listing 1.9. Przykład nowego interfejsu interf2
Zauważ, że znaki nowej linii nie są usuwane z linii i że musimy sprawdzać, czy linie nie są puste. Klasa SplFileObject mogłaby wyjść poza koniec pliku, gdybyśmy ominęli sprawdzanie pustych wierszy. Mimo to jest to klasa znacznie ułatwiająca pracę. Jedyną bardzo użyteczną funkcją, której brakuje w klasie SplFileObject, jest fputcsv, zwracająca tablice w formacie CSV. Można jednak z łatwością ją sobie napisać.
34
ROZDZIAŁ 1. OBIEKTOWOŚĆ
W bibliotece SPL jest wiele innych przydatnych klas i interfejsów. Pełny opis biblioteki SPL wykracza poza zakres niniejszej książki. Odpowiednią dokumentację możesz znaleźć pod adresem http://www.php.net/ manual/pl/book.spl.php. Istnieje także standardowy zestaw klas implementujących iterator dla kursorów i zapytań bazodanowych. Zestaw ten nazwano ADOdb. Pozwala on programiście wykorzystywać wyniki zapytań w pętlach foreach, podobnie jak pliki i tablice. Zestaw ADOdb będzie omówiony szczegółowo w dalszej części książki. Jaka jest różnica między klasami abstrakcyjnymi a interfejsami? Jedne i drugie wykorzystuje się jako szablony dla innych klas dziedziczących po nich lub implementujących je; klasa abstrakcyjna jest jednak dużo bardziej restrykcyjna i znacznie ściślej definiuje strukturę. Dodatkowo poza metodami abstrakcyjnymi klasy abstrakcyjne mogą mieć nieabstrakcyjne właściwości i metody — nawet metody ze słowem kluczowym final, które nie mogą być przeciążane.
Kontekst klasy i elementy statyczne Do tej pory pracowaliśmy wyłącznie z właściwościami i metodami, które są definiowane w kontekście obiektu — każdy obiekt posiadał własne właściwości i metody. Są jeszcze właściwości i metody działające w kontekście klasy. Oznacza to, że są wspólne dla wszystkich obiektów danej klasy. Problem, który próbujemy rozwiązać, jest następujący: w jaki sposób możemy policzyć wszystkie obiekty danej klasy utworzone w skrypcie. Oczywiście potrzebujemy licznika, który będzie działał raczej na poziomie klasy niż obiektu. Zmienne i metody zadeklarowane w kontekście klasy, nie w kontekście obiektu, nazywają się zmiennymi statycznymi (listing 1.12). Listing 1.12. Przykład zmiennych statycznych
Wykonanie skryptu zwróci następujący wynik: X: 1 obiekt został utworzony Y: 2 obiekty zostały utworzone Ponownie sprawdźmy zmienną x: X: 2 obiekty zostały utworzone Jeżeli odwołamy się do właściwości obiektu, PHP utworzy nową liczbę dla X... i zainicjuje ją na:0
35
ROZDZIAŁ 1. OBIEKTOWOŚĆ
Zmienna test4::$liczba_obiektow jest zmienną statyczną rezydującą w kontekście klasy. Kiedy została zwiększona do dwóch podczas tworzenia obiektu $y, zmiana była widoczna także dla obiektu $x. Jeżeli podjęta będzie próba odczytania zmiennej jako właściwości obiektu, tak jak w przypadku funkcji blad(), PHP utworzy nową publiczną właściwość o takiej nazwie. Wszystko stało się teraz bardziej zagmatwane. Fakt, że element klasy został oznaczony jako statyczny, nie ma nic wspólnego z jego widocznością. Mogą występować elementy statyczne typu public, private i protected, z takimi samymi restrykcjami jak przy właściwościach obiektu. Zwróć także uwagę, że do tej samej zmiennej odwoływaliśmy się zarówno poprzez self::$liczba_obiektow, jak i test4::$liczba_obiektow. Słowo kluczowe self jest skrótem dla „ta klasa” i zawsze dotyczy klasy, w której zostało wykorzystane. Innymi słowy, nie uwzględnia dziedziczenia — zawsze jest takie samo (listing 1.13). Listing 1.13. Słowo kluczowe self zawsze odnosi się do klasy, w której zostało zdefiniowane
Jeśli kod metody get_wlasciwosc w klasie B jest oznaczony jako komentarz, oba wiersze będą wyświetlały liczbę 4, ponieważ obie funkcje będą wywoływane w kontekście klasy A. Jeżeli nie będzie oznaczony jako komentarz, linia printf("B:%d\n", $y->get_wlasciwosc()); wyświetli liczbę 9. Zmienne klas najlepiej wywoływać poprzez ich nazwy. Takie odwołanie jest jednoznaczne i sprawia, że kod jest czytelniejszy. Oprócz właściwości statycznych istnieją metody statyczne. One także są wywoływane w kontekście klasy: class::metoda_statyczna(...). Należy wspomnieć, że brak jest jakiejkolwiek serializacji, leży ona całkowicie w gestii użytkownika.
Podsumowanie Z tego rozdziału dowiedziałeś się całkiem sporo o klasach i obiektach w PHP. Powinieneś już znać pojęcia: klasa, obiekt, metoda, właściwość, konstruktor, destruktor, dziedziczenie, przeciążenie, interfejs, klasa abstrakcyjna, metoda statyczna oraz iterator. Rozdział ten nie jest w żadnym wypadku kompletnym spisem elementów obiektowych w PHP5, zawiera jednak główne pojęcia i może być solidną podstawą dalszej nauki. Oficjalna dokumentacja zamieszczona pod adresem www.php.net jest doskonałym źródłem wiedzy i zawiera wszystko, co zostało pominięte w tym rozdziale.
36
ROZDZIAŁ 2
Wyjątki i referencje
W tym rozdziale przedstawimy wyjątki i referencje — dwa podstawowe aspekty nowoczesnego programowania obiektowego (OOP — Object-oriented programming). Wyjątki są zdarzeniami synchronicznymi. Słowo „synchroniczne” oznacza, że wyjątki występują w konsekwencji zdarzeń w kodzie, a nie zdarzeń zewnętrznych, takich jak sygnały. Kiedy na przykład operator stosuje kombinację klawiszy Ctrl+C, sygnał przesyłany jest do wykonywanego programu. Wyjątki są wykorzystywane do obsługi błędów w sposób uporządkowany i zgodny ze standardami. Kiedy program (lub jak w przypadku PHP — skrypt) próbuje wykonać dzielenie przez zero, zgłaszany jest wyjątek. Wyjątki mogą być zgłaszane (lub wywoływane) oraz przechwytywane. Wywołanie wyjątku oznacza przekierowanie kontroli programu do części kodu przeznaczonej do obsługi tych zdarzeń. Współczesne języki programowania, takie jak PHP, mają możliwość wykonania tego w logiczny i uporządkowany sposób.
Wyjątki Wyjątki są obiektami klasy Exception lub dowolnej klasy dziedziczącej po niej. Na pewno pamiętasz z poprzedniego rozdziału, że dziedziczenie jest hierarchicznym związkiem między klasami. Definicja klasy Exception zgodnie ze specyfikacją jest następująca: Exception { /* Właściwości */ protected string $message ; protected int $code ; protected string $file ; protected int $line ; /* Metody */ public __construct ([ string $message = "" [, int $code = 0 [, Exception $previous = NULL ]]] ) final public string getMessage ( void ) final public Exception getPrevious ( void ) final public int getCode ( void ) final public string getFile ( void ) final public int getLine ( void ) final public array getTrace ( void ) final public string getTraceAsString ( void ) public string __toString ( void ) final private void __clone ( void ) }
ROZDZIAŁ 2. WYJĄTKI I REFERENCJE
Wyjątki są zatem obiektami mieszczącymi przynajmniej powyższe informacje w momencie wystąpienia błędu, czyli zawierają: treść błędu, kod błędu, nazwę pliku oraz linię, w której wystąpił wyjątek. Wyjątki są bardzo przydatne podczas szukania i usuwania błędów w programach. Listing 2.1 przedstawia przykład. Listing 2.1. Przykład wyjątku
Skrypt wykonany z wiersza poleceń z innymi argumentami zwróci następujące wyniki: ./listing2_1.php 4 2 Wynik: 2.000000 Zmienna a:mój string ./listing2_1.php 4 A Błąd: wartość A nie jest liczbą!
38
ROZDZIAŁ 2. WYJĄTKI I REFERENCJE
./listing2_1.php 4 0 Wyjątek: Niedozwolone dzielenie przez zero.
Z punktu widzenia wyjątków ten niewielki skrypt zawiera sporo ważnych rzeczy. Tablica $argv jest predefiniowaną tablicą globalną z argumentami wiersza poleceń. Istnieje także predefiniowana zmienna globalna $argc zawierająca liczbę argumentów wiersza poleceń, jak w języku C. Teraz zwróćmy uwagę na wyjątki i ich składnię. Najpierw zdefiniowaliśmy klasę wyjątku, która ignoruje istniejącą strukturę klasy Exception i nie wywołuje nawet metody konstruktora klasy nadrzędnej. Nie jest to dobrą praktyką programistyczną i zostało tu przedstawione jedynie jako przykład. W konsekwencji nasza klasa nie ma metod getMessage oraz getCode, przez co jest trudniejsza w wykorzystaniu. Zwyczajowa składnia wyjątku nie odnosi się do naszej klasy, co może powodować problemy, jeżeli ktoś spróbuje na przykład wywołać metodę getMessage(). Następnie utworzyliśmy blok try, w którym wystąpił wyjątek. Pojawienie się wyjątku sprawdzane jest w blokach catch (zwanych także blokami obsługi wyjątków), występujących bezpośrednio po bloku try. Blok try nie jest zwykłym blokiem programu; zmienne zdefiniowane wewnątrz bloku try będą zdefiniowane także poza nim. Zmienna $a jest wyświetlana po wykonaniu pierwszej części, po dzieleniu 4 przez 2. Kolejną sprawą jest składnia instrukcji throw. W tej instrukcji „rzucany” jest wyjątek. Bloki obsługi błędów są bardzo podobne do funkcji przyjmujących jeden argument — obiekt wyjątku. Kolejność bloków obsługi błędów jest istotna. PHP przekaże wyjątek do pierwszego bloku obsługi przyjmującego wyjątek danego typu. Blok obsługi dla wyjątku klasy Exception musi zawsze być ostatni, ponieważ przechwyci wszystkie zgłaszane wyjątki dowolnego typu. Kiedy zgłaszany jest wyjątek, PHP znajduje pierwszy pasujący blok obsługi i wykorzystuje go. Gdyby blok obsługujący wyjątki typu Exception został utworzony przed blokiem obsługującym wyjątki typu WyjatekNieLiczba, to ten drugi nie zostałby nigdy wywołany. Bloki obsługi błędów lub bloki catch wyglądają jak funkcje. Podobieństwo nie jest przypadkowe. PHP posiada także „magiczną” metodę set_exception_handler, dzięki której możliwe jest ustawienie obsługi dla wszystkich nieprzechwyconych wyjątków. Przepiszmy skrypt z listingu 2.1 (listing 2.2). Listing 2.2. Przepisany skrypt z listingu 2.1
Wynik powyższego skryptu będzie identyczny z wynikiem działania skryptu z listingu 2.1. Blok obsługi wyjątków zadeklarowany przy wykorzystaniu funkcji set_exception_handler jest funkcją przyjmującą jeden argument typu Exception i wykonywaną po wszystkich innych blokach obsługi wyjątków. ./listing2_2.php 4 A Błąd: wartość A nie jest liczbą!
Powyższy kod pochodzi z bloku obsługi wyjątku WyjatekNieLiczba, a nie z bloku domyślnego. Jeżeli drugi argument zostałby zastąpiony przez 0 podczas wykonywania skryptu, otrzymalibyśmy wynik zgodny z poprzednim skryptem: ./listing2_2.php 4 0 Wyjątek: Niedozwolone dzielenie przez zero.
Teraz wykonany został domyślny blok obsługi wyjątków. Domyślna obsługa wyjątków jest szczególnie użyteczna podczas pracy z klasami napisanymi przez kogoś innego, takimi jak klasa SplFileObject z poprzedniego rozdziału. Jeśli pójdzie coś nie tak, obiekty tej klasy zgłoszą wyjątki typu Exception, analogicznie do ADOdb. UWAGA. Klasy z repozytorium PEAR zgłaszają wyjątki klasy PEAR_Exception w momencie wystąpienia błędu. Klasa PEAR_Exception posiada wszystkie elementy standardowej klasy Exception, wzbogacone o dodatkową zmienną $trace. PEAR_Exception spróbuje także pokazać stos wywołań, kiedy zostanie zgłoszony i przechwycony.
Listing 2.3 pokazuje przykład skryptu, który próbuje otworzyć nieistniejący plik, wykorzystując klasę SplFileObject. Zadeklarowany został także domyślny blok obsługi błędów, który przechwyci wyjątek zgłoszony przez klasę SplFileObject, pomimo że nie ma w kodzie jawnych bloków try { ..} catch {...}.
Listing 2.3. Przykład skryptu próbującego otworzyć nieistniejący plik przy wykorzystaniu klasy SplFileObject
40
ROZDZIAŁ 2. WYJĄTKI I REFERENCJE
Wykonanie skryptu zwróci następujący wynik: Exception: SplFileObject::__construct(nieistniejacy_plik.txt) [splfileobject.--construct]: failed to open ´stream: No such file or directory Plik:C:\ksiazka\Rozdzial02\listing2_3.php Linia:14
Przy korzystaniu z klas napisanych przez kogoś innego domyślny blok obsługi wyjątków może być bardzo użytecznym, chociaż niewymagającym narzędziem. Domyślny blok obsługi wyjątków przechwyci wszystkie nieprzechwycone w inny sposób wyjątki. Przeważnie służy on do kończenia działania programu oraz ułatwia proces identyfikacji błędów. Oczywiście, w pewnych sytuacjach programista może przeprowadzić specjalną obsługę i wykonać coś takiego: try { $file = new SplFileObject("nieistniejacy_plik.txt", "r"); } catch (Exception $e) { $plik=STDIN; }
Jeżeli wystąpi problem z otwarciem pliku do odczytu, zostaną zwrócone standardowe dane wejściowe. Nie będzie to obiekt klasy SplFileObject, a programista będzie musiał uporać się z ewentualnymi konsekwencjami. Ponieważ domyślny blok obsługi zostanie wykonany jako ostatni dla nieprzechwyconych wyjątków, nie ma żadnych przeszkód, aby dokładnie obsłużyć wyjątki i napisać własne bloki obsługi. Jest jeszcze jedna rzecz warta wspomnienia — zagnieżdżanie wyjątków. PHP nie wspiera zagnieżdżania, jeżeli także bloki try nie zostaną zagnieżdżone. Innymi słowy, w poniższej sytuacji obsługa dla ExcB nie zostanie wywołana, jeżeli wyjątek jest zgłoszony wewnątrz obsługi ExcA: class ExcA extends Exception {...} class ExcB extends Exception {...} try {... throw new ExcA(..) } catch(ExcA $e) { throw new ExcB(); } catch(ExcB $e) { // Nie zostanie wykonany, jeżeli wyjątek będzie zgłoszony wewnątrz ExcA. }
Jedynym sposobem na zagnieżdżanie wyjątków jest zagnieżdżenie bloków try. W kontekście zagnieżdżania wyjątków PHP5 nie różni się od Javy czy C++.
Referencje Kolejnym ważnym typem obiektów w PHP są referencje. Referencje w PHP nie są wskaźnikami. PHP w odróżnieniu od Perla nie ma typu referencyjnego, który może być wykorzystany do adresowania obiektów przez dereferencje. W PHP referencja oznacza inną nazwę dla obiektu. Przyjrzyjmy się skryptowi z listingu 2.4. Listing 2.4. W PHP referencje są obiektami
Wywołanie skryptu zwraca następujący wynik: Element X posiada właściwość 10 Element X posiada właściwość 5 1 2 3 4 5
Dla zmiennej obiektowej $x wartość została zmieniona przez operacje wewnątrz metody funkc, a dla tablicy $arr wartości nie zostały zmienione przez operacje wewnątrz pętli foreach. Dzieje się tak, ponieważ PHP przekazuje parametry przez kopiowanie. Oznacza to, że dla typów nieobiektowych, takich jak liczby, łańcuchy znaków czy tablice, tworzona jest nowa, identyczna kopia obiektu, dla obiektów natomiast tworzona jest referencja lub, inaczej mówiąc, nowa nazwa dla obiektu. Kiedy do metody funkc został przekazany argument $x typu test5, powstała nowa nazwa dla obiektu. Poprzez operacje na nowej zmiennej modyfikowaliśmy zawartość pierwotnego obiektu, a nowa zmienna była tylko nową nazwą dla obiektu już istniejącego. Więcej szczegółów znajdziesz w rozdziale 1. Pomimo że PHP w przeciwieństwie do Perla nie zapewnia bezpośredniego dostępu do referencji, nadal umożliwia w pewnym stopniu kontrolę nad sposobem kopiowania obiektów. Listing 2.5 przedstawia przykład kopiowania przez referencję. Listing 2.5. Kopiowanie przez referencję
Wywołanie skryptu zwróci wynik: Zwykłe przypisanie. x=2 Przypisanie przez referencję. x=3
42
ROZDZIAŁ 2. WYJĄTKI I REFERENCJE
Powyższy skrypt składa się z dwóch części — zwykłego przypisania oraz przypisania przez referencję. W pierwszej części podczas normalnego przypisania tworzona jest nowa kopia zmiennej $y. Kopia ta jest przypisywana do zmiennej $x, poprzednia zawartość zmiennej $x jest usuwana. Zwiększenie zmiennej $y nie miało żadnego wpływu na zmienną $x. W drugiej części przez przypisanie przez referencję poprzednia zawartość zmiennej $x także została usunięta, jednak zmienna stała się aliasem (referencją) zmiennej $y. Zwiększenie wartości zmiennej $y o jeden było widoczne także w zmiennej $x, która zwróciła 3 zamiast 2. Analogiczna operacja może także dotyczyć pętli. Na listingu 2.4 mieliśmy następujący fragment kodu: $arr = range(1, 5); foreach ($arr as $a) { $a*= 2; } foreach ($arr as $a) { print "$a\n";
Wynikiem były niezmienione liczby od 1 do 5. Zmieńmy teraz ten fragment, korzystając z operatora referencji &: $arr = range(1, 5); foreach ($arr as $a) { $a*= 2; } print_r($arr);
Wynikiem będzie zmieniona tablica: Array ( [0] [1] [2] [3] [4] )
=> => => => =>
2 4 6 8 10
Innymi słowy, dodając operator & do zmiennej $a, nie utworzyliśmy kopii elementu tablicy — inaczej niż przy wyrażeniu foreach($arr as $a), gdzie kopia była tworzona. Zamiast tego utworzyliśmy referencję do elementów tablicy, co oznacza, że wszystko, co zrobimy ze zmienną $a wewnątrz pętli, zmodyfikuje element tablicy, a nie jego kopię. Niemożliwe jest utworzenie referencji do funkcji. UWAGA. Gdy po referencji do tablicy wykonywana jest pętla, należy zachować szczególną ostrożność. Jeżeli kod zmieni tablicę, efekty mogą być nieprzewidywalne.
Możliwe jest jednakże zwrócenie referencji jako wyniku działania funkcji oraz przekazanie referencji jako parametru funkcji. Argumenty powinny być przekazywane do funkcji przez referencję, jeżeli funkcja może zmienić pierwotną zmienną. Składnia jest taka sama jak w przypadku pętli — zmienna przekazywana przez referencję jest poprzedzana ampersandem (&). Listing 2.6 przedstawia przykład. Listing 2.6. Możliwe jest zwracanie referencji jako wyniku działania funkcji oraz przekazywanie referencji do tej funkcji
Uruchomienie powyższego fragmentu kodu spowoduje wyświetlenie następującego wyniku: x=8 a=5 x=8 a=8
Kiedy została wywołana funkcja f1, nastąpiło przekazanie argumentu przez wartość. Polecenie print wewnątrz funkcji wyświetliło liczbę 8, jednak pierwotna zmienna nie uległa zmianie, pozostała ustawiona wartość 5. Kiedy nastąpiło wywołanie funkcji f2, pierwotna zmienna uległa modyfikacji. Widać to po ostatniej wyświetlonej wartości. Referencje można także zwracać jako wyniki funkcji. Nie powinno się tego stosować w celu zwiększenia wydajności, ponieważ PHP robi to automatycznie. Powtórzmy: referencja jest po prostu inną nazwą dla zmiennej. Referencje mogą być wykorzystane do obejścia zabezpieczenia widoczności zmiennej, ustawionego za pomocą słowa kluczowego private lub protected (listing 2.7). Listing 2.7. Referencje mogą być wykorzystane do obejścia zabezpieczenia widoczności zmiennej
Po wykonaniu skryptu wynik jest zgodny z oczekiwaniami: b=10 b=15 $a->get_x()=16
W tym przykładzie zmienna $b jest ustawiana jako referencja na $a->x, która jest prywatną właściwością klasy test6. Zostało to wykonane poprzez zwrócenie referencji w wyniku działania metody get_x(). Oczywiście
44
ROZDZIAŁ 2. WYJĄTKI I REFERENCJE
deklarowanie publicznej referencji do prywatnej właściwości przeczy celowi kontroli widoczności. Zwracanie wartości przez referencję jest rzadko stosowaną praktyką. Wykorzystywanie tej metody powinno być dobrze przemyślane — łatwo można zezwolić na niepowołany dostęp do referencji zwróconych przez funkcję.
Podsumowanie Z tego rozdziału dowiedziałeś się o wyjątkach i referencjach w PHP. Oba elementy funkcjonują także w innych nowoczesnych językach programowania. Celem wyjątków jest zapewnienie łatwego systemu obsługi błędów. Głównym zadaniem referencji jest zwiększenie szybkości wykonywania kodu oraz (sporadycznie) umożliwienie wykorzystania sztuczek programistycznych. Oba elementy języka są bardzo przydatne i mogą ułatwić pracę programiście. Obsługa wyjątków pozwala na sprawdzanie błędów w elegancki sposób, co zostanie zademonstrowane w rozdziale dotyczącym integracji z bazami danych.
45
ROZDZIAŁ 2. WYJĄTKI I REFERENCJE
46
ROZDZIAŁ 3
Mobilne PHP
Tworzenie aplikacji mobilnych staje się z roku na rok coraz popularniejsze. O zwiększenie udziału w rynku walczą iPhone, Android czy BlackBerry. Każdy producent smartfona potrzebuje aplikacji dla swojego urządzenia, by przyciągnąć jak najwięcej użytkowników. Ponadto istnieją tablety, takie jak iPad, PlayBook i Galaxy, oraz czytniki, np. Kindle czy Nook. Nawet standardowe telefony komórkowe mają przeglądarki i różne dodatki. Na każdym urządzeniu mobilnym posiadającym dostęp do internetu można przeglądać strony internetowe i uruchamiać aplikacje utworzone w technologii PHP. Dlatego potrzebny jest sposób sensownego prezentowania zawartości stron na mniejszych urządzeniach. Z tego rozdziału dowiesz się, jak rozpoznać urządzenie klienckie za pomocą żądania HTTP, poznasz WURFL i Tera-WURFL. Obecnie działają tysiące urządzeń mobilnych umożliwiających przeglądanie stron internetowych. Może się wydawać, że tworzenie oprogramowania dla starszych przeglądarek jest trudne, ale urządzenia mobilne są jeszcze mniej ustandaryzowane. Na szczęście są dostępne systemy pomocne w procesie tworzenia takiego oprogramowania. Mając na uwadze renderowanie na urządzenia mobilne, pokażemy, jak sprawić przy użyciu WALL, by znaczniki były bardziej abstrakcyjne, jak automatycznie zmieniać rozmiar obrazków i spowodować, by CSS był bardziej płynny. Zaprezentujemy także emulatory urządzeń, omówimy tworzenie aplikacji PHP na urządzenia z Androidem i program Flash Builder dla PHP.
Różnorodność urządzeń Podczas pracy z urządzeniami mobilnymi jednym z największych wyzwań jest zapewnienie czytelności strony po jej wyrenderowaniu. Przy tworzeniu aplikacji internetowych na komputery osobiste sprawdzamy najpopularniejsze przeglądarki, takie jak Chrome, Firefox, Safari, Opera czy Internet Explorer, i być może inne systemy, np. Windows XP, Windows 7, Linux bądź Mac OS X. Zapewnienie wsparcia dla różnych kombinacji przeglądarek i systemów może być pracochłonne. W przypadku urządzeń mobilnych renderowanie jest jeszcze mniej ustandaryzowane i dużo bardziej złożone. Na przykład prawie wszystkie współczesne komputery osobiste umożliwiają wyświetlanie tysięcy kolorów i zapewniają rozdzielczość minimum 800 na 600 pikseli. Jednakże telefony komórkowe, smartfony, tablety, czytniki e-booków i inne urządzenia mobilne mogą mieć ograniczoną paletę kolorów lub tylko skalę szarości. Rozmiary wyświetlaczy także znacznie się różnią. To są tylko trzy parametry — istnieją setki innych, którymi mogą się różnić poszczególne urządzenia. Omówimy kilka z tych parametrów w dalszej części tego rozdziału. W przeciwieństwie do tworzenia stron przeznaczonych dla komputerów stacjonarnych naiwne próby programowania dla każdego urządzenia oddzielnie są nierealne lub przynajmniej zajęłyby zbyt wiele czasu i pracy, niż ktokolwiek byłby skłonny na to poświęcić. Zamiast tego omówimy systemy pozwalające na określenie urządzenia i wyrenderowanie strony dynamicznie oraz płynne zmienianie stylów CSS.
ROZDZIAŁ 3. MOBILNE PHP
Rozpoznanie urządzenia Pierwszym krokiem różnicowania zawartości strony jest sprawdzenie, dla jakiego urządzenia ta strona będzie renderowana. Przeanalizujemy kilka technik pozwalających na ustalenie, jakie urządzenie jest używane.
Aplikacja kliencka U podstaw każdego systemu detekcji urządzeń leży nagłówek aplikacji klienckiej wysyłany w standardowym zapytaniu HTTP. W PHP możemy uzyskać dostęp do informacji o aplikacji klienckiej dzięki superglobalnej zmiennej serwerowej $_SERVER['HTTP_USER_AGENT']. Nagłówek takiej aplikacji może zawierać informacje o przeglądarce, silniku renderującym i systemie operacyjnym. Ma postać podobną do poniższego, wygenerowanego dla przeglądarki Firefox 4: Mozilla/5.0 (Windows NT 5.1; rv:2.0) Gecko/20100101 Firefox/4.0
Z tego nagłówka możemy wyczytać, że systemem operacyjnym klienta jest Windows, silnikiem renderującym jest Gecko, natomiast przeglądarką jest Firefox w wersji 4.0. UWAGA. Rozpoznawanie urządzeń nie jest pewne. Nagłówki dla dwóch różnych urządzeń mogą nie być unikalne, chociaż rzadko tak bywa; mogą także być fałszowane, co zostanie omówione w dalszej części rozdziału.
Wbudowane funkcje PHP PHP ma funkcję get_browser, która próbuje uzyskać informacje o wykorzystywanej przeglądarce. Funkcja działa na podstawie pliku browscap.ini. W tym kontekście jest jak prostsza, ograniczona wersja systemu WURFL, który będzie omówiony dalej. UWAGA. Ta funkcja wymaga zainstalowanego w systemie pliku browscap.ini oraz ustawienia ścieżki do niego w pliku php.ini, na przykład: browscap = "C:\twoja\sciezka\do\browscap.ini"
Więcej informacji o funkcji get_browser można uzyskać pod adresem http://php.net/manual/pl/function.get-browser.php, natomiast aktualne pliki browscap.ini pod adresem http://browsers.garykeith.com/downloads.asp.
Jeżeli pierwszy parametr będzie ustawiony na wartość null lub przekazany zostanie nagłówek aplikacji klienckiej, uzyskamy informacje o przeglądarce. Możemy także przekazać inny nagłówek, aby uzyskać informacje o nim. Drugi parametr jest opcjonalny. Ustawienie go na wartość true spowoduje zwrócenie wyniku w postaci tabeli zamiast domyślnego obiektu (listingi 3.1 i 3.2). Listing 3.1. Wykorzystanie funkcji get_browser
Listing 3.2. Wynik dla przeglądarki Chrome Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.65 Safari/534.24
48
ROZDZIAŁ 3. MOBILNE PHP
array 'browser_name_regex' => string '§^.*$§' (length=6) 'browser_name_pattern' => string '*' (length=1) 'browser' => string 'Default Browser' (length=15) 'version' => string '0' (length=1) 'majorver' => string '0' (length=1) 'minorver' => string '0' (length=1) 'platform' => string 'unknown' (length=7) 'alpha' => string '' (length=0) 'beta' => string '' (length=0) 'win16' => string '' (length=0) 'win32' => string '' (length=0) 'win64' => string '' (length=0) 'frames' => string '1' (length=1) 'iframes' => string '' (length=0) 'tables' => string '1' (length=1) 'cookies' => string '' (length=0) 'backgroundsounds' => string '' (length=0) 'cdf' => string '' (length=0) 'vbscript' => string '' (length=0) 'javaapplets' => string '' (length=0) 'javascript' => string '' (length=0) 'activexcontrols' => string '' (length=0) 'isbanned' => string '' (length=0) 'ismobiledevice' => string '' (length=0) 'issyndicationreader' => string '' (length=0) 'crawler' => string '' (length=0) 'cssversion' => string '0' (length=1) 'supportscss' => string '' (length=0) 'aol' => string '' (length=0) 'aolversion' => string '0' (length=1)
Jak widać, funkcja nie zwraca żadnych informacji dla tej nowej przeglądarki. Dzieje się tak dlatego, że plik browscap.ini załączony do serwera WAMP (Windows, Apache, MySQL, PHP) ma już ponad rok. Rozwiązaniem problemu jest pobranie aktualnej wersji pliku. Może także być potrzebny restart serwera, jeżeli plik zostanie złożony w pamięci podręcznej. Po aktualizacji pliku otrzymamy dokładniejsze informacje, pokazane na listingu 3.3. Listing 3.3. Wynik dla przeglądarki Chrome po aktualizacji pliku browscap.ini Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.65 Safari/534.24 array 'browser_name_regex' => string '§^mozilla/5\.0 \(.*windows nt 6\.1.*wow64.*\) ´applewebkit/.*\(khtml, like gecko\).*chrome/11\..*safari/.*$§' (length=108) 'browser_name_pattern' => string 'Mozilla/5.0 (*Windows NT 6.1*WOW64*) AppleWebKit/* (KHTML, ´like Gecko)*Chrome/11.*Safari/*' (length=90) 'parent' => string 'Chrome 11.0' (length=11) 'platform' => string 'Win7' (length=4) 'win32' => string '' (length=0) 'win64' => string '1' (length=1) 'browser' => string 'Chrome' (length=6) 'version' => string '11.0' (length=4) 'majorver' => string '11' (length=2) 'frames' => string '1' (length=1) 'iframes' => string '1' (length=1) 'tables' => string '1' (length=1) 'cookies' => string '1' (length=1)
49
ROZDZIAŁ 3. MOBILNE PHP
'javascript' => string '1' (length=1) 'javaapplets' => string '1' (length=1) 'cssversion' => string '1' (length=1) 'minorver' => string '0' (length=1) 'alpha' => string '' (length=0) 'beta' => string '' (length=0) 'win16' => string '' (length=0) 'backgroundsounds' => string '' (length=0) 'vbscript' => string '' (length=0) 'activexcontrols' => string '' (length=0) 'isbanned' => string '' (length=0) 'ismobiledevice' => string '' (length=0) 'issyndicationreader' => string '' (length=0) 'crawler' => string '' (length=0) 'aolversion' => string '0' (length=1)Using Regex
Jeżeli zależy Ci na sprawdzeniu tylko kilku głównych urządzeń mobilnych, możesz wykorzystać wyrażenia regularne w celu przeszukania nagłówka aplikacji klienckiej. Na listingu 3.4 sprawdzamy, czy zapytanie przyszło z jednego z popularnych telefonów. Jeżeli łańcuch zostanie znaleziony, przekierowujemy żądanie do odrębnej strony przeznaczonej dla urządzeń mobilnych oraz ładujemy alternatywny szablon i arkusz stylów. Opcja /i w wyrażeniu regularnym (Regex) powoduje, że nasze zapytanie ignoruje wielkość znaków. Znak | oznacza „lub” — zostanie znaleziony zarówno łańcuch „iPhone”, jak i „iPad”, ale nie „iPod”. Podobnie będą znalezione „windows ce” oraz „windows phone”, ale nie „windows xp”. Zajrzyj do dodatku „Wyrażenia regularne”. Listing 3.4. Wykorzystanie wyrażeń regularnych w celu zweryfikowania urządzeń mobilnych
Aby wykryć więcej urządzeń, potrzebujemy znacznie większego wyrażenia regularnego. Możemy skorzystać z popularnej strony http://detectmobilebrowsers.com/, pozwalającej generować wyrażenie regularne w kilku różnych językach programowania i dla różnych frameworków. Wygenerowany skrypt przekieruje klienta na witrynę przeznaczoną dla urządzeń mobilnych. Listing 3.5 pokazuje przykładowy skrypt wygenerowany przez wyżej wymienioną stronę. Listing 3.5. Wyrażenie regularne wygenerowane przez stronę detectmobilebrowsers.com
To rozwiązanie będzie poprawne tylko w niektórych przypadkach. Aby uzyskać dokładniejsze wyniki oraz rozpoznać możliwości urządzenia, potrzebny jest zaawansowany system. Ten system to WURFL, omówiony w kolejnym podrozdziale.
Rozpoznawanie możliwości urządzenia System WURFL pozwala wyjść poza proste wykrywanie rodzaju urządzenia i ustalić, jakie są jego możliwości.
WURFL Wireless Universal Resource FiLe (WURFL) jest plikiem XML opracowanym przez Luca Passaniego, zawierającym informacje o możliwościach urządzeń mobilnych.
Wprowadzenie Aktualnie w pliku WURFL jest ponad pięćset różnych właściwości urządzeń mobilnych. Implementacje WURFL zostały opracowane w wielu językach i na wiele platform, włączając w to Javę i .NET. Dla PHP oficjalne API to The New PHP WURFL API, dostępne pod adresem http://wurfl.sourceforge.net/nphp/. Właściwości urządzeń są ułożone hierarchicznie. Jeżeli właściwość nie jest wyszczególniona dla danego modelu, to sprawdzany jest ogólniejszy typ urządzenia. Jeśli właściwość ponownie nie zostanie znaleziona, WURFL sprawdza kolejny ogólniejszy typ urządzenia i powtarza ten proces, dopóki nie dotrze do korzenia pliku. Struktura hierarchiczna oszczędza przestrzeń na dysku i przyspiesza wyszukiwanie. WURFL próbuje także wykorzystywać wersje pliku XML spakowaną za pomocą ZipArchiwe, pakietu dostępnego w PHP od wersji 5.2.0. Ponieważ wersja ZIP pliku ma aktualnie poniżej megabajta (MB), a wersja rozpakowana pliku ponad 16 MB, jest to duże usprawnienie. Niektóre użyteczne właściwości to rozdzielczość ekranu, kodeki i formaty lub wsparcie dla JavaScriptu, Javy czy Flasha. UWAGA. Plik XML jest tworzony głównie przez developerów i użytkowników, więc może zawierać błędy. Ponadto na rynek ciągle trafiają nowe urządzenia. Pomimo rozmiarów i kompletności pliku WURFL nie powinniśmy nigdy ufać mu w stu procentach. Jeżeli potrzebujesz szybko wykorzystać informacje o urządzeniu, możesz wyszczególnić jego właściwości oraz umieścić informacje o nim w głównym pliku XML. Jeżeli dokładność informacji ma kluczowe znaczenie, można użyć systemów o znacznie większej skuteczności.
Instalacja Na potrzeby wszystkich przykładów z tego rozdziału umieścimy bibliotekę WURFL w katalogu wurfl, który będzie się znajdował w głównym katalogu web jako ./wurfl/. Wykorzystamy standardowy plik konfiguracyjny, a obiekt WURFLManager będziemy za każdym razem pozyskiwać za pomocą kodu z listingu 3.6.
51
ROZDZIAŁ 3. MOBILNE PHP
Listing 3.6. Utworzenie obiektu WURFLManager: wurflSetup.php
Rozpoznawanie urządzeń za pomocą WURFL W naszym pierwszym przykładzie rozpoznawania urządzenia wyświetlimy stos urządzenia przy wykorzystaniu WURFL PHP API. Wyświetlimy hierarchię aplikacji klienckiej z zastosowaniem właściwości fallback oraz id (listing 3.7). Listing 3.7. Wyświetlenie stosu dla aplikacji klienckiej od szczegółowej do ogólnej
Poniżej znajduje się wynik działania skryptu na komputerze stacjonarnym dla przeglądarki Firefox 4: Stos Id: firefox_1 firefox generic_web_browser generic_xhtml generic
oraz dla przeglądarki Chrome: Stos Id: google_chrome_1 google_chrome generic_web_browser generic_xhtml generic
52
ROZDZIAŁ 3. MOBILNE PHP
UWAGA. Uruchomienie skryptu po raz pierwszy może zająć dużo czasu, ponieważ WURFL buduje bufor. Konieczne może być zwiększenie wartości dla dyrektywy max_execution_time w pliku php.ini.
Jeżeli chcemy emulować inne urządzenie, możemy wprowadzić inną zmienną serwerową zawierającą nagłówek aplikacji klienckiej. Zmodyfikowana wersja listingu 3.7 pokazana jest na listingu 3.8. Wynik skryptu przedstawiono na listingu 3.9. Listing 3.8. Emulowanie innego urządzenia — wprowadzenie innej zmiennej serwerowej
Listing 3.9. Wynik działania WURFL dla emulowanego iPhone’a 4 Stos ID: apple_iphone_ver4_sub405 apple_iphone_ver4 apple_iphone_ver3_1_3 apple_iphone_ver3_1_2 apple_iphone_ver3_1 apple_iphone_ver3 apple_iphone_ver2_2_1 apple_iphone_ver2_2 apple_iphone_ver2_1 apple_iphone_ver2 apple_iphone_ver1 apple_generic generic_xhtml generic
Rozpoznawanie i wyświetlanie właściwości urządzenia za pomocą WURFL Na listingu 3.10 pokazano dostępne grupy właściwości, które możemy sprawdzić. Wyświetlimy wszystkie dostępne właściwości dla grup display i css. Wynik pokazany jest na listingu 3.11. Listing 3.10. Wyświetlanie dostępnych grup atrybutów
Listing 3.11. Wynik działania skryptu z listingu 3.10 ajax bearer bugs cache chtml_ui css display drm flash_lite html_ui image_format j2me markup mms object_download pdf playback product_info rss security sms sound_format storage streaming transcoding wap_push wml_ui wta xhtml_ui
Aby wyświetlić listę wszystkich dostępnych właściwości, możemy zmodyfikować skrypt z listingu 3.10, tak by wykorzystywał metodę getCapabilitiesNameForGroup. Zmodyfikowany skrypt pokazany jest na listingu 3.12. Początkowa część wyniku widnieje na listingu 3.13. Listing 3.12. Wyświetlanie listy wszystkich właściwości, które mogą być sprawdzone
54
ROZDZIAŁ 3. MOBILNE PHP
Listing 3.13. Początek wyniku skryptu z listingu 3.12 ajax array 0 => 1 => 2 => 3 => 4 => 5 => 6 => 7 => 8 => bearer array 0 => 1 => 2 => 3 => 4 => …
string string string string string string string string string
'ajax_preferred_geoloc_api' (length=25) 'ajax_xhr_type' (length=13) 'ajax_support_getelementbyid' (length=27) 'ajax_support_event_listener' (length=27) 'ajax_manipulate_dom' (length=19) 'ajax_support_javascript' (length=23) 'ajax_support_inner_html' (length=23) 'ajax_manipulate_css' (length=19) 'ajax_support_events' (length=19)
string string string string string
'sdio' (length=4) 'wifi' (length=4) 'has_cellular_radio' (length=18) 'max_data_rate' (length=13) 'vpn' (length=3)
Możemy zmodyfikować skrypt z listingu 3.12 tak, aby wyświetlały się tylko niektóre właściwości urządzenia, by wspierane właściwości były oznaczone kolorem zielonym i znacznikami (renderowanymi przez encje HTML) oraz by niewspierane właściwości były oznaczone kolorem czerwonym i przekreśleniem (listing 3.14). Wynik pokazany jest na rysunku 3.1. Listing 3.14. Wyświetlanie właściwości urządzeń wraz z kolorowaniem
WALL jest super
Nagłówek
To będzie paragraf w HTML
zapytanie:
Tytuł | Data | Autor |
---|
testowa | kolumna |
---|---|
a | 1 |
b | 2 |
c | 3 |
po załadowaniu strony modyfikowana jest przy wykorzystaniu jQuery — skrypt jest równoważny z listingiem 15.5. Listing 15.10. Modyfikacja elementu
po załadowaniu strony za pomocą jQuery
Pierwszy przykład jQuery
Oryginalna zawartość
za pomocą selektorów CSS, druga ustawia zawartość elementu. UWAGA. Zapis $("p") odpowiada wszystkim elementom
w dokumencie. Jeżeli chcemy wybrać tylko pierwszą instancję elementu, tak jak na listingu 15.5, moglibyśmy zastosować funkcje wbudowane $("p").first(). Moglibyśmy także użyć selektorów CSS, np.: $("p:first") lub $("p:eq(0)").
Wersja skryptu używająca jQuery jest krótsza niż wersja oryginalna, wykorzystująca obiekt XMLHttpRequest. W przypadku bardziej skomplikowanych skryptów wartość API wyższego poziomu, takich jak jQuery, uwydatnia się w jeszcze większym stopniu. Skrypt z listingu 15.11 jest równoważny ze skryptem z listingu 15.6, ładującym tekst z pliku XML. Listing 15.11. Wykorzystanie jQuery do załadowania tekstu z pliku XML
Ładowanie tekstu z jQuery
Ajax pobrał tekst:
Ajax pobrał tekst:
Ajax pobrał text:
JSON sparsowany przez Ajax:
Odpowiedź z PHP:
Paleta kolorów:
Rysuj!
Konsola debugowania:
Paleta kolorów:
Rysuj!
Konsola debugowania: