Cyfroteka.pl

klikaj i czytaj online

Cyfro
Czytomierz
00578 006863 13265787 na godz. na dobę w sumie
PHP i MySQL. Projekty do wykorzystania - książka
PHP i MySQL. Projekty do wykorzystania - książka
Autor: , Liczba stron: 360
Wydawca: Helion Język publikacji: polski
ISBN: 978-83-246-2069-2 Data wydania:
Lektor:
Kategoria: ebooki >> komputery i informatyka >> webmasterstwo >> php - programowanie
Porównaj ceny (książka, ebook (-25%), audiobook).

Zaoszczędź swój czas - korzystaj z najlepszych gotowców!

Ile czasu zajmuje Ci przygotowanie formularza rejestracyjnego? Czy jest on wykorzystywany tylko raz? Popularność tandemu PHP-MySQL sprawiła, że mnóstwo powszechnie stosowanych mechanizmów ileś razy napisało wielu programistów. A wśród nich są i tacy, którzy te same mechanizmy tworzyli więcej niż raz! Czyż nie jest to klasyczny przykład marnotrawienia czasu?

Dzięki książce 'PHP i MySQL. Projekty do wykorzystania' nie zmarnujesz już ani jednej cennej minuty. Stanowi ona zbiór najpopularniejszych mechanizmów, używanych na co dzień przy tworzeniu serwisów WWW. Dzięki niej łatwo (a co najważniejsze - szybko) zaimplementujesz funkcjonalność rejestracji użytkownika, listy dystrybucyjnej czy też wyszukiwarki. Dowiesz się, w jaki sposób stworzyć forum dyskusyjne, osobisty kalendarz, galerię zdjęć czy też menedżer plików, korzystający z technologii AJAX. Po przewertowaniu tego podręcznika nie będzie stanowiła dla Ciebie problemu rejestracja zdarzeń oraz wykonywanie skryptów powłoki. Pozwoli Ci to na szybkie tworzenie nowych serwisów WWW za pomocą sprawdzonych i elastycznych mechanizmów. Jeżeli cenisz swój czas - oto Twoja lektura obowiązkowa!

Nie trać czasu - korzystaj ze sprawdzonych projektów!

Znajdź podobne książki Ostatnio czytane w tej kategorii

Darmowy fragment publikacji:

PHP i MySQL. Projekty do wykorzystania Autorzy: Timothy Boronczyk, Martin E. Psinas T³umaczenie: Daniel Kaczmarek ISBN: 978-83-246-2069-2 Tytu³ orygina³u: PHP and MySQL: Create - Modify - Reuse Format: 172×245, stron: 360 ZaoszczêdŸ swój czas – korzystaj z najlepszych gotowców! (cid:129) Korzystaj z najlepszych mechanizmów! (cid:129) Wzbogaæ stronê o praktyczne funkcjonalnoœci! (cid:129) Szybko twórz profesjonalne serwisy! Ile czasu zajmuje Ci przygotowanie formularza rejestracyjnego? Czy jest on wykorzystywany tylko raz? Popularnoœæ tandemu PHP-MySQL sprawi³a, ¿e mnóstwo powszechnie stosowanych mechanizmów ileœ razy napisa³o wielu programistów. A wœród nich s¹ i tacy, którzy te same mechanizmy tworzyli wiêcej ni¿ raz! Czy¿ nie jest to klasyczny przyk³ad marnotrawienia czasu? Dziêki ksi¹¿ce „PHP i MySQL. Projekty do wykorzystania” nie zmarnujesz ju¿ ani jednej cennej minuty. Stanowi ona zbiór najpopularniejszych mechanizmów, u¿ywanych na co dzieñ przy tworzeniu serwisów WWW. Dziêki niej ³atwo (a co najwa¿niejsze – szybko) zaimplementujesz funkcjonalnoœæ rejestracji u¿ytkownika, listy dystrybucyjnej czy te¿ wyszukiwarki. Dowiesz siê, w jaki sposób stworzyæ forum dyskusyjne, osobisty kalendarz, galeriê zdjêæ czy te¿ mened¿er plików, korzystaj¹cy z technologii AJAX. Po przewertowaniu tego podrêcznika nie bêdzie stanowi³a dla Ciebie problemu rejestracja zdarzeñ oraz wykonywanie skryptów pow³oki. Pozwoli Ci to na szybkie tworzenie nowych serwisów WWW za pomoc¹ sprawdzonych i elastycznych mechanizmów. Je¿eli cenisz swój czas – oto Twoja lektura obowi¹zkowa! (cid:129) Rejestracja u¿ytkowników w serwisie (cid:129) Zabezpieczenie przed spamem – mechanizm CAPTCHA (cid:129) Implementacja forum dyskusyjnego (cid:129) Zastosowanie listy dystrybucyjnej (cid:129) Wyszukiwanie informacji w serwisie (cid:129) Tworzenie kalendarza (cid:129) Zarz¹dzanie plikami – mened¿er plików, korzystaj¹cy z AJAX (cid:129) Prezentacja zdjêæ – galeria online (cid:129) Statystyki serwisu WWW (cid:129) Rejestracja zdarzeñ (cid:129) Wykonywanie skryptów pow³oki Nie traæ czasu – korzystaj ze sprawdzonych projektów! Spis treÊci O autorze ................................................................................................................................................... 7 O wspóÄautorze ......................................................................................................................................... 9 Wprowadzenie ..........................................................................................................................................11 Dla kogo jest ta ksiñĔka? .............................................................................................. 11 UĔywane technologie .................................................................................................... 12 Struktura ksiñĔki .......................................................................................................... 12 Czego potrzeba w trakcie lektury tej ksiñĔki? .................................................................. 13 UĔyte konwencje .......................................................................................................... 14 Kody Ēródäowe .............................................................................................................. 14 RozdziaÄ 1. Rejestracja uÑytkowników ...................................................................................................15 Plan struktury katalogów ............................................................................................... 15 Plan struktury bazy danych ............................................................................................ 16 Kod wspóäuĔytkowany ................................................................................................... 17 Klasa User .................................................................................................................. 20 CAPTCHA ..................................................................................................................... 24 Szablony ...................................................................................................................... 25 Rejestracja nowego uĔytkownika .................................................................................... 27 Wysyäanie e-maila z äñczem do weryfikacji ....................................................................... 32 Logowanie i wylogowywanie ........................................................................................... 35 Zmiana danych ............................................................................................................ 39 Zapomniane hasäa ........................................................................................................ 42 Podsumowanie ............................................................................................................ 44 RozdziaÄ 2. Forum spoÄecznoÊciowe ......................................................................................................45 Wymagania funkcjonalne wobec forum ........................................................................... 45 Projekt bazy danych ...................................................................................................... 46 Uprawnienia i operatory bitowe ...................................................................................... 47 Zmiany w kodzie klasy User .......................................................................................... 49 Kod Ēródäowy i objaĈnienia do kodu ............................................................................... 54 Dodawanie forów .......................................................................................................... 54 Dodawanie wiadomoĈci ................................................................................................ 57 4 PHP i MySQL. Projekty do wykorzystania WyĈwietlanie forów i wiadomoĈci ................................................................................... 60 Stronicowanie ......................................................................................................... 67 Awatary ....................................................................................................................... 69 BBCode ....................................................................................................................... 72 Podsumowanie ............................................................................................................ 75 RozdziaÄ 3. Lista dystrybucyjna .............................................................................................................77 Projekt listy dystrybucyjnej ............................................................................................ 77 Wybór serwera POP3 .................................................................................................... 78 Projekt bazy danych ...................................................................................................... 80 Kod Ēródäowy i objaĈnienia kodu .................................................................................... 80 Klient POP3 ............................................................................................................ 81 Plik konfiguracyjny ................................................................................................... 87 Zarzñdzanie kontem ................................................................................................ 88 Przetwarzanie wiadomoĈci ....................................................................................... 94 Przetwarzanie wiadomoĈci z podsumowaniem ........................................................... 97 Konfiguracja listy dystrybucyjnej ..................................................................................... 98 Podsumowanie .......................................................................................................... 100 RozdziaÄ 4. Wyszukiwarka ....................................................................................................................103 Projekt wyszukiwarki ................................................................................................... 103 Problemy z wyszukiwaniem peänotekstowym ................................................................. 104 Projekt bazy danych .................................................................................................... 106 Kod Ēródäowy i objaĈnienia kodu .................................................................................. 108 Interfejs administracyjny ........................................................................................ 108 Robot i indekser ................................................................................................... 114 Interfejs uĔytkownika ............................................................................................. 120 Podsumowanie .......................................................................................................... 126 RozdziaÄ 5. Osobisty kalendarz .............................................................................................................129 Projekt aplikacji .......................................................................................................... 129 Projekt bazy danych .................................................................................................... 131 Kod Ēródäowy i objaĈnienia kodu .................................................................................. 131 Widok miesiöczny kalendarza ................................................................................. 132 Kalendarz w ukäadzie dnia ...................................................................................... 136 Dodawanie i prezentowanie zdarzeþ ....................................................................... 137 Wysyäanie przypomnieþ .......................................................................................... 145 Eksport danych z kalendarza .................................................................................. 146 Podsumowanie .......................................................................................................... 150 RozdziaÄ 6. MenedÑer plików Ajax ........................................................................................................153 Projekt menedĔera plików Ajax .................................................................................... 153 JavaScript i Ajax ......................................................................................................... 155 Obiekt XMLHttpRequest ........................................................................................ 156 Kod Ēródäowy i objaĈnienia kodu .................................................................................. 159 Gäówny interfejs .................................................................................................... 159 Funkcje dziaäajñce po stronie klienta ...................................................................... 163 Funkcje dziaäajñce po stronie serwera ..................................................................... 176 Podsumowanie .......................................................................................................... 191 Spis treÊci 5 RozdziaÄ 7. Album fotograficzny online .................................................................................................193 Projekt albumu fotograficznego online ............................................................................... 193 Kod Ēródäowy i objaĈnienia kodu .................................................................................. 194 Widoki .................................................................................................................. 194 Pliki pomocnicze ................................................................................................... 202 Miniatury QuickTime ................................................................................................... 206 Zapisywanie miniaturek w pamiöci podröcznej .............................................................. 208 Podsumowanie .......................................................................................................... 209 RozdziaÄ 8. Koszyk na zakupy .................................................................................................................211 Projekt koszyka na zakupy .......................................................................................... 211 Projekt bazy danych .................................................................................................... 212 Kod Ēródäowy i objaĈnienia kodu .................................................................................. 213 Klasa ShoppingCart .............................................................................................. 213 Sposób uĔycia koszyka na zakupy .......................................................................... 217 Interfejs uĔytkownika ............................................................................................. 225 Dodawanie produktów ........................................................................................... 233 Podsumowanie .......................................................................................................... 253 RozdziaÄ 9. Statystyki witryny internetowej ......................................................................................255 Zakres gromadzonych danych ...................................................................................... 255 Projekt bazy danych .................................................................................................... 256 Gromadzenie danych .................................................................................................. 258 Kod Ēródäowy i objaĈnienia kodu .................................................................................. 260 Wykres koäowy ...................................................................................................... 261 Wykres säupkowy ................................................................................................... 264 Raport .................................................................................................................. 268 Podsumowanie .......................................................................................................... 278 RozdziaÄ 10. System grup dyskusyjnych lub blogów ...........................................................................281 Tabele ....................................................................................................................... 282 Dodawanie wpisów ..................................................................................................... 283 Generowanie kanaäu RSS ............................................................................................ 294 WyĈwietlanie wpisów .................................................................................................. 298 Dodawanie komentarzy ............................................................................................... 300 Podsumowanie .......................................................................................................... 304 RozdziaÄ 11. Skrypty powÄoki ................................................................................................................307 Projekt skryptu ........................................................................................................... 308 Ogólne wskazówki dotyczñce implementacji skryptów powäoki ........................................ 309 Kod Ēródäowy i objaĈnienia kodu .................................................................................. 311 Klasa CommandLine ............................................................................................. 311 Skrypt startproject ................................................................................................ 320 Szkielet struktury ....................................................................................................... 329 Podsumowanie .......................................................................................................... 330 RozdziaÄ 12. BezpieczeÆstwo i rejestracja zdarzeÆ ............................................................................331 Cross-site scripting ..................................................................................................... 332 Przeglñdanie ĈcieĔek .................................................................................................. 334 Wstrzykiwanie ............................................................................................................ 336 Wstrzykiwanie kodu jözyka SQL .............................................................................. 336 Wstrzykiwanie poleceþ .......................................................................................... 340 6 PHP i MySQL. Projekty do wykorzystania Säabe uwierzytelnianie ................................................................................................ 342 Rejestrowanie zdarzeþ ................................................................................................ 344 Zapobieganie przypadkowemu usuniöciu rekordów ........................................................ 346 Podsumowanie .......................................................................................................... 348 Skorowidz ............................................................................................................................................349 1 Rejestracja uÑytkowników UmoĪliwienie rejestracji kont i logowania siĊ przez uĪytkowników pozwala nadawaü witry- nom indywidualny charakter i udostĊpniaü zawartoĞü dostosowaną do konkretnych oczekiwaĔ. Tego rodzaju mechanizm uwierzytelnienia jest centralnym punktem wielu witryn spoáeczno- Ğciowych i e-commerce. Ze wzglĊdu na tak duĪą wagĊ mechanizmów uwierzytelniania pierw- szą prezentowaną aplikacją jest system rejestracji uĪytkowników. Gáówną funkcją systemu jest umoĪliwienie uĪytkownikom tworzenia kont. Czáonkowie sys- temu muszą podaü adres poczty elektronicznej, który posáuĪy do weryfikacji poprawnoĞci rejestracji. UĪytkownicy bĊdą równieĪ mogli zmieniaü hasáa i uaktualniaü adresy pocztowe, a takĪe resetowaü hasáa, gdy je zapomną. Są to caákowicie standardowe funkcje, oczekiwane przez uĪytkowników witryn internetowych. JeĞli chodzi o architekturĊ, katalog przechowujący kod Ĩródáowy powinien mieü logiczną strukturĊ. Na przykáad pliki pomocnicze i doáączane powinny znajdowaü siĊ w innym katalogu niĪ pliki dostĊpne publicznie. Ponadto dane na temat uĪytkowników powinny byü przecho- wywane w bazie danych. PoniewaĪ na rynku dostĊpnych jest wiele narzĊdzi przeznaczonych do przeglądania i przetwarzania danych przechowywanych w relacyjnych bazach danych takich jak MySQL, áatwo jest zapewniü przezroczystoĞü i elastycznoĞü rozwiązania. Plan struktury katalogów W pierwszym kroku naleĪy zaplanowaü strukturĊ katalogów aplikacji. Zaleca siĊ utworzenie trzech gáównych folderów: public_files bĊdzie przechowywaá wszystkie pliki dostĊpne publicz- nie, w lib przechowywane bĊdą pliki doáączane, wspóáuĪytkowane przez dowolną liczbĊ innych plików Ĩródáowych, w templates zaĞ znajdą siĊ pliki odpowiedzialne za prezentacjĊ stron. Choü PHP moĪe siĊ odwoáywaü do plików poáoĪonych w dowolnych lokalizacjach, ser- wer WWW powinien udostĊpniaü wyáącznie pliki z folderu public_files. Przechowywanie pli- ków pomocniczych poza katalogiem udostĊpnianym publicznie zwiĊksza poziom bezpieczeĔ- stwa witryny. 16 PHP i MySQL. Projekty do wykorzystania W folderze public_files zostanie utworzony folder css przechowujący katalogi stylów, folder js dla plików Ĩródáowych JavaScript oraz img do przechowywania plików graficznych. MoĪna utworzyü jeszcze dodatkowe foldery, aby zorganizowaü strukturĊ katalogów wedáug wáasnych potrzeb. Dodatkowymi folderami mogą byü na przykáad sql do przechowywania plików serwera MySQL, doc dla dokumentacji systemu i dokumentów implementacyjnych oraz tests do prze- chowywania plików dla testów wstĊpnych i testów jednostkowych. Plan struktury bazy danych Oprócz zaplanowania struktury katalogów konieczne jest równieĪ pochylenie siĊ nad struk- turą bazy danych systemu. Zakres zapisywanych informacji na temat uĪytkowników bĊdzie zaleĪaá od rodzaju usáug Ğwiadczonych na witrynie. To z kolei bĊdzie wyznaczaü wygląd tabel bazy danych. Minimalnym wymaganiem jest, by w bazie danych przechowywaü przynajmniej unikatowy identyfikator uĪytkownika, nazwĊ uĪytkownika, zaszyfrowane hasáo i adres poczty elektronicznej. Trzeba bĊdzie teĪ zaimplementowaü funkcje sprawdzające, które konta zostaáy juĪ zweryfikowane, a które dopiero oczekują na weryfikacjĊ. DROP TABLE IF EXISTS HELION_PENDING; DROP TABLE IF EXISTS HELION_USER; CREATE TABLE HELION_USER ( USER_ID INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, USERNAME VARCHAR(20) NOT NULL, PASSWORD CHAR(40) NOT NULL, EMAIL_ADDR VARCHAR(100) NOT NULL, IS_ACTIVE TINYINT(1) DEFAULT 0, PRIMARY KEY (USER_ID) ) ENGINE=MyISAM DEFAULT CHARACTER SET latin1 COLLATE latin1_general_cs AUTO_INCREMENT=0; CREATE TABLE HELION_PENDING ( USER_ID INTEGER UNSIGNED NOT NULL, TOKEN CHAR(10) NOT NULL, CREATED_DATE TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (USER_ID) REFERENCES HELION_USER(USER_ID) ) ENGINE=MyISAM DEFAULT CHARACTER SET latin1 COLLATE latin1_general_cs; W tabeli HELION_USER na przechowywanie zaszyfrowanego hasáa przewidziano kolumnĊ o sze- rokoĞci 40 znaków, poniewaĪ do szyfrowania haseá uĪywana bĊdzie funkcja sha1(), zwraca- jąca wáaĞnie 40-znakowy szesnastkowy ciąg znaków. Nigdy nie powinno siĊ przechowywaü w bazie danych haseá w oryginalnej postaci — jest to podstawowa zasada bezpieczeĔstwa. Zasadą dziaáania zastosowanego rozwiązania jest zaszyfrowanie hasáa, gdy zostanie ono podane przez uĪytkownika po raz pierwszy. To samo hasáo wpisywane póĨniej teĪ podlega szyfro- waniu, a wynik szyfrowania funkcją sha1() jest porównywany z zaszyfrowanym hasáem prze- chowywanym w bazie danych. RozdziaÄ 1. Q Rejestracja uÑytkowników 17 Jako maksymalną dáugoĞü ciągu znaków przechowującego adres poczty elektronicznej wyzna- czono 100 znaków. Z technicznego punktu widzenia obecnie obowiązujące standardy pozwa- lają na definiowanie adresów pocztowych o maksymalnej dáugoĞci 320 znaków (64 znaki na nazwĊ uĪytkownika, 1 znak na symbol @ i 255 znaków na nazwĊ komputera). Trudno jed- nak znaleĨü kogokolwiek, kto uĪywaáby tak dáugiego adresu pocztowego, dlatego w schema- tach baz danych adresy pocztowe standardowo przechowuje siĊ w kolumnach o szerokoĞci 100 znaków. W bazie danych moĪna by dodatkowo przechowywaü imiĊ i nazwisko uĪytkownika, jego adres, miasto zamieszkania, województwo, kod pocztowy, numery telefonów i tak dalej. W tabeli HELION_PENDING znajduje siĊ inicjalizowana automatycznie kolumna znacznika czasu. DziĊki temu w dowolnym momencie moĪna usunąü z bazy wszystkie zarejestrowane konta uĪytkownika, które przez okreĞlony czas nie doczekaáy siĊ weryfikacji. Kolumny tabeli moĪna by poáączyü z kolumnami tabeli HELION_USER, jednak ze wzglĊdu na to, Īe znacznik wskazujący koniecznoĞü weryfikacji konta jest uĪywany tylko jeden raz, zdecydowano siĊ na ich wydzie- lenie do odrĊbnej tabeli. Dane uĪytkowników są przechowywane znacznie dáuĪej, a dziĊki zastosowanemu rozwiązaniu tabela HELION_USER nie jest zaĞmiecana danymi tymczasowymi. Kod wspóÄuÑytkowany Kod, który jest wspóáuĪytkowany przez wiĊkszą liczbĊ plików, powinien zostaü wyáączony z pliku docelowego i doáączony do niego przy uĪyciu instrukcji include lub require. DziĊki temu ten sam kod nie bĊdzie duplikowany i áatwiej bĊdzie utrzymywaü aplikacjĊ. Tam, gdzie to moĪliwe, kod potencjalnie przydatny w przyszáych aplikacjach (taki jak funkcje albo klasy) powinien byü przechowywany oddzielnie. Dobrym zaáoĪeniem jest pisanie kodu z myĞlą o tym, by móc go ponownie wykorzystaü w przyszáoĞci. Plik common.php zawiera kod wspóáuĪytko- wany, który bĊdzie doáączany do innych skryptów aplikacji, aby ustanowiü w ten sposób jednolite Ğrodowisko fazy wykonania. Kod tego rodzaju nigdy nie powinien byü wywoáy- wany przez uĪytkowników bezpoĞrednio, dlatego naleĪy go umieĞciü w katalogu lib. ?php // true, jeĞli Ğrodowisko produkcyjne; w przeciwnym razie false define ( IS_ENV_PRODUCTION , true); // ustawienie opcji raportowania báĊdów error_reporting(E_ALL | E_STRICT); ini_set( display_errors , !IS_ENV_PRODUCTION); ini_set( error_log , log/phperror.txt ); // ustawienie strefy czasowej, by uniknąü ostrzeĪeĔ // w przypadku uĪycia funkcji czasu i daty date_default_timezone_set( Europe/Warsaw ); // uwzglĊdnienie „magic quotes” w razie koniecznoĞci if (get_magic_quotes_gpc()) { function _stripslashes_rcurs($variable, $top = true) { $clean_data = array(); 18 PHP i MySQL. Projekty do wykorzystania foreach ($variable as $key = $value) { $key = ($top) ? $key : stripslashes($key); $clean_data[$key] = (is_array($value)) ? stripslashes_rcurs($value, false) : stripslashes($value); } return $clean_data; } $_GET = _stripslashes_rcurs($_GET); $_POST = _stripslashes_rcurs($_POST); // $_REQUEST = _stripslashes_rcurs($_REQUEST); // $_COOKIE = _stripslashes_rcurs($_COOKIE); } ? Nie zawsze ma siĊ kontrolĊ nad konfiguracją uĪywanego serwera, dlatego dobrze jest zdefi- niowaü kilka podstawowych dyrektyw, dziĊki którym przenoszenie aplikacji bĊdzie znacznie áatwiejsze. Na przykáad zdefiniowanie opcji raportowania báĊdów pozwoli na wyĞwietlanie báĊdów w Ğrodowisku rozwojowym lub przekierowanie ich w Ğrodowisku produkcyjnym, tak by wewnĊtrzne komunikaty o báĊdach nie byáy widoczne dla uĪytkownika. Magiczne apostrofy (ang. magic quotes) to opcja konfiguracyjna, dziĊki której PHP moĪe automatycznie poprzedzaü znakami ucieczki symbole apostrofu, cudzysáowu i ukoĞników odwrotnych zawarte w danych wejĞciowych. Funkcja ta moĪe siĊ wydawaü przydatna, jednak nigdy z góry nie powinno siĊ przyjmowaü zaáoĪenia, Īe na danym serwerze jest ona wáączona lub nie, poniewaĪ moĪe to doprowadziü do káopotów. Lepiej jest najpierw znormalizowaü dane, a nastĊpnie w razie koniecznoĞci poprzedzaü je znakami ucieczki przy uĪyciu funkcji addslashes() lub mysql_real_escape_string() (jeĪeli dane mają byü przechowywane w bazie danych, zalecane jest zastosowanie drugiej ze wspomnianych funkcji). ZastĊpowanie magicz- nych apostrofów zapewni, Īe znaki ucieczki zostaną zastosowane w danych odpowiednio i we wáaĞciwym momencie, bez wzglĊdu na sposób konfiguracji PHP. DziĊki temu dalsza imple- mentacja bĊdzie prostsza i zmniejszy siĊ zagroĪenie popeánieniem báĊdów. Ustanawianie poáączenia z serwerem bazy danych MySQL jest czynnoĞcią wykonywaną powszechnie, dlatego warto przenieĞü wykonujący ją kod do oddzielnego pliku. Plik o nazwie db.php przechowuje staáe konfiguracyjne oraz kod zestawiający poáączenie z bazą danych. RównieĪ ten plik ma byü doáączany do innych plików, a nie naleĪy go wywoáywaü w sposób bezpoĞredni, dlatego naleĪy zapisaü go w katalogu lib. ?php // staáe bazy danych i schematów define( DB_HOST , localhost ); define( DB_USER , uľytkownik ); define( DB_PASSWORD , hasđo ); define( DB_SCHEMA , HELION_DATABASE ); define( DB_TBL_PREFIX , HELION_ ); // ustanowienie poáączenia z serwerem bazy danych if (!$GLOBALS[ DB ] = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD)) { die( Bđæd: Nie udađo siú nawiæzaè pođæczenia z bazæ danych. ); } if (!mysql_select_db(DB_SCHEMA, $GLOBALS[ DB ])) { RozdziaÄ 1. Q Rejestracja uÑytkowników 19 mysql_close($GLOBALS[ DB ]); die( Bđæd: Nie udađo siú wybraè schematu bazy danych. ); } ? Staáe DB_HOST, DB_USER, DB_PASSWORD i DB_SCHEMA reprezentują wartoĞci niezbĊdne do sku- tecznego zestawienia poáączenia z bazą danych. JeĪeli kod zostanie przeniesiony do Ğrodo- wiska produkcyjnego, w którym serwer bazy danych pracuje na innym komputerze niĪ PHP i serwer WWW, moĪna wówczas dodatkowo zdefiniowaü wartoĞü DB_PORT i odpowiednio zmodyfikowaü wywoáanie funkcji mysql_connect(). Uchwyt poáączenia z bazą danych jest nastĊpnie zapisywany w tablicy superglobalnej $GLOBALS, aby staá siĊ dostĊpny w dowolnym zasiĊgu kaĪdego pliku doáączającego plik db.php (albo doáączanego do pliku, który odwoáuje siĊ do db.php). DziĊki poprzedzeniu nazw tabel prefiksami moĪna uniknąü konfliktu z tabelami uĪywanymi przez inne aplikacje, przechowywanymi w tym samym schemacie. Ponadto, jeĪeli prefiks zosta- nie zdefiniowany w postaci staáej, áatwiej bĊdzie uaktualniü kod Ĩródáowy póĨniej, gdy zaj- dzie koniecznoĞü zmiany prefiksu, poniewaĪ bĊdzie on definiowany tylko w jednym miejscu. Wspólne funkcje równieĪ moĪna umieszczaü w oddzielnym, przeznaczonym dla nich pliku. W projekcie uĪyta zostanie funkcja random_text(), której zadaniem bĊdzie wygenerowanie ciągu znaków CAPTCHA i znacznika weryfikacji. FunkcjĊ random_text() moĪna zatem zapi- saü w pliku functions.php. ?php // zwrócenie ciągu losowych znaków o okreĞlonej dáugoĞci function random_text($count, $rm_similar = false) { // utworzenie listy znaków $chars = array_flip(array_merge(range(0, 9), range( A , Z ))); // usuniĊcie podobnie wyglądających znaków, aby uniknąü pomyáek if ($rm_similar) { unset($chars[0], $chars[1], $chars[2], $chars[5], $chars[8], $chars[ B ], $chars[ I ], $chars[ O ], $chars[ Q ], $chars[ S ], $chars[ U ], $chars[ V ], $chars[ Z ]); } // wygenerowanie ciągu losowych znaków for ($i = 0, $text = ; $i $count; $i++) { $text .= array_rand($chars); } return $text; } ? Bez wzglĊdu na to, w jakim jĊzyku implementuje siĊ kod Ĩródáowy, zawsze trzeba prze- strzegaü podstawowej zasady, by nigdy nie ufaü danym wpisywanym przez uĪytkowników. UĪytkownicy mogą (i bĊdą) wpisywaü wszelkiego rodzaju bezsensowne i niezrozumiaáe dane. Czasami przez przypadek, niekiedy jednak jest to dziaáanie zamierzone. Za pomocą funkcji 20 PHP i MySQL. Projekty do wykorzystania filter_input() i filter_var() jĊzyka PHP moĪna oczyĞciü dane wejĞciowe, jednak niektórzy programiĞci wciąĪ wolą implementowaü wáasne procedury, poniewaĪ rozszerzenie udostĊp- niające filtry moĪe nie byü dostĊpne w wersjach PHP wczeĞniejszych niĪ 5.2.0. Kod Ĩró- dáowy tego rodzaju wáasnych procedur równieĪ warto umieĞciü w pliku functions.php. Klasa User Znakomitą wiĊkszoĞü kodu utrzymującego konta uĪytkowników moĪna zawrzeü w ramach jednej struktury danych, którą bĊdzie moĪna póĨniej rozszerzaü albo ponownie wykorzystywaü w kolejnych aplikacjach. Struktura bĊdzie implementowaü logikĊ interakcji z bazą danych, a przez to uáatwiaü operacje zapisywania i odczytywania danych. PoniĪej przedstawiono zawartoĞü pliku User.php. ?php class User { private $uid; // identyfikator uĪytkownika private $fields; // inne pola rekordu // inicjalizacja obiektu User public function __construct() { $this- uid = null; $this- fields = array( username = , password = , emailAddr = , isActive = false); } // nadpisanie metody odczytującej wáaĞciwoĞci public function __get($field) { if ($field == userId ) { return $this- uid; } else { return $this- fields[$field]; } } // nadpisanie metody ustawiającej wáaĞciwoĞci public function __set($field, $value) { if (array_key_exists($field, $this- fields)) { $this- fields[$field] = $value; } } RozdziaÄ 1. Q Rejestracja uÑytkowników 21 // sprawdzenie, czy nazwa uĪytkownika ma wáaĞciwy format public static function validateUsername($username) { return preg_match( /^[A-Z0-9]{2,20}$/i , $username); } // sprawdzenie, czy adres e-mail ma wáaĞciwy format public static function validateEmailAddr($email) { return filter_var($email, FILTER_VALIDATE_EMAIL); } // zwrócenie obiektu wypeánionego na podstawie identyfikatora uĪytkownika public static function getById($uid) { $u = new User(); $query = sprintf( SELECT USERNAME, PASSWORD, EMAIL_ADDR, IS_ACTIVE . FROM sUSER WHERE USER_ID = d , DB_TBL_PREFIX, $uid); $result = mysql_query($query, $GLOBALS[ DB ]); if (mysql_num_rows($result)) { $row = mysql_fetch_assoc($result); $u- username = $row[ USERNAME ]; $u- password = $row[ PASSWORD ]; $u- emailAddr = $row[ EMAIL_ADDR ]; $u- isActive = $row[ IS_ACTIVE ]; $u- uid = $uid; } mysql_free_result($result); return $u; } // zwrócenie obiektu wypeánionego na podstawie nazwy uĪytkownika public static function getByUsername($username) { $u = new User(); $query = sprintf( SELECT USER_ID, PASSWORD, EMAIL_ADDR, IS_ACTIVE . FROM sUSER WHERE USERNAME = s , DB_TBL_PREFIX, mysql_real_escape_string($username, $GLOBALS[ DB ])); $result = mysql_query($query, $GLOBALS[ DB ]); if (mysql_num_rows($result)) { $row = mysql_fetch_assoc($result); $u- username = $username; $u- password = $row[ PASSWORD ]; $u- emailAddr = $row[ EMAIL_ADDR ]; $u- isActive = $row[ IS_ACTIVE ]; $u- uid = $row[ USER_ID ]; } mysql_free_result($result); return $u; } 22 PHP i MySQL. Projekty do wykorzystania // zapisanie rekordu w bazie danych public function save() { if ($this- uid) { $query = sprintf( UPDATE sUSER SET USERNAME = s , . PASSWORD = s , EMAIL_ADDR = s , IS_ACTIVE = d . WHERE USER_ID = d , DB_TBL_PREFIX, mysql_real_escape_string($this- username, $GLOBALS[ DB ]), mysql_real_escape_string($this- password, $GLOBALS[ DB ]), mysql_real_escape_string($this- emailAddr, $GLOBALS[ DB ]), $this- isActive, $this- userId); mysql_query($query, $GLOBALS[ DB ]); } else { $query = sprintf( INSERT INTO sUSER (USERNAME, PASSWORD, . EMAIL_ADDR, IS_ACTIVE) VALUES ( s , s , s , d) , DB_TBL_PREFIX, mysql_real_escape_string($this- username, $GLOBALS[ DB ]), mysql_real_escape_string($this- password, $GLOBALS[ DB ]), mysql_real_escape_string($this- emailAddr, $GLOBALS[ DB ]), $this- isActive); mysql_query($query, $GLOBALS[ DB ]); $this- uid = mysql_insert_id($GLOBALS[ DB ]); } } // oznaczenie rekordu jako nieaktywnego i zwrócenie znacznika aktywacji public function setInactive() { $this- isActive = false; $this- save(); // zapewnienie, Īe rekord jest zapisany $token = random_text(5); $query = sprintf( INSERT INTO sPENDING (USER_ID, TOKEN) . VALUES ( d, s ) , DB_TBL_PREFIX, $this- uid, $token); mysql_query($query, $GLOBALS[ DB ]); return $token; } // wyczyszczenie tymczasowego statusu uĪytkownika i oznaczenie rekordu jako aktywnego public function setActive($token) { $query = sprintf( SELECT TOKEN FROM sPENDING WHERE USER_ID = d . AND TOKEN = s , DB_TBL_PREFIX, $this- uid, mysql_real_escape_string($token, $GLOBALS[ DB ])); $result = mysql_query($query, $GLOBALS[ DB ]); if (!mysql_num_rows($result)) { mysql_free_result($result); return false; } else { RozdziaÄ 1. Q Rejestracja uÑytkowników 23 mysql_free_result($result); $query = sprintf( DELETE FROM sPENDING WHERE USER_ID = d . AND TOKEN = s , DB_TBL_PREFIX, $this- uid, mysql_real_escape_string($token, $GLOBALS[ DB ])); mysql_query($query, $GLOBALS[ DB ]); $this- isActive = true; $this- save(); return true; } } } ? W klasie zdefiniowano dwie wáaĞciwoĞci prywatne: $uid, która odpowiada kolumnie USER_ID tabeli HELION_USER, oraz tablicĊ $fields, która odpowiada pozostaáym kolumnom. Obydwie wáaĞciwoĞci są udostĊpniane intuicyjnie, poprzez nadpisanie metod __get() i __set(). Jednak wáaĞciwoĞü $uid jest nadal chroniona przed przypadkową zmianą. Statyczne metody getById() i getByUsername() zawierają kod odpowiedzialny za odczyty- wanie rekordu z bazy danych i wypeánianie obiektu danymi. Metoda save() zapisuje rekord w bazie danych i jest na tyle inteligentna, Īe rozpoznaje, kiedy naleĪy wykonaü zapytanie INSERT, a kiedy zapytanie UPDATE, zaleĪnie od tego, czy ustawiony jest identyfikator uĪyt- kownika. W celu utworzenia nowego konta uĪytkownika wystarczy stworzyü nową instancjĊ obiektu User, zdefiniowaü wartoĞci pól w rekordzie i wywoáaü metodĊ save(). ?php $u = new User(); $u- username = timothy ; $u- password = sha1( sekret ); $u- emailAddr = timothy@helion.pl ; $u- save(); ? W taki sam sposób przebiega czynnoĞü zmiany danych konta. Najpierw odczytywane są dane aktualne, nastĊpnie w danych wprowadzane są zmiany, po czym nastĊpuje ich zapisanie w bazie danych przez metodĊ save(). ?php $u = User::getByUsername( timothy ); $u- password = sha1( nowe_hasđo ); $u- save(); ? Metody setInactive() i setActive() obsáugują proces aktywacji konta. W wyniku wywo- áania metody setInactive() konto zostaje oznaczone jako nieaktywne, nastĊpuje wygenero- wanie znacznika aktywacji, informacja o tym fakcie zostaje zapisana w bazie danych i znacz- nik jest zwracany. Gdy uĪytkownik uaktywni konto, znacznik aktywacji jest przekazywany do metody setActive(). Metoda setActive() usuwa rekord ze znacznikiem aktywacji i ozna- cza konto jako aktywne. 24 PHP i MySQL. Projekty do wykorzystania CAPTCHA WyraĪenie CAPTCHA to skrót od angielskich sáów Completely Automated Public Turing Test to Tell Computers and Humans Apart, co w wolnym táumaczeniu moĪe oznaczaü Caákowicie Zautomatyzowany Publiczny Test Turinga Wskazujący Komputerom i Ludziom, by Trzymali siĊ z Daleka. CAPTCHA, oprócz tego, Īe jest trudnym do rozszyfrowania akronimem, czĊsto bywa uĪywany jako narzĊdzie powstrzymującego spamerów i innych záoĞliwych uĪytkow- ników przed automatycznym rejestrowaniem kont uĪytkowników. W tym celu uĪytkownikowi stawia siĊ zadanie, które czĊsto ma postaü obrazka zawierają- cego litery i cyfry. UĪytkownik musi odczytaü z niego tekst i przepisaü do pola tekstowego. JeĪeli obydwie wartoĞci są identyczne, moĪna zaáoĪyü, Īe system ma do czynienia z inteligentną istotą ludzką, a nie z komputerem próbującym automatycznie zaáoĪyü konto w systemie. Nie jest to jednak rozwiązanie idealne. CAPTCHA moĪe sprawiaü problemy osobom z wadami wzroku, a poza tym niektóre programy potrafią juĪ odczytywaü tekst zawarty na obrazkach CAPTCHA (wiĊcej na ten temat pod adresem www.cs.sfu.ca/~mori/research/gimpy/). Zadania CAPTCHA stawiane przed uĪytkownikami mogą mieü takĪe inną postaü. Istnieją na przykáad zadania CAPTCHA w postaci dĨwiĊkowej — uĪytkownik musi wówczas wpisywaü litery i cyfry usáyszane po odtworzeniu pliku audio. Niektóre zadania mają nawet postaü prostych zadaĔ matematycznych. Zadania CAPTCHA naleĪy traktowaü jako jedno z tych narzĊdzi w arsenale administratorów, które sáuĪą do odstraszania leniwych záoczyĔców, nie powinny natomiast zastĊpowaü stan- dardowych metod monitorowania i zabezpieczeĔ. NiedogodnoĞci dla uĪytkowników wzrastają wraz ze stopniem skomplikowania zadania CAPTCHA, dlatego w tym projekcie ograniczymy siĊ do najprostszego przykáadu, polegającego na wykorzystaniu obrazka. ?php include ../../lib/functions.php ; // naleĪy utworzyü lub kontynuowaü sesjĊ i zapisaü ciąg znaków CAPTCHA // w $_SESSION, by byá dostĊpny w ramach innych wywoáaĔ if (!isset($_SESSION)) { session_start(); header( Cache-control: private ); } // utworzenie obrazka o wymiarach 65x20 pikseli $width = 65; $height = 20; $image = imagecreate(65, 20); // wypeánienie obrazka kolorem táa $bg_color = imagecolorallocate($image, 0x33, 0x66, 0xFF); imagefilledrectangle($image, 0, 0, $width, $height, $bg_color); // pobranie losowego tekstu $text = random_text(5); RozdziaÄ 1. Q Rejestracja uÑytkowników 25 // ustalenie wspóárzĊdnych x i y do wyĞrodkowania tekstu $font = 5; $x = imagesx($image) / 2 - strlen($text) * imagefontwidth($font) / 2; $y = imagesy($image) / 2 - imagefontheight($font) / 2; // wypisanie tekstu na obrazku $fg_color = imagecolorallocate($image, 0xFF, 0xFF, 0xFF); imagestring($image, $font, $x, $y, $text, $fg_color); // zapisanie ciągu znaków CAPTCHA do póĨniejszego porównania $_SESSION[ captcha ] = $text; // zwrócenie obrazka header( Content-type: image/png ); imagepng($image); imagedestroy($image); ? Skrypt najlepiej jest zapisaü w folderze public_files/img (poniewaĪ musi on byü publicznie dostĊpny i zwracaü obrazek graficzny), w pliku o nazwie captcha.php. Skrypt tworzy obrazek PNG o wymiarach 65 na 20 pikseli, z táem koloru niebieskiego oraz biaáym, losowym cią- giem piĊciu znaków, jak na rysunku 1.1. Ciąg znaków musi byü przechowywany w zmiennej $_SESSION, aby nieco póĨniej moĪna byáo sprawdziü, czy uĪytkownik przepisaá go prawi- dáowo. Aby bardziej skomplikowaü obrazek, moĪna uĪyü róĪnych czcionek, kolorów oraz zastosowaü obrazki w tle. Rysunek 1.1 Szablony DziĊki szablonom programistom áatwiej jest utrzymywaü spójny wygląd i ukáad poszczegól- nych stron witryny. Szablony nadają organizacjĊ kodu oraz przenoszą logikĊ prezentacji poza wáaĞciwy kod Ĩródáowy, dziĊki czemu pliki PHP oraz HTML stają siĊ bardziej czytelne. Na rynku dostĊpnych jest wiele rozwiązaĔ do obsáugi szablonów — niektóre rozbudowane (na przykáad Smarty: http://smarty.php.net), inne niepozorne (TinyButStrong: www.tinybut ´strong.com). KaĪde z tych rozwiązaĔ ma wáasne wady i zalety, bez wzglĊdu na to, czy jest to produkt komercyjny o otwartym dostĊpie do kodu Ĩródáowego, czy tworzony na uĪytek domowy. W wielu przypadkach ostateczna decyzja o tym, którego z tych rozwiązaĔ uĪyü, jest podejmowana na podstawie wáasnych upodobaĔ programisty. JeĞli chodzi o osobiste upodobania, moĪna caáym sercem popieraü sam pomysá wykorzystania szablonów, a jednoczeĞnie nie przepadaü za wiĊkszoĞcią implementacji tej idei. Pomimo niewątpliwych zalet obecnie dostĊpne rozwiązania do obsáugi szablonów wiele rzeczy kom- plikują. W niektórych stosowana jest ich wáasna, specjalna skáadnia, której trzeba siĊ nauczyü; poza tym praktycznie wszystkie wydáuĪają proces przetwarzania kodu. PrawdĊ mówiąc, w wiĊkszoĞci projektów wykorzystanie oddzielnego mechanizmu obsáugi szablonów nie jest w ogóle potrzebne, poniewaĪ PHP sam moĪe byü uwaĪany za moduá obsáugi szablonów, 26 PHP i MySQL. Projekty do wykorzystania zdolny obsáugiwaü nawet witryny o Ğredniej wielkoĞci, tworzone przez wiĊkszą liczbĊ pro- gramistów. Wystarczy zastosowaü w takich przypadkach odpowiednie planowanie i orga- nizacjĊ prac. Rozwiązanie, które wydaje siĊ najlepsze, polega na wydzieleniu najwaĪniejszych elemen- tów prezentacji w plikach HTML w folderze templates. Folder ten zwykle umieszczany jest poza folderem dostĊpnym publicznie (choü pliki CSS, JavaScript i graficzne przywoáywane w kodzie HTML muszą juĪ byü publicznie dostĊpne), aby uniknąü sytuacji, w której uĪyt- kownik lub wyszukiwarka znajduje pliki w praktyce pozbawione treĞci. PoniĪej przedstawiono podstawowy szablon, speániający wymagania naszego projektu. !DOCTYPE html PUBLIC -//W3C//DTD XHTML 1.0 Strict//EN http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd html xmlns= http://www.w3.org/1999/xhtml xml:lang= en lang= en head meta http-equiv= Content-Type content= text/html; charset=iso-8859-2 / title ?php if (!empty($GLOBALS[ TEMPLATE ][ title ])) { echo $GLOBALS[ TEMPLATE ][ title ]; } ? /title link rel= stylesheet type= text/css href= css/styles.css / ?php if (!empty($GLOBALS[ TEMPLATE ][ extra_head ])) { echo $GLOBALS[ TEMPLATE ][ extra_head ]; } ? /head body div id= header ?php if (!empty($GLOBALS[ TEMPLATE ][ title ])) { echo $GLOBALS[ TEMPLATE ][ title ]; } ? /div div id= content ?php if (!empty($GLOBALS[ TEMPLATE ][ content ])) { echo $GLOBALS[ TEMPLATE ][ content ]; } ? /div div id= footer Copyright #169; ?php echo date( Y ); ? /div /div /body /html RozdziaÄ 1. Q Rejestracja uÑytkowników 27 Zgodnie z powszechnie przyjĊtymi zasadami naleĪy ustaliü pewne konwencje. TreĞü bĊdzie przechowywana w tablicy $GLOBALS w skrypcie wywoáującym, dziĊki czemu bĊdzie równieĪ dostĊpna w dowolnym zasiĊgu wewnątrz doáączonego pliku szablonu. Zwykle uĪywane są nastĊpujące klucze: Q title — Tytuá strony. Q description — Opis strony. Q keywords — Sáowa kluczowe dla strony (tytuá strony, opis i sáowa kluczowe mogą byü przechowywane w bazie danych). Q extra_head — Klucz do wstawiania dodatkowych nagáówków HTML lub kodu JavaScript do kodu strony. Q content — Gáówna treĞü strony. Czasami uĪywa siĊ równieĪ kluczy dla menu lub ramek, zaleĪnie od ukáadu, jaki zaplanowano dla strony. Za kaĪdym razem jednak konkretne nazwy zmiennych bĊdą zaleĪeü od szablonu. JeĞli tylko zdefiniuje siĊ i zapisze standardowe konwencje, które potem bĊdą konsekwentnie stosowane, zespóá implementacyjny dowolnej wielkoĞci moĪe z powodzeniem wykorzysty- waü tak opracowany mechanizm obsáugi szablonów. Rejestracja nowego uÑytkownika Zdefiniowano juĪ strukturĊ katalogów, zaimplementowano takĪe odpowiednią czĊĞü kodu pomocniczego, moĪna siĊ wiĊc teraz skupiü na rejestrowaniu nowego uĪytkownika. Kod Ĩró- dáowy przedstawiony poniĪej moĪna zapisaü w folderze public_files, w pliku o nazwie regi- ster.php. Na rysunku 1.2 przedstawiono tĊ samą stronĊ wyĞwietloną w przeglądarce. Rysunek 1.2 28 PHP i MySQL. Projekty do wykorzystania ?php // doáączenie kodu wspóáuĪytkowanego include ../lib/common.php ; include ../lib/db.php ; include ../lib/functions.php ; include ../lib/User.php ; // rozpoczĊcie lub kontynuacja sesji, by udostĊpniü // test CAPTCHA przechowywany w zmiennej $_SESSION session_start(); header( Cache-control: private ); // przygotowanie formularza HTML do rejestracji ob_start(); ? form method= post action= ?php echo htmlspecialchars($_SERVER[ PHP_SELF ]); ? table tr td label for= username Nazwa uľytkownika /label /td td input type= text name= username id= username value= ?php if (isset($_POST[ username ])) echo htmlspecialchars($_POST[ username ]); ? / /td /tr tr td label for= password1 Hasđo /label /td td input type= password name= password1 id= password1 value= / /td /tr tr td label for= password2 Powtórzenie hasđa /label /td td input type= password name= password2 id= password2 value= / /td /tr tr td label for= email Adres email /label /td td input type= text name= email id= email value= ?php if (isset($_POST[ email ])) echo htmlspecialchars($_POST[ email ]); ? / /td /tr tr td label for= captcha Weryfikacja /label /td td Wpisz tekst widoczny na obrazku br/ img src= img/captcha.php?nocache= ?php echo time(); ? alt= / br / input type= text name= captcha id= captcha / /td /tr tr td /td td input type= submit value= Zarejestruj / /td td input type= hidden name= submitted value= 1 / /td /tr tr /table /form ?php $form = ob_get_clean(); // wyĞwietlenie formularza, jeĞli strona jest wyĞwietlana po raz pierwszy if (!isset($_POST[ submitted ])) { $GLOBALS[ TEMPLATE ][ content ] = $form; } RozdziaÄ 1. Q Rejestracja uÑytkowników 29 // w przeciwnym razie przetworzenie danych wejĞciowych else { // weryfikacja hasáa $password1 = (isset($_POST[ password1 ])) ? $_POST[ password1 ] : ; $password2 = (isset($_POST[ password2 ])) ? $_POST[ password2 ] : ; $password = ($password1 $password1 == $password2) ? sha1($password1) : ; // weryfikacja tekstu CAPTCHA $captcha = (isset($_POST[ captcha ]) strtoupper($_POST[ captcha ]) == $_SESSION[ captcha ]); // jeĞli wszystkie dane są prawidáowe — dodanie rekordu if ($password $captcha User::validateUsername($_POST[ username ]) User::validateEmailAddr($_POST[ email ])) { // sprawdzenie, czy uĪytkownik juĪ istnieje $user = User::getByUsername($_POST[ username ]); if ($user- userId) { $GLOBALS[ TEMPLATE ][ content ] = p strong Przepraszamy, . takie konto juľ istnieje. /strong /p p Prosimy podaè . innæ nazwú uľytkownika. /p ; $GLOBALS[ TEMPLATE ][ content ] .= $form; } else { // utworzenie nieaktywnego rekordu uĪytkownika $u = new User(); $u- username = $_POST[ username ]; $u- password = $password; $u- emailAddr = $_POST[ email ]; $token = $u- setInactive(); $GLOBALS[ TEMPLATE ][ content ] = p strong Dziúkujemy za . zarejestrowanie siú. /strong /p p Naleľy pamiútaè o . zweryfikowaniu konta i kliknæè đæcze a href= verify.php?uid= . $u- userId . token= . $token . verify.php?uid= . $u- userId . token= . $token . /a /p ; } } // dane nieprawidáowe else { $GLOBALS[ TEMPLATE ][ content ] .= p strong Podano nieprawidđowe . dane. /strong /p p Prosimy prawidđowo wypeđniè . wszystkie pola, abyħmy mogli zarejestrowaè konto uľytkownika. /p ; $GLOBALS[ TEMPLATE ][ content ] .= $form; } } // wyĞwietlenie strony include ../templates/template-page.php ; ? 30 PHP i MySQL. Projekty do wykorzystania Najpierw kod z pliku register.php importuje pliki z kodem wspóáuĪytkowanym, który bĊdzie póĨniej wykorzystywany. Niektórzy programiĞci wolą umieszczaü wszystkie instrukcje include w jednym wspólnym pliku nagáówkowym, a nastĊpnie doáączaü sam plik nagáówkowy — dziĊki temu kod wáaĞciwy jest krótszy. W projekcie bĊdziemy jednak oddzielnie doáączaü pojedyncze pliki, poniewaĪ wydaje siĊ, Īe takie rozwiązanie jest prostsze w utrzymaniu. Inni programiĞci wykorzystują funkcjĊ chdir() do zmiany katalogu roboczego PHP, dziĊki czemu nie trzeba za kaĪdym razem odwracaü ĞcieĪek w systemie w celu doáączenia pliku. RównieĪ tutaj decydują osobiste upodobania. Jednak w przypadku wyboru takiego rozwiązania trzeba zwróciü szczególną uwagĊ na starsze instalacje PHP, w których uĪywany jest tryb bezpieczny. Wykonanie funkcji chdir() moĪe bowiem siĊ nie udaü i nie zwróci Īadnego komunikatu o báĊdzie, jeĪeli wskazany katalog bĊdzie niedostĊpny. ?php // doáączenie kodu wspóáuĪytkowanego chdir( ../ ); include lib/common.php ; include lib/db.php ; include lib/functions.php ; include lib/User.php ; … ? Po zaimportowaniu plików z kodem wspóáuĪytkowanym wywoáywana jest metoda session_ ´start(). Wywoáania HTTP są bezstanowe, co oznacza, Īe serwer WWW zwraca kaĪdą stronĊ bez Ğledzenia, co dziaáo siĊ z nią wczeĞniej, i bez przewidywania, co moĪe siĊ z nią zdarzyü w przyszáoĞci. Mechanizm Ğledzenia sesji dostĊpny w PHP umoĪliwia utrzymywanie w prosty sposób stanów miĊdzy kolejnym wywoáaniami oraz przenoszenie wartoĞci z jed- nego wywoáania do nastĊpnego. Wykorzystanie sesji jest niezbĊdne, aby utrzymaü wartoĞü CAPTCHA wygenerowaną w pliku captcha.php. Gdy przygotowywane są wiĊksze bloki kodu HTML, na przykáad kod formularza do reje- stracji, warto jest je buforowaü dla zwiĊkszenia czytelnoĞci kodu Ĩródáowego. Niektórzy pro- gramiĞci preferują natomiast definiowanie zmiennej buforowej i cykliczne doklejanie do niej kolejnych fragmentów HTML, na przykáad: ?php $GLOBALS[ TEMPLATE ][ content ] = form action= . htmlspecialchars(currentFile()) . method= post ; $GLOBALS[ TEMPLATE ][ content ] .= table ; $GLOBALS[ TEMPLATE ][ content ] .= tr ; $GLOBALS[ TEMPLATE ][ content ] .= td label for= username Nazwa ´uľytkownika /label . /td ; … ? Takie podejĞcie wydaje siĊ jednak doĞü niewygodne i stosunkowo czasocháonne. W przypadku buforowania danych wynikowych wystarczy rozpocząü buforowanie wywoáaniem funkcji ob_start(), odczytaü zawartoĞü bufora funkcją ob_get_contents() i zatrzymaü buforowanie funkcją ob_end_clean(). Funkcja ob_get_clean() áączy w sobie wywoáanie dwóch funkcji: ob_get_contents() i ob_end_clean(). Ponadto dla interpretera áatwiej jest wáączaü i wyáączaü tryb PHP, dlatego tak skonstruowany kod obsáugi duĪych bloków danych wyjĞciowych powi- nien dziaáaü szybciej niĪ w metodzie z dopisywaniem danych do bufora. RozdziaÄ 1. Q Rejestracja uÑytkowników 31 Gdy uĪytkownik po raz pierwszy wywoáuje stronĊ, nie powinno byü zdefiniowanych Īadnych wartoĞci $_POST, dlatego kod po prostu zwraca formularz rejestracji. Gdy uĪytkownik zatwierdzi formularz, ustawiana jest zmienna $_POST[ submitted ], dziĊki czemu wiadomo, Īe naleĪy rozpocząü przetwarzanie danych wejĞciowych. Kod, którego zadaniem jest weryfikacja poprawnoĞci nazwy uĪytkownika i hasáa, naleĪy do klasy User. Obydwa hasáa wpisane w formularzu są ze sobą porównywane, a nastĊpnie hasáo jest szyfrowane i juĪ w postaci zaszyfrowanej zapisywane w bazie danych do póĨniejszego uĪycia. Na koniec wartoĞü wpisana przez uĪytkownika na podstawie obrazka CAPTCHA jest porównywana z wartoĞcią wczeĞniej zapisaną w sesji przez kod z pliku captcha.php. JeĪeli wszystkie dane są poprawne, rekord zostaje zapisany w bazie danych. Skrypt verify.php przywoáywany w kodzie HTML odpowiada za odczytanie identyfikatora uĪytkownika i znacznika aktywacji, sprawdzenie odpowiednich danych w bazie i uaktyw- nienie konta uĪytkownika. Skrypt ten równieĪ musi zostaü zapisany w katalogu dostĊpnym publicznie. ?php // doáączenie kodu wspóáuĪytkowanego include ../lib/common.php ; include ../lib/db.php ; include ../lib/functions.php ; include ../lib/User.php ; // sprawdzenie, czy otrzymano identyfikator uĪytkownika i znacznik if (!isset($_GET[ uid ]) || !isset($_GET[ token ])) { $GLOBALS[ TEMPLATE ][ content ] = p strong Otrzymane informacje . sæ niepeđne. /strong /p p Prosimy spróbowaè ponownie. /p ; include ../templates/template-page.phptemplate_page.php ; exit(); } // weryfikacja identyfikatora uĪytkownika if (!$user = User::getById($_GET[ uid ])) { $GLOBALS[ TEMPLATE ][ content ] = p strong Podane konto nie ´istnieje. /strong . /p p Prosimy spróbowaè ponownie. /p ; } // upewnienie siĊ, Īe konto jest nieaktywne else { if ($user- isActive) { $GLOBALS[ TEMPLATE ][ content ] = p strong Konto . zostađo juľ zweryfikowane. /strong /p ; } // uaktywnienie konta else { if ($user- setActive($_GET[ token ])) { $GLOBALS[ TEMPLATE ][ content ] = p strong Dziúkujemy . za zweryfikowanie konta. /strong /p p Moľna siú . teraz a href= login.php zalogowaè /a . /p ; 32 PHP i MySQL. Projekty do wykorzystania } else { $GLOBALS[ TEMPLATE ][ content ] = p strong Podano . nieprawidđowe dane. /strong /p p Prosimy spróbowaè ´ponownie. /p ; } } } // wyĞwietlenie strony include ../templates/template-page.php ; ? WysyÄanie e-maila z ľczem do weryfikacji Aktualnie skrypt register.php wyĞwietla bezpoĞrednie áącze sáuĪące do weryfikacji konta, natomiast w Ğrodowisku produkcyjnym zwykle odpowiednie áącze wysyáa siĊ pocztą elek- troniczną na adres wpisany przez uĪytkownika. Wychodzi siĊ przy tym z zaáoĪenia, Īe praw- dziwy uĪytkownik poda prawidáowy adres pocztowy i samodzielnie potwierdzi zaáoĪenie konta, czego nie robi znakomita wiĊkszoĞü spamerów. Funkcja mail() sáuĪy do wysyáania poczty elektronicznej przez PHP. Pierwszym argumentem funkcji jest adres pocztowy uĪytkownika, drugim jest temat wiadomoĞci pocztowej, trzecim zaĞ — treĞü samej wiadomoĞci. Zazwyczaj zaleca siĊ, by nie wstrzymywaü wyĞwietlania ostrzeĪeĔ przy uĪyciu symbolu @, w tym przypadku jednak jest to konieczne, poniewaĪ w razie niepowodzenia funkcja mail() zwróci wartoĞü false oraz wygeneruje komunikat z ostrzeĪeniem. Kod, który naleĪy umieĞciü w pliku register.php, aby zamiast wyĞwietlaü áącze do weryfikacji konta w przeglądarce, wysyáaü je w wiadomoĞci pocztowej, moĪe mieü nastĊpującą postaü: ?php … // utworzenie nieaktywnego rekordu uĪytkownika $u = new User(); $u- username = $_POST[ username ]; $u- password = $password; $u- emailAddr = $_POST[ email ]; $token = $u- setInactive(); $message = Dziúkujemy za zarejestrowanie siú! Przed zalogowaniem siú . naleľy pamiútaè o zweryfikowaniu konta. W tym celu trzeba wejħè . na stronú http://www.przyklad.com/verify.php?uid= . $u- userId . token= . $token . . ; if (@mail($u- emailAddr, Aktywacja nowego konta , $message)) { $GLOBALS[ TEMPLATE ][ content ] = p strong Dziúkujemy za . zarejestrowanie siú. /strong /p p Wkrótce otrzymasz . wiadomoħè pocztowæ z instrukcjami na temat sposobu . aktywowania konta. /p ; RozdziaÄ 1. Q Rejestracja uÑytkowników 33 } else { $GLOBALS[ TEMPLATE ][ content ] = p strong Wystæpiđ bđæd . w trakcie wysyđania đæcza aktywacyjnego. /strong /p . p Prosimy skontaktowaè siú z administratorem . pod adresem a href= mailto:admin@przyklad.com . admin@przyklad.com /a , aby uzyskaè pomoc. /p ; } … ? Na rysunku 1.3 przedstawiono wiadomoĞü pocztową z potwierdzeniem, odczytaną w progra- mie pocztowym. Rysunek 1.3 Wysyáanie wiadomoĞci pocztowej zawierającej zwykáy tekst jest prostym zadaniem, nato- miast wysyáanie wiadomoĞci sformatowanej w jĊzyku HTML wymaga nieco wiĊcej pracy. Obydwa rodzaje wiadomoĞci mają niewątpliwe zalety: wiadomoĞci tekstowe są bardziej czy- telne, a prawdopodobieĔstwo ich zablokowania przez filtry antyspamowe jest stosunkowo niskie, natomiast wiadomoĞci w jĊzyku HTML są bardziej przyjazne dla uĪytkowników, mniej sterylne, a poza tym mogą zawieraü w treĞci hiperáącza, dziĊki którym áatwiej jest skie- rowaü uĪytkownika na stronĊ odpowiadającą za weryfikacjĊ konta. WiadomoĞü pocztowa w jĊzyku HTML moĪe wyglądaü nastĊpująco: html p Dziúkujemy za zarejestrowanie siú! /p p Przed zalogowaniem siú naleľy pamiútaè o zweryfikowaniu konta. 34 PHP i MySQL. Projekty do wykorzystania W tym celu trzeba wejħè na stronú a href= http://www.przyklad.com/verify.php?uid=### amp;token=xxxxx http://www.przyklad.com/verify.php?uid=### amp;token=xxxxx /a . /p p Jeľeli uľywany program pocztowy nie pozwala na klikniúcie hiperđæczy obecnych w tej wiadomoħci, naleľy skopiowaè hiperđæcze i wkleiè je w pasku adresów przeglædarki, aby wyħwietliè stronú do weryfikacji konta. /p /html Gdyby jednak powyĪszą wiadomoĞü wysáaü w sposób przedstawiony w poprzednim przy- káadzie, wówczas i tak dotaráaby ona do adresata w postaci zwykáego tekstu, pomimo Īe zawiera przecieĪ znaczniki jĊzyka HTML. Aby wskazaü klientowi pocztowemu prawidáowy sposób wyĞwietlania wiadomoĞci, konieczne jest równieĪ przesáanie odpowiednich nagáów- ków MIME i Content-Type. Dodatkowe nagáówki stanowią opcjonalny czwarty parametr funk- cji mail(). ?php // treĞü sformatowanej wiadomoĞci przechowywana w zmiennej $html_message // sformatowany e-mail wymaga podania nagáówków MIME i Content-Type $headers = array( MIME-Version: 1.0 , Content-Type: text/html; charset= iso-8859-2 ); // dodatkowe nagáówki są przekazywane jako czwarty argument funkcji mail() mail($user- emailAddr, Prosimy aktywowaè nowe konto , $html_message, join( \n , $headers)); ? MoĪliwe jest poáączenie zalet obu rodzajów wiadomoĞci pocztowych — wystarczy w tym celu wysáaü wiadomoĞü w formacie mieszanym. WiadomoĞü w formacie mieszanym zawiera tak naprawdĊ dwie wiadomoĞci: tekstową i sformatowaną w jĊzyku HTML, a juĪ do decyzji klienta pocztowego pozostaje, która czĊĞü wiadomoĞci zostanie wyĞwietlona. PoniĪej przed- stawiono wiadomoĞü mieszaną: --==A.BC_123_XYZ_678.9 Content-Type: text/plain; charset= iso-8859-2 Dziúkujemy za zarejestrowanie siú! Przed zalogowaniem siú naleľy pamiútaè o zweryfikowaniu konta. W tym celu trzeba wejħè na stronú ´http://www.przyklad.com/verify.php?uid=### amp;token=xxxxx. --==A.BC_123_XYZ_678.9 Content-Type: text/plain; charset= iso-8859-2 html p Dziúkujemy za zarejestrowanie siú! /p p Przed zalogowaniem siú naleľy pamiútaè o zweryfikowaniu konta. W tym celu trzeba wejħè na stronú a href= http://www.przyklad.com/verify.php?uid=### amp;token=xxxxx http://www.przyklad.com/verify.php?uid=### amp;token=xxxxx /a . /p p Jeľeli uľywany program pocztowy nie pozwala na klikniúcie hiperđæczy obecnych w tej wiadomoħci, naleľy skopiowaè hiperđæcze i wkleiè je w pasku adresów przeglædarki, aby wyħwietliè stronú do weryfikacji konta. /p /html --==A.BC_123_XYZ_678.9-- RozdziaÄ 1. Q Rejestracja uÑytkowników 35 Aby wysáaü tak skonstruowaną wiadomoĞü, trzeba uĪyü nastĊpujących nagáówków: MIME-Version: 1.0 Content-Type: multipart/alternative; boundary= ==A.BC_123_XYZ_678.9 Warto zwróciü uwagĊ, Īe poszczególne segmenty wiadomoĞci pocztowej są od siebie od- dzielone specjalnym ciągiem znaków. Ciąg znaków w postaci ==A.BC_123_XYZ_678.9 nie ma tak naprawdĊ konkretnego znaczenia; wystarczy, by byá to losowy ciąg znaków, który nie pojawi siĊ nigdzie w treĞci któregoĞ z elementów wiadomoĞci. Ciąg znaków oddzielają- cy od siebie poszczególne bloki wiadomoĞci jest zawsze poprzedzany dwoma myĞlnikami, a przed nim wystĊpuje pusty wiersz. MyĞlniki na koĔcu tego ciągu wskazują jednoczeĞnie koniec caáej wiadomoĞci. Logowanie i wylogowywanie MoĪna juĪ tworzyü nowe konta uĪytkowników i weryfikowaü je jako konta zaáoĪone przez prawdziwych uĪytkowników dziĊki wykorzystaniu podanego adresu poczty elektronicznej. Kolejnym krokiem jest zatem opracowanie mechanizmu, który bĊdzie dostĊpny dla uĪyt- kowników i pozwoli im na logowanie siĊ i wylogowywanie z systemu. WiĊkszoĞü uciąĪli- wych zadaĔ związanych ze Ğledzeniem sesji bĊdzie wykonywana przez PHP, dlatego nam pozostaje tylko zapisywanie danych identyfikacyjnych w zmiennej $_SESSION. PoniĪszy kod naleĪy zapisaü w pliku login.php. ?php // do
Pobierz darmowy fragment (pdf)

Gdzie kupić całą publikację:

PHP i MySQL. Projekty do wykorzystania
Autor:
,

Opinie na temat publikacji:


Inne popularne pozycje z tej kategorii:


Czytaj również:


Prowadzisz stronę lub blog? Wstaw link do fragmentu tej książki i współpracuj z Cyfroteką: