56
Wydawnictwo Helion ul. Chopina 6 44-100 Gliwice tel. (32)230-98-63 e-mail: [email protected] PRZYK£ADOWY ROZDZIA£ PRZYK£ADOWY ROZDZIA£ IDZ DO IDZ DO ZAMÓW DRUKOWANY KATALOG ZAMÓW DRUKOWANY KATALOG KATALOG KSI¥¯EK KATALOG KSI¥¯EK TWÓJ KOSZYK TWÓJ KOSZYK CENNIK I INFORMACJE CENNIK I INFORMACJE ZAMÓW INFORMACJE O NOWOCIACH ZAMÓW INFORMACJE O NOWOCIACH ZAMÓW CENNIK ZAMÓW CENNI K CZYTELNIA CZYTELNIA FRAGMENTY KSI¥¯EK ONLINE FRAGMENTY KSI¥¯EK ONLINE SPIS TRECI SPIS TRECI DODAJ DO KOSZYKA DODAJ DO KOSZYKA KATALOG ONLINE KATALOG ONLINE Zaawansowane programowanie w PHP4 Autor: praca zbiorowa ISBN: 83-7197-729-8 Tytu³ orygina³u: Professional PHP 4 Format: B5, stron: 990 W opinii autorów niniejsza ksi¹¿ka stanowi doskona³e ród³o wiedzy dla aktywnych programistów, wykorzystuj¹cych w swojej pracy PHP. Ta ksi¹¿ka ma na celu umo¿liwienie twórcom aplikacji internetowych tworzenie programów, które bêd¹: • skalowalne, • wydajne, • bezpieczne, • modularne, • wielowarstwowe. Ksi¹¿ka ta adresowana jest do programistów, których znajomoæ PHP pozwala na tworzenie i rozwijanie niewielkich aplikacji WWW. Pomimo ¿e przedstawiamy sk³adniê PHP, liczymy na to, ¿e programici czytaj¹cy tê ksi¹¿kê nie bêd¹ potrzebowali wyk³adu na temat podstaw programowania.

PHP4. Zaawansowane programowanie

  • View
    2.351

  • Download
    2

Embed Size (px)

DESCRIPTION

PHP jedna z najpopularniejszych technologii służących do budowy aplikacji internetowych. Jest to niezależny od platformy prosty język o łatwej składni, przyjazny dla początkujących programistów. Ta ostatnia cecha zadecydowała o jego szerokim rozpowszechnieniu. Dzięki książce " PHP4. Zaawansowane programowanie" poznasz wiele sekretów profesjonalnych zastosowań tego języka. Nauczy Cię tworzyć programy, które są skalowalne, wydajne i bezpieczne, a także, dzięki modularnej, wielowarstwowej konstrukcji, łatwe w rozbudowie. Ta książka nie jest tylko zbiorem sztuczek i tricków. Poznasz dzięki niej wiele zaawansowanych koncepcji pomagających tworzyć wydajne aplikacje internetowe na dużą skalę. Dowiesz się, jak stworzyć program kliencki do odczytywania e-maili, nauczysz się tworzyć zabezpieczone aplikacje, używać sesji i korzystać ze złożonych struktur danych.Dla kogo jest ta książka:"PHP4. Zaawansowane programowanie" to książka dla programistów, którzy opanowali podstawy programowania i posiadają ogólną znajomość technologii bazodanowych i są zainteresowani tworzeniem dużych aplikacji internetowych w PHP.Co opisuje ta książka: * Instalację PHP w systemach uniksowych, Windows i MacOS X * Sesje i cookies, pisanie klientów FTP, korzystanie z funkcji sieciowych i usług katalogowych * Wsparcie dla LDAP dostępne w PHP * Tworzenie wielowarstwowych aplikacji w PHP * Korzystanie z dokumentów XML * Korzystanie z baz danych MySQL, PostgreSQL i interfejsu ODBC * Zabezpieczanie, optymalizację aplikacji, tworzenie wersji językowych programów * Przykłady z życia wzięte: aplikacja do obsługi spisu pracowników, sieciowa biblioteka * Tworzenie interfejsu GTK do aplikacji * Studium przypadku: system uprawnień dla użytkowników i wielowarstwowa aplikacja e-commerce z wykorzystaniem WML

Citation preview

Page 1: PHP4. Zaawansowane programowanie

Wydawnictwo Helion

ul. Chopina 6

44-100 Gliwice

tel. (32)230-98-63

e-mail: [email protected]

PRZYK£ADOWY ROZDZIA£PRZYK£ADOWY ROZDZIA£

IDZ DOIDZ DO

ZAMÓW DRUKOWANY KATALOGZAMÓW DRUKOWANY KATALOG

KATALOG KSI¥¯EKKATALOG KSI¥¯EK

TWÓJ KOSZYKTWÓJ KOSZYK

CENNIK I INFORMACJECENNIK I INFORMACJE

ZAMÓW INFORMACJEO NOWO�CIACH

ZAMÓW INFORMACJEO NOWO�CIACH

ZAMÓW CENNIKZAMÓW CENNIK

CZYTELNIACZYTELNIA

FRAGMENTY KSI¥¯EK ONLINEFRAGMENTY KSI¥¯EK ONLINE

SPIS TRE�CISPIS TRE�CI

DODAJ DO KOSZYKADODAJ DO KOSZYKA

KATALOG ONLINEKATALOG ONLINE

Zaawansowane

programowanie w PHP4

Autor: praca zbiorowa

ISBN: 83-7197-729-8

Tytu³ orygina³u: Professional PHP 4

Format: B5, stron: 990

W opinii autorów niniejsza ksi¹¿ka stanowi doskona³e �ród³o wiedzy dla aktywnych

programistów, wykorzystuj¹cych w swojej pracy PHP.

Ta ksi¹¿ka ma na celu umo¿liwienie twórcom aplikacji internetowych tworzenie

programów, które bêd¹:

• skalowalne,

• wydajne,

• bezpieczne,

• modularne,

• wielowarstwowe.

Ksi¹¿ka ta adresowana jest do programistów, których znajomo�æ PHP pozwala na

tworzenie i rozwijanie niewielkich aplikacji WWW. Pomimo ¿e przedstawiamy sk³adniê

PHP, liczymy na to, ¿e programi�ci czytaj¹cy tê ksi¹¿kê nie bêd¹ potrzebowali wyk³adu

na temat podstaw programowania.

Page 2: PHP4. Zaawansowane programowanie

Spis treści

O Autorach.....................................................................................................................................19

Wstęp...........................................................................................................................................23Dla kogo jest przeznaczona ta książka?................................................................................ 23Zawartość książki .................................................................................................................. 24Czego potrzeba, aby można było korzystać z tej książki? ...................................................... 27Konwencje............................................................................................................................. 27

Rozdział 1. Droga do PHP................................................................................................................29Dlaczego PHP?...................................................................................................................... 29Ewolucja języka PHP.............................................................................................................. 30

Przeszłość PHP ................................................................................................................ 30PHP dzisiaj ....................................................................................................................... 30PHP na ringu.................................................................................................................... 30Przyszłość PHP................................................................................................................. 31

PHP a inne języki ................................................................................................................... 31PHP a ASP........................................................................................................................ 31PHP a Cold Fusion ........................................................................................................... 32PHP a Perl........................................................................................................................ 32PHP a Java....................................................................................................................... 32

Licencje PHP ......................................................................................................................... 33Dodatkowe źródła informacji ................................................................................................. 33

Rozdział 2. Instalacja.....................................................................................................................35Mamy już PHP........................................................................................................................ 35Przed instalacją ..................................................................................................................... 37Decyzje instalacyjne .............................................................................................................. 38

Który system operacyjny? ................................................................................................ 38Moduł czy CGI?................................................................................................................ 38Który serwer WWW?......................................................................................................... 40

Instalacja MySQL, Apache i PHP............................................................................................ 40Instalacja w systemie Windows............................................................................................. 40

Instalacja bazy MySQL..................................................................................................... 41Jakie komplikacje mogą wystąpić?............................................................................. 42

Instalacja serwera Apache............................................................................................... 43Jakie komplikacje mogą wystąpić?............................................................................. 46

Instalacja PHP ................................................................................................................. 46Konfiguracja Apache do obsługi PHP................................................................................ 48

Jakie komplikacje mogą wystąpić?............................................................................. 49

Page 3: PHP4. Zaawansowane programowanie

4 PHP4. Zaawansowane programowanie

Testowanie instalacji PHP................................................................................................ 50Jakie komplikacje mogą wystąpić?............................................................................. 51

Czynności po instalacji..................................................................................................... 52Przejście na ISAPI ............................................................................................................ 54

Instalacja w systemach klasy UNIX ....................................................................................... 54Instalacja MySQL............................................................................................................. 55

Utworzenie użytkownika dla MySQL-a......................................................................... 55Konfiguracja kodu źródłowego MySQL-a ..................................................................... 56Kompilacja MySQL-a................................................................................................... 57Inicjalizacja MySQL-a.................................................................................................. 58Uruchamianie MySQL-a .............................................................................................. 59Testowanie MySQL-a.................................................................................................. 59Zabezpieczanie MySQL-a............................................................................................ 60Jakie komplikacje mogą wystąpić?............................................................................. 60

Instalacja Apache ............................................................................................................ 60Czynności po instalacji Apache .................................................................................. 61Jakie komplikacje mogą wystąpić?............................................................................. 62

Instalacja PHP ................................................................................................................. 63Jakie komplikacje mogą wystąpić?............................................................................. 64Kompilacja PHP.......................................................................................................... 65Jakie komplikacje mogą wystąpić?............................................................................. 66

Czynności po instalacji..................................................................................................... 66Integracja PHP z Apache.................................................................................................. 66

Jakie komplikacje mogą wystąpić?............................................................................. 68Czynności po instalacji ............................................................................................... 69

Dodatkowe źródła informacji ................................................................................................. 71PHP.net............................................................................................................................ 71Zend.com......................................................................................................................... 72php4win.de...................................................................................................................... 72Apache ............................................................................................................................ 73MySQL ............................................................................................................................. 73

Rozdział 3. Podstawy PHP..............................................................................................................75Programy w PHP .................................................................................................................... 75

Skrypty PHP ..................................................................................................................... 76Instrukcje .............................................................................................................................. 77

Komentarze ..................................................................................................................... 79Literały .................................................................................................................................. 80

Literały tekstowe ............................................................................................................. 80Dokumenty osadzone ...................................................................................................... 81Literały liczbowe .............................................................................................................. 82Literały logiczne............................................................................................................... 82

Zmienne................................................................................................................................ 83Przypisanie ...................................................................................................................... 83Odwołanie........................................................................................................................ 84

Stałe...................................................................................................................................... 85Typy danych........................................................................................................................... 85

Rzutowanie ...................................................................................................................... 86Operatory i funkcje ................................................................................................................ 87

Operacje ogólnego przeznaczenia.................................................................................... 89Operacje na napisach...................................................................................................... 90Funkcje napisowe ............................................................................................................ 91

substr()....................................................................................................................... 91strpos()....................................................................................................................... 91

Page 4: PHP4. Zaawansowane programowanie

Spis treści 5

htmspecialchars()....................................................................................................... 92trim() .......................................................................................................................... 92chr() oraz ord()............................................................................................................ 93strlen()........................................................................................................................ 93printf() oraz sprintf().................................................................................................... 93

Operacje liczbowe............................................................................................................ 95Operacje bitowe ......................................................................................................... 96Operacje porównania.................................................................................................. 97Priorytety operatorów ................................................................................................. 98

Operacje logiczne............................................................................................................. 98Priorytety operatorów ................................................................................................. 99

Tablice................................................................................................................................... 99Zmienne zewnętrzne.............................................................................................................. 99

Zmienne systemowe, zmienne GET oraz $HTTP_ Arrays .......................................... 100Zmienne POST ......................................................................................................... 101Cookies.................................................................................................................... 101Zmienne CGI ............................................................................................................ 101Zmienne nagłówków HTTP........................................................................................ 102

Rozdział 4. Struktury w PHP.........................................................................................................103Struktury kontroli przebiegu programu................................................................................. 103

Instrukcje warunkowe .................................................................................................... 103If .............................................................................................................................. 103switch....................................................................................................................... 106

Pętle .............................................................................................................................. 107while......................................................................................................................... 108do...while.................................................................................................................. 109for ............................................................................................................................ 109Alternatywna składnia pętli ...................................................................................... 110

Funkcje................................................................................................................................ 110Definiowanie funkcji....................................................................................................... 110Zakres zmiennej ............................................................................................................ 112Czas życia zmiennej....................................................................................................... 113Rekurencja..................................................................................................................... 114Przypisywanie funkcji zmiennym..................................................................................... 114Zastosowanie funkcji w celu uporządkowania kodu....................................................... 115Komentarze ................................................................................................................... 118

Tablice................................................................................................................................. 118Inicjacja tablic................................................................................................................ 119Sekwencyjne przeglądanie tablic ................................................................................... 120Wbudowane funkcje tablicowe....................................................................................... 120

count()...................................................................................................................... 120in_array() .................................................................................................................. 121reset() ...................................................................................................................... 121sort() ........................................................................................................................ 121explode() oraz implode() ........................................................................................... 122

Tablice predefiniowane.................................................................................................. 122Tablice wielowymiarowe................................................................................................. 122

Rozdział 5. Programowanie obiektowe w PHP4.............................................................................125Programowanie zorientowane obiektowo............................................................................. 125

Programowanie proceduralne a programowanie obiektowe............................................ 127Znaczenie programowania obiektowego......................................................................... 128

Page 5: PHP4. Zaawansowane programowanie

6 PHP4. Zaawansowane programowanie

Zstępująca metoda tworzenia oprogramowania................................................................... 128Klasy.............................................................................................................................. 129Obiekty .......................................................................................................................... 132

Metody fabryczne ..................................................................................................... 133Hermetyzacja (ang.Encapsulation) ................................................................................. 135Dziedziczenie................................................................................................................. 137

Operator wywołania metody klasy ............................................................................ 141Ponowne wykorzystanie kodu................................................................................... 141

Polimorfizm.................................................................................................................... 142Metody abstrakcyjne ................................................................................................ 143

Adekwatność i powiązania............................................................................................. 146Modelowanie obiektowe z użyciem UML.............................................................................. 148

Delegacja....................................................................................................................... 150Analiza i decyzje projektowe................................................................................................ 152Funkcje PHP obsługujące klasy ........................................................................................... 154

get_class() ..................................................................................................................... 154get_parent_class() ......................................................................................................... 155

Ograniczenia PHP ................................................................................................................ 155Brak atrybutów statycznych............................................................................................ 156Brak destruktorów ......................................................................................................... 157Brak wielokrotnego dziedziczenia................................................................................... 158

Modelowanie złożonego komponentu WWW........................................................................ 160

Rozdział 6. Wykrywanie i usuwanie błędów..................................................................................165Przegląd błędów programistycznych..................................................................................... 166

Błędy składni ................................................................................................................. 166Błędy semantyczne........................................................................................................ 167Błędy logiczne................................................................................................................ 168Błędy środowiska........................................................................................................... 169

Poziomy błędów w PHP........................................................................................................ 169Błędy analizy.................................................................................................................. 170Błędy krytyczne .............................................................................................................. 170Ostrzeżenia.................................................................................................................... 170Uwagi............................................................................................................................. 170Błędy na poziomie jądra................................................................................................. 171Poziomy błędów etapu kompilacji .................................................................................. 171Poziomy błędów definiowanych przez użytkownika......................................................... 171Ustawianie poziomów zgłaszania błędów....................................................................... 171

Obsługa błędów................................................................................................................... 172Wyciszanie komunikatów błędach.................................................................................. 172Postępowanie w przypadku wystąpienia błędu............................................................... 173Sprawdzanie błędów w nietypowych sytuacjach............................................................. 174Raportowanie błędów..................................................................................................... 175

Programy wspomagające wykrywanie błędów ...................................................................... 176Narzędzia do wykrywania błędów wykorzystujące protokół HTTP .................................... 177

Klient telnet ............................................................................................................. 177Serwery nasłuchujące .............................................................................................. 178

Metoda śledzenia .......................................................................................................... 179phpCodeSite ............................................................................................................ 180

Zdalne systemy wykrywania błędów............................................................................... 185BODY........................................................................................................................ 185Zend IDE .................................................................................................................. 187

Testowanie skryptowe......................................................................................................... 188

Page 6: PHP4. Zaawansowane programowanie

Spis treści 7

Rozdział 7. Wprowadzanie danych i wyrażenia regularne ............................................................193Wprowadzanie danych......................................................................................................... 193Formularze .......................................................................................................................... 194

Formularze HTML........................................................................................................... 194Atrybut action........................................................................................................... 195Atrybut method......................................................................................................... 195

Obsługa wprowadzanych danych ......................................................................................... 196Skomplikowane formularze............................................................................................ 197Weryfikacja danych ........................................................................................................ 200

OOH Forms............................................................................................................... 201Przykładowa aplikacja .............................................................................................. 201Zabezpieczenie przed niewłaściwym użyciem........................................................... 210

Wyrażenia regularne............................................................................................................ 211Podstawy składni wyrażeń regularnych .......................................................................... 211Tworzenie wyrażeń regularnych...................................................................................... 213

Weryfikacja poprawności adresów e-mail ................................................................. 215Wyrażenia regularne w PHP............................................................................................ 215Wyrażenia regularne zgodne z mechanizmami języka Perl.............................................. 218

Funkcje PHP obsługujące PCRE................................................................................ 220

Rozdział 8. Sesje oraz ciasteczka................................................................................................225Sesje................................................................................................................................... 226

Uaktywnianie obsługi sesji w PHP.................................................................................. 226Zastosowanie sesji PHP................................................................................................. 227Uruchamianie sesji ........................................................................................................ 228Rejestrowanie zmiennych sesji ...................................................................................... 228Tworzenie własnych procedur obsługi sesji .................................................................... 230

Ustawianie bazy danych ........................................................................................... 230Adresy URL.......................................................................................................................... 235

Bezpieczeństwo ............................................................................................................. 235Ciasteczka........................................................................................................................... 236

Bezpieczeństwo ............................................................................................................. 237Zastosowania ciasteczek............................................................................................... 237

Termin ważności....................................................................................................... 238Ścieżka .................................................................................................................... 239Domena ................................................................................................................... 239

Przykładowa aplikacja wykorzystująca ciasteczka .......................................................... 240setcookie()..................................................................................................................... 241

Ustawianie parametru okresu ważności ciasteczka ................................................. 242Ograniczanie dostępu............................................................................................... 243

Usuwanie ciasteczka ..................................................................................................... 246Łączenie informacji z ciasteczek.................................................................................... 246Problemy z ciasteczkami................................................................................................ 248

Dodatkowe funkcje obsługi sesji.......................................................................................... 250

Rozdział 9. Obsługa plików ..........................................................................................................253Pliki...................................................................................................................................... 253

Otwieranie plików........................................................................................................... 254Zamykanie plików .......................................................................................................... 255Wypisywanie zawartości plików...................................................................................... 255Odczyt zawartości plików ............................................................................................... 256Zapis do plików.............................................................................................................. 257

Page 7: PHP4. Zaawansowane programowanie

8 PHP4. Zaawansowane programowanie

Nawigowanie po pliku .................................................................................................... 257Kopiowanie, usuwanie i zmiana nazw plików ................................................................. 258Określanie atrybutów plików .......................................................................................... 259

Katalogi ............................................................................................................................... 260Dodawanie i usuwanie katalogów.................................................................................. 262

Przesyłanie plików z przeglądarki......................................................................................... 263Przesyłanie plików za pośrednictwem metody PUT ........................................................ 264Przesyłanie plików z wykorzystaniem metody POST ....................................................... 264

Przykładowa aplikacja obsługi systemu plików .................................................................... 267Aplikacja służąca do przechowywania plików online....................................................... 267

Wspólne mechanizmy............................................................................................... 270Rejestracja nowego użytkownika.............................................................................. 272Logowanie................................................................................................................ 276Tworzenie katalogów................................................................................................ 282Usuwanie katalogu lub pliku..................................................................................... 282Wysyłanie plików na serwer...................................................................................... 283Przeglądanie plików.................................................................................................. 284Przeglądanie katalogów............................................................................................ 285Wylogowanie ............................................................................................................ 286

Rozdział 10. Programowanie klientów FTP ...................................................................................287Uaktywnianie obsługi FTP w PHP ......................................................................................... 288Rozszerzenia obsługi FTP w PHP.......................................................................................... 288

Tworzenie aplikacji klientów FTP .................................................................................... 289Procedury ułatwiające korzystanie z FTP................................................................... 290

Klient FTP oparty na WWW .................................................................................................. 299Tworzymy klienta FTP..................................................................................................... 308

Przegląd funkcji FTP według zastosowania .......................................................................... 311Nawiązywanie i zrywanie połączenia .............................................................................. 311Operacje na katalogach................................................................................................. 312Obsługa plików............................................................................................................... 312

Alfabetyczny przegląd funkcji FTP......................................................................................... 313Podstawowe polecenia FTP oraz odpowiadające im funkcje PHP......................................... 323

Rozdział 11. Poczta elektroniczna i grupy dyskusyjne...................................................................327Jak działa poczta elektroniczna? ......................................................................................... 328

Niezbyt tajni agenci........................................................................................................ 329SMTP ............................................................................................................................. 329

Struktura listu elektronicznego............................................................................................ 331Nagłówki listu elektronicznego....................................................................................... 331

Nagłówki wymagane................................................................................................. 332Nagłówki opcjonalne ................................................................................................ 334

Wysyłanie listów elektronicznych z wykorzystaniem funkcji mail() .................................. 335Wykorzystanie funkcji mail()...................................................................................... 335Tworzenie klasy KlasaPocztowa ............................................................................... 338Testowanie klasy KlasaPocztowa............................................................................. 344Tworzenie klasy KlasaPocztowaSMTP ...................................................................... 345Testujemy klasę KlasaPocztowaSMTP ..................................................................... 352

List elektroniczny w formacie MIME............................................................................... 353Pola nagłówka listu elektronicznego w formacie MIME............................................. 354Tworzenie klasy KlasaPocztowaMIME ...................................................................... 358Testowanie klasy KlasaPocztowaMIME .................................................................... 362

Tworzenie klasy KlasaPocztowaSMTP_MIME ................................................................. 363

Page 8: PHP4. Zaawansowane programowanie

Spis treści 9

Usenet ................................................................................................................................ 364Jak działa Usenet? ........................................................................................................ 365Przykładowa sesja NNTP................................................................................................ 365Kody odpowiedzi serwera NNTP..................................................................................... 368Anatomia artykułu grupy dyskusyjnej ............................................................................. 370Tworzenie klasy NNTP.................................................................................................... 371

Testowanie klasy KlasaNNTP ................................................................................... 377Łączymy w całość wszystkie elementy................................................................................. 378Dodatkowe źródła informacji ............................................................................................... 385

Rozdział 12. Pobieranie listów elektronicznych i artykułów grup dyskusyjnych...........................387Protokoły służące do pobierania poczty elektronicznej ........................................................ 388

POP................................................................................................................................ 388Przykładowa sesja POP............................................................................................. 389

IMAP .............................................................................................................................. 390Znaczniki .................................................................................................................. 391Formaty skrzynek pocztowych................................................................................... 391Przykładowa sesja IMAP........................................................................................... 392

Porównanie protokołu POP z IMAP ................................................................................. 396Pobieranie poczty elektronicznej za pomocą PHP ................................................................ 397

Połączenie z serwerem .................................................................................................. 397Przykład połączenia.................................................................................................. 399

Tworzenie klasy Webmail ............................................................................................... 400Atrybuty .................................................................................................................... 400Testowanie klasy Webmail ....................................................................................... 403

Pobieranie zawartości skrzynki pocztowej lub grupy dyskusyjnej.................................... 403Pobieranie zawartości skrzynki lub grupy dyskusyjnej w klasie Webmail ........................ 410

Nowe atrybuty .......................................................................................................... 410Testowanie klasy Webmail ....................................................................................... 413

Pobieranie listów i artykułów.......................................................................................... 414Odczytywanie listów z wykorzystaniem klasy Webmail ................................................... 416

Nowe atrybuty .......................................................................................................... 416Testujemy klasę Webmail......................................................................................... 420

Praca ze skrzynkami ...................................................................................................... 422Zarządzanie skrzynkami z wykorzystaniem klasy Webmail ............................................. 425

Nowe atrybuty .......................................................................................................... 425Operacje na listach i artykułach..................................................................................... 428Operacje na listach wykonywane z wykorzystaniem klasy Webmail................................ 430

Nowe atrybuty .......................................................................................................... 430System obsługi poczty elektronicznej oparty na przeglądarce WWW.................................... 433

Atrybuty .................................................................................................................... 433Dodatkowe źródła informacji ............................................................................................... 447

Rozdział 13. Sieci i protokół TCP/IP ..............................................................................................449Internet Protocol.................................................................................................................. 450Protokoły warstwy transportowej ......................................................................................... 451

TCP — Transmission Control Protocol ........................................................................... 451UDP — User Datagram Protocol .................................................................................... 452

Tłumaczenie nazw domen ................................................................................................... 452Hierarchiczny system rozproszony ................................................................................. 453Wykorzystanie DNS w PHP ............................................................................................. 454Biblioteka Resolver ........................................................................................................ 458

Page 9: PHP4. Zaawansowane programowanie

10 PHP4. Zaawansowane programowanie

Gniazda............................................................................................................................... 463Gniazda i PHP ................................................................................................................ 464Aplikacja klienta pocztowego ......................................................................................... 469

Network Information Service ............................................................................................... 471Serwery NIS ................................................................................................................... 472Klienci NIS ..................................................................................................................... 473Mapowania NIS.............................................................................................................. 473NIS i PHP ....................................................................................................................... 475

Simple Network Management Protocol................................................................................ 477Agenci i zarządcy ........................................................................................................... 477Protokół SNMP............................................................................................................... 478

Get ........................................................................................................................... 478Get Next................................................................................................................... 479Set ........................................................................................................................... 479Trap.......................................................................................................................... 479

Organizacja danych SNMP ............................................................................................. 479Funkcje SNMP w PHP..................................................................................................... 480

Rozdział 14. LDAP.........................................................................................................................485Katalogi ............................................................................................................................... 485LDAP.................................................................................................................................... 486

LDAP a tradycyjne bazy danych...................................................................................... 486Składniki LDAP............................................................................................................... 488LDAP — charakterystyka ............................................................................................... 488

Globalne usługi katalogowe ..................................................................................... 489Otwarty standard komunikacyjny .............................................................................. 489Rozszerzalność i elastyczność ................................................................................. 489Heterogeniczne repozytorium danych....................................................................... 489Bezpieczny protokół z kontrolą dostępu ................................................................... 490

Zastosowania LDAP....................................................................................................... 490Elementy terminologii LDAP ........................................................................................... 492Modele LDAP ................................................................................................................. 493

Model informacyjny .................................................................................................. 493Model nazw.............................................................................................................. 495Model funkcjonalny .................................................................................................. 496

Zaawansowane cechy LDAP........................................................................................... 499Operacje asynchroniczne.......................................................................................... 499Replikacja ................................................................................................................ 499Odsyłacze................................................................................................................. 500Bezpieczeństwo........................................................................................................ 500Właściwości rozszerzone.......................................................................................... 500

Oprogramowanie LDAP ........................................................................................................ 501Instalacja i konfiguracja serwera LDAP .......................................................................... 502

Plik konfiguracyjny serwera OpenLDAP..................................................................... 502Uruchamianie serwera slapd.................................................................................... 504

Sprawdzanie instalacji ................................................................................................... 505Obsługa LDAP w języku PHP ................................................................................................ 505

Interfejs LDAP API języka PHP........................................................................................ 506Funkcje połączeniowe i kontrolne............................................................................. 506Funkcje wyszukujące................................................................................................ 508Funkcje modyfikujące............................................................................................... 514Funkcje obsługi błędów ............................................................................................ 516

Przykładowa aplikacja klienta LDAP w języku PHP ............................................................... 516

Page 10: PHP4. Zaawansowane programowanie

Spis treści 11

Rozdział 15. Wprowadzenie do programowania aplikacji wielowarstwowych ..............................533Rozwój aplikacji WWW......................................................................................................... 533Wielowarstwowość .............................................................................................................. 535

Warstwa danych............................................................................................................. 535Model plikowy .......................................................................................................... 536Model relacyjny ........................................................................................................ 537Model XML............................................................................................................... 538Model mieszany ....................................................................................................... 540

Warstwa logiki aplikacji.................................................................................................. 540Warstwa prezentacji....................................................................................................... 540Urządzenia korzystające z sieci WWW............................................................................ 541

Architektury projektowania wielowarstwowego..................................................................... 541Architektura oparta na języku HTML............................................................................... 542

Warstwa danych....................................................................................................... 543Warstwa logiczna ..................................................................................................... 543Warstwa prezentacji ................................................................................................. 543

Architektura oparta na języku XML................................................................................. 545Wyodrębnianie warstw......................................................................................................... 546

Programowanie modułowe............................................................................................. 547Niezależność warstw logiki i prezentacji......................................................................... 547Niezależność warstw logiki i danych .............................................................................. 547Niezależność od bazy danych......................................................................................... 547

Ankieta — projektowanie aplikacji wielowarstwowej............................................................ 548Projektowanie modelu danych ....................................................................................... 548

Warstwa danych....................................................................................................... 548Warstwa logiczna ..................................................................................................... 549Warstwa prezentacji ................................................................................................. 550

Klasyczna architektura wielowarstwowa ........................................................................ 550Przypadek 1. Zmiana sposobu wyświetlania wyników głosowania............................ 550Przypadek 2. Zablokowanie możliwości wielokrotnego głosowania użytkownika....... 550Przypadek 3. Wersja Flash aplikacji ......................................................................... 551

Rozdział 16. Aplikacja WAP — studium przypadku .......................................................................553Analiza wymagań................................................................................................................. 553Interakcja z użytkownikiem.................................................................................................. 555Dobór oprogramowania ....................................................................................................... 555

Alternatywy dla bazy danych zaplecza............................................................................ 557Alternatywy dla warstwy pośredniej................................................................................ 557

Projekt schematu bazy danych ............................................................................................ 558Tabele bazy danych........................................................................................................ 558Użytkownik bazy danych................................................................................................. 560Indeksy.......................................................................................................................... 561

Kwestie projektowe warstwy pośredniej .............................................................................. 562Uwierzytelnianie............................................................................................................. 562Przechowywanie danych sesji......................................................................................... 562Kwestie związane z językiem WML................................................................................. 563Wydajność ..................................................................................................................... 564

Implementacja..................................................................................................................... 564Kod aplikacji .................................................................................................................. 566

Warstwa danych i logiki aplikacji .............................................................................. 572Karta powitalna........................................................................................................ 595Rejestracja nowego użytkownika.............................................................................. 598Logowanie................................................................................................................ 599

Page 11: PHP4. Zaawansowane programowanie

12 PHP4. Zaawansowane programowanie

Karta główna aplikacji .............................................................................................. 601Przeglądanie zasobów księgarni............................................................................... 605Przeglądanie zasobów sklepu muzycznego............................................................... 607Wyszukiwanie........................................................................................................... 609Dodawanie pozycji do koszyka użytkownika ............................................................. 612Przeglądanie zawartości koszyka użytkownika.......................................................... 614Zmiana liczby sztuk poszczególnych pozycji koszyka................................................ 616Zatwierdzanie zakupów ............................................................................................ 618Przeglądanie informacji o koncie użytkownika.......................................................... 620Wylogowanie ............................................................................................................ 623

Rozdział 17. PHP i MySQL .............................................................................................................625Relacyjne bazy danych......................................................................................................... 626

Indeksy.......................................................................................................................... 627Klucze............................................................................................................................ 627Normalizacja .................................................................................................................. 629

Strukturalny język zapytań ................................................................................................... 631Zapytania definicji danych.............................................................................................. 632

CREATE DATABASE................................................................................................... 632USE.......................................................................................................................... 633CREATE TABLE.......................................................................................................... 633DESCRIBE ................................................................................................................ 634ALTER TABLE............................................................................................................ 636DROP TABLE............................................................................................................. 637DROP DATABASE...................................................................................................... 637

Zapytania manipulacji danymi........................................................................................ 638INSERT..................................................................................................................... 638REPLACE .................................................................................................................. 638DELETE..................................................................................................................... 639UPDATE.................................................................................................................... 639SELECT..................................................................................................................... 640

Połączenia ..................................................................................................................... 641Indeksy.......................................................................................................................... 642Niepodzielność operacji ................................................................................................. 644

PHP a relacyjne bazy danych ............................................................................................... 645Interfejs MySQL języka PHP ........................................................................................... 645Biblioteka sieciowa........................................................................................................ 651Wyodrębnianie bazy danych........................................................................................... 658

Warstwa abstrakcji bazy danych............................................................................... 660Konstrukcja klasy BD ............................................................................................... 660Testowanie klasy BD................................................................................................ 664

Rozdział 18. PHP i PostgreSQL......................................................................................................667PostgreSQL — podstawy..................................................................................................... 668

Zapytania definicji danych.............................................................................................. 669CREATE DATABASE................................................................................................... 669CREATE TABLE.......................................................................................................... 669ALTER TABLE............................................................................................................ 672DROP TABLE............................................................................................................. 673DROP DATABASE...................................................................................................... 673

Zapytania manipulacji danymi........................................................................................ 673INSERT..................................................................................................................... 673DELETE..................................................................................................................... 674UPDATE.................................................................................................................... 674SELECT..................................................................................................................... 675

Page 12: PHP4. Zaawansowane programowanie

Spis treści 13

Interfejs PostgreSQL języka PHP ......................................................................................... 676Biblioteka sieciowa.............................................................................................................. 683Wyodrębnianie bazy danych................................................................................................. 687

Rozdział 19. PHP i ODBC.................................................................................................................691ODBC — historia i przeznaczenie ........................................................................................ 692Architektura ODBC............................................................................................................... 693

Standardy SQL............................................................................................................... 694Instalacja PHP i ODBC w systemie Windows ....................................................................... 694Instalacja ODBC i PHP w systemach z rodziny UNIX ............................................................ 695

Moduł serwera Apache............................................................................................. 695Interfejs ODBC języka PHP................................................................................................... 698

Funkcje połączeniowe .............................................................................................. 698Funkcje manipulujące metadanymi........................................................................... 699Funkcje obsługi transakcji ........................................................................................ 702Funkcje dostępu do danych i kursory ....................................................................... 703Najczęstsze problemy .............................................................................................. 706

Wymagania dla połączeń ODBC........................................................................................... 708MS SQL Server .............................................................................................................. 708MS Access..................................................................................................................... 710

Nawiązywanie połączenia .................................................................................................... 711Wyodrębnianie bazy danych................................................................................................. 713

Unified ODBC................................................................................................................. 713PEARDB ......................................................................................................................... 713ADODB........................................................................................................................... 714Metabase ...................................................................................................................... 715

Biblioteka sieciowa.............................................................................................................. 715

Rozdział 20. Programowanie aplikacji nieserwerowych w języku PHP .........................................721Czym jest GTK? ................................................................................................................... 721Czym jest PHP-GTK?............................................................................................................ 722Język PHP w wierszu poleceń .............................................................................................. 722

Konfiguracja dla systemu Linux ..................................................................................... 722Biblioteka libedit ...................................................................................................... 722

Instalacja PHP-GTK ........................................................................................................ 723Konfiguracja dla systemu Windows................................................................................ 724

Środowisko .............................................................................................................. 724Instalacja PHP-GTK................................................................................................... 725

Automatyzacja zadań........................................................................................................... 726Format plików dziennika NCSA CLFF.............................................................................. 727

Skrypt analizatora pliku dziennika............................................................................ 728cron ............................................................................................................................... 730AT .................................................................................................................................. 731

Harmonogram zadań systemu Windows................................................................... 731Przyjmowanie parametrów wiersza poleceń ................................................................... 731

Skrypty interaktywne............................................................................................................ 732Programowanie aplikacji z użyciem PHP-GTK....................................................................... 734

PHP-GTK — podstawy.................................................................................................... 734Przykład — program Hello World.................................................................................... 737Interfejs graficzny aplikacji biblioteki sieciowej .............................................................. 739

Dodatkowe źródła informacji ............................................................................................... 746

Page 13: PHP4. Zaawansowane programowanie

14 PHP4. Zaawansowane programowanie

Rozdział 21. PHP i XML.................................................................................................................747XML — przegląd.................................................................................................................. 748

Rodzina standardów XML............................................................................................... 750XML a bazy danych ........................................................................................................ 751

SML..................................................................................................................................... 752Konwersja dokumentu XML na format SML ................................................................... 752

XML i PHP............................................................................................................................ 754Weryfikacja obsługi XML-a.............................................................................................. 754Porównanie interfejsów XML.......................................................................................... 755

SAX a DOM............................................................................................................... 756PRAX a DOM i SAX.................................................................................................... 756

Model SAX ..................................................................................................................... 756Obsługa SAX w języku PHP....................................................................................... 758SAX — kod przykładowy ........................................................................................... 758

Model DOM.................................................................................................................... 764Obsługa DOM w języku PHP ..................................................................................... 764DOM — kod przykładowy.......................................................................................... 766

Model RAX ..................................................................................................................... 775Obsługa PRAX w języku PHP..................................................................................... 776

XSL i XSLT ........................................................................................................................... 780Sablotron....................................................................................................................... 781Instalacja i weryfikacja konfiguracji XSL......................................................................... 781

Instalacja w systemie UNIX...................................................................................... 781Instalacja w systemie Windows................................................................................ 781

XSL — kod przykładowy................................................................................................. 782

Rozdział 22. Internacjonalizacja aplikacji ....................................................................................787Internacjonalizacja — pojęcia.............................................................................................. 787

Internacjonalizacja ......................................................................................................... 788Lokalizacja..................................................................................................................... 788Obsługa języka ojczystego ............................................................................................. 789

Motywy internacjonalizacji aplikacji ..................................................................................... 789W czym tkwi problem? ................................................................................................... 790

Ciągi tekstowe..................................................................................................................... 790Ciągi statyczne .............................................................................................................. 791Ciągi dynamiczne........................................................................................................... 791Przechowywanie ciągów................................................................................................. 792

Wyodrębnienie danych tekstowych z programu ........................................................ 793GNU Gettext ........................................................................................................................ 794

Gettext — informacje podstawowe ................................................................................ 794xgettext i inne narzędzia pomocnicze............................................................................. 795Aktualizacja tłumaczeń .................................................................................................. 798Wady biblioteki Gettext .................................................................................................. 798

Obiektowe rozszerzenie systemu tłumaczenia..................................................................... 799Zalety podejścia obiektowego........................................................................................ 799Korzystanie z obiektów i przełączanie języków............................................................... 800

Konwersja istniejących programów...................................................................................... 800Program nieprzetłumaczony ........................................................................................... 801Tłumaczenie programu................................................................................................... 801

Obiekty przystosowane do wielojęzyczności przekładu ........................................................ 804Integracja klasy Wyjscie z aplikacją ..................................................................................... 806Dalsze doskonalenie skryptu............................................................................................... 808Wyrażenia regularne............................................................................................................ 808

Page 14: PHP4. Zaawansowane programowanie

Spis treści 15

Wielkość liter....................................................................................................................... 810Lokalne formaty daty i czasu............................................................................................... 810Pozyskiwanie dodatkowych informacji lokalizacyjnych — funkcja localeconv()..................... 813Sortowanie .......................................................................................................................... 816

Własna funkcja porównująca ......................................................................................... 817Kodowanie znaków.............................................................................................................. 819

Zapisywanie locali.......................................................................................................... 819Przeglądarka a język................................................................................................. 819Reagowanie na konfigurację przeglądarki................................................................. 821

Ciągi poszerzone ................................................................................................................. 825Moduł obsługi ciągów poszerzonych w języku PHP......................................................... 826Moduł mod_mime serwera Apache................................................................................ 826

Przykład lokalizacji rzeczywistej aplikacji — PHP Weather ................................................... 826

Rozdział 23. Bezpieczeństwo aplikacji PHP ...................................................................................831Czym jest bezpieczeństwo?................................................................................................. 832Zabezpieczanie serwera ...................................................................................................... 832

Zbrojenie serwera.......................................................................................................... 833Monitorowanie systemu................................................................................................. 833Monitorowanie powiadomień o nowych lukach .............................................................. 834

Najpowszechniejsze rodzaje zagrożeń...................................................................... 834Zabezpieczanie serwera Apache.......................................................................................... 836

Dyrektywa User.............................................................................................................. 836Dyrektywa Directory ....................................................................................................... 837Zbrojenie serwera Apache ............................................................................................. 838

Zabezpieczanie PHP ............................................................................................................ 839Bezpieczeństwo instalacji PHP w trybie CGI ................................................................... 839Konfiguracja PHP ........................................................................................................... 840Tryb bezpieczny.............................................................................................................. 843

Zabezpieczanie serwera MySQL .......................................................................................... 844MySQL i użytkownik root ................................................................................................ 844Sprzątanie ..................................................................................................................... 845Zarządzanie użytkownikami baz danych MySQL ............................................................. 846

Kryptografia ......................................................................................................................... 847Szyfrowanie jednokierunkowe ........................................................................................ 847Szyfrowanie symetryczne ............................................................................................... 850Szyfrowanie asymetryczne ............................................................................................. 852

Bezpieczeństwo sieci komputerowej ................................................................................... 852Moduł mod_ssl serwera Apache.................................................................................... 853

Instalacja modułu mod_ssl w systemie Linux........................................................... 853Instalacja modułu mod_ssl w systemie Windows..................................................... 854Konfiguracja modułu mod_ssl .................................................................................. 854Kiedy należy korzystać z połączeń SSL?................................................................... 855

Bezpieczne programowanie................................................................................................. 855Zagrożenia związane z dyrektywą register_global........................................................... 856Kontrola danych wprowadzanych przez użytkownika ...................................................... 858Zagrożenia płynące z nieuprawnionego wykonania kodu HTML...................................... 859Pułapki dyrektywy include .............................................................................................. 859

Kilka porad.......................................................................................................................... 860Dodatkowe źródła informacji ............................................................................................... 861

Zabezpieczanie serwerów linuksowych .......................................................................... 861Bezpieczne powłoki (SSH) .............................................................................................. 861

Page 15: PHP4. Zaawansowane programowanie

16 PHP4. Zaawansowane programowanie

Tripwire .......................................................................................................................... 861Zabezpieczanie Apache ................................................................................................. 862Zabezpieczanie PHP....................................................................................................... 862Zabezpieczanie MySQL .................................................................................................. 862Kryptografia ................................................................................................................... 862mod_ssl ......................................................................................................................... 863Bezpieczne programowanie ........................................................................................... 863Strony WWW poświęcone bezpieczeństwu..................................................................... 863Pozostałe źródła ............................................................................................................ 863

Rozdział 24. Optymalizacja aplikacji PHP......................................................................................865Właściwy język..................................................................................................................... 865

Wyniki testów................................................................................................................. 866Optymalizacja kodu PHP...................................................................................................... 867

Profilowanie kodu .......................................................................................................... 867Profilowanie skryptów PHP ....................................................................................... 867

Klasyfikacja wąskich gardeł ........................................................................................... 871Techniki optymalizacji.......................................................................................................... 871

Optymalizacja kodu........................................................................................................ 872Analiza pętli.............................................................................................................. 872Wykorzystanie szybszych funkcji............................................................................... 873Wybór właściwego sposobu przekazywania danych wyjściowych .............................. 873Wybór właściwego sposobu pobierania danych wejściowych.................................... 873Minimalizacja liczby wywołań funkcji echo().............................................................. 874Wykorzystanie optymalizatora Zend Optimizer.......................................................... 874

Buforowanie i kompresja danych wyjściowych ............................................................... 874Przykład skryptu buforującego wyjście...................................................................... 875Funkcje obsługujące buforowanie wyjścia ................................................................ 875Buforowanie kaskadowe .......................................................................................... 877Kompresja wyjścia skryptu PHP................................................................................ 877

Optymalizacja bazy danych ............................................................................................ 878Analiza zapytań ........................................................................................................ 878Szacowanie efektywności zapytania......................................................................... 878Optymalizacja tabel .................................................................................................. 883Optymalizacja modelu danych .................................................................................. 883Stosowanie indeksów .............................................................................................. 884Optymalizacja zapytań SELECT................................................................................. 885Optymalizacja zapytań INSERT ................................................................................. 885Optymalizacja zapytań UPDATE ................................................................................ 886Optymalizacja zapytań DELETE................................................................................. 886Optymalizacja połączeń............................................................................................ 886Optymalizacja — wskazówki dodatkowe................................................................... 887

Buforowanie wyników obliczeń....................................................................................... 887Czym jest buforowanie? ........................................................................................... 888Waga buforowania.................................................................................................... 888Zalety buforowania................................................................................................... 888Wady buforowania.................................................................................................... 888Ogólna metodologia buforowania............................................................................. 889Wybór metody składowania buforowanych danych ................................................... 890Konwencje nazewnicze............................................................................................. 892Kryteria poprawności................................................................................................ 892Opróżnianie bufora................................................................................................... 893Jakie dane powinny być składowane w buforach wyników?...................................... 893

Optymalizacja interpretera PHP...................................................................................... 895

Page 16: PHP4. Zaawansowane programowanie

Spis treści 17

Rozdział 25. Biblioteki rozszerzeń języka PHP.............................................................................897Biblioteka PDF..................................................................................................................... 898

Instalacja....................................................................................................................... 898Korzystanie z biblioteki PDFlib ....................................................................................... 899

Macromedia Flash............................................................................................................... 903Ming i LibSWF ................................................................................................................ 903Korzystanie z biblioteki Ming.......................................................................................... 904

WAP i WML .......................................................................................................................... 912A gdzie tu biblioteka? .................................................................................................... 913Korzystanie z biblioteki HAWHAW .................................................................................. 914

Tworzenie dynamicznych rysunków...................................................................................... 918Instalacja biblioteki GD.................................................................................................. 918Korzystanie z biblioteki GD ............................................................................................ 919Licznik odwiedzin wykonany za pomocą GD ................................................................... 921

Kod licznika odwiedzin ............................................................................................. 921

Rozdział 26. System uprawnień użytkowników ...........................................................................925Definicja wymagań............................................................................................................... 925

Wymagania aplikacji ...................................................................................................... 926Projektowanie aplikacji ........................................................................................................ 926

Projektowanie schematu bazy danych............................................................................ 927Tabela Uzytkownik.................................................................................................... 927Tabela Uprawnienie.................................................................................................. 927Tabela UzytkownikUprawnienie ................................................................................ 927

Projektowanie warstwy pośredniczącej .......................................................................... 927Dostęp do bazy danych ............................................................................................ 928Klasa Uprawnienie ................................................................................................... 928Klasa Uzytkownik ..................................................................................................... 928Warstwa logiki aplikacji ............................................................................................ 929

Projektowanie warstwy prezentacji................................................................................. 930Kodowanie aplikacji............................................................................................................. 931

Kod obsługi bazy danych ............................................................................................... 931Klasa Uprawnienie......................................................................................................... 932Klasa Uzytkownik ........................................................................................................... 934Testowanie klas............................................................................................................. 938

uprawnienia.php....................................................................................................... 939uzytkownikuprawnienia.php...................................................................................... 944

Wykorzystanie systemu uprawnień użytkowników................................................................ 950Kilka propozycji rozszerzenia systemu................................................................................. 951

Skorowidz..................................................................................................................................953

Page 17: PHP4. Zaawansowane programowanie

5Programowanie obiektowe w PHP4

Programowanie zorientowane obiektowo (Object Oriented Programming) istnieje już od kil-

ku lat. Jego historia wiąże się z powstaniem języków Smalltalk oraz C++. Koncepcja pro-gramowania obiektowego zaowocowała następnie powstaniem nowych języków, takich jakJava czy Python. Gdy w grę wchodzi tworzenie skomplikowanych programów, takich jak

edytor tekstu czy też gra komputerowa, programowanie obiektowe nie jest zaledwie jednąz opcji dostępnych programiście. Jest to obecnie standardowy sposób tworzenia skompli-kowanych programów w sposób ułatwiający ich rozwijanie i zwiększający poziom ich

skalowalności, stosowany zarówno w oprogramowaniu komercyjnym, jak i bezpłatnym.

Usprawnienie mechanizmów obiektowych w PHP4 spowodowało znaczne ożywienie w spo-łeczności programistów PHP. Zaczęli oni wykorzystywać zalety programowania obiekto-wego. W tym rozdziale przyjrzymy się technikom programowania obiektowego od podstaw,

pokazując, jaką rolę odgrywają one w PHP, a także wskazując sposoby ich wykorzystaniaw celu tworzenia eleganckich rozwiązań w dziedzinie aplikacji WWW. Przyjrzymy się kilkusposobom analizy oraz pożytecznym praktykom programistycznym pozwalającym na zwięk-

szenie możliwości powtórnego wykorzystania kodu, a także uproszczenia procesu dalszegorozwoju programów. Zanim jednak zagalopujemy się za daleko, zobaczmy, w jaki sposóbpowstała koncepcja programowania obiektowego, a także czym różni się ona od tradycyj-

nych technik programowania proceduralnego. Jeśli jesteś doświadczonym programistą sto-sującym techniki obiektowe i chcesz zapoznać się z zagadnieniami obiektowymi specyficz-nymi dla PHP, możesz od razu przejść do podrozdziału „Klasy”.

Programowanie zorientowane obiektowo

Na początku prześledźmy różnice pomiędzy programowaniem obiektowym a klasycznym

programowaniem proceduralnym. Przed powstaniem idei programowania obiektowegoprogramy stawały się coraz bardziej rozbudowane i skomplikowane. Systemy te dla dalszegorozwoju wymagały pracy wielu architektów i inżynierów, a proces ten pochłaniał coraz wię-

cej czasu i pieniędzy. Często zachodzi potrzeba dopasowania oprogramowania do zmianw strategii biznesowej. W takim przypadku zmiana istniejących funkcji programu lub do-danie nowych wymagały tygodni, a często miesięcy pracy i okazywało się, że napisanie

programu od nowa trwałoby znacznie krócej.

Page 18: PHP4. Zaawansowane programowanie

126 PHP4. Zaawansowane programowanie

Aplikacje rozrastały się, a usuwanie błędów w nich stawało się poważnym problemem.

Wysiłki w celu utrzymania istniejących możliwości systemu zajmowały więcej czasu niż

dodawanie nowych funkcji. Kod stawał się coraz bardziej chaotyczny, ponieważ rosła liczba

pracowników zaangażowanych w projekt. Błędy projektowe popełnione na początku (co

często ma miejsce w przypadku projektów programistycznych prowadzonych w językach

takich jak Fortran czy C) były często przyczyną nawarstwiania się problemów. W wielkich

firmach, inwestujących ogromne pieniądze w systemy informatyczne niezbędne do prowa-

dzenia biznesu, uświadomiono sobie ogromną potrzebę usprawnienia procesu projektowa-

nia i tworzenia oprogramowania.

Wtedy właśnie naukowcy z wielu dziedzin, takich jak informatyka, filozofia czy biologia,

stworzyli podstawy nowego sposobu tworzenia oprogramowania, który został ostatecznie

nazwany „programowaniem zorientowanym obiektowo”. W procesie tym najbardziej za-

służyli się Alan Kay, twórca języka Smalltalk, oraz Grady Booch, autor nowoczesnych zasad

analizy i programowania obiektowego.

Celem tych prac było zażegnanie kryzysu w przemyśle programistycznym przez stworzenie

łatwego w użyciu zestawu narzędzi programistycznych. Wspomniani pionierzy techniki

obiektowej odkryli, że rozwiązanie problemów programistycznych jest możliwe przez za-

stosowanie kilku nowych zasad tworzenia oprogramowania, wymagających od programisty

nieco więcej wysiłku na początku pracy. Programowanie obiektowe zmusza programistę do

spojrzenia na problemy i sposoby ich rozwiązania z nieco innej perspektywy. Kosztem za-

stosowania technik obiektowych jest niewielkie zmniejszenie wydajności oprogramowania,

ale jego dalsza rozbudowa staje się niezwykle łatwa.

Oczywista jest konieczność kompromisu pomiędzy wydajnością i łatwością rozbudowy.

W przypadku niektórych systemów komputerowych, w których krytycznym czynnikiem

jest działanie w czasie rzeczywistym lub też które wykorzystują operacje wymagające bar-

dzo dużej wydajności, zastosowanie rozwiązań obiektowych nie wchodzi w grę — właśnie

z powodu wymagań dotyczących czasu wykonania. Jednak wszędzie tam, gdzie zastoso-

wanie programowania obiektowego jest uzasadnione, programista może tworzyć programy

w sposób niezwykle elastyczny i o wiele bardziej intuicyjny niż do tej pory. Programowa-

nie zorientowane obiektowo wspomaga tworzenie oprogramowania w sposób ułatwiający

ponowne wykorzystanie kodu, rozbudowę, wykrywanie błędów i zwiększający czytelność

programów.

Wraz z rozwojem technik obiektowych powstawały nowe metodologie prowadzenia pro-

jektów informatycznych, takie jak osławione programowanie ekstremalne (eXtreme Pro-

gramming) czy też ujednolicony proces (Unified Process). Łatwiej jest obecnie planować

fazy projektów, gospodarować zasobami, wtórnie wykorzystywać istniejący kod, a także

testować i analizować kod w większych projektach. Faktem jest, że powstanie technik pro-

gramowania obiektowego miało ogromny wpływ na nasz dzisiejszy, oparty na elektronice

świat. Technologie takie jak Java wykorzystują techniki obiektowe do granic możliwości,

udostępniając pojedyncze, zorientowane obiektowo rozwiązanie przeznaczone dla różnych

platform, począwszy od urządzeń elektronicznych codziennego użytku, poprzez oprogra-

mowanie dla komputerów klasy PC, na potężnych aplikacjach internetowych skończywszy.

Page 19: PHP4. Zaawansowane programowanie

Rozdział 5. � Programowanie obiektowe w PHP4 127

Programowanie proceduralne a programowanie obiektowe

A zatem co powoduje, że programowanie obiektowe tak różni się od programowania pro-

ceduralnego? Gdy tworzymy oprogramowanie przy użyciu procedur (funkcji), tworzymy

programy zorientowane na kod. Programy wywołują funkcje, które wywołują funkcje

i tak dalej. Dane są przesyłane jako argument wywołania funkcji, funkcja dokonuje mody-

fikacji danych i zwraca odpowiednie wyniki. Programowanie zorientowane obiektowo to

zupełnie inna metodologia. Tutaj programowanie jest zorientowane na dane. Obiekty, które

wewnętrznie reprezentują dane, zawierają dodatkowo mechanizmy funkcji, zwanych w tym

przypadku metodami.

Metoda jest usługą (w swej implementacji niezwykle podobną do funkcji), którą obiekt

udostępnia swoim klientom (innym obiektom). Gdy obiekt wysyła żądanie usługi do drugiego

obiektu, odbywa się to na zasadzie przesłania komunikatu i uzyskania odpowiedzi. Oto po-

równanie obydwu metod:

m

Obiekt 3 Obiekt 4m

Obiekt 2

m

Obiekt 1

m

wywołaniea() b()

c()

wywołaniewynik

wyjście

wejściewynik

Model proceduralny Model obiektowy

Wprowadzenie danych powoduje wywołanie funkcji ���, która wywołuje funkcję ���.

Funkcja ��� wywołuje ���, która zwraca swój wynik do ���, która z kolei zwraca swój wy-

nik funkcji ���. Funkcja ��� ostatecznie generuje wynik programu. Funkcja ��� w typowym

programie w ��� nosiłaby nazwę ������. W modelu obiektowym obiekt wysyła żądania usług

do innych obiektów, co widać na przykładzie. Tutaj ���� � wysyła żądanie do ���� �.

Z kolei ���� � wysyła żądanie do ���� � i tak dalej, aż do momentu, gdy ���� �

uzyska odpowiedź od ���� � zawierającą wynik końcowy.

Ten mechanizm opiera się na udostępnianiu usług obiektom przez inne obiekty celem prze-

kazywania informacji niezbędnej do ich pracy. Oznacza to możliwość podejmowania decy-

zji na podstawie informacji uzyskanych z innych obiektów. Przekazywanie komunikatów

stanowi samo w sobie przebieg programu. Dane i metody, a także sam kod implementujący

obiekty, są zgromadzone w jednym centralnym miejscu.

Różnica pomiędzy tymi dwoma sposobami polega na tym, że obiekty zawierają całe dane

oraz mechanizmy działania, które powinny być ze sobą związane, natomiast w rozwiązaniu

proceduralnym dane i mechanizmy działania istnieją niezależnie od siebie. Cecha ta pozwala

na łatwą analizę kodu wykorzystującego technikę obiektową i zwiększa modularność projektu.

Nie oznacza to jednak, że programy wykorzystujące rozwiązanie proceduralne nie dają się

łatwo rozwijać. Wymaga to jednak znacznie więcej uwagi i organizacji ze strony programi-

sty, aby zapewnić odpowiednie umiejscowienie wszystkich elementów. Najlepszą rzeczą

Page 20: PHP4. Zaawansowane programowanie

128 PHP4. Zaawansowane programowanie

w programowaniu obiektowym jest to, że tworzone obiekty mają sens w projekcie, opierają

się na jasnych założeniach, dzięki czemu wszystko wydaje się być dobrze zorganizowane.

W bardziej skomplikowanych projektach można wykorzystać wyspecjalizowane rozwiąza-

nia, które dodatkowo usprawnią projekt naszego systemu, zapewniając dodatkowe korzyści.

Znaczenie programowania obiektowego

Programista musi sobie uświadomić, że programowanie obiektowe jest czymś więcej niż

techniką programistyczną. Nie jest to język ani platforma systemowa. PHP, C++ czy Java

są językami obiektowymi, ponieważ wykorzystują to samo rozwiązanie, choć każdy z nich

realizuje to na swój unikalny sposób. Nie zmienia to faktu, że programowanie w C++ różni

się dość znacznie od programowania w PHP, ponieważ języki te różnią się składnią oraz

działaniem konstrukcji językowych.

Jednak ponieważ języki zorientowane obiektowo są skonstruowane wg podobnych zasad,

podstawy programowania obiektowego we wszystkich tych językach są podobne. Dlatego

należy najpierw nauczyć się podstaw samych koncepcji obiektowych, aby następnie zagłę-

bić się w szczegóły implementacji tych technik w wybranym języku programowania. Przy

bliższej obserwacji okazuje się, że PHP obsługuje jedynie podzbiór cech oczekiwanych od

obiektowego języka programowania. Ograniczenia PHP w tej dziedzinie zostaną omówione

w dalszej części tego rozdziału, a pod koniec rozdziału przedstawimy ich podsumowanie.

Zstępująca metoda tworzenia oprogramowania

Od czasów powstania nauki ludzie wykazują skłonność do dzielenia na kategorie, definio-

wania i formalizowania wszystkiego, co istnieje na świecie. Programowanie nie jest tu wy-

jątkiem, ponieważ informatyka wyrasta z silnych korzeni matematyki i logiki. Piękno pro-

gramowania obiektowego polega na tym, że pozwala ono nie tylko umieścić dane i kod na

swoim miejscu, ale również umożliwia podzielenie na kategorie i zdefiniowanie elementów

programów w sposób, w jaki postrzegamy elementy naszego świata. Technika ta umożliwia

kompleksowe opracowanie projektu, zanim zagłębimy się w szczegóły. Pozwala to na łatwe

oszacowanie czasu, zagrożeń i różnych zasobów, które mają związek z naszym projektem.

Gdy tworzymy program, możemy podzielić go na wyspecjalizowane części lub moduły.

Możemy na przykład wyodrębnić różne warstwy prezentacji, warstwę dostępu do bazy da-

nych, mechanizmy wyszukiwania czy też komponenty odpowiedzialne za bezpieczeństwo.

Gdy tworzymy nasze moduły jako wyodrębnione elementy, zyskujemy pewność, że zmiany

dokonane w jednym z obiektów nie będą miały wpływu na drugi. Dodatkowo będziemy

mogli ponownie wykorzystać obiekty w innych aplikacjach. Możemy również z łatwością

rozbić nasze moduły na podmoduły, a w końcu na pojedyncze klasy, które stanowią naj-

mniejszy komponent w programowaniu zorientowanym obiektowo. Przyjrzyjmy się teraz

temu najmniejszemu komponentowi w programie zorientowanym obiektowo, czyli klasie.

Page 21: PHP4. Zaawansowane programowanie

Rozdział 5. � Programowanie obiektowe w PHP4 129

Klasy

Klasa jest definicją reprezentacji określonego typu danych. Klasy służą jako sposób mode-

lowania różnych typów danych w naszym systemie. Gdy chcemy utworzyć obiekt, najpierw

użyjemy słowa kluczowego �����, aby zdefiniować go, zanim użyjemy go w naszym skrypcie

w PHP. Różnica pomiędzy klasą a obiektem polega na tym, że klasa definiuje obiekty używane

w programie. Zanim dowiemy się, w jaki sposób tworzyć klasy, musimy zacząć myśleć

o klasach jak o reprezentacji pojedynczej idei. W trakcie projektowania klasy trzeba starać

się, aby realizowała konkretny cel w sposób jak najbardziej kompletny, nie wykraczając

jednak poza przeznaczenie przypisane tej idei.

Klasa w PHP składa się z trzech głównych elementów: atrybutów (reprezentujących dane),

metod oraz konstruktorów. Atrybut stanowi porcję danych przechowywanych przez obiekt.

Obiekty mogą zawierać dowolną liczbę atrybutów — na przykład jeśli chcielibyśmy przed-

stawić samochód w postaci klasy, kierownica i skrzynia biegów byłyby atrybutami klasy

��������. Metody określają usługi, które obiekt udostępnia swoim klientom w celu mani-

pulowania atrybutami. Przykładowo klasa �������� może udostępniać metody umożliwia-

jące wykonanie manewru skrętu pojazdem, wykorzystując wewnętrzny atrybut reprezentu-

jący kierownicę.

Konstruktor jest specjalną metodą inicjującą obiekt do stanu gotowości. W PHP w każdej

klasie może być zdefiniowany tylko jeden konstruktor. W klasie �������� sensowne wydaje

się dodanie atrybutów �������, ������, ����, ��������������, ������� i tym podobne.

Gdy klient zechce użyć metod obiektu, konstruktor zapewnia, że każda z metod będzie

działać na prawidłowych atrybutach i zwróci oczekiwany wynik, na przykład aby można

było włączyć radio w samochodzie, musi być ono zamontowane. W tym przypadku kon-

struktor jest odpowiedzialny za zamontowanie radia przed jego użyciem.

Oprócz realizowania funkcji inicjowania obiektu do stanu gotowości, dodatkową różnicą

między konstruktorami a metodami jest to, że konstruktory nie zwracają jawnie żadnych

wartości. Każdy konstruktor zwraca nowo zainicjowany obiekt, gotowy do użycia w progra-

mie. Dlatego użycie instrukcji ����� w definicji konstruktora jest nielegalne. W dalszej czę-

ści rozdziału zajmiemy się szerzej problematyką wykorzystania obiektów w programach.

Często spotykanym problemem jest konieczność opracowania prawidłowego projektu

obiektów i konstruktorów. Jeśli konstrukcja klasy zmusza programistę do „ręcznego” inicjo-

wania atrybutów przed ich użyciem lub też zachowania określonej kolejności inicjowania

atrybutów, prowadzi to do powstania zagmatwanego i nieczytelnego kodu. Programowanie

zorientowane obiektowo pozwala uniknąć takich sytuacji. Jeśli klasa zostanie zaprojekto-

wana w sposób nie wykorzystujący konstruktora do inicjacji kluczowych atrybutów, pro-

jekt taki uznajemy za nieprawidłowy. Uważaj, aby nie wpaść w tę pułapkę.

Dobrze zaprojektowana klasa może nam zaoszczędzić wielu problemów w trakcie pro-

gramowania, usuwania błędów i rozwijania projektu.

Przyjrzyjmy się ogólnej składni definicji klas w PHP, demonstrującej wykorzystanie trzech

typów komponentów:

Page 22: PHP4. Zaawansowane programowanie

130 PHP4. Zaawansowane programowanie

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

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

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

�������

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

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

����!����"�����������#$��

����%

����!����"���&������#$��

����%

����!����"���&������#$��

����%

���

����!����"���&������#$��

����%

%

Jak widać, klasa jest po prostu zestawem definicji atrybutów (zmiennych) i metod (funkcji).

Atrybuty mogą być zmiennymi typów prostych, takich jak liczby czy napisy, lub bardziej

złożonych, jak tablice czy inne obiekty. Ponieważ PHP nie wymaga definicji typów, wy-

starczy po prostu wymienić nazwy atrybutów na początku definicji klasy, tak jak w powyż-

szym przykładzie.

PHP umożliwia tworzenie nowych atrybutów w metodach w trakcie wykonania programu

i będą one działać prawidłowo. Jest to jednak uważane za zły nawyk programistyczny. Inni

programiści powinni podczas analizy kodu poznać wszystkie atrybuty klasy na podstawie

definicji klasy bez konieczności zagłębiania się w szczegóły implementacji metod.

Metody stanowią wszelkie usługi udostępniane przez tę klasę jej klientom. Klientami mogą

być inne programy, obiekty, skrypty itd.

Utwórzmy kod dla klasy ��������. W tym przykładzie rozpoczynamy definicję klasy, uży-

wając słowa kluczowego �����. Za dobrą praktykę programistyczną uważa się rozpoczynanie

wszystkich nazw klas z wielkich liter, w celu odróżnienia ich od nazw zmiennych i funkcji.

Programiści przestrzegają tej zasady od lat. Dzięki temu łatwo jest odróżnić konstruktor od

innych metod w klasie. Innym dobrym zwyczajem jest nazywanie plików tak samo, jak

klasy, na przykład Samochod.php. Pojedynczy plik powinien zawierać definicję tylko jed-

nej klasy. Jeśli masz wiele klas odwołujących się wzajemnie do siebie — tworzą kolekcję

klas, powinieneś umieścić je w katalogu głównym swojej aplikacji. W przypadku dużych

projektów taki zwyczaj staje się wymogiem.

Gdy projekt się rozrośnie, konieczne stanie się wykorzystanie struktury drzewiastej

w celu przechowywania klas wykorzystywanych w aplikacji. Będziesz zmuszony do wy-korzystania dyrektyw include_once() lub require_once(), aby włączyć pliki definicji tych

klas do swoich skryptów.

Page 23: PHP4. Zaawansowane programowanie

Rozdział 5. � Programowanie obiektowe w PHP4 131

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

W nieprawdopodobnie prostym modelu samochodu klasa składa się z silnika i stacyjki rozrusz-

nika służącej do uruchomienia pojazdu. Prawdziwy samochód będzie składał się z nadwozia,

drzwi, pedałów gazu, sprzęgła, hamulca, kierownicy, skrzyni biegów i wielu, wielu innych

elementów. W naszym przypadku chodzi jednak jedynie o demonstrację:

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

Nasz samochód również posiada konstruktor inicjujący silnik i stacyjkę. Gdybyśmy nie

zainicjowali tych elementów, każde użycie metod ������� lub ������ zakończyłoby się

błędem. Jak wspomnieliśmy wcześniej, zadaniem konstruktora jest zainicjowanie wszystkich

elementów obiektu w celu zapewnienia, że wszystkie usługi będą mogły zostać wykorzy-

stane wtedy, gdy będą potrzebne.

Aby odwołać się do atrybutu, należy użyć konstrukcji ����� ! przed nazwą atrybutu. Jest to

różnica w porównaniu z Javą i C++, gdzie takie odwołanie do obiektu klasy jest opcjonal-

ne. PHP wymaga tego zapisu, ponieważ język ten nie jest dobrze wyposażony w obsługę

zakresów widzialności zmiennych. W PHP istnieją trzy poziomy przestrzeni nazw, w któ-

rych przechowywane są zmienne (przestrzeń nazw jest, ogólnie rzecz biorąc, kolekcją nazw

zmiennych).

Na najniższym poziomie występuje przestrzeń nazw używana w celu przechowywania lo-

kalnych zmiennych funkcji i metod. Każda zmienna definiowana na tym poziomie jest do-

dawana do lokalnej przestrzeni nazw. Kolejna przestrzeń nazw zawiera atrybuty obiektów.

Przestrzeń nazw najwyższego poziomu jest używana do przechowywania zmiennych glo-

balnych. Konstrukcja ����� ! wskazuje, że odwołujemy się do zmiennej z przestrzeni nazw

obiektu (środkowa warstwa). Jeśli zapomnisz zastosować zapis ����� !, utworzysz zupeł-

nie nową zmienną w lokalnej przestrzeni nazw. Ponieważ będzie ona odwoływać się do zu-

pełnie innej wartości, mogą powstać trudne do wychwycenia błędy logiczne.

Koniecznie uaktywnij opcję raportowania błędów, którą omówimy w następnym rozdziale.

Dodatkowo dodaj kilka asercji, aby zabezpieczyć się przed tym błędem, tak powszech-

nym przy pracy z klasami.

Metoda ������� uruchomi samochód użytkownikowi posiadającemu kluczyk, jeśli kluczyk

ten jest właściwy.

����������������������������������� !��������"��#$�%$�� �������������������� !�� ����"��#$��� ������&

��������������� �'��������������� �'�� !�����#������ !�����������

Page 24: PHP4. Zaawansowane programowanie

132 PHP4. Zaawansowane programowanie

������������ !�� ��� !����������������#��������#�����&�����#������� �#�&

Metoda ������ sprawdza, czy silnik działa, i jeśli tak, zatrzymuje samochód. Zauważmy, że

sprawdzenie stanu uruchomienia samochodu mogłoby zostać przeniesione do metody ������

obiektu silnika, co zwolniłoby nas z konieczności obsługi tego przypadku. Projektując klasy,

często napotkasz takie rozterki dotyczące umiejscowienia logiki obiektów. Podejmowanie

właściwych decyzji projektowych jest podstawą dobrego i skutecznego tworzenia aplikacji.

�������������������������� !�� ��� !�����#����������������� !�� ��� !����������&&������#��#���(������'��)���*�)�+�����,����(����'���������&�!

Teraz przedstawimy, w jaki sposób można stosować obiekty w programach.

Obiekty

Obiekt w programie jest egzemplarzem klasy. Obiekty nazywamy egzemplarzami, ponie-

waż można utworzyć wiele obiektów (czyli egzemplarzy) tej samej klasy — tak jak na dro-

dze może być wiele samochodów tego samego typu. Aby utworzyć dwa nowe samochody,

musimy wykonać następujące dwa wiersze kodu:

�����������-�"��#$���������������.�"��#$���������

W celu utworzenia nowego egzemplarza klasy (to znaczy utworzenia obiektu) używamy

słowa kluczowego ��. Odwołania do nowo utworzonych obiektów zostają umieszczone

w zmiennych ���������� oraz ���������". Mamy więc dwa obiekty samochodów, których

możemy użyć. Gdybyśmy chcieli utworzyć dziesięć samochodów, moglibyśmy użyć tablicy

obiektów:

��������"����������������"�/�������-/����00��������������1��2�"��#$���������&

Gdy zechcemy uruchomić samochód, wywołujemy jego metodę ������� w następujący

sposób:

������3��������"������� !���������� �'��������������3���������#��4����5��'���)����������4��

Page 25: PHP4. Zaawansowane programowanie

Rozdział 5. � Programowanie obiektowe w PHP4 133

A gdy zechcemy zatrzymać samochód, piszemy:

������ !�������!

Zauważ, że interfejs naszego obiektu jest łatwy w użyciu. Nie musimy martwić się o to, jak

został zaimplementowany. Jako programista musisz tylko znać serwisy udostępniane przez

obiekt. Ten program mógłby z powodzeniem sterować procesem uruchamiania i zatrzymy-

wania silnika prawdziwego samochodu. Szczegóły kryjące się za metodami, a także atry-

butami mogą pozostać zupełnie nieznane. Koncepcja tworzenia łatwych w użyciu obiektów

doprowadza nas do tematu następnego podrozdziału, czyli hermetyzacji. Na razie zajmiemy

się jednak tworzeniem egzemplarzy obiektów z wykorzystaniem metod fabrycznych.

Metody fabryczne

Czasem wygodniej jest poprosić obiekt o utworzenie innego obiektu, zamiast samemu wy-

woływać konstruktor. Klasy udostępniające takie usługi nazywamy klasami fabrycznymi,

a metody używane do tworzenia obiektów nazywamy metodami fabrycznymi. Określenie

fabryczny wywodzi się ze skojarzenia z fabryką — instytucją wytwarzającą gotowe wyroby.

Na przykład fabrykę silników General Motors, produkującą silniki do samochodów, można

porównać z obiektem fabrycznym tworzącym obiekty określonego typu. Nie zagłębiając się

w szczegóły zaawansowanych technik obiektowych, zademonstrujemy teraz możliwe za-

stosowanie obiektów fabrycznych w tworzeniu aplikacji WWW. Można je zastosować do:

� zdefiniowania obiektu tworzącego elementy formularzy (takie jak pola tekstowe,

grupy opcji, przyciski formularzy itd.) celem umieszczenia go w formularzu

HTML. Klasa ta będzie realizować zadania analogiczne do zadań klasy dostępnej

w ramach biblioteki eXtremePHP (dostępnej na stronie http://www.extremephp.org/);

� zdefiniowania obiektu fabrycznego wstawiającego do tabeli bazy danych nowe

wiersze i zwracającego odpowiedni obiekt dostępu do danych zawartych w tym

konkretnym wierszu.

Przyjrzyjmy się teraz sposobowi definiowania klas fabrycznych na przykładzie tworzenia

obiektów #��$����� oraz #�������#���������� z poziomu klasy %������&���

���%��������� (zapożyczonej z biblioteki eXtremePHP).

W przykładzie wykorzystujemy dwa pliki zawierające klasy. Zakładamy, że zostały one

utworzone wcześniej. Plik PoleTekstowe.php zawiera kod definiujący klasę #��$�����,

natomiast Przycisk.php zawiera kod klasy #�������. Konstruktory tych klas wymagają

podania nazwy i wartości tworzonego elementu:

������� ��#6�#�4��7 #8#���$#����4���� ��#6�#�4��7�'��������4��

Dobrym zwyczajem programistycznym jest dodawanie przyrostka „Factory” na końcu na-

zwy klasy. Zachowanie tej konwencji, stosowanej powszechnie w środowisku programi-

stów wykorzystujących techniki obiektowe, pozwoli innym programistom na pierwszy rzut

oka zidentyfikować zadanie klasy:

Page 26: PHP4. Zaawansowane programowanie

134 PHP4. Zaawansowane programowanie

���9 #�#��:��� ��'�:�������� ����9 #�#��:��� ��'�:�����

Naszą pierwszą metodą fabryczną jest ������#��$�������. Metoda ta po prostu tworzy

pole tekstowe, przekazując parametry ������ oraz �������� przekazane przez klienta.

�������������$�'7 #8#���$#����'$�(��$��������������������#������#$�7 #8#���$#����'$�(��$����������&

Metoda ������#��������� zostanie zdefiniowana w podobny sposób. Warto używać podanej

przez nas (lub podobnej) konwencji nazywania metod fabrycznych (przedrostek ������),

aby jednoznacznie zasygnalizować innym programistom, że przeznaczeniem metody jest

utworzenie nowego obiektu. Taka praktyka ujednolici terminologię w tworzonych aplika-

cjach i polepszy przejrzystość kodu.

�������������$�'7�'��������'$�(��$�������������������#������#$�7�'��������'$�(��$����������&&

Teraz zamiast tworzyć egzemplarze klas #��$����� oraz #������� za pomocą operatora

��, możemy skorzystać z obiektu klasy &����%���������%������, aby dokonał tego za nas:

���*����9 #�#��$:��� ��'��"��#$�9 #�#��:��� ��'�:��������� #8#���$#;��#�"�������*����9 #�#��$:��� ��'� !��$�'7 #8#���$#�<���#<(�<=��<���� #8#���$#>�'$����"�������*����9 #�#��$:��� ��'� !��$�'7 #8#���$#�<��'$���<(�<�$� ���<�����'����%��$�#��'�"�������*����9 #�#��$:��� ��'� !��$�'7�'�����<'��$�#��'<(�<%��$�#��?����,���������'$���<���!

Utworzyliśmy egzemplarz klasy &����%���������%������, a następnie utworzyliśmy trzy

nowe obiekty z użyciem metod obiektu fabrycznego. Pierwsze dwa wywołania metody

������#��$������� powodują utworzenie pól tekstowych do wpisania imienia i nazwi-

ska. Wywołanie metody ������#��������� powoduje utworzenie przycisku z napisem

'������( ���) � ��������. W tym momencie nasza aplikacja może wykorzystać utwo-

rzone obiekty do dowolnych celów. Nie chodziło nam jednak o znaczenie aplikacji, lecz

o zastosowanie obiektów fabrycznych w aplikacjach internetowych.

Klasy fabryczne nie ograniczają się jedynie do udostępniania metod tworzących obiekty.

Można swobodnie dodawać metody, które wydają się zasadne w modelu fabrycznym, takie

jak metody wyszukujące obiekty w naszej „fabryce” czy metody usuwające, które umożli-

wiają pozbywanie się obiektów z zasobów fabryki. Decyzje dotyczące takich metod są ści-

śle uzależnione od projektu i zależą wyłącznie od projektanta aplikacji. Teraz przyjrzyjmy

się zasadom hermetyzacji i ukrywania informacji.

Page 27: PHP4. Zaawansowane programowanie

Rozdział 5. � Programowanie obiektowe w PHP4 135

Hermetyzacja (ang.Encapsulation)

Gdy zażywasz środek przeciw bólowi głowy, zwykle nie wiesz, z czego się składa. Jedyne,

co Cię interesuje, to jego działanie polegające na usunięciu bólu głowy. W podobny sposób

programiści wykorzystują obiekty. Gdy stosowaliśmy obiekt klasy ��������, nie wiedzieli-

śmy niczego o jego skrzyni biegów, układzie wydechowym czy też silniku. Chcieliśmy tylko

przekręcić kluczyk i uruchomić samochód. Umożliwienie takiego wykorzystania obiektu

powinno stać się głównym celem jego projektanta.

Wszelkie skomplikowane dane i logikę obiektu należy ukryć wewnątrz obiektu, udostępnia-

jąc jedynie ważne usługi służące do posługiwania się obiektem. W ten sposób dokonujemy

hermetyzacji skomplikowanych danych i szczegółów implementacyjnych wewnątrz obiektu.

Jeśli dokonamy tego właściwie, osiągniemy dodatkowy zysk w postaci ukrycia informacji.

Jak wspomnieliśmy wcześniej, nieświadomość istnienia oraz rodzaju atrybutów danych

przechowywanych w strukturze klasy może stanowić korzyść dla wykorzystujących ją pro-

gramistów.

Mimo że modyfikacja atrybutów obiektu jest poprawną operacją w PHP, jest to uznane

za zły nawyk programistyczny.

Zademonstrujemy kilka możliwych sytuacji, do których może doprowadzić modyfikacja

atrybutów obiektu bez korzystania z pośrednictwa interfejsu obiektu. W naszym przykła-

dzie zakładamy, że istnieje metoda ustalająca prędkość samochodu o nazwie #������

����������, która kontroluje przekroczenie prędkości 200 km/h, a także sprawdza, czy

prędkość nie jest mniejsza od zera. Załóżmy również, że konstruktor nie zainicjował silnika

i stacyjki:

���� �'���"��#$�� �'���<� �'�����7��'���<���������"��#$��������������� !�� ����"��#$��� ������

������ !��#����"�@//������� !���������� �'����

������ !�� ����"�/������� !������

Powyższy kod zawiera wiele błędów, które w konsekwencji spowodują błąd interpretera

lub, co gorsza, spowodują, że program będzie działać nieprawidłowo. W pierwszych trzech

wierszach nie utworzyliśmy kluczyka pasującego do naszego samochodu, ponieważ nie sko-

rzystaliśmy z naszego konstruktora.

Kluczyk nie jest potrzebny przed uruchomieniem samochodu, więc nie pojawią się żadne

błędy. Następnie przyjrzyjmy się fragmentowi, w którym tworzymy obiekt klasy ������.

Co stałoby się, gdybyśmy zamiast tego fragmentu wpisali ��������� !������ * �� ���

����� (zwróć uwagę na wielką literę w błędnej nazwie atrybutu ������)? Samochód rów-

nież nie działałby prawidłowo, ponieważ silnik nie zostałby zainicjowany. Oczywiście, błędy

tego typu można łatwo odnaleźć i usunąć, ale nie powinny się one w ogóle pojawić. Następ-

nie usiłujemy uruchomić samochód:

Page 28: PHP4. Zaawansowane programowanie

136 PHP4. Zaawansowane programowanie

������ !��#����"�@//������*��'��'��)�)������ �(��$����A����B�C������������������������������������ !���� 7�#����@//������� !���������� �'����

Gdy samochód zostanie uruchomiony, wystartuje z prędkością 400 km/h. Może to spowo-

dować wypadek i śmierć wielu użytkowników ruchu drogowego. Oczywiście, nie chcemy

dopuścić do wystąpienia takiej sytuacji.

Skąd samochód wie, jaki rodzaj kluczyka jest wymagany do jego uruchomienia? W tym

celu porówna nasz poprawnie skonstruowany kluczyk ze zmienną, która nie istnieje (co

w wyniku daje wartość +) i w konsekwencji spowoduje, że samochód nie uruchomi silnika.

Taki błąd nie zostanie wykryty przez interpreter, ponieważ porównujemy zmienną ��������,

nie kontrolując przynależności do klasy. Dziwną sytuacją byłoby zakupienie nowiutkiego

samochodu od dealera tylko w celu sprawdzenia, że kluczyk nie współpracuje ze stacyjką.

Na końcu sprawdźmy, co może się stać, gdy przypiszemy wartość + atrybutowi �������:

������ !�� ����"�/������� !������

Gdy wywoływana jest metoda ������, zostaje wywołany błąd wykonania, ponieważ atrybut

������ klasy �������� nie jest obiektem klasy ������, gdyż wymusiliśmy zmianę wartości

atrybutu ������� na +. Jak widać, przypisywanie wartości atrybutom bez pośrednictwa

metod klasy może spowodować wiele problemów. Gdy nad projektem pracuje wielu pro-

gramistów, należy przewidzieć sytuację, w której Twój kod będzie czytany, a nawet uży-

wany przez innych programistów.

Jaka nauka płynie z powyższego przykładu? Używanie atrybutów obiektu bezpośrednio

może mieć następujące konsekwencje:

� brak kontroli wykorzystania atrybutów w przewidywalny sposób;

� naruszenie integralności atrybutów obiektu (lub stanu obiektu) w jeden

z następujących sposobów:

� pogwałcenie zasad określających poprawne wartości danych;

� pominięcie inicjacji atrybutów;

� tworzenie zbyt skomplikowanych interfejsów;

� zmuszenie programisty do zapamiętania większej liczby informacji na temat

powiązań atrybutów z metodami;

� w przypadku ponownego wykorzystania obiektu może pojawić się potrzeba

modyfikacji atrybutów. Może to doprowadzić do ponownych błędów podczas

tworzenia nowego projektu, a właśnie tego chcielibyśmy uniknąć.

Dobrą zasadą jest takie zaprojektowanie klasy, aby udostępniała usługi realizujące

wszelkie operacje na obiekcie. Należy unikać bezpośredniej modyfikacji atrybutów

obiektu z zewnątrz i zawsze stosować techniki hermetyzacji danych, aby wykorzystać

zalety ukrywania informacji. Niektóre języki oferują techniki blokowania dostępu do

atrybutów obiektów z zewnątrz przez deklarowanie ich jako prywatne (private) lub chro-

nione (protected). W obecnej implementacji PHP nie obsługuje żadnej z tych technik,

ale na pewno pomocne okaże się przestrzeganie ustalonych zasad programistycznych.

Page 29: PHP4. Zaawansowane programowanie

Rozdział 5. � Programowanie obiektowe w PHP4 137

Dziedziczenie

Zapoznaliśmy się już z podstawowymi elementami programowania zorientowanego obiekto-

wo i z niektórymi jego dobrymi praktykami. Nadszedł czas, aby zapoznać się z mechani-

zmami udostępnianymi przez programowanie obiektowe, pozwalającymi na podejmowanie

przejrzystych strategii rozwiązywania skomplikowanych problemów.

Załóżmy, że naszym celem jest uporządkowanie i zarządzanie sklepem internetowym typu

amazon.com. Chcielibyśmy sprzedawać płyty CD, oprogramowanie, kasety VHS, płyty DVD

oraz książki. Korzystając z tradycyjnych rozwiązań opartych na funkcjach, możemy utwo-

rzyć tradycyjną strukturę do przechowywania informacji o tych mediach, na przykład:

MediumidnazwatypwMagazyniecenaocena

Oczywiście, istnieje mnóstwo różnic pomiędzy książkami, filmami, płytami CD i oprogra-

mowaniem, więc zechcemy utworzyć dodatkowe struktury przechowujące dane dla okre-

ślonych typów medium:

PlytaCDnumerSeryjnyartystaliczbaUtworownazwyUtworow

OprogramowanienumerSeryjnywydawcaplatformawymagania

FilmnumerSeryjnyczasTrwaniareżyserobsadatyp

KsiazkaISBNautorliczbaStron

Aby napisać program wypisujący elementy tablicy zawierającej nasze media, zastosujemy

następujący kod:

����������* ���'�$�#���D��.�# #�#����# #�#����"��������������'���"����������� ���E��"���������

�# #�#�� !���"�-��# #�#�� !����"�4����'��4��# #�#�� !��'$��"�47�+���$���#�$�7F7@�� �����#���� ���5$4��# #�#�� !$G�+�'���#�"�HH��# #�#�� !#���"�@I�IJ��# #�#�� !#���"�J��# #�#���12�"��# #�#��������'�� !��*��"�-.@KJH@H@H@@H������'�� !�����"�4�#��9+#�����(�������4������'�� ! �'*������"�J//������'��1�# #�#�� !��2�"������'���

Page 30: PHP4. Zaawansowane programowanie

138 PHP4. Zaawansowane programowanie

�# #�#�� !���"�.��# #�#�� !����"�4�4��# #�#�� !��'$��"�48����L��4��# #�#�� !$G�+�'���#�"�-./��# #�#�� !#���"�-K�IJ��# #�#�� !#���"�@��# #�#���12�"��# #�#���

�� !���#��#������"�H.H.J@HJ@��� !��������"�4=#$# 4��� ! �'*�3�$�$�"�-H��� ���E�1�# #�#�� !��2�"����

���$�������#�# #�#��5$�'���* ����#�����# #�#��������# #�#���������#��4>�'$�M�4����# #�#�� !��'$����4�*�!4������#��4; AC��'����$���+�'���#M�4����# #�#�� !$G�+�'���#���4�*�!4������#��4E#��M�4����# #�#�� !#�����4�*�!4������#��4N#��M�4����# #�#�� !#�����4�*�!4��

�����$������# #�#�� !������������#�<�<M��������#��4>��#���#�����M�4������ ���E�1�# #�#�� !��2 !�#��� >���4�*�!4����������#��4L����$�M�4����� ���E�1�# #�#�� !��2 !$����$����4�*�!4����������#��4O�'*����$�5$M�4������ ���E�1�# #�#�� !��2 ! �'*�3�$�$���4�*�!4����������*�#���

�������#�<���$��#<M������������$������#����������#���#���'�#�� ����+���$�������������*�#���

�����#�<�� �<M������������$������#����������#���#���'�#�� ���� �5$���������*�#���

�����#�<����'��<M������������$������#����������#���#���'�#�� �����DB#����������*�#���������&&

A jeśli zechcemy dodać jeszcze jeden typ medium? Musielibyśmy wrócić do tego kodu,

dodać jeszcze jedną instrukcję ��� i prawdopodobnie uaktualnić w podobny sposób kod

w wielu innych miejscach naszej aplikacji. Programowanie zorientowane obiektowo udo-

stępnia nam technikę zwaną dziedziczenie, która umożliwia umieszczenie szczegółów spe-

cyficznych dla poszczególnych typów obiektów w jednym miejscu, a także pozwala na

zgrupowanie cech wspólnych dla wszystkich typów obiektów. Wykorzystując tę technikę,

możemy zupełnie wykluczyć instrukcję ������ w przypadkach podobnych do rozpatrywa-

nego przez nas.

W naszym przykładzie sklepu multimedialnego możemy wyodrębnić podobieństwa pomię-

dzy rodzajami mediów w jednej klasie obiektów. Klasa taka nosi nazwę klasy macierzystej,

klasy podstawowej lub klasy nadrzędnej. W ten sposób utworzymy najbardziej abstrakcyj-

ną implementację (atrybuty i metody), która odnosi się do każdego elementu, jaki chcemy

umieścić w naszym sklepie. Poniżej przedstawiamy fikcyjną implementację klasy ,����:

Page 31: PHP4. Zaawansowane programowanie

Rozdział 5. � Programowanie obiektowe w PHP4 139

������#���#�4G;>6NE9>P4(�/���#���#�4GPQ6NE9>P4(�J�����G#������� ����G#�����������������������������'$�����������$G�+�'���#����������#������������#��������������G#��������(����'$�(��$G�+�'���#(��#��(��#������������������$G�+�'���#���/���$G�+�'���#�"�/��������������#�����/���#���"/��������������#�����G;>6NE9>P���#���"�G;>6NE9>P��������������#���!�GPQ6NE9>P���#���"�GPQ6NE9>P�������������� !���"������������������ !��'$��"����'$��������������� !$G�+�'���#�"��$G�+�'���#�������������� !#���"��#���������������� !#���"��#�������&������������������������������� !$G�+�'���# �����&��������������'������������#��4�'$�M�4�������� !��'$����4�*�!4��#��4O�'*���'����$���+�'���#M�4�������� !$G�+�'���#���4�*�!4����������#��4E#��M�4�������� !#�����4�*�!4����������#��4N#��M�4�������� !#�����4�*�!4������&�������$�,#���#��&�!

Teraz, gdy mamy zdefiniowaną klasę macierzystą, możemy zastosować słowo kluczowe

-����, aby odziedziczyć atrybuty i metody po tej klasie i zdefiniować klasę potomną klasy

,���� wyspecjalizowaną pod kątem konkretnego typu mediów, na przykład książek lub

filmów. Klasa wyspecjalizowana, powstała wskutek dziedziczenia po klasie macierzystej,

nazywana jest klasą potomną lub podklasą. Przedstawiamy klasę .������, która jest klasą

potomną klasy ,����. Pozostałe klasy można zdefiniować w podobny sposób.

Dobrą praktyką programistyczną jest tworzenie podklas na podstawie elementu, który

w przypadku podejścia proceduralnego wymuszałby wiele rozgałęzień kodu. W naszym

przykładzie jest to atrybut ����, który zmuszał nas do tworzenia rozbudowanych instrukcji

���. Wyeliminowanie tego atrybutu i utworzenie klasy na podstawie informacji, które

przechowywał, pozwoli nam znacznie ograniczyć komplikacje logiki w naszej aplikacji.

������������'������ ��������'���#R�#����G#������������*����������������� �'*������

Page 32: PHP4. Zaawansowane programowanie

140 PHP4. Zaawansowane programowanie

�����������'������(����'$�(��$G�+�'���#(��#��(��#��(���*�(������(�� �'*�����������L�B�#��#��(��*�������#�$�$�$)�$�C������������ ������'��#�(��������#����#����'�����$�C�$���A��$)����������*��5$����� !G#��������(����'$�(��$G�+�'���#(��#��(��#���������� !��*��"����*�������� !�����"������������� ! �'*������"�� �'*������&����������'��������G#����MM���'�������#��4;�S>M�4�������� !��*���4�*�!4������#��4P���M�4�������� !������4�*�!4������#��4O�'*������M�4�������� ! �'*��������4�*�!4��&����#���&�!

Gdy klasa .������ dziedziczy po klasie ,����, automatycznie zawiera atrybuty i metodyklasy macierzystej. Aby utworzyć nowy obiekt klasy .������, w jej konstruktorze stosuje-

my konstruktor klasy macierzystej ,������, a następnie inicjujemy własne atrybuty. Taki

projekt uznaje się za elegancki, ponieważ oszczędza nam inicjacji wielu atrybutów, które sąjuż inicjowane w konstruktorze klasy macierzystej. Dotyczy to w szczególności logiki kon-

trolującej poprawność danych przekazanych w argumentach konstruktora. Na przykład, war-tość atrybutu ��,������� nie powinna być mniejsza od ���, a atrybut ���� nie powinien

być liczbą ujemną. Umieszczając tę logikę w metodach klasy ,����, możemy mieć pewność,że wszystkie klasy potomne będą również miały zapewnioną tę samą integralność danych.

Zwróćmy uwagę na metodę �������� w klasie .������. Udostępniamy tutaj nową imple-mentację metody wypisującej informacje o obiekcie klasy .������. W tej nowej metodzie

wypisujemy atrybuty klasy ,���� (używając operatora wywołania metody klasy, opisanegow dalszej części rozdziału), jak również atrybuty specyficzne dla tej klasy. Nowa metoda

�������� przesłania metodę �������� klasy macierzystej ,����.

Ponieważ nasze klasy potomne posiadają wspólny interfejs udostępniony przez klasę ,����,

możemy używać ich w ten sam sposób, co powoduje, że są łatwiejsze w użyciu, a takżełatwiej jest je dalej rozwijać. Poniżej przedstawiamy kod wypisujący informacje o dwóch

obiektach: pierwszego klasy .������ i drugiego klasy /�.

�����'���"��#$�����'���/(�47�+���$���#�$�7F74(�.H(�JI�II(�@(�4--.@ @HHH @@@H4(�<�#��9+#�����<(�-/.@�������'�� !$����'������"��#$�E�� (�47�����#�9�+#4(�-I--(�-K�II(�J(�4�#��9+#�����4(�-/(����* ��>�'$3�$�$���� !$����'���

Zwróćmy uwagę, że wszystkie nasze obiekty klasy ,���� zachowują się identycznie. Udo-

stępniają metodę ��������, która nie pobiera argumentów i wypisuje informacje o odpowied-nich elementach, ponieważ obiekty „wiedzą”, jakiego są typu. Pozwala to na opracowanie

wspólnego interfejsu dla różnych typów obiektów. W jaki sposób może to pomóc nam wypisy-wać informacje o różnych elementach w naszym sklepie? Zademonstrujemy to w podrozdziale

zatytułowanym „Polimorfizm” w dalszej części rozdziału. Teraz jednak przyjrzyjmy sięjeszcze kilku interesującym zagadnieniom dotyczącym dziedziczenia.

Page 33: PHP4. Zaawansowane programowanie

Rozdział 5. � Programowanie obiektowe w PHP4 141

Operator wywołania metody klasy

Przyjrzyjmy się nowemu operatorowi oznaczanemu jako podwójny dwukropek (00), który

pozwala na wywołanie metody określonej klasy bez potrzeby tworzenia nowego obiektu.

W ten sposób dla wywoływanej metody klasy nie będzie dostępny żaden atrybut ani kon-

struktor. Składnia wywołania wygląda następująco:

��������''�����(�� ��"#$�

Powyższa instrukcja po prostu wywoła metodę klasy 1����.���� o nazwie �����%����2���.

Jeśli metoda o podanej nazwie nie istnieje w definicji klasy, interpreter PHP zasygnalizuje

błąd.

Wróćmy do przykładu klasy .������. W metodzie �������� wykorzystaliśmy wywołanie:

G#����MM$����'��

Wywołanie to wywołuje metodę �������� klasy ,����. Ponieważ nasza klasa .������ (jak

również /�, %���, ������������) dziedziczy po klasie ,����, w efekcie wykorzystujemy

metodę �������� klasy macierzystej. To spowoduje wypisanie informacji o obiekcie klasy

,����, po czym możemy uzupełnić te informacje o specyficzne dla klasy .������, wyko-

rzystując instrukcję ���.

Jeśli 1����.���� nie jest nazwą klasy macierzystej obiektu, w którym nastąpiło wywołanie,

metoda zostanie użyta w sposób statyczny, to znaczy nie będą dostępne atrybuty klasy

1����.����. To może być użyteczne w celu zgrupowania podobnych funkcji w obrębie klasy.

Możemy zdefiniować klasę ,��� definiującą metody 3������, �����, ����� oraz ��-��. Jest

to przykład banalny, niemniej jednak ilustruje możliwość grupowania funkcji, które powinny

być zgrupowane. Zamiast wywołania:

��"�� ��-�JK��

możemy zastosować klasę ,��� w następujący sposób:

��"�G���MM� ��-�JK���

Zaletą jest zgrupowanie podobnych funkcji w ramach klasy ,���, co pozwala na łatwiejszą

modyfikację kodu w późniejszym okresie. Ponadto kod staje się bardziej „zorientowany

obiektowo”, udostępniając wszelkie zalety programowania obiektowego.

Wadą takiego rozwiązania jest to, że wyrażenia będą dłuższe, ponieważ za każdym razem

musimy dodawać nazwę klasy przed nazwą wywoływanej metody.

Ponowne wykorzystanie kodu

Dziedziczenie udostępnia dobry sposób ponownego wykorzystania kodu, lecz głównym

zadaniem tej techniki jest specjalizacja klasy w wyniku dodania nowych możliwości do już

istniejących w ramach klasy macierzystej. Ponowne wykorzystanie kodu nie jest zadaniem,

do realizacji którego zostało wymyślone dziedziczenie w programowaniu obiektowym,

choć jest ono jedną z zalet specjalizacji klas. Zadaniem dziedziczenia jest udostępnienie

Page 34: PHP4. Zaawansowane programowanie

142 PHP4. Zaawansowane programowanie

możliwości wykorzystania klas potomnych w podobny sposób. Nie martw się jednak, po-

nieważ przyjrzymy się innym sposobom ponownego wykorzystania kodu w podrozdziale

zatytułowanym „Delegacja”.

Dobrą praktyką programistyczną jest niewykorzystywanie dziedziczenia wyłącznie w celu

uzyskania korzyści z ponownego wykorzystania kodu.

Wszystkie klasy potomne (takie jak /�, .������ czy %���) będą posiadały tę samą liczbę

danych i funkcji, co klasa macierzysta, lub będą posiadały dodatkowe atrybuty i metody,

niedostępne w klasie macierzystej. Innymi słowy, klasy potomne są zwykle „lepiej wypo-

sażone” w funkcje od ich klasy macierzystej.

Polimorfizm

Polimorfizm jest kolejną cechą programowania obiektowego, która pozwala na traktowanie

obiektów w jednolity sposób. Możemy wykorzystać możliwości istniejących klas, a także

dowolnych ich klas potomnych zdefiniowanych w przyszłości, pozostawiając interpreterowi

wszelkie szczegóły dotyczące różnic pomiędzy klasami. Polimorfizm powoduje, że bardzo

łatwo jest dodawać nowe klasy do systemu bez wprowadzania błędów w istniejącym kodzie.

Wróćmy do przykładu ze sklepem z artykułami multimedialnymi. Gdy użytkownik syste-

mu zażąda listy nowych artykułów, nie powinno mieć znaczenia, czy to książka, film czy

płyta CD. W tym miejscu wkracza właśnie polimorfizm. Technika ta pozwala traktować

obiekty reprezentujące wymienione media w jednakowy sposób. Nie musimy kłopotać się

sprawdzaniem typów zmiennych przy użyciu instrukcji �3 lub ������. Zadanie to pozosta-

wiamy interpreterowi PHP.

Polimorfizm jest techniką łatwą do opanowania, gdy rozumiemy już zasady dziedziczenia,

ponieważ jedynym sposobem uzyskania zjawiska polimorfizmu jest dziedziczenie. Dzie-

dziczenie pozwala na tworzenie abstrakcyjnej klasy macierzystej, a następnie implemento-

wanie metod tej klasy w klasach potomnych. W naszym przykładzie wszystkie klasy

potomne posiadają własne metody służące prezentacji informacji na ich temat. Nasza klasa

macierzysta zawiera metodę ��������, co gwarantuje nam, że wszelkie klasy potomne będą

posiadać tę samą metodę. Oto przykład:

������# #�#����"��������#$�����'�������(��#$�E������(��#$�����'�������(��#$�E����������#�����# #�#��������# #�#����������# #�#�� !$����'�������#��4�*�!�*�!4���&

Powyższy kod wypisze kolejno informacje na temat każdego obiektu medium, niezależnie

od tego, czy to jest CD, książka, czy też film lub też program komputerowy. Pomimo ist-

nienia różnic w klasach potomnych klasy ,����, możemy traktować je podobnie, ponie-

waż wszystkie posiadają metodę ��������. Interpreter PHP rozpozna sytuację i zdecyduje,

co należy zrobić.

Page 35: PHP4. Zaawansowane programowanie

Rozdział 5. � Programowanie obiektowe w PHP4 143

Przedstawiony kod demonstruje eleganckie rozwiązanie problemu wypisania listy artyku-łów w sklepie. Jest ono o wiele prostsze od rozbudowanego rozwiązania opierającego się

na technice przedstawionego wcześniej programowania proceduralnego. Załóżmy, że musimydodać klasę o nazwie ���1�.�����. Dodamy nową klasę potomną klasy ,���� i utworzymykilka obiektów nowej klasy w tablicy ������, a nasza metoda wypisania elementów nie

będzie wymagać żadnych zmian:

�# #�#���12�"��#$�+��>���� #��������#�����# #�#��������# #�#����������# #�#�� !$����'�������#��4�*�!�*�!4��&�!

Powyższy kod wypisze istniejącą listę, a także nowo utworzony obiekt klasy ���1�.�����.Zwróć uwagę na to, że nie musieliśmy wprowadzić jakichkolwiek zmian w instrukcji 3��

���. Polimorfizm umożliwia tworzenie takiego właśnie kodu, łatwego w rozbudowie i zro-zumieniu. Dziedziczenie samo w sobie posiada niewiele zalet. Używamy dziedziczenia,aby skorzystać z zalet polimorfizmu, który pozwala nam tworzyć kod przejrzysty i łatwy

w rozbudowie. Dziedziczenie nie jest tylko sposobem na ponowne wykorzystanie kodu, jakzauważyliśmy wcześniej, jest przede wszystkim sposobem na udostępnienie polimorfizmuw kodzie aplikacji. Gdy zapoznamy się z różnymi układami projektowymi, uzmysłowimy

sobie, jak wiele problemów programistycznych można rozwiązać dzięki wykorzystaniudziedziczenia i polimorfizmu.

Metody abstrakcyjne

Gdy stosujemy dziedziczenie, często klasa macierzysta definiuje metody nie zawierającekodu, ponieważ zdefiniowanie mechanizmów w postaci wspólnej dla wszystkich klas po-tomnych nie jest możliwe. Technikę taką, zwaną metodami abstrakcyjnymi, wykorzy-

stujemy, aby zaznaczyć fakt, że metoda nie zawiera kodu i programista implementującyklasy potomne musi zaimplementować mechanizmy tych metod. Jeśli metoda nie zostajeprzesłonięta (co zostało omówione w podrozdziale „Dziedziczenie”), nadal nie będzie re-

alizować żadnych zadań.

Jeśli nie zdefiniujemy metody abstrakcyjnej, a klasy potomne nie przesłonią jej, zostaniewywołany błąd wykonania zgłaszający brak metody w obiekcie. Dlatego ważne jest defi-

niowanie pustej metody w sytuacji, gdy nie chcemy lub nie możemy zdefiniować żadnegomechanizmu działania metody.

W terminologii obiektowej zdefiniowanie metody jako abstrakcyjnej z reguły wymusza

na programiście przesłonięcie jej w klasie potomnej. PHP nie obsługuje takiego wymu-szenia z powodu ograniczeń w zaimplementowanym modelu obiektowym. Osoby im-plementujące klasy potomne powinny zapoznać się z dokumentacją klas macierzys-tych, aby określić, które z metod powinny zostać przesłonięte.

Pomimo braku słów kluczowych w PHP, które definiowałyby metody abstrakcyjne, przy-jęła się notacja używana przez programistów dla wskazania metody abstrakcyjnej. Abywskazać osobie implementującej klasy potomne, że metoda jest abstrakcyjna i powinna zo-

stać przesłonięta, definiujemy ją jako pustą. W naszym przykładzie metoda abstrakcyjnajest zaznaczona pogrubioną czcionką:

Page 36: PHP4. Zaawansowane programowanie

144 PHP4. Zaawansowane programowanie

��������7��$������� ����7��$����������������#������������'$���������������7��$��������#(����'$������������������� !���#�"�����#�������������� !��'$����"����'$��������&������������*�#�';��#�������������#���������� !���#�����&������������*�#�'>�'$����������������#���������� !��'$��������&�������&������������ ����

����!����"���)��"���*"��"�����+���� "#$��%

&�!

W klasie #�������� metodę ������,������'�������� zdefiniowaliśmy jako pustą, aby

zaznaczyć, że jest to metoda abstrakcyjna. Przyczyną zdefiniowania tej metody jako abstrak-

cyjnej jest brak możliwości określenia sposobu wyliczania zarobków każdego pracownika

w jednolity sposób. Gdy w firmie istnieją różne stanowiska, takie jak dyrektorzy, handlowcy,

inżynierowie i pracownicy produkcyjni, płaca każdego z pracowników jest naliczana w inny

sposób. Przeanalizuj, w jaki sposób określamy płacę dyrektora:

������#T���#6�#�47��$�������4��

���U��#������� ����U��#����#R�#����7��$��������������#�����

�����������7��$��������#(����'$���(���#���������������7��$���MM7��$��������#(����'$������������������ !���� 7#���#���#����������&

��������������� 7#���#���#���������������������#�������/����#�����"�/�������������� !�#�����"���#���������&

������������*�#�'G�#��#'�#%��*������������������#���������� !�#���������&&�!

Metodę abstrakcyjną ������,������'�������� klasy #�������� przesłaniamy metodą

obsługującą działanie specyficzne dla dyrektorów. W naszym przykładzie po prostu zwra-

camy wartość atrybutu ����2�.

Page 37: PHP4. Zaawansowane programowanie

Rozdział 5. � Programowanie obiektowe w PHP4 145

Handlowiec może otrzymywać miesięczną pensję, ale może też otrzymywać dodatek obli-

czany na podstawie wielkości zysku, który przyniósł firmie w danym miesiącu. Poniżej

przedstawiamy implementację klasy 4��������, która realizuje powyższe założenia:

������#T���#6�#�4U��#�������4��

�#���#�4UNGV�O>P67W9G;P4(��-J��

���F��� $�#���� ����F��� $�#�#R�#����U��#���������������#����������������#��������$���AC���/���-���������$�������'#��'������ �'*��'��#����'#���$�

������������F��� $�#�����#(����'$���(���#����(����������������������������#���(��$�������'#��'������������U��#���MMU��#��������#(����'$���(���#������������������� !���� 7�#��#����#������������������� !���� L�������'#��'���$�������'#��'�������&

��������������� 7�#��#����#���������������������#������/�XX����#����!�-�����#����"�UNGV�O>P67W9G;P�������������� !��#����"����#��������&

��������������� L�������'#��'���$�������'#��'�����������������$�������'#��'����/���$�������'#��'��"�/�������������� !$�������'#��'��"��L�������'#��'������&

������������*�#�'G�#��#'�#%��*���������������#�����U��#���MM�*�#�'G�#��#'�#%��*�����0�������������� !��#����Y������ !$�������'#��'�������&&�!

W naszej klasie 4�������� wykorzystujemy mechanizmy klasy 5������ i dodajemy dwa

atrybuty, ������ oraz ����������������. Atrybut ������ określa procent od wartości

sprzedaży, który służy wyliczeniu premii doliczanej do pensji w celu obliczenia wypłaty,

natomiast ���������������� stanowi wartość sprzedaży dokonanej przez naszego han-

dlowca w miesiącu, za który obliczamy zarobki. Sposób obliczania miesięcznych zarobków

różni się więc od sposobu przyjętego dla dyrektora, dlatego inna jest też implementacja

metody ������,������'��������.

Podobnie możemy postąpić z płacami inżynierów i pracowników produkcyjnych. Poniżej

przedstawiamy przykład metody ������,������'�������� dla pracownika rozliczanego

na podstawie godzin pracy:

��������*�#�'G�#��#'�#%��*�����������#���������� ! �'*���'#���$����Z�'���Y������ !���$��%�Z�'��#�&

Page 38: PHP4. Zaawansowane programowanie

146 PHP4. Zaawansowane programowanie

Jak widać w powyższych przykładach, klasa #�������� nie może definiować logiki obli-

czania miesięcznych zarobków w klasie macierzystej, dlatego rozwiązanie tego problemupozostawiono klasom potomnym.

Adekwatność i powiązania

Omówiliśmy już sposób przechowywania danych wewnątrz obiektów, a także wykorzysta-liśmy więcej niż jedną klasę w celu rozwiązania problemu. W tym miejscu napotykamy

pojęcia adekwatności oraz powiązań klas.

Adekwatność jest stopniem dostosowania atrybutów i metod do potrzeb obiektu. Czy me-

tody i atrybuty klasy są ściśle powiązane, powodując, że obiekt jest w dużym stopniu do-

stosowany do swojego przeznaczenia, czy też obiekty tej klasy są zmuszone do realizacjisetek różnych zadań?

Niektórzy programiści nie zdają sobie sprawy z potencjału drzemiącego w programuobiektowym, choć być może są skuteczni w tworzeniu oprogramowania wykorzystującego

obiekty. Utworzenie modułu i „opakowanie” go w klasę nie wystarczy, by rozwiązanie takiebyło naprawdę zorientowane obiektowo. Obiekty tworzone w ten sposób w rzeczywistości

realizują zadania całego programu w ramach jednej klasy. Przyjrzyjmy się przykładowi,w którym pominięto implementację metod, aby zademonstrować podejście do programo-

wania obiektowego charakteryzujące się niskim poziomem adekwatności, polegające naimplementacji całości w postaci pojedynczej „klasy boskiej”. W tym przykładzie zademon-

strujemy mechanizm formularzy, który sprawdza poprawność wprowadzanych danych,wypisuje kod formularza, a także generuje kod JavaScript do obsługi formularza:

�����#����'�:��� ��'���������������� ��'#����������# #�#���:��� ��'�������������� #:��� ��'��������������� ��'��������������$�':��� ��'����&���������������9 #�#��:��� ��'������� ��'(����'$�(��$����(������*������&���������������$�'7���$��:��� ��'������� ��'���&���������������$�'7���$��9 #�#�����# #�#��:��� ��'����&�����������+#�#�����=����������# #�#���:��� ��'����&������������*�#�'��=��������9 #�#���:��� ��'���# #�#��:��� ��'����&�����������$����':��� ��'������ ��'���&�����������$����'9 #�#��:��� ��'���# #�#��:��� ��'����&��������������� ��� :��� ��'������� ��'���&&

Powyższy kod to klasa zawierająca struktury i metody przetwarzające wszystko, co mazwiązek z formularzami. W wielu spośród tych metod będzie występować instrukcja ������

z dziesięcioma lub więcej elementami, w zależności od poziomu komplikacji obsługiwa-

nych formularzy, wliczając w to kilka specjalnych kombinacji, takich jak elementy formu-larza obsługujące przesyłanie plików, wprowadzanie dat i tak dalej. Aby obsłużyć przypi-

sywanie stylu do elementów formularzy, również trzeba będzie zastosować instrukcję������. Jaka jest więc różnica między tym sposobem a rozwiązaniem proceduralnym, z dużą

ilością zmiennych globalnych zamiast atrybutów i użyciem zwykłych funkcji w miejscemetod? Absolutnie żadna.

Page 39: PHP4. Zaawansowane programowanie

Rozdział 5. � Programowanie obiektowe w PHP4 147

Jak widać w powyższym przykładzie, zastosowanie nieadekwatnych klas prowadzi do po-

wstania „klas boskich” i stanowi błędne podejście do rozwiązania problemu. Przedstawiony

przykład nie wykorzystuje zalet programowania obiektowego. Gdy projektujesz klasę, sta-

raj się ją zminimalizować tak, jakby to była funkcja. Najlepszym podejściem jest specjali-

zacja funkcji w sposób, który zapewnia jak najdoskonalszą realizację pojedynczego zada-

nia. Dokładnie ta sama zasada dotyczy obiektów. Gdy wystąpi konieczność wprowadzenia

zmian w kodzie, będziesz wiedział dokładnie, gdzie go szukać. To znacznie upraszcza pro-

ces usuwania błędu, oszczędzając nam konieczności przeglądania tysięcy wierszy kodu

w ramach pojedynczego pliku. Dlatego należy poświęcić sporo uwagi projektowi klas i od-

powiedniemu oddzieleniu logiki od danych, ponieważ tworzenie wysoce adekwatnych

obiektów jest w dalszej perspektywie bardzo korzystne.

Przenieśmy naszą dyskusję na zagadnienia związane z powiązaniami.

Pojęcie powiązań dotyczy liczby wzajemnych relacji pomiędzy dwoma lub większą liczbą

obiektów. Gdy mamy do czynienia z dwoma obiektami, które są świadome wzajemnego

istnienia, mówimy o silnych powiązaniach. Można to porównać do błędnego zdefiniowa-

nia kanałów komunikacyjnych celem wymiany informacji pomiędzy kilkoma osobami.

W tym przypadku każdy ma powiązania z prawie każdym:

A B

EC

D

Powyższy diagram przedstawia pięć obiektów, z których każdy ma powiązania z przy-

najmniej jednym z pozostałych. Strzałki określają kierunek komunikacji (jedno bądź dwu-

kierunkową). Obiekt D zawiera kod, który zakłada istnienie obiektów A, C oraz E. Podobnie

obiekty A, C oraz E zawierają kod, który zakłada istnienie obiektu D. Ponieważ obiekt D

wykorzystuje dwustronną komunikację z pozostałymi obiektami, widać od razu, że został źle

zaprojektowany. Przyjmijmy, że możemy dodać następną klasę, aby rozbić powiązania

w następujący sposób:

A B

EC

X

D

Przenosząc część zadań z obiektu D do X, zmniejszyliśmy poziom powiązań pomiędzy

obiektami w programie. Można założyć, że X jest naszym programem głównym, ponieważ

zarządza on działaniem pozostałych klas. Najprawdopodobniej obiekt D realizował dwa

zadania zamiast jednego, więc istnieje związek pomiędzy adekwatnością a powiązaniami.

Page 40: PHP4. Zaawansowane programowanie

148 PHP4. Zaawansowane programowanie

Minimalizacja liczby powiązań stanowi dobrą praktykę programistyczną. Gdy moduły są

powiązane w sposób luźny, znacznie zwiększa się nasza możliwość ich ponownego zasto-

sowania, ponieważ stają się bardziej adekwatne. Warto poświęcić wiele czasu i wysiłku

w trakcie projektowania aplikacji. Wysiłek ten opłaci się podczas pracy nad projektem re-

alizującym podobne zadania. Będzie można oszczędzić sporo czasu na tworzeniu kompo-

nentów programistycznych realizujących podobne zadania.

Pisanie adekwatnych, lecz luźno powiązanych modułów powinno być naszym nadrzęd-

nym celem podczas tworzenia kodu z założenia przeznaczonego do ponownego wyko-rzystania i rozwoju.

Modelowanie obiektowe z użyciem UML

Wszystkie języki wymagają pewnej formalizacji opisu. Diagramy klas utworzone w UML-u

(Unified Modeling Language) dają nam możliwość opisu projektów za pomocą symboli

graficzno-tekstowych zamiast fragmentów kodu. Język UML jest określany jako meta-język.

Został opracowany przez Object Management Group (http://www.omg.org/) i jest przezna-

czony do opisu różnych faz procesu projektowania i tworzenia oprogramowania. UML bar-

dzo dobrze sprawdza się jako sposób opisu projektów baz danych oraz programów zorien-

towanych obiektowo.

Zastosowanie UML-u jest doskonałym sposobem realizacji projektu aplikacji przed rozpo-

częciem pisania kodu. Etap ten umożliwia spojrzenie na poszczególne elementy projektu

w sposób niezależny od zastosowanego języka programowania, przypisanie programistom

poszczególnych elementów systemu, a także oszacowanie czasu trwania cyklu tworzenia

aplikacji. W tym podrozdziale omówimy kilka kluczowych schematów projektowych, które

pomogą w tworzeniu elastycznych i skalowalnych aplikacji internetowych. Zapoznamy się

z jednym z elementów UML-u, nazywanym diagramem klas używanym do opisu modelu

obiektowego.

Klasa jest przedstawiana w UML-u w postaci prostokąta zawierającego nazwę, atrybuty

i usługi oddzielone liniami. Podstawowy symbol klasy w UML-u wygląda następująco:

Klasaatrybut 1

...

atrybut N

metoda 1...

metoda N

Często atrybuty są pomijane, a wyliczone zostają tylko metody. To zależy od tego, jak dużo

czasu potrzebujesz na zapisanie swoich koncepcji.

Wyliczenie atrybutów wraz z metodami jest dobrą praktyką, szczególnie w przypadku

współpracy z bazami danych.

Page 41: PHP4. Zaawansowane programowanie

Rozdział 5. � Programowanie obiektowe w PHP4 149

Teraz, gdy znamy sposób modelowania prostych klas, przyjrzyjmy się sposobowi modelo-

wania bardziej skomplikowanych klas zawierających inne klasy. Nie przedstawiamy ich ja-

ko atrybuty klasy. Przedstawiamy je jako dwa diagramy klas w UML-u i łączymy je linią

z symbolem równoległoboku w następujący sposób:

Klasa 1

atrybut 1...atrybut N

metoda 1...

metoda N

Klasa 2

atrybut 1...atrybut N

metoda 1...

metoda N

Ten diagram przedstawia, że .���� " jest zagnieżdżona w .���� �. Nasz przykład klasy ��

������ można zobrazować następująco:

Kluczykpasuje()

Samochodstart()

stop()ustalPredkosc()

Silnikstart()

stop()pracuje()

Oznacza to, że �������� zagnieżdża w sobie obiekty klas �����2�� oraz ������. Wypełnione

równoległoboki oznaczają, że komponenty muszą zostać utworzone w celu prawidłowego

funkcjonowania obiektu, w którym są zagnieżdżone. Pamiętajmy, że za prawidłową inicjację

wszelkich atrybutów klasy odpowiedzialne są konstruktory. Analizując powyższy diagram,

programista widzi, jakie obiekty muszą zostać utworzone w celu udostępnienia wszelkich

usług obiektu nadrzędnego.

Możliwe jest również zastosowanie symbolu pustego (niewypełnionego) równoległoboku

w diagramie powiązań obiektów. Zastosowanie tego symbolu wskazuje, że nie ma koniecz-

ności inicjacji obiektu w celu prawidłowego funkcjonowania klasy nadrzędnej. Oto przy-

kład dodania obiektu klasy ���������/� do klasy ��������:

Samochódstart()stop()ustalPredkosc()utworzOdtawrzaczCd()

OdtwarzaczCdodtwarzaj()stop()pauza()

Nie wszystkie samochody muszą mieć zainstalowane odtwarzacze CD, więc sygnalizujemy

ten fakt, stosując symbol pustego równoległoboku. W przypadku występowania obiektów,

które nie muszą być inicjowane w konstruktorze klasy nadrzędnej, należy zastosować me-

todę fabryczną (omówioną wcześniej) służącą do utworzenia takiego obiektu, na przykład

���������������/��� w przypadku naszej klasy ��������. Różnica w stosunku do klas

������ oraz �����2�� polega na tym, że nie udostępniamy metod fabrycznych ���������

����� czy też �����������2��� w klasie ��������, ponieważ nie mają one sensu w sytu-

acji, gdy obiekty wspomnianych klas są inicjowane w konstruktorze.

Page 42: PHP4. Zaawansowane programowanie

150 PHP4. Zaawansowane programowanie

Zdarza się, że klasa „wykorzystuje” obiekty innych klas w swoich metodach, lecz ich niezagnieżdża. Na przykład możemy potrzebować klasy 5��� w celu wykonywania operacji na

znacznikach czasu systemu UNIX. Taki związek pomiędzy obiektami oznaczany jest w po-staci linii bez symbolu równoległoboku.

Kalendarz

wypisz()

Data

jestPrzed()jestPo()jestRowna()

sklonuj()pobierzDzien()pobierzDzienTygodnia()

...

Skoro poznaliśmy sposób modelowania zagnieżdżania obiektów, przejdźmy do sposobu mo-

delowania dziedziczenia. W naszym przykładzie sklepu z multimediami mieliśmy do czy-nienia z różnymi rodzajami mediów, na przykład z książkami, płytami CD czy też filmami.Utworzyliśmy klasę macierzystą o nazwie ,����, a następnie utworzyliśmy jej klasy po-

tomne w celu reprezentacji różnych typów mediów dostępnych w naszym sklepie. Abyprzedstawić związki dziedziczenia pomiędzy klasami .������, /� i innymi a klasą ,����,użyjemy symbolu wypełnionego trójkąta łączącego za pomocą linii klasę macierzystą z kla-

sami potomnymi. Oto model w UML-u dla naszego sklepu z multimediami:

Medium

kup()wypiszMedia()wypisz()

Ksiazka

wypisz()

CD

wypisz()

Oprogramowanie

wypisz()

Film

wypisz()

Warto zwrócić uwagę, że nie ma potrzeby wyliczania w diagramach klas potomnych wszyst-kich metod klasy macierzystej. Z założenia wiadomo, że wszystkie klasy potomne posia-dają metody klasy macierzystej. Dobrą praktyką jest jednak umieszczanie nazw metod klasy

macierzystej przesłoniętych w klasach potomnych, jak metoda �������� z naszego przykładu.

Gdy klasy rozrastają się, można również pominąć je dla oszczędzenia miejsca. Oczywiście,można również zastosować kolejne dziedziczenie, na przykład klasa %��� może mieć klasy

potomne o nazwach 64� oraz 565, o ile taka decyzja stanowi właściwe rozwiązanie uprasz-czające implementację. W dalszej części rozdziału zajmiemy się analizą przypadków,w których lepiej zastosować dziedziczenie oraz innych, które są lepiej reprezentowane w po-

staci zagnieżdżania obiektów. W tej chwili jednak zajmijmy się specyficznym typem zawie-rania, nazywanym delegacją.

Delegacja

Delegacja jest specyficzną odmianą zawierania się obiektów służącą ponownemu wyko-rzystaniu kodu obiektów. Gdy klasa ma za zadanie udostępnienie usługi, może po prostu

Page 43: PHP4. Zaawansowane programowanie

Rozdział 5. � Programowanie obiektowe w PHP4 151

oddelegować jej realizację obiektowi, który jest w niej zawarty i po prostu przekazać wynik.Używając delegacji, obiekt nie posiada fizycznego powiązania, jak na przykład silnik z samo-

chodem. Jedynym zadaniem obiektu zawartego w obiekcie nadrzędnym jest udostępnienieusługi w celu uproszczenia projektu obiektu nadrzędnego i uczynienia go bardziej spójnym.

Jako przykład utworzymy obiekt formularza, który wypisuje i sprawdza poprawność da-

nych formularzy WWW. Jednym z projektów mogłoby być sprawdzanie danych wewnątrz

obiektu formularza. Jednakże nie jest to najlepsze rozwiązanie. O wiele lepiej byłoby utwo-

rzyć osobną klasę obiektu sprawdzającego poprawność i wykorzystać go do udostępnienia

metod sprawdzania poprawności danych formularza, w którym obiekt kontrolny jest zawarty.

Oto diagram w UML-u ilustrujący ten przykład:

FormularzdodajElement()

dodajPrzycisk()weryfikuj()

wypisz()ustalStyl()pobierzKomunikatOBledzie()

WeryfikatorDanychdodaj()

weryfikuj()pobierzKomunikatOBledzie()

Obiekt klasy 7��3������5����� jest zawarty w obiekcie klasy %�������� i jest tworzony

w trakcie jego tworzenia. Dlaczego postępujemy w ten sposób? Załóżmy, że potrzebujemy

obiektu weryfikującego dane w innej aplikacji, na przykład w programie e-mailowym.

W innym przypadku konieczne byłoby ponowne zakodowanie mechanizmów klasy 7��3�

�����5����� w każdej nowej aplikacji. Lepiej jest utworzyć klasę 7��3������5�����, którą

można wykorzystać w każdej chwili, gdy wyda się potrzebna.

Zgodnie z naszą wcześniejszą dyskusją dotyczącą adekwatności, klasa %�������� zachowuje

się w sposób kojarzący się z klasą boską, obsługując elementy formularza, kod JavaScript,

wypisywanie formularza z uwzględnieniem formatowania i weryfikacji danych. Rozsądniej

byłoby umieścić obsługę tych zadań w osobnych klasach i po prostu delegować zadania

klasy %��������.

Kolejną ważną obserwacją jest to, że klasa %�������� jest świadoma istnienia klasy 7��3�

�����5�����, lecz klasa 7��3������5����� nie wie nic o tym, że jest zawarta w klasie %��

������. Dzieje się tak, ponieważ klasa 7��3������5����� nie posiada żadnego odwołania

do klasy %��������. Dzięki temu komunikacja pomiędzy klasami jest jednokierunkowa za-

miast dwukierunkowej. A zatem wykorzystując możliwości delegacji, zmniejszyliśmy liczbę

powiązań obiektów. Bardzo ważne jest poznanie możliwości ponownego wykorzystania

kodu, ponieważ celem programisty powinno być tworzenie adekwatnych obiektów, które są

ze sobą bardzo luźno powiązane. Przeanalizujmy poniższy przykład.

Przykład prezentuje trzy metody delegujące zadania do klasy 7��3������5�����. Pierwszą

metodą jest ����2&������, która zgłasza obiektowi klasy 7��3������5����� wartość, typ

oraz komunikat o błędzie dotyczące elementu formularza.

�Y U���#��$��# #�#��������� ��'����'+)��'��+�$#��������$� Y������������9 #�#����# #�#�������������� !# #�#���12�"��# #�#���

Page 44: PHP4. Zaawansowane programowanie

152 PHP4. Zaawansowane programowanie

���'+)�'#��#�# #�#����$�$#��������'#��������'#*��L#���������"����#���# #�#�� !$���'#��#W#+� ���#��[[�������������������������������#����# #�#�� !��������NS #�'�#��������������'#*��L#������������������������ !$#�������� !�����# #�#�� !$����(���������# #�#�� !$���'#��#W#+� ���#(��# #�#�� !��������NS #�'�#������&&

Zadaniem metody ����2&������ jest dodawanie elementów do formularza, jak również

zgłaszanie ich do weryfikacji. Innym sposobem mogłoby być utworzenie dodatkowej listy

obiektów do weryfikacji w ramach klasy %��������, lecz zdecydowaliśmy się na przekazanietego zadania obiektowi ����3������. Przyjrzyjmy się następnej metodzie przekazującej

część zadań weryfikatorowi:

�Y L#�������#�*�#�������� ��'���:������'$����$���AC����#(��#A ��$�'�����## #�#�����D�����$�#(�$���'#�$����$�������'$������ �# Y��������$#���������# #�#����������#���������� !$#�������� !$#����������&

Powyższa funkcja przekazuje zadanie weryfikacji obiektów formularza metodzie ���3�

��2�� klasy 7��3������5�����. Operacja ta spowoduje przechowanie komunikatów o błę-dach, które można wydobyć za pomocą następującej metody:

�Y L��*�$�������������*),����$�+#�#�$��#���'���$���������#���$#�����������7$�����*�C�$�$)�$����$�)D'��#�$���'�������'$�5#���$���A���� �#���'#'��#��,�$#��������� Y���������*�#�'���������NS #������������#���������� !$#�������� !�*�#�'���������NS #������&

Udostępniając interfejs na podstawie obiektu weryfikatora, obiekt klasy %�������� działajak obiekt pośredni przekazujący wykonywanie zadań swoim obiektom składowym.

Jak widać zatem, możemy tworzyć eleganckie rozwiązania częstych problemów, stosującdelegację usług do wyspecjalizowanych obiektów, i w ten sposób tworząc moduły lepiej na-

dające się do ponownego wykorzystania i dalszego rozwoju.

Analiza i decyzje projektowe

Obiekty są często projektowane w sposób sugerujący, że ich głównym zadaniem jest przecho-

wywanie danych. Taka metodologia jest nieprawidłowa w programowaniu zorientowanymobiektowo. Cechą różniącą obiekt od innych struktur danych jest umiejętność świadczenia

usług specyficznych dla obiektu. Przyjrzyjmy się przykładowi, w którym obiekt nie udo-stępnia usług, których można byłoby od niego oczekiwać:

Page 45: PHP4. Zaawansowane programowanie

Rozdział 5. � Programowanie obiektowe w PHP4 153

����7���������������R���������������������� �������������7������R(������������������� !����$Q��R��������������� !����$V���������&���������������$Q��R���������������� !R�"��R�����&���������������$V������������������� !��"��������&���������������$� ���� ����������������� !� ��"��� ������&������������*�#�'Q�������������#���������� !R�����&������������*�#�'V�������������#���������� !������&������������*�#�'� ��������������#���������� !� ������&�����������������������������������&&

Na pierwszy rzut oka wygląda to na niezłą reprezentację punktu na płaszczyźnie. Przyj-

rzyjmy się jednak możliwościom zastosowania takiej klasy:

�������"��#$�7�����/(�@/�������� !���������R�"������� !�*�#�'Q����R�0"�H.����"������� !�*�#�'V������0"�IK������� !����$Q��R�������� !����$V����������� !��������

Zastanówmy się przez chwilę, jakie problemy mogą pojawić się z wykorzystaniem takiego

kodu. Mimo że pozornie wszystko jest w porządku, po głębszym zastanowieniu można wy-

kryć problemy. Dlaczego nasz kod podejmuje decyzje w imieniu obiektu? Dlaczego stosu-

jemy operacje typu �- * �- 8 �", skoro powinien robić to sam obiekt? Czy obiekt nie po-

winien umieć dokonywać operacji na swoich atrybutach? Przykładowa klasa nie została

zdefiniowana prawidłowo, ponieważ nie wykorzystuje osadzania. Poniżej przedstawiamy

lepszą definicję klasy #����:

����7���������������R���������������������� ��

Page 46: PHP4. Zaawansowane programowanie

154 PHP4. Zaawansowane programowanie

�����������7������R�"/(����"�/���������������� !��'#���U��R(���������&�������������'#���U��R(������������������� !R�"��R�������������� !��"��������&�������������'#���Q��$�������������������� !R�0"��$���������&�������������'#���V��$���������������� !��0"���$���������&�������������'#�����$����Q(��$����V���������������� !��'#���Q��$����Q��������������� !��'#���V��$����V������&���������������$� ���� ����������������� !� ��"��� ������&�����������������������������������&&

Zobaczmy, jak bardzo uprościł się nasz kod i w jaki sposób osiągnęliśmy hermetyzację

obiektu. Wykorzystanie klasy jest podobne jak w poprzednim przykładzie:

�������"��#$�7�����/(�@/�������� !��'#����H.(�IK�������� !��������

Szczegóły implementacji zostały ukryte, a obiekt podejmuje samodzielne decyzje. Stosując

się do podobnych zasad zwiększających hermetyzację wszystkich obiektów w programie,

osiągamy większą czytelność i możliwość łatwiejszego dokonywania zmian w programie.

Funkcje PHP obsługujące klasy

PHP udostępnia szereg funkcji upraszczających pracę z obiektami i klasami. Niektóre z tych

funkcji pozwalają uniknąć niektórych problemów w przypadku konieczności wykorzysty-

wania kiepskich projektów obiektowych.

get_class()

���"�,�,��-�����#���������$

Funkcja ���������� zwraca nazwę klasy obiektu. Szczególnie użyteczna jest podczas pro-

cesu wyszukiwania i usuwania błędów, umożliwiając sprawdzenie, czy w programie biorą

udział właściwe obiekty. Na przykład, gdy posiadamy metodę oczekującą obiektu klasy

9���������, możemy zastosować tę funkcję w celu usprawnienia wyszukiwania błędów:

Page 47: PHP4. Zaawansowane programowanie

Rozdział 5. � Programowanie obiektowe w PHP4 155

������������'������'���$�������������#���+#�6 ������'���$�����""�<�'���$���<�������������#� !$��'�� �""������ !$���+���L��'�� ������������#��������#�����&�����#������� �#�&

Funkcja ���������� umożliwia weryfikację poprawności danych i jest użyteczną alterna-

tywą funkcji �����2���� sprawdzającej, czy argument jest obiektem klasy. Taka możli-wość pozwala na zaoszczędzenie czasu podczas usuwania błędów w aplikacjach wykorzy-

stujących wiele powiązań pomiędzy obiektami różnych klas.

Należy zwrócić uwagę na fakt, że PHP zamienia nazwy klas na małe litery, należy więc

w porównaniach stosować nazwy klas składające się z małych liter. W naszym przykładzie po-równywaliśmy wynik działania funkcji ���������� z napisem ���������� zamiast 9���������.

Porównanie z napisem 9��������� dałoby wynik negatywny, ponadto wywołałoby błąd asercji.

get_parent_class()

���"�,�,��-)�����-�����#���������$

Funkcja ta jest szczególnie użyteczna podczas sprawdzania poprawności kodu wykorzy-stującego mechanizmy polimorfizmu. Nie będzie potrzebna w ostatecznej wersji aplikacji,

ponieważ w tym przypadku wszystkie obiekty powinny być egzemplarzami klas potom-nych prawidłowo skomponowanych klas macierzystych. Jeśli założenie takie nie jest speł-

nione, tworzona aplikacja zawiera poważne błędy koncepcyjne. Oto fragment kodu kon-trolnego w metodzie polimorficznej:

�������$����'L�'��������������#��������� !# #�#���������# #�#����������������#���+#�6���#��6 �����# #�#����""�<# #�#��<�����������# #�#�� !���� ���������&�����#������� �#�&

Funkcja oczekuje tablicy elementów będących egzemplarzami klas potomnych klasy &����i w kolejności wypisuje je na wyjście. Program stosuje asercję zakładającą przynależność

każdego elementu do klasy potomnej klasy &����. Kod podobny do powyższego może oka-zać się użytecznym w trakcie usuwania błędów, lecz powinien być wyłączany w środowisku

produkcyjnym. Więcej informacji na temat usuwania błędów znajdziesz w rozdziale 6.

Ograniczenia PHP

Jak wspomnieliśmy wcześniej w tym rozdziale, implementacja technik zorientowanych

obiektowo w PHP posiada swoje ograniczenia. W tym podrozdziale omówimy najczęściejwspominane ograniczenia PHP, takie jak brak atrybutów statycznych, brak destruktorów

oraz brak wielokrotnego dziedziczenia.

Page 48: PHP4. Zaawansowane programowanie

156 PHP4. Zaawansowane programowanie

Brak atrybutów statycznych

PHP udostępnia programistom operator wywołania metody klasy (wspomniany w podroz-

dziale dotyczącym dziedziczenia) umożliwiający statyczne wywoływanie metod. Niestety,język ten nie udostępnia statycznych atrybutów. Czym jest atrybut statyczny? Jest to zmienna

globalna przywiązana do przestrzeni nazw klasy (w przeciwieństwie do przestrzeni nazwobiektu). Oznacza to, że jest to pojedyncza zmienna używana przez wszystkie egzemplarze

klasy, nie zaś unikalna dla każdego z egzemplarzy.

Do czego są potrzebne atrybuty statyczne? Czasem wygodniej jest używać jednego zestawu

danych we wszystkich obiektach tej samej klasy, zamiast stosować je wielokrotnie w każ-

dym egzemplarzu, oszczędzając w ten sposób pamięć. Drugi powód stosowania atrybutówstatycznych to kontrola stanu jakiegoś atrybutu, jednolitego dla wszystkich obiektów klasy,

jak na przykład liczba obiektów klasy istniejących w danym momencie.

Wiele języków, na przykład Java, obsługuje atrybuty statyczne, jednak PHP nie posiada takiej

własności. Można jednak zasymulować tę obsługę, stosując kombinację zmiennych global-nych i metod statycznych. Przyjrzyjmy się zastosowaniu takiej techniki na przykładzie klasy

:����� wykorzystującej symulację atrybutu statycznego w celu śledzenia liczby egzemplarzyklasy istniejących w pamięci:

����������* ����� ����=�* ���������#��%�#�'�#�

Konstruktor klasy :����� zawiera kod zwiększający o jeden wartość zmiennej globalnej

�������:����, co odzwierciedla fakt utworzenia nowego jabłka.

�����������=�* �������������+ *� �� �'*�=�* #����������� �'*�=�* #�00�������������� !�#��%�#�'�#�"��� �#�����&

Z kolei metoda �2���� zmniejsza o jeden wartość zmiennej globalnej �������:����:

�����������'�#�'����������������\����� !�#��%�#�'�#�����������������+ *� �� �'*�=�* #��������������� �'*�=�* #� ������������������ !�#��%�#�'�#�"����#���������&����&

������������#��%�#�'�#�������������#���������� !�#��%�#�'�#�����&

Zwróć uwagę, że zmienna globalna zostanie zmniejszona wyłącznie w przypadku, gdy jabłko

nie zostało jeszcze zjedzone. Pozwala to na zachowanie spójności emulowanego atrybutustatycznego. Na końcu definiujemy metodę �������� zwracającą liczbę istniejących w pa-

mięci obiektów klasy :�����:

Page 49: PHP4. Zaawansowane programowanie

Rozdział 5. � Programowanie obiektowe w PHP4 157

��������#���������'������������� �'*�������������+ *� �� �'*�=�* #�����������#������ �'*�=�* #������&&

��-�"��#$�=�* ������������$���� �'*�=�* #�����-��.�"��#$�=�* ������������$���� �'*�=�* #�����.��H�"��#$�=�* ������������$���� �'*�=�* #�����H#��=�* �MM �'*������4�*�!4������$������#�H��- !'�#�'�����������$���� �'*�=�* #�����.��. !'�#�'�����������$���� �'*�=�* #�����-��@�"��#$�=�* ������������$���� �'*�=�* #�����.#��=�* �MM �'*������4�*�!4������$������#�.�!

Mimo że stosowanie zmiennych globalnych jest powszechnie uważane za nieeleganc-kie, zastosowanie tej metody w celu zasymulowania atrybutu statycznego w PHP jest

całkiem efektywne.

Po wywołaniu powyższego kodu przeglądarka wyświetli liczby � oraz ", zgodnie z komenta-

rzami w powyższym kodzie. Emulowanie atrybutów statycznych to użyteczna technika,

lecz należy być świadomym problemów związanych z jej stosowaniem:

� technika ta nie zabezpiecza zmiennych przed modyfikacją „z zewnątrz”

bez wykorzystania do tego celu metod statycznych, co w konsekwencji

może doprowadzić do zaburzenia integralności atrybutu z klasą;

� atrybut nie jest w rzeczywistości związany z klasą, co utrudnia innym

programistom orientację i wymaga zastosowania większej liczby komentarzy

w celu zaznaczenia wykorzystania atrybutu statycznego;

� inne obiekty mogą bez problemu zamazać (usunąć) zawartość zmiennej globalnej,

jeśli nie są świadome wykorzystania jej w charakterze atrybutu statycznego.

Wymienione problemy są typowe dla stosowania zmiennych globalnych, więc symulowa-

nie atrybutów statycznych za pomocą zmiennych globalnych nie stanowi wyjątku.

Brak destruktorów

Konstruktory inicjują stan obiektów tak, aby można było z nich korzystać natychmiast po

utworzeniu. Inną koncepcją programowania zorientowanego obiektowo jest pojęcie destruk-

tora, używanego do usuwania atrybutów obiektu, w tym zagnieżdżonych obiektów, lub też

wykonania innych czynności związanych z kończeniem działania obiektu, jak na przykład

zamykania połączenia z bazą danych. W PHP nie istnieje możliwość likwidowania obiek-

tów w ten sposób. Zamiast tego PHP po prostu usuwa z pamięci obiekty utworzone przez

skrypt w momencie zakończenia działania skryptu.

Page 50: PHP4. Zaawansowane programowanie

158 PHP4. Zaawansowane programowanie

Brak wielokrotnego dziedziczenia

Wielokrotne dziedziczenie umożliwia jednoczesne dziedziczenie atrybutów i metod klasy

po kilku klasach macierzystych. Na przykład istnienie klas ;������ oraz 5������ umoż-

liwia utworzenie klasy potomnej 5������$�������� dziedziczącej po obu wspomnianych

klasach.

W PHP nie można zdefiniować dziedziczenia atrybutów oraz metod po więcej niż jednej

klasie macierzystej za pomocą słowa kluczowego -����. W przeciwieństwie do PHP, inne

języki, na przykład C++, umożliwiają wielokrotne dziedziczenie. Podobnie jak ma to miej-

sce w przypadku atrybutów statycznych, możemy emulować pożądane mechanizmy, w tym

przypadku stosując kombinację dziedziczenia i delegacji. Sztuczka polega na dziedziczeniu

po jednej klasie, natomiast możliwości pozostałych klas osiągniemy, definiując metody

delegujące zadania do metod obiektów zagnieżdżonych. Takie rozwiązanie nie jest optymalne

w przypadku, gdy liczba klas, po których chcemy dziedziczyć, jest duża, lecz w przypadku

dziedziczenia po dwóch, trzech klasach może wydać się dobrym rozwiązaniem.

Oto przykład klasy 5������$�������� będącej przykładem zastosowania powyższej tech-

niki symulacji wielokrotnego dziedziczenia po klasach ;������ oraz 5������:

�����������#������� ����U��#�����������������#(����'$���������������U��#��������#(����'$��������������� !���#�"�����#���������� !��'$����"����'$��������&�����������'��'��'��7��$����#������$��������������������'��'D�'��D�����$����#����������������&������������ �7��$���$������$�����������������������$��)���D���#���,����$���$����������������&&�!

Nie ma tu na razie nic nadzwyczajnego. Ta klasa macierzysta zawiera dwie metody umoż-

liwiające dyrektorowi zarządzanie pracownikami oraz wypłacanie im pensji, czyli to, czego

nie robią inżynierowie.

����������'���#����� ����;�'���#���������������#(����'$���������������;�'���#������#(����'$���(����'��;�'���#�������������� !���#�"�����#���������� !��'$����"����'$��������&

Page 51: PHP4. Zaawansowane programowanie

Rozdział 5. � Programowanie obiektowe w PHP4 159

��������������#���������#���������������������'������D�����#�����B���#�$�����&

������������*�#�'W�'��;�'���#������������������#���������� !��'��;�'���#�������&&�!

Klasa ;������ udostępnia metodę definiującą projekty prowadzone przez inżyniera. Chcączdefiniować klasę implementującą dyrektora technicznego, oczekujemy, że będzie zarzą-

dzał inżynierami, zatwierdzał ich listy płac i rozdzielał im projekty. Zastosujmy więc nasząsztuczkę z dziedziczeniem i delegacją, aby zasymulować wielokrotne dziedziczenie.

����� ����U��#���8#���'���#R�#����U��#����������������'���#�

Klasa 5������$�������� dziedziczy po klasie 5������, więc zawiera te same atrybuty oraz

metody co klasa macierzysta. Aby udostępnić mechanizmy klasy ;������, zagnieździmyklasę ;������ wewnątrz klasy 5������$��������, a w konstruktorze umieścimy inicjację

tego obiektu:

�����������U��#���8#���'�������#(����'$���(����'��;�'���#�������������U��#���MMU��#��������#(����'$������������������ !��'���#��"��#$�;�'���#������#(����'$���(����'��;�'���#��������&��������������#���������#������������������ !��'���#� !���#���������#��������&������������*�#�'W�'��;�'���#���������������#���������� !��'���#� !�*�#�'8��;�'���#���������&&����#���8#���'���"��#$�U��#���8#���'���<=��<(�<�$� ���<(�<G#������<���!

Takie rozwiązanie zapewnia wystąpienie obiektu klasy ;������ w każdym obiekcie klasy

5������$��������. Aby udostępnić metodę ���2���2��, po prostu delegujemy ją do osa-dzonego obiektu ��������:

����������#���������#�������������� !��'���#� !���#���������#���&

Aby udostępnić metodę ������<����2;���������, postępujemy podobnie:

��������*�#�'W�'��;�'���#�����������#���������� !��'���#� !�*�#�'W�'��;�'���#�����&

Dzięki temu każdy egzemplarz klasy 5������$�������� będzie udostępniać metody obu

klas. Zastosowanie przedstawionego sposobu znacznie się komplikuje, gdy chcemy jedno-cześnie dziedziczyć po większej liczbie klas, dlatego bardzo trudno byłoby tworzyć nowe

Page 52: PHP4. Zaawansowane programowanie

160 PHP4. Zaawansowane programowanie

klasy i dziedziczyć po różnych kombinacjach klas. Podana przez nas metoda powinna być

stosowana z rozwagą, ponieważ mamy nadzieję, że w przyszłych wersjach PHP opcja wielo-krotnego dziedziczenia będzie już dostępna.

Podana metoda może pomóc w rozwiązaniu niektórych problemów, lecz wraz ze wzro-stem liczby klas, po których chcemy dziedziczyć, kod może stać się mniej czytelny

i trudniejszy w dalszym rozwoju.

Modelowanie złożonego komponentu WWW

W tym podrozdziale zaprojektujemy mechanizm omówionego wcześniej formularza WWW.

Przy tej okazji przekażemy kilka dodatkowych sposobów realizacji struktury obiektów orazkilka układów projektowych, które mogą być użyteczne w realizowanych projektach. Zde-

finiujmy wymagania dotyczące naszego mechanizmu. Mechanizm ten powinien:

� umożliwiać tworzenie kilku formularzy na stronie;

� umożliwiać zmianę wyglądu formularzy bez modyfikacji logiki formularza;

� udostępniać jednolity interfejs służący do dodawania elementów formularza

oraz przycisków;

� udostępniać weryfikację danych po stronie użytkownika (z użyciem JavaScriptu)

oraz weryfikację po stronie serwera (z użyciem wyrażeń regularnych);

� udostępniać kilka standardowych definicji weryfikacji najczęściej spotykanych

danych, na przykład adresów e-mail;

� umożliwiać wypisywanie etykiet wymaganych pól pogrubioną czcionką;

� umożliwiać ponowne wypisanie formularza z zaznaczeniem błędnie wypełnionychelementów;

� automatycznie wypisywać błędy, bez formatowania;

� wykonywać wszystkie wymienione wyżej zadania za pomocą pojedynczego

skryptu PHP.

Na pierwszy rzut oka może wydawać się, że realizacja powyższych zadań wymaga utwo-rzenia skomplikowanego modułu. Jednak dzięki odpowiedniemu projektowi architektury

możemy osiągnąć zadowalające wyniki bez wprowadzania zbędnej komplikacji. W rzeczy-wistości istnieje bardziej elastyczny projekt mechanizmu formularzy, niż ten, który chcemy

zademonstrować, jednakże wymaga on zastosowania wielu klas zewnętrznych. Celem na-szego przykładu jest zademonstrowanie wszystkich koncepcji, które przedstawiliśmy do tej

pory. Chcemy pokazać, w jaki sposób można rozwiązać problem utworzenia mechanizmuformularza WWW z zastosowaniem obiektów.

Na początku należy zdefiniować klasę %��������, ponieważ to ona jest główną klasą w na-szym mechanizmie. %�������� powinien umieć wypisać swoją zawartość, używając definicji

stylu, dodawać elementy i przyciski, tworzyć kod weryfikujący dane w JavaScripcie działającypo stronie klienta, weryfikować swoje dane po stronie serwera, a także wypisywać komuni-

kat o błędzie w przypadku problemów z weryfikacją danych.

Page 53: PHP4. Zaawansowane programowanie

Rozdział 5. � Programowanie obiektowe w PHP4 161

Następnie potrzebna nam będzie struktura obiektów modelująca wszelkie możliwe ele-

menty formularzy oraz przyciski. Zastosujemy klasę macierzystą o nazwie &����%������

��� i rozszerzymy ją za pomocą dziedziczenia tak, aby obejmowała wszystkie elementy

formularza. Takimi elementami mogą być pola tekstowe, pola daty, duże pola tekstowe, ha-

sła, pola wysyłki plików czy też listy wielokrotnego wyboru. Tworząc klasę macierzystą

&����%��������� i wykorzystując możliwości polimorfizmu, możemy dodawać dowolną

liczbę typów elementów formularza bez konieczności modyfikacji logiki definiującej wypi-

sywanie, weryfikację oraz generowanie kodu w JavaScripcie. Przyjrzyjmy się naszemu mo-

delowi obiektowemu:

ElementFormularzawypiszElementFormularza()wypisz()pobierzParametrHtml()

FormularzdodajElement()dodajPrzycisk()weryfikuj()wypisz ()generujJavaScript()ustalStyl()pobierzKomunikatOBledzie()

Tablica

elementów

formularza

GrupaPrzelacznikowdodaj()

GrupaOpcjipobierzHtml()

PoleTekstowe PoleHasła PoleUkryte PoleDaty

DużePoleTekstowe WyborPlikuListaWyborudodaj()ustalWielokrotnyWybor()

ListaWielokrotnegoWyborupobierzH tml()

Ten model wykorzystuje niemal tę samą standardową hierarchię zagnieżdżania i dziedzi-czenia, którą omówiliśmy przy okazji omawiania wcześniejszych przykładów w tym roz-dziale, z dwoma wyjątkami. Po pierwsze, schemat pokazuje, że elementy formularza nie są

zawarte w obiekcie formularza. Chociaż fizycznie elementy są składowymi formularza, za-chowują się inaczej w momencie jego utworzenia. Dodaliśmy metody ����2&������ oraz����2#��������� służące do dodawania elementów do formularza. Formularz nie posiada-

jący elementów jest nadal pełnoprawnym, choć niezbyt użytecznym obiektem klasy.

Druga komplikacja dotyczy związków zawierania oraz metody ����2�� w klasach =����7� ���� oraz =����7����������7�����. Pozwala to na dodawanie elementów do pola wyboru

w ten sam sposób, w jaki można to zrobić w przypadku formularza. Mechanizm ten jestpraktycznie przezroczysty dla programisty. Znaczenie naszego kodu polega na tym, że meto-da �������� każdej z klas potomnych klasy &����%��������� może zostać zrealizowana

w dowolny sposób. Możemy wypisać znaczniki elementów pola wyboru w dowolny spo-sób, nie naruszając żadnej z zasad opisanych w modelu dziedziczenia. Mniejsze, lecz po-dobne modele dziedziczenia możemy zdefiniować dla przycisków:

Page 54: PHP4. Zaawansowane programowanie

162 PHP4. Zaawansowane programowanie

FormularzdodajElement()dodajPrzycisk()weryfikuj()wypisz()generujJavaScript()ustalStyl()pobierzKomunikatOBledzie()

ElementFormularzawypiszElementFormularza()wypisz()

PrzyciskZatwierdzajacy PoleDaty

Tablica

elementów

formularza

Posiadamy już solidny fundament dla struktur formularzy, lecz w jaki sposób zadbać o ichatrakcyjny wygląd? Zastosujemy osobną klasę ����%���������, co pozwoli nam na dowolne

definiowanie stylu formularza. W naszym przypadku zdecydowaliśmy się na wykorzysta-nie HTML-u. Często logika prezentacji jest umieszczana w tym samym miejscu, co logikaaplikacji, lecz nie jest to dobra praktyka. Komponenty stylu lub elementy dekoracyjne po-

zwalają na umieszczenie logiki prezentacji osobno, dzięki czemu nasz obiekt jest bardziejspójny. Dodatkową korzyścią płynącą z oddzielenia elementów dekoracyjnych od logikiobiektu jest to, że można zmienić sposób prezentacji obiektu bez zmiany logiki obiektu, dzię-

ki czemu łatwiej go rozbudowywać i stosować w nowym projekcie.

W celu zdefiniowania stylu formularzy wykorzystamy możliwość delegacji. Jednym ze sto-sowanych układów projektowych jest zastosowanie zewnętrznego obiektu dekoratora.

Dzięki strukturalnej naturze języka HTML łatwo jest zrealizować taką funkcję za pomocąobiektu osadzonego. Dzięki temu diagram przepływu informacji pomiędzy obiektami jesto wiele czytelniejszy bez negatywnych efektów ubocznych, ponieważ możemy osiągnąć te

same możliwości, co w przypadku zastosowania zewnętrznego obiektu dekoratora.

Klasa ����%��������� została rozszerzona o trzy klasy potomne. Klasa ����5������� jestwykorzystywana przez konstruktor klasy %��������. Pozostałe dwie klasy reprezentują do-

wolne style, które można zastąpić własnymi, w zależności od upodobań. Dzięki takiemuprojektowi możemy tworzyć efektowne formularze, definiując nowe obiekty stylu.

����� ��' !����$��� ��#$���� :����'������������� ��' !$����'���

Oto diagram w UML-u przedstawiający formularz z komponentem definicji stylu:

FormularzdodajElement()dodajPrzycisk()

weryfikuj()wypisz()generujJavaScript()

ustalStyl()pobierzKomunikatOBledzie()

StylFormularzawypiszNaglowekFormularza()wypiszStopkeFormularza()

wypiszElementNaglowka()wypiszElementStopki()wypiszPrzyciskNaglowka()

wypiszPrzyciskStopki()

StylKlasyczny StylFantazyjnyStylDomyslny

Page 55: PHP4. Zaawansowane programowanie

Rozdział 5. � Programowanie obiektowe w PHP4 163

Jeśli chcemy zmodyfikować kolorystykę, możemy powyższy zapis zmodyfikować nastę-

pująco:

����� ��' !����$��� ��#$�>$���� ��������� ��' !$����'���

Dzięki temu nie ma potrzeby przeprowadzania jakiejkolwiek modyfikacji w ramach logiki

aplikacji.

Przedostatni element stanowi obiekt weryfikacji danych formularza. Omawiając delegację,

stworzyliśmy już odpowiednią klasę. Model obiektowy tej klasy przedstawiamy na kolej-

nym diagramie:

Formularz

dodajElement()dodajPrzycisk()weryfikuj()

wypisz()generujJavaScript()

ustalStyl()pobierzKomunikatOBledzie()

WeryfikatorDanych

dodaj()weryfikuj()pobierzKomunikatOBledzie()

pasuje()

Aby zarządzać wieloma formularzami, potrzebujmy wspomnianej wcześniej klasy ,�����

��%���������, która jest naszą ostatnią klasą. ,�������%��������� będzie narzędziem słu-

żącym do zarządzania większą liczbą formularzy i posłuży do odtwarzania kodu JavaScript.

Klasa ta działa również jako klasa fabryczna, ponieważ możemy tworzyć formularze za jej

pomocą. Oto diagram przedstawiający model obiektowy klasy ,�������%���������:

MechanizmFormularzy

utworz()wypiszKodBiliotekiJavaScript()

Formularz

dodajElement()dodajPrzycisk()weryfikuj()

wypisz()generujJavaScript()

ustalStyl()pobierzKomunikatOBledzie()

Tablicaformularzy

Powodem, dla którego obiekt klasy ,�������%��������� tworzy formularze, jest możli-

wość kontroli przezeń zależności określających kod JavaScript niezbędny do realizacji za-dań formularzy. Jest to potrzebne dla implementacji mechanizmu weryfikacji poprawności

danych po stronie klienta. W tym momencie nasz mechanizm jest już prawie ukończony.Poniżej przedstawiamy kod demonstrujący łatwość wykorzystania naszego modelu w celu

utworzenia formularza, który przedstawiliśmy wcześniej:

��#����'�:��� ��'��"��#$�G#����'�:��� ��'��������� ��'�"���#����'�:��� ��'� !��$�'�<���� ��'<(�<>�'$��:��� ��'�<(�������������������������������������������7F76�9O:(�<���<������� ��' !����9 #�#����#$�>�+ $#�:��� ��'��<;������#�+5 �#<�������� ��' !����9 #�#����#$�7 #8#���$#�<���#6��'$���<(�<<(�������������������������<;��,�����'$���<(�PO7FP(�������������������������<S�������#��������'$����<(����#�������� ��' !����9 #�#����#$�7 #3����#�<��3'���$����<(�<-<���

Page 56: PHP4. Zaawansowane programowanie

164 PHP4. Zaawansowane programowanie

����� ��' !����9 #�#����#$�7 #F�� ��<��� <(�<<(�<F��)<(�7P��LNWU(�����������������������<F��)��������)���C���,��������#��'�'�#�#��'���5$<(������������������������������������������#�������� ��' !����9 #�#����#$�7 #8#���$#�<#��� -(�<<(�<P��#��# ��� <(�9GP;O(������������������������������������������<>�#���$��)$�����#��# ��� <(���������������������������������������������#�������� ��' !����9 #�#����#$�U�'#7 #8#���$#�<���<(�<<(�<N���<(�PO7FP>3G9W;E(����������������������������������������������<S����������*�<(��� �#(����������������������������������������������������<�$�<�"!�-/(����������������������������������������������������< �<�"!�@/(��������� ��' !����9 #�#����#$�7 #U����<����6'�������#���<(�<<(��������������������������������������<U����'�������#���<(��� �#�������� ��' !����9 #�#����#$�L�*�7 ����<� ��<(�<7 ��<(��� �#����$�*��"��#$�O����L�*���<��'��6���$��<(�<�<(�<W�'������$��<(����#���$�*� !����<Z�'��$�<(�<Z<���$�*� !����<G�#��,'��<(�<G<������� ��' !����9 #�#����$�*����$�*��"��#$�O����L�# ����#+L�*���<����$���<(������$���(�<����$���<(��������������������������������������� �#���$�*� !����<7 ������<(�<7<���$�*� !����<U��#���<(�<U<���$�*� !����<;�B���#�<(�<;<���$�*� !����<P�� ����<(�<P<�&����� ��' !����9 #�#����$�*�������� ��' !����7�'������#$�7�'����%��$�#��'�����<$�� ��<(�<L�A ��<�������� ��' !����7�'������#$�7�'����%#������<$�'��<(�<L�'�AC<���

�����$�� ���""�<L�A ��<�����������#7���$�#�"������ ��' !$#����������������������#7���$�#�����������#��<$���'D���<���������������'#�$��'���#����������$�*�'�#���������������&�# �#����������#�������� ��' !�*�#�'��������NS #�'�#������������������ ��' !$����'�������������#����'�:��� ��'� !$����'��S� ��#��=�������������������#������� ��' !+#�#�����=����������������&&�# �#��������#����'�:��� ��'� !$����'��S� ��#��=�������������������� ��' !$����'�������#������� ��' !+#�#�����=������������&

Ojej, nie ma ani kawałka kodu implementacji? Co robić? Na to pytanie łatwo odpowiedzieć

— napisz to. Jeśli masz zamiar nauczyć się programowania zorientowanego obiektowo

i doceniasz koncepcje, które tutaj poznałeś, Twoim pierwszym zadaniem powinno być do-

kończenie tego modułu. Nie będzie to strata czasu, ponieważ będziesz mógł wykorzystać

ten kod w wielu programach. Pożegnaj się z tymi wszystkimi darmowymi modułami znaj-

dowanymi w Sieci i zacznij stosować elementy utworzone własnoręcznie.