PHP, MySQL i MVC. Tworzenie witryn WWW opartych na bazie danych 9788328324091

Model architektoniczny MVC Szablony PHP i szablony Smarty Wizualne projektowanie baz danych Mapowanie relacyjno-obiektow

650 143 6MB

Polish Pages [526] Year 2010

Report DMCA / Copyright

DOWNLOAD FILE

Polecaj historie

PHP, MySQL i MVC. Tworzenie witryn WWW opartych na bazie danych
 9788328324091

Table of contents :
Spis treści
Wstęp
Część I. Akcje, widoki, translacje adresów URL i bazy danych, czyli podstawy użycia MVC
Rozdział 1. Hello world — pierwsza aplikacja korzystająca z MVC
Projekt 1.1. Hello world!
Krok pierwszy: utworzenie modułu main
Krok drugi: utworzenie akcji hello w module main
Krok trzeci: utworzenie układu witryny WWW
Krok czwarty: reguła translacji adresu pierwszy-projekt.html na wykonanie akcji main/hello
Krok piąty: skrypt index.php
Pliki, które należy utworzyć
Uruchomienie projektu
Przebieg wykonania
Rozdział 2. Dołączanie zewnętrznych zasobów .css, .jpg, .js
Projekt 2.1. Wlazł kotek na schody…
Analiza ścieżek zawartych w kodzie HTML
Rozdział 3. Błędy 404
Projekt 3.1. Żółta Turnia
Oglądanie strony błędu oraz nagłówka HTTP
Rozdział 4. Zmienne i widoki
Projekt 4.1. Data i godzina — szablon PHP
Projekt 4.2. Data i godzina — szablon Smarty
Projekt 4.3. Ojciec i syn — szablon PHP
Projekt 4.4. Ojciec i syn — szablony Smarty
Projekt 4.5. Stefan Żeromski: Zmierzch — szablon PHP
Projekt 4.6. Stefan Żeromski: Zmierzch — szablony Smarty
Projekt 4.7. Kolory CSS
Projekt 4.8. Kolory CSS — szablony Smarty
Rozdział 5. Pre- i postprzetwarzanie
Projekt 5.1. Fraszki
Projekt 5.2. Fraszki — szablony Smarty
Rozdział 6. Translacja adresów URL
Projekt 6.1. Kolędy
Analiza różnych rodzajów adresów URL
Dwukierunkowość konwersji adresów
Konwersje adresów w generowanych stronach WWW
Włączanie i wyłączanie translacji wyjściowych
Konwersja adresów URL przy użyciu funkcji pomocniczych
Implementacja funkcji pomocniczych w postaci wtyczek Smarty
Kilka zmiennych w adresach URL
Projekt 6.2. Ligi piłkarskie
Zmienne $path_prefix oraz ###PATH_PREFIX###
Rozdział 7. Bazy danych
Wizualne projektowanie bazy danych
Oprogramowanie ORM
Konwersja pliku .mwb do formatu Propel XML
Konwersja pliku .mwb do formatu Doctrine YML
db-frame-tool
Propel — generowanie klas dostępu do bazy
ORM Propel — pierwsze kroki
Zestawienie wygenerowanych klas oraz najważniejszych metod
Podstawy użycia klas wygenerowanych przez Propel
Doctrine — generowanie klas dostępu do bazy
ORM Doctrine — pierwsze kroki
Zestawienie wygenerowanych klas oraz najważniejszych metod
Podstawy użycia klas wygenerowanych przez Doctrine
Projekt 7.1. Tatry (szablony PHP, Propel)
Krok pierwszy: projekt bazy danych
Krok drugi: generowanie klas dostępu do bazy danych
Krok trzeci: tworzenie pustej bazy danych
Krok czwarty: wypełnianie bazy danych na podstawie pliku tekstowego
Krok piąty: zrzut wypełnionej bazy danych
Krok szósty: aplikacja prezentująca zawartość bazy danych
Projekt 7.2. Tatry (szablony PHP, Doctrine)
Krok pierwszy: projekt bazy danych
Krok drugi: generowanie klas dostępu do bazy danych
Krok trzeci: tworzenie pustej bazy danych
Krok czwarty: wypełnianie bazy danych na podstawie pliku tekstowego
Krok piąty: zrzut wypełnionej bazy danych
Krok szósty: aplikacja prezentująca zawartość bazy danych
Projekt 7.3. Tatry (szablony Smarty, Propel)
Projekt 7.4. Tatry (szablony Smarty, Doctrine)
Rozdział 8. Czego powinieneś nauczyć się z części pierwszej?
Część II. Operowanie klasami wygenerowanymi przez Propel oraz Doctrine
Rozdział 9. Wybieranie wszystkich rekordów z tabeli w zadanym porządku
Propel — sortowanie rekordów
Doctrine — sortowanie rekordów
Projekt 9.1. Słownik (Propel, PHP)
Krok pierwszy: projekt bazy danych
Krok drugi: generowanie klas dostępu do bazy danych
Krok trzeci: tworzenie pustej bazy danych
Krok czwarty: wypełnianie bazy danych na podstawie pliku tekstowego
Krok piąty: zrzut wypełnionej bazy danych
Krok szósty: aplikacja prezentująca zawartość bazy danych
Projekt 9.2. Słownik (Doctrine, PHP)
Krok pierwszy: projekt bazy danych
Krok drugi: generowanie klas dostępu do bazy danych
Krok trzeci: tworzenie pustej bazy danych
Krok czwarty: wypełnianie bazy danych na podstawie pliku tekstowego
Krok piąty: zrzut wypełnionej bazy danych
Krok szósty: aplikacja prezentująca zawartość bazy danych
Rozdział 10. Wybieranie pojedynczego rekordu
Propel
Doctrine
Projekt 10.1. Treny (Propel, PHP)
Identyfikacja trenu wewnątrz akcji tren/show
Projekt 10.2. Treny (Doctrine, PHP)
Rozdział 11. Relacje 1:n
Metody generowane przez Propel dla relacji 1:n
Doctrine i relacje 1:n
Projekt 11.1. Kontynenty, państwa, miasta (Propel, PHP)
Przygotowanie bazy danych
Aplikacja
Projekt 11.2. Kontynenty, państwa, miasta (Doctrine, PHP)
Rozszerzanie właściwości klas generowanych przez Doctrine
Wstawianie rekordów
Aplikacja
Rozdział 12. Relacje n:m
Metody generowane przez Propel dla relacji n:m
Doctrine i relacje n:m
Projekt 12.1. Filmy (Propel, PHP)
Przygotowanie bazy danych
Aplikacja
Projekt 12.2. Filmy (Doctrine, PHP)
Propel. Sortowanie rekordów stojących w relacji n:m
Projekt 12.3. Filmy (Propel, PHP, sortowanie)
Doctrine. Sortowanie rekordów stojących w relacji n:m
Projekt 12.4. Filmy (Doctrine, PHP, sortowanie)
Rozdział 13. Zagadnienia dodatkowe dotyczące warstw M oraz V
Czyszczenie zawartości bazy danych
Konwersja obiektu w napis
Konwersje toArray(), fromArray()
Warunkowe wstawianie nieistniejących obiektów
Wielokrotne wykorzystanie widoku
Projekt 13.1. Aparaty foto (Propel, PHP)
Warstwa M
Wypełnianie bazy danych
Aplikacja
Projekt 13.2. Aparaty foto (Doctrine, PHP)
Rozszerzanie funkcjonalności klas wygenerowanych przez Doctrine
Wstawianie rekordów do bazy danych
Aplikacja
Rozdział 14. Zapisywanie w bazie danych obrazów i plików binarnych
Zapisywanie w bazie danych zdjęć JPG
Prezentowanie zdjęć JPG zapisanych w bazie danych na stronie WWW
Zapisywanie w bazie danych dowolnych plików binarnych
Wysyłanie danych binarnych z bazy do przeglądarki
Projekt 14.1. NotH (Propel, PHP)
Skrypt wstaw.php
Aplikacja
Tytuły stron
Rozwijane menu pionowe
Wartości atrybutów href oraz src w tekstach zapisanych w bazie danych
Projekt 14.2. NotH (Doctrine, PHP)
Skrypt wstaw.php
Aplikacja
Rozdział 15. Akcje list i show, czyli publikowanie zawartości bazy danych w postaci witryny WWW
Projekt 15.1. Czcionki projektów CSS Zen Garden (Propel, PHP)
Aplikacja
Menu główne witryny oraz tytuły podstron
Rozdział 16. Czego powinieneś nauczyć się z części drugiej?
Część III. Zwiększanie funkcjonalności interfejsu aplikacji internetowej
Rozdział 17. Kontekstowe hiperłącza do stron ze szczegółowymi informacjami
Projekt 17.1. Angaże (szablony PHP, Propel)
Unikatowość kolumny slug
Pliki tekstowe o bardziej złożonej strukturze
Rozszerzenia warstwy M
Filtry konwertujące generowany kod HTML
Aplikacja
Hiperłącza kontekstowe
Menu kontekstowe
Rozdział 18. Następny, poprzedni, czyli przewijanie zawartości witryny WWW
Projekt 18.1. PHP. Praktyczne projekty
Ograniczenia kluczy obcych
Wstępne opracowanie aplikacji
Implementacja hiperłączy następny/poprzedni
Hiperłącza link zawarte w nagłówku strony WWW
Rozdział 19. Wskaźnik położenia
Projekt 19.1. Kolekcja płyt DVD z fotografiami
Rozszerzanie klas dostępu do bazy danych
Wypełnianie bazy danych rekordami
Aplikacja
Translacje adresów stosujących cztery zmienne URL
Tabela zdjęć wykonana bez użycia tabel HTML
Wskaźniki następny/poprzedni do przewijania zdjęć i kategorii
Efekt rollover ze wskaźnikiem wybranej opcji
Fotografie podążające za wskaźnikiem myszki
Wskaźnik breadcrumbs
Rozdział 20. Sortowanie tabel
Projekt 20.1. Piłka nożna — sezon 2002/2003
Wielokrotne klucze obce z tej samej tabeli
Sortowanie złączeń dla wielokrotnych kluczy
Wypełnianie bazy danych
Zarys aplikacji
Implementacja sortowalnych tabelek HTML
Rozdział 21. Stronicowanie
Projekt 21.1. 33 1/3
Automatyczne generowanie identyfikatorów slug dla rekordów o zdublowanych tytułach
Klasa Pager
Widok wskaźnika stronicowania
Prezentacja rekordów poddanych stronicowaniu
Kontekstowe stronicowanie rekordów
Rozdział 22. Alfabet
Projekt 22.1. Imiona
Wybieranie alfabetu liter
Komponent wyświetlający alfabet
Prezentacja liter rozpoczynających się od wybranej litery na stronie WWW
Umieszczanie kontrolki z listą liter w szablonie layout.html
Rozdział 23. Chmura tagów
Projekt 23.1. Katalog Open Clipart
Wypełnianie bazy danych
Waga słów kluczowych
Aplikacja
Rozdział 24. Spis treści
Projekt 24.1. Artykuły
Wypełnianie bazy danych rekordami
Funkcje odpowiedzialne za odczytywanie i usuwanie fragmentów kodu HTML
Funkcje odpowiedzialne za tworzenie spisu treści
Kolorowanie składni
Aplikacja
Rozdział 25. Czego powinieneś nauczyć się z części trzeciej?
Część IV. Formaty danych
Rozdział 26. Podstawy przetwarzania dokumentów XML w PHP
Klasa SimpleXML
Tworzenie obiektu SimpleXMLElement
Dostęp do węzłów drzewa
Lista identycznych elementów
Dostęp do atrybutów
Przetwarzanie wszystkich elementów i ich atrybutów
Wielokrotne zagnieżdżenia
Język XPath
Przykładowe dokumenty XML dostępne w internecie
Kursy walut
Książki wydawnictwa Helion
Projekt 26.1. Turniej Czterech Skoczni
Aplikacja
Rozdział 27. Generowanie dokumentów XML w PHP
Statyczne pliki XML
Generowanie dokumentu XML w PHP
Echo — drukowanie kodu XML
Generowanie XML na podstawie tablicy
Generowanie XML na podstawie pliku tekstowego
Zapisywanie kodu XML do pliku
Konwersja pliku tekstowego do formatu XML
Dane w formacie XML opisujące witrynę WWW
Mapa witryny: sitemap.xml
Kanał RSS
Projekt 27.1. Kursy walut
Ustalanie adresów dokumentów XML z kursami walut
Projekt bazy danych
Wypełnianie bazy danych rekordami
Aplikacja
Kanał RSS
Mapa witryny
Wykresy kursów walut
Rozdział 28. XML_Serializer, XML_Unserializer — dwukierunkowe transformacje tablic w XML
XML_Serializer
Konwersja tablicy w kod XML
Tablica asocjacyjna
Opcje
Tablica opcji
Jednowymiarowa tablica indeksowana
Wielowymiarowe tablice indeksowane
Atrybuty
Wybiórcze stosowanie atrybutów
Przekształcenia
XML_Serializer — przykłady
Projekt 28.1. Konwersja pliku nobel.txt
Projekt 28.2. Konwersja pliku mecze.txt
Projekt 28.3. Konwersja pliku tcs.txt
Klasa XML_Unserializer
Podstawowe użycie
Odczyt pliku
Parsing atrybutów
Konwersja formatu XML
Projekt 28.4. Konwersja jeden-w-wiele
Projekt 28.5. Konwersja wiele-w-jeden
Projekt 28.6. Klasyfikacja zwierząt
Wypełnianie bazy danych rekordami
Moduły i akcje aplikacji
Akcja main/drzewo
Kanał RSS
Generowanie statycznego dokumentu sitemap.xml
Rozdział 29. Arkusze kalkulacyjne MS Excel XLS
Odczyt pliku XLS
Odczyt kilku arkuszy
Tworzenie pliku XLS
Wysyłanie arkusza do przeglądarki
Konwersja pliku tekstowego do formatu XLS
Konwersja pliku XLS do formatu tekstowego
Projekt 29.1. Generowanie danych autokomisu
Projekt 29.2. Autokomis
Wypełnianie bazy danych rekordami
Aplikacja
Rozdział 30. Konwersja plików z danymi
Format danych tekstowych
Format danych XML
Format danych XLS
Projekt 30.1. Konwersja formatu TXT do formatu XML
Projekt 30.2. Konwersja formatu TXT do formatu XLS
Projekt 30.3. Konwersja formatu XML do formatu TXT
Projekt 30.4. Konwersja formatu XML do formatu XLS
Projekt 30.5. Konwersja formatu XLS do formatu TXT
Projekt 30.6. Konwersja formatu XLS do formatu XML
Projekt 30.7. Zestawienia artykułów „Magazynu INTERNET”
Aplikacja
Akcja list prezentująca sortowalną i stronicowaną tabelkę HTML
Akcja show prezentująca sortowalną i stronicowaną tabelkę HTML
Rozdział 31. Skompresowane dokumenty XML zawierające dane binarne
Kodowanie base64
Dekodowanie base64
Kompresja danych
Dekompresja danych
Projekt 31.1. Format danych systemu do publikowania artykułów
Umieszczanie ilustracji, listingów, ramek i tabel w treści artykułu
Projekt 31.2. Konwersja artykułu z formatu tekstowego do spakowanego pliku XML
Projekt 31.3. System publikacji artykułów w postaci witryny WWW
Baza danych
Propel i dostęp tylko do wybranych kolumn tabeli
Wypełnianie bazy danych
Aplikacja
Rozdział 32. Czego powinieneś nauczyć się z części czwartej?
Skorowidz
Dodatkowe materiały

Citation preview

Wszelkie prawa zastrzeżone. Nieautoryzowane rozpowszechnianie całości lub fragmentu niniejszej publikacji w jakiejkolwiek postaci jest zabronione. Wykonywanie kopii metodą kserograficzną, fotograficzną, a także kopiowanie książki na nośniku filmowym, magnetycznym lub innym powoduje naruszenie praw autorskich niniejszej publikacji. Wszystkie znaki występujące w tekście są zastrzeżonymi znakami firmowymi bądź towarowymi ich właścicieli. Autor oraz Wydawnictwo HELION dołożyli wszelkich starań, by zawarte w tej książce informacje były kompletne i rzetelne. Nie biorą jednak żadnej odpowiedzialności ani za ich wykorzystanie, ani za związane z tym ewentualne naruszenie praw patentowych lub autorskich. Autor oraz Wydawnictwo HELION nie ponoszą również żadnej odpowiedzialności za ewentualne szkody wynikłe z wykorzystania informacji zawartych w książce. Redakcja: Ewelina Burska Projekt okładki: Jan Paluch Materiały graficzne na okładce zostały wykorzystane za zgodą iStockPhoto Inc. Dodatkowe materiały do książki można znaleźć pod adresem: ftp://ftp.helion.pl/przyklady/aplphp.zip Wydawnictwo HELION ul. Kościuszki 1c, 44-100 GLIWICE tel. 32 231 22 19, 32 230 98 63 e-mail: [email protected] WWW: http://helion.pl (księgarnia internetowa, katalog książek) Drogi Czytelniku! Jeżeli chcesz ocenić tę książkę, zajrzyj pod adres http://helion.pl/user/opinie?aplphp_ebook Możesz tam wpisać swoje uwagi, spostrzeżenia, recenzję. ISBN: 978-83-283-2409-1 Copyright © Helion 2010, 2016

 Poleć książkę na Facebook.com  Kup w wersji papierowej  Oceń książkę

 Księgarnia internetowa  Lubię to! » Nasza społeczność

Dla Beaty Wszechświat, nieskończoność, ja i Ty…

Spis treści Wstęp . .......................................................................................... 13

Część I

Akcje, widoki, translacje adresów URL i bazy danych, czyli podstawy użycia MVC . .......................................... 15

Rozdział 1. Hello world — pierwsza aplikacja korzystająca z MVC . ................... 17 Projekt 1.1. Hello world! ................................................................................................. 18 Krok pierwszy: utworzenie modułu main . ................................................................ 19 Krok drugi: utworzenie akcji hello w module main . ................................................ 19 Krok trzeci: utworzenie układu witryny WWW . ...................................................... 20 Krok czwarty: reguła translacji adresu pierwszy-projekt html na wykonanie akcji main/hello . ............................................................................. 20 Krok piąty: skrypt index.php ..................................................................................... 21 Pliki, które należy utworzyć ...................................................................................... 22 Uruchomienie projektu .............................................................................................. 23 Przebieg wykonania .................................................................................................. 24

Rozdział 2. Dołączanie zewnętrznych zasobów .css, .jpg, .js . ............................ 27 Projekt 2.1. Wlazł kotek na schody… . ........................................................................... 28 Analiza ścieżek zawartych w kodzie HTML . ................................................................. 31

Rozdział 3. Błędy 404 . .................................................................................... 35 Projekt 3.1. Żółta Turnia .................................................................................................. 36 Oglądanie strony błędu oraz nagłówka HTTP . ......................................................... 38

Rozdział 4. Zmienne i widoki . .......................................................................... 41 Projekt 4.1. Data i godzina — szablon PHP . .................................................................. 42 Projekt 4.2. Data i godzina — szablon Smarty . .............................................................. 45 Projekt 4.3. Ojciec i syn — szablon PHP . ...................................................................... 47 Projekt 4.4. Ojciec i syn — szablony Smarty . ................................................................ 49 Projekt 4.5. Stefan Żeromski: Zmierzch — szablon PHP . .............................................. 50 Projekt 4.6. Stefan Żeromski: Zmierzch — szablony Smarty . ........................................ 53 Projekt 4.7. Kolory CSS .................................................................................................. 54 Projekt 4.8. Kolory CSS — szablony Smarty . ................................................................ 56

Rozdział 5. Pre- i postprzetwarzanie . ............................................................... 59 Projekt 5.1. Fraszki .......................................................................................................... 60 Projekt 5.2. Fraszki — szablony Smarty . ....................................................................... 68

6

PHP, MySQL i MVC. Tworzenie witryn WWW opartych na bazie danych

Rozdział 6. Translacja adresów URL . ............................................................... 71 Projekt 6.1. Kolędy .......................................................................................................... 73 Analiza różnych rodzajów adresów URL . ...................................................................... 77 Dwukierunkowość konwersji adresów . .......................................................................... 78 Konwersje adresów w generowanych stronach WWW . ................................................. 79 Włączanie i wyłączanie translacji wyjściowych . ............................................................ 80 Konwersja adresów URL przy użyciu funkcji pomocniczych . ....................................... 81 Implementacja funkcji pomocniczych w postaci wtyczek Smarty .................................. 82 Kilka zmiennych w adresach URL . ................................................................................ 83 Projekt 6.2. Ligi piłkarskie .............................................................................................. 84 Zmienne $path_prefix oraz ###PATH_PREFIX### . ............................................... 92

Rozdział 7. Bazy danych . ................................................................................. 95 Wizualne projektowanie bazy danych . ........................................................................... 95 Oprogramowanie ORM ................................................................................................... 99 Konwersja pliku mwb do formatu Propel XML . ......................................................... 100 Konwersja pliku mwb do formatu Doctrine YML . ...................................................... 101 db-frame-tool ................................................................................................................. 101 Propel — generowanie klas dostępu do bazy . .............................................................. 102 ORM Propel — pierwsze kroki . ................................................................................... 104 Zestawienie wygenerowanych klas oraz najważniejszych metod ........................... 104 Podstawy użycia klas wygenerowanych przez Propel . ........................................... 105 Doctrine — generowanie klas dostępu do bazy . ........................................................... 106 ORM Doctrine — pierwsze kroki . ................................................................................ 107 Zestawienie wygenerowanych klas oraz najważniejszych metod ........................... 107 Podstawy użycia klas wygenerowanych przez Doctrine ........................................ 108 Projekt 7.1. Tatry (szablony PHP, Propel) . ................................................................... 109 Krok pierwszy: projekt bazy danych . ..................................................................... 110 Krok drugi: generowanie klas dostępu do bazy danych . ........................................ 110 Krok trzeci: tworzenie pustej bazy danych . ............................................................ 110 Krok czwarty: wypełnianie bazy danych na podstawie pliku tekstowego .............. 110 Krok piąty: zrzut wypełnionej bazy danych . .......................................................... 113 Krok szósty: aplikacja prezentująca zawartość bazy danych .................................. 114 Projekt 7.2. Tatry (szablony PHP, Doctrine) . ............................................................... 116 Krok pierwszy: projekt bazy danych . ..................................................................... 116 Krok drugi: generowanie klas dostępu do bazy danych . ........................................ 116 Krok trzeci: tworzenie pustej bazy danych . ............................................................ 117 Krok czwarty: wypełnianie bazy danych na podstawie pliku tekstowego .............. 117 Krok piąty: zrzut wypełnionej bazy danych . .......................................................... 118 Krok szósty: aplikacja prezentująca zawartość bazy danych .................................. 118 Projekt 7.3. Tatry (szablony Smarty, Propel) . ............................................................... 119 Projekt 7.4. Tatry (szablony Smarty, Doctrine) . ........................................................... 120

Rozdział 8. Czego powinieneś nauczyć się z części pierwszej? . ...................... 123

Część II

Operowanie klasami wygenerowanymi przez Propel oraz Doctrine . ............................................................ 129

Rozdział 9. Wybieranie wszystkich rekordów z tabeli w zadanym porządku . ..... 131 Propel — sortowanie rekordów ..................................................................................... 132 Doctrine — sortowanie rekordów . ................................................................................ 134 Projekt 9.1. Słownik (Propel, PHP) . ............................................................................. 134 Krok pierwszy: projekt bazy danych . ..................................................................... 135 Krok drugi: generowanie klas dostępu do bazy danych . ............................................. 135

Spis treści

7 Krok trzeci: tworzenie pustej bazy danych . ............................................................ 137 Krok czwarty: wypełnianie bazy danych na podstawie pliku tekstowego .............. 137 Krok piąty: zrzut wypełnionej bazy danych . .......................................................... 138 Krok szósty: aplikacja prezentująca zawartość bazy danych .................................. 138 Projekt 9.2. Słownik (Doctrine, PHP) . .......................................................................... 141 Krok pierwszy: projekt bazy danych . ..................................................................... 141 Krok drugi: generowanie klas dostępu do bazy danych . ............................................. 141 Krok trzeci: tworzenie pustej bazy danych . ............................................................ 142 Krok czwarty: wypełnianie bazy danych na podstawie pliku tekstowego .............. 142 Krok piąty: zrzut wypełnionej bazy danych . .......................................................... 142 Krok szósty: aplikacja prezentująca zawartość bazy danych .................................. 143

Rozdział 10. Wybieranie pojedynczego rekordu . ............................................... 145 Propel . ........................................................................................................................... 145 Doctrine . ........................................................................................................................ 147 Projekt 10.1. Treny (Propel, PHP) ................................................................................. 147 Identyfikacja trenu wewnątrz akcji tren/show . ....................................................... 151 Projekt 10.2. Treny (Doctrine, PHP) . ............................................................................ 153

Rozdział 11. Relacje 1:n . ................................................................................ 157 Metody generowane przez Propel dla relacji 1 n . ......................................................... 158 Doctrine i relacje 1:n ..................................................................................................... 160 Projekt 11.1. Kontynenty, państwa, miasta (Propel, PHP) . .......................................... 162 Przygotowanie bazy danych .................................................................................... 163 Aplikacja ................................................................................................................. 167 Projekt 11.2. Kontynenty, państwa, miasta (Doctrine, PHP) . ....................................... 173 Rozszerzanie właściwości klas generowanych przez Doctrine .............................. 174 Wstawianie rekordów .............................................................................................. 176 Aplikacja ................................................................................................................. 178

Rozdział 12. Relacje n:m . ............................................................................... 181 Metody generowane przez Propel dla relacji n m . ........................................................ 182 Doctrine i relacje n:m .................................................................................................... 183 Projekt 12.1. Filmy (Propel, PHP) . ............................................................................... 184 Przygotowanie bazy danych .................................................................................... 184 Aplikacja ................................................................................................................. 187 Projekt 12.2. Filmy (Doctrine, PHP) . ........................................................................... 189 Propel. Sortowanie rekordów stojących w relacji n:m . ................................................. 192 Projekt 12.3. Filmy (Propel, PHP, sortowanie) . ............................................................ 192 Doctrine. Sortowanie rekordów stojących w relacji n m . ............................................. 193 Projekt 12.4. Filmy (Doctrine, PHP, sortowanie) . ........................................................ 194

Rozdział 13. Zagadnienia dodatkowe dotyczące warstw M oraz V . ..................... 197 Czyszczenie zawartości bazy danych . .......................................................................... 197 Konwersja obiektu w napis ............................................................................................ 198 Konwersje toArray(), fromArray() . .............................................................................. 198 Warunkowe wstawianie nieistniejących obiektów . ...................................................... 200 Wielokrotne wykorzystanie widoku . ............................................................................ 201 Projekt 13.1. Aparaty foto (Propel, PHP) . .................................................................... 202 Warstwa M .............................................................................................................. 202 Wypełnianie bazy danych ....................................................................................... 205 Aplikacja ................................................................................................................. 206 Projekt 13.2. Aparaty foto (Doctrine, PHP) . ................................................................. 208 Rozszerzanie funkcjonalności klas wygenerowanych przez Doctrine .................... 209 Wstawianie rekordów do bazy danych . .................................................................. 211 Aplikacja . ................................................................................................................ 212

8

PHP, MySQL i MVC. Tworzenie witryn WWW opartych na bazie danych

Rozdział 14. Zapisywanie w bazie danych obrazów i plików binarnych . ............. 215 Zapisywanie w bazie danych zdjęć JPG . ...................................................................... 215 Prezentowanie zdjęć JPG zapisanych w bazie danych na stronie WWW ..................... 216 Zapisywanie w bazie danych dowolnych plików binarnych . ........................................ 218 Wysyłanie danych binarnych z bazy do przeglądarki . .................................................. 220 Projekt 14.1. NotH (Propel, PHP) .................................................................................. 221 Skrypt wstaw.php .................................................................................................... 223 Aplikacja . ................................................................................................................ 224 Tytuły stron ............................................................................................................. 225 Rozwijane menu pionowe ....................................................................................... 226 Wartości atrybutów href oraz src w tekstach zapisanych w bazie danych .............. 227 Projekt 14.2. NotH (Doctrine, PHP) . ............................................................................ 229 Skrypt wstaw.php .................................................................................................... 230 Aplikacja ................................................................................................................. 230

Rozdział 15. Akcje list i show, czyli publikowanie zawartości bazy danych w postaci witryny WWW . ............................................................. 233 Projekt 15.1. Czcionki projektów CSS Zen Garden (Propel, PHP) . ............................. 234 Aplikacja . ................................................................................................................ 235 Menu główne witryny oraz tytuły podstron . ........................................................... 240

Rozdział 16. Czego powinieneś nauczyć się z części drugiej? . .......................... 243

Część III Zwiększanie funkcjonalności interfejsu aplikacji internetowej . ............................................... 245 Rozdział 17. Kontekstowe hiperłącza do stron ze szczegółowymi informacjami .. 247 Projekt 17.1. Angaże (szablony PHP, Propel) . ............................................................. 248 Unikatowość kolumny slug ..................................................................................... 248 Pliki tekstowe o bardziej złożonej strukturze . ........................................................ 250 Rozszerzenia warstwy M ......................................................................................... 251 Filtry konwertujące generowany kod HTML . ........................................................ 260 Aplikacja ................................................................................................................. 261 Hiperłącza kontekstowe .......................................................................................... 263 Menu kontekstowe .................................................................................................. 264

Rozdział 18. Następny, poprzedni, czyli przewijanie zawartości witryny WWW .... 267 Projekt 18.1. PHP. Praktyczne projekty . ....................................................................... 269 Ograniczenia kluczy obcych .................................................................................... 270 Wstępne opracowanie aplikacji . ............................................................................. 271 Implementacja hiperłączy następny/poprzedni . ...................................................... 276 Hiperłącza link zawarte w nagłówku strony WWW . .............................................. 285

Rozdział 19. Wskaźnik położenia . .................................................................... 287 Projekt 19.1. Kolekcja płyt DVD z fotografiami . ......................................................... 288 Rozszerzanie klas dostępu do bazy danych . ........................................................... 291 Wypełnianie bazy danych rekordami . .................................................................... 295 Aplikacja . ................................................................................................................ 302 Translacje adresów stosujących cztery zmienne URL . ........................................... 304 Tabela zdjęć wykonana bez użycia tabel HTML . ................................................... 305 Wskaźniki następny/poprzedni do przewijania zdjęć i kategorii ............................ 306 Efekt rollover ze wskaźnikiem wybranej opcji . ...................................................... 307 Fotografie podążające za wskaźnikiem myszki . ..................................................... 307 Wskaźnik breadcrumbs ........................................................................................... 310

Spis treści

9

Rozdział 20. Sortowanie tabel . ........................................................................ 311 Projekt 20.1. Piłka nożna — sezon 2002/2003 . ............................................................ 312 Wielokrotne klucze obce z tej samej tabeli . ........................................................... 314 Sortowanie złączeń dla wielokrotnych kluczy . ....................................................... 314 Wypełnianie bazy danych ....................................................................................... 317 Zarys aplikacji ......................................................................................................... 320 Implementacja sortowalnych tabelek HTML . ........................................................ 320

Rozdział 21. Stronicowanie . ............................................................................ 331 Projekt 21.1. 33 ⅓ ......................................................................................................... 332 Automatyczne generowanie identyfikatorów slug dla rekordów o zdublowanych tytułach ...................................................................................... 333 Klasa Pager .............................................................................................................. 335 Widok wskaźnika stronicowania . ........................................................................... 343 Prezentacja rekordów poddanych stronicowaniu . ................................................... 345 Kontekstowe stronicowanie rekordów . .................................................................. 348

Rozdział 22. Alfabet . ....................................................................................... 351 Projekt 22.1. Imiona ...................................................................................................... 351 Wybieranie alfabetu liter ......................................................................................... 352 Komponent wyświetlający alfabet . ............................................................................... 353 Prezentacja liter rozpoczynających się od wybranej litery na stronie WWW ......... 354 Umieszczanie kontrolki z listą liter w szablonie layout html ................................. 355

Rozdział 23. Chmura tagów . ........................................................................... 357 Projekt 23.1. Katalog Open Clipart . ............................................................................. 358 Wypełnianie bazy danych ....................................................................................... 360 Waga słów kluczowych ........................................................................................... 363 Aplikacja . ................................................................................................................ 365

Rozdział 24. Spis treści . ................................................................................. 371 Projekt 24.1. Artykuły ................................................................................................... 372 Wypełnianie bazy danych rekordami . .................................................................... 373 Funkcje odpowiedzialne za odczytywanie i usuwanie fragmentów kodu HTML .....376 Funkcje odpowiedzialne za tworzenie spisu treści . ................................................ 378 Kolorowanie składni ............................................................................................... 380 Aplikacja . ................................................................................................................ 381

Rozdział 25. Czego powinieneś nauczyć się z części trzeciej? . ......................... 383

Część IV Formaty danych . ....................................................... 385 Rozdział 26. Podstawy przetwarzania dokumentów XML w PHP . ...................... 387 Klasa SimpleXML ......................................................................................................... 387 Tworzenie obiektu SimpleXMLElement . ............................................................... 388 Dostęp do węzłów drzewa ....................................................................................... 389 Lista identycznych elementów . .............................................................................. 390 Dostęp do atrybutów ............................................................................................... 391 Przetwarzanie wszystkich elementów i ich atrybutów . .......................................... 391 Wielokrotne zagnieżdżenia ..................................................................................... 392 Język XPath ............................................................................................................. 395 Przykładowe dokumenty XML dostępne w internecie . ................................................ 395 Kursy walut ............................................................................................................. 395 Książki wydawnictwa Helion . ................................................................................ 397 Projekt 26.1. Turniej Czterech Skoczni . ....................................................................... 398 Aplikacja . ................................................................................................................ 400

10

PHP, MySQL i MVC. Tworzenie witryn WWW opartych na bazie danych

Rozdział 27. Generowanie dokumentów XML w PHP . ....................................... 403 Statyczne pliki XML ..................................................................................................... 403 Generowanie dokumentu XML w PHP . ....................................................................... 405 Echo — drukowanie kodu XML ................................................................................... 406 Generowanie XML na podstawie tablicy . .................................................................... 407 Generowanie XML na podstawie pliku tekstowego . .................................................... 408 Zapisywanie kodu XML do pliku .................................................................................. 409 Konwersja pliku tekstowego do formatu XML . ........................................................... 409 Dane w formacie XML opisujące witrynę WWW . ....................................................... 410 Mapa witryny: sitemap xml ..................................................................................... 410 Kanał RSS ............................................................................................................... 411 Projekt 27.1. Kursy walut .............................................................................................. 412 Ustalanie adresów dokumentów XML z kursami walut . ........................................ 412 Projekt bazy danych ................................................................................................ 413 Wypełnianie bazy danych rekordami . .................................................................... 413 Aplikacja . ................................................................................................................ 415 Kanał RSS ............................................................................................................... 415 Mapa witryny .......................................................................................................... 416 Wykresy kursów walut ............................................................................................ 418

Rozdział 28. XML_Serializer, XML_Unserializer — dwukierunkowe transformacje tablic w XML . ......................... 423 XML_Serializer ............................................................................................................. 423 Konwersja tablicy w kod XML . ............................................................................. 423 Tablica asocjacyjna ................................................................................................. 424 Opcje . ...................................................................................................................... 425 Tablica opcji ............................................................................................................ 426 Jednowymiarowa tablica indeksowana . .................................................................. 426 Wielowymiarowe tablice indeksowane . ................................................................. 427 Atrybuty . ................................................................................................................. 428 Wybiórcze stosowanie atrybutów . .......................................................................... 429 Przekształcenia ........................................................................................................ 430 XML_Serializer — przykłady ....................................................................................... 431 Projekt 28.1. Konwersja pliku nobel.txt . ...................................................................... 431 Projekt 28.2. Konwersja pliku mecze.txt . ..................................................................... 432 Projekt 28.3. Konwersja pliku tcs.txt . ........................................................................... 434 Klasa XML_Unserializer ............................................................................................... 436 Podstawowe użycie ................................................................................................. 436 Odczyt pliku ............................................................................................................ 437 Parsing atrybutów .................................................................................................... 437 Konwersja formatu XML .............................................................................................. 439 Projekt 28.4. Konwersja jeden-w-wiele . ....................................................................... 439 Projekt 28.5. Konwersja wiele-w-jeden . ....................................................................... 440 Projekt 28.6. Klasyfikacja zwierząt . ............................................................................. 441 Wypełnianie bazy danych rekordami . .................................................................... 442 Moduły i akcje aplikacji .......................................................................................... 443 Akcja main/drzewo ................................................................................................. 444 Kanał RSS . .............................................................................................................. 444 Generowanie statycznego dokumentu sitemap xml . ............................................... 447

Rozdział 29. Arkusze kalkulacyjne MS Excel XLS . ........................................... 449 Odczyt pliku XLS .......................................................................................................... 449 Odczyt kilku arkuszy ............................................................................................... 451 Tworzenie pliku XLS .................................................................................................... 452

Spis treści

11 Wysyłanie arkusza do przeglądarki . ............................................................................. 453 Konwersja pliku tekstowego do formatu XLS . ...................................................... 453 Konwersja pliku XLS do formatu tekstowego . ............................................................. 454 Projekt 29.1. Generowanie danych autokomisu . ........................................................... 455 Projekt 29.2. Autokomis ................................................................................................ 460 Wypełnianie bazy danych rekordami . .................................................................... 460 Aplikacja . ................................................................................................................ 465

Rozdział 30. Konwersja plików z danymi . ....................................................... 467 Format danych tekstowych ............................................................................................ 467 Format danych XML ..................................................................................................... 469 Format danych XLS ...................................................................................................... 470 Projekt 30.1. Konwersja formatu TXT do formatu XML . ............................................ 470 Projekt 30.2. Konwersja formatu TXT do formatu XLS . ............................................. 474 Projekt 30.3. Konwersja formatu XML do formatu TXT . ............................................ 476 Projekt 30.4. Konwersja formatu XML do formatu XLS . ............................................ 477 Projekt 30.5. Konwersja formatu XLS do formatu TXT . ............................................. 478 Projekt 30.6. Konwersja formatu XLS do formatu XML . ............................................ 480 Projekt 30.7. Zestawienia artykułów „Magazynu INTERNET” . .................................. 480 Aplikacja . ................................................................................................................ 483 Akcja list prezentująca sortowalną i stronicowaną tabelkę HTML ........................ 484 Akcja show prezentująca sortowalną i stronicowaną tabelkę HTML ..................... 486

Rozdział 31. Skompresowane dokumenty XML zawierające dane binarne . ......... 489 Kodowanie base64 ......................................................................................................... 490 Dekodowanie base64 ..................................................................................................... 490 Kompresja danych ......................................................................................................... 491 Dekompresja danych ..................................................................................................... 492 Projekt 31.1. Format danych systemu do publikowania artykułów .............................. 493 Umieszczanie ilustracji, listingów, ramek i tabel w treści artykułu ........................ 495 Projekt 31.2. Konwersja artykułu z formatu tekstowego do spakowanego pliku XML . .......................................................................................................................... 495 Projekt 31.3. System publikacji artykułów w postaci witryny WWW .......................... 498 Baza danych ............................................................................................................ 499 Propel i dostęp tylko do wybranych kolumn tabeli . ............................................... 499 Wypełnianie bazy danych ....................................................................................... 501 Aplikacja ................................................................................................................. 508

Rozdział 32. Czego powinieneś nauczyć się z części czwartej? . ....................... 511 Skorowidz . .................................................................................. 513

12

PHP, MySQL i MVC. Tworzenie witryn WWW opartych na bazie danych

Wstęp Książka PHP, MySQL i MVC. Tworzenie witryn WWW opartych na bazie danych jest poświęcona tworzeniu witryn WWW w języku PHP. Zawiera ona zwięzły opis oraz mnóstwo przykładów wyjaśniających nowoczesne rozwiązania i obecnie panujące trendy w dziedzinie webmasteringu. Treść podręcznika koncentruje się wokół wzorca architektonicznego MVC i jest podzielona na cztery części:  Część I: „Akcje, widoki, translacje adresów URL i bazy danych, czyli podstawy

użycia MVC”  Część II: „Operowanie klasami wygenerowanymi przez Propel oraz Doctrine”  Część III: „Zwiększanie funkcjonalności interfejsu aplikacji internetowej”  Część IV: „Formaty danych”

Pierwsza część wyjaśnia podstawy użycia MVC. Wprowadza ona podział aplikacji na moduły i akcje oraz wyjaśnia szczegółowo, w jaki sposób definiujemy strukturę aplikacji. Znajomość rozwiązań opartych o MVC jest kluczowym momentem pozwalającym na przejście od pisania skryptów do tworzenia aplikacji. Główną cechą projektów powstających z wykorzystaniem MVC jest to, że aplikacja jest tworzona i rozwijana jako jeden duży spójny program, w którym nowe funkcje definiujemy w postaci modułów i akcji. Omówienie części pierwszej kończymy, wyjaśniając proces projektowania bazy danych oraz metody uzyskiwania dostępu do bazy danych z wnętrza skryptu PHP. Omówione projekty wykorzystują MVC, w którym warstwą dostępu do bazy danych są obiekty wygenerowane przez oprogramowanie Propel lub Doctrine, kod HTML zaś jest generowany przez widoki napisane w językach PHP lub Smarty. Otrzymane w ten sposób cztery rozwiązania:  MVC, Propel, szablony PHP;  MVC, Propel, szablony Smarty;  MVC, Doctrine, szablony PHP;  MVC, Doctrine, szablony Smarty;

14

PHP, MySQL i MVC. Tworzenie witryn WWW opartych na bazie danych

pokazują, że kluczowym czynnikiem mającym wpływ na efektywność tworzonych aplikacji jest użycie MVC systemu ORM oraz szablonów, natomiast decyzje:  Czy w roli warstwy M użyć Propel czy Doctrine?  Czy w roli warstwy V użyć PHP czy Smarty?

są drugorzędne. Druga część podręcznika jest poświęcona oprogramowaniom Propel oraz Doctrine. Są to dwa najlepsze obecnie systemy ORM dla języka PHP. Zadaniem systemu ORM jest wygenerowanie klas, które zapewnią dostęp do bazy danych. Operowanie danymi zawartymi w bazie sprowadza się wówczas do operacji na obiektach. Bazę danych projektujemy wizualnie w programie MySQL Workbench, a następnie uruchamiamy skrypt, który wygeneruje klasy dostępu. Jeśli nie znasz żadnego systemu ORM, to opisane rozwiązania zmienią twoje podejście do procesu projektowania baz danych! Kolejna, trzecia część podręcznika skupia się na interfejsie aplikacji internetowej. Opisane projekty szczegółowo wyjaśniają, w jaki sposób zwiększyć funkcjonalność witryny WWW, w szczególności:  Jak wykonać hiperłącza następny/poprzedni pozwalające na przewijanie rekordów?  W jaki sposób wykonać stronicowanie?  Jak zaimplementować wskaźnik położenia?  Jak wykonać tabele HTML pozwalające na sortowanie danych względem

dowolnych kolumn?  W jaki sposób przygotować chmurę tagów?  Jak sporządzić alfabet umożliwiający wybór rekordów rozpoczynających się

od zadanej litery?  Wreszcie, w jaki sposób automatycznie wygenerować interaktywny spis treści?

Ostatnia część podręcznika zawiera opis wykorzystania dwóch formatów danych: XML oraz XLS. Cały materiał zawarty w książce jest dokładnie zilustrowany przykładami. Czytając książkę, należy najpierw przeanalizować, a następnie samodzielnie wykonać wszystkie projekty. Książka jest skierowana do osób znających podstawy języków PHP oraz HTML.

Część I

Akcje, widoki, translacje adresów URL i bazy danych, czyli podstawy użycia MVC

Rozdział 1.

Hello world — pierwsza aplikacja korzystająca z MVC Model architektoniczny MVC (ang. Model-View-Controller) w znacznym stopniu upraszcza tworzenie aplikacji internetowych. Wprowadza on ich podział na trzy niezależne składowe:  warstwę M (model),  warstwę V (widok),  warstwę C (kontroler).

Sercem aplikacji jest warstwa C, która odpowiada między innymi za przetwarzanie żądań HTTP oraz sterowanie przebiegiem wykonania całej aplikacji. Kontroler uzyskuje dostęp do danych zapisanych w bazie danych za pośrednictwem warstwy M. Rolą warstwy M jest dostarczenie kontrolerowi wygodnego interfejsu do komunikacji z bazą danych. Dane pobrane przez kontroler za pośrednictwem warstwy M są formatowane przy użyciu szablonów nazywanych widokami. Przetworzone widoki generują kod HTML, który jest ostatecznie wysyłany do przeglądarki WWW. Wygoda korzystania z modelu MVC wynika stąd, że ten sam kod kontrolera C może być wykorzystany w bardzo wielu różnych aplikacjach, gdyż przebieg przetwarzania żądań HTTP i wysyłania stron WWW do przeglądarki jest niezależny od danych prezentowanych na stronie oraz od kodu HTML/CSS generowanych witryn. Pierwszym krokiem do opanowania MVC jest umiejętność użycia kontrolera.

W większości współczesnych bibliotek kontroler jest implementowany z wykorzystaniem technik programowania obiektowego. Jego zadanie polega na dostarczeniu mechanizmu programistycznego do przetworzenia żądania HTTP w wykonanie odpowiedniej

18

Część I  Akcje, widoki, translacje adresów URL i bazy danych

funkcji PHP oraz przetworzenie odpowiedniego szablonu HTML. Zadanie to możemy sformułować następująco: W odpowiedzi na adres powitanie.html w aplikacji ma zostać wykonana funkcja execute_strona() oraz przetworzony ma zostać szablon strona.html. W ten sposób wykonanie strony WWW sprowadzi się do:  podania reguły przyporządkowania adresowi powitanie.html funkcji execute_strona() i szablonu strona.html;  zaimplementowania funkcji execute_strona();  oraz utworzenia szablonu strona.html.

Podział pracy kontrolera na osobne funkcje jest obecnie1 wykonywany dwupoziomowo. Pomaga to w zarządzaniu większymi projektami. Kontroler jest dzielony na moduły, a moduły — na akcje. Moduły zwykle są definiowane w postaci oddzielnych folderów, a akcje — jako metody klasy. Również przetwarzanie szablonu jest wykonywane dwuetapowo. Wynikowy kod HTML powstaje po przetworzenia dwóch szablonów: układu witryny oraz widoku akcji. Podejście takie ułatwia modyfikowanie układu wszystkich podstron aplikacji bez konieczności ingerencji w kod widoków.

Projekt 1.1. Hello world! Wykorzystując kontroler MVC zaimplementowany w postaci klasy Controller zawartej w pliku controller.class.php, napisz aplikację, która będzie zawierała jedną stronę WWW o adresie pierwszy-projekt.html. W treści strony umieść komunikat Hello world!.

Wykonanie projektu 1.1 sprowadza się do pięciu prostych kroków:  krok pierwszy: utworzenie modułu o nazwie main;  krok drugi: zdefiniowanie akcji o nazwie hello w module main, czyli:  implementacja metody execute_hello();  utworzenie widoku hello.html;  krok trzeci: utworzenie układu witryny WWW layout.html,  krok czwarty: ustalenie reguły translacji adresu pierwszy-projekt.html na wykonanie akcji hello modułu main;  krok piąty: napisanie skryptu index.php.

1

Takie rozwiązanie jest wykorzystywane m.in. w Symfony oraz Zend Framework — dwóch najważniejszych frameworkach dostępnych dla języka PHP.

Rozdział 1.  Hello world — pierwsza aplikacja korzystająca z MVC

19

Krok pierwszy: utworzenie modułu main Nowy moduł aplikacji definiujemy, tworząc folder o nazwie takiej samej jak modułu, czyli folder o nazwie main/.W folderze tym należy umieścić plik actions.class.php zawierający definicję klasy Actions, która dziedziczy po klasie ActionsBase. Nowo zdefiniowana klasa może być początkowo pusta.

Krok drugi: utworzenie akcji hello w module main W celu utworzenia nowej akcji należy:  ustalić nazwę akcji;  zaimplementować funkcję wykonywaną po wystąpieniu akcji;  utworzyć szablon służący do formatowania wyników działania funkcji.

Nazwę akcji ustalamy jako hello. Akcja hello modułu main będzie określana w skrócie jako akcja main/hello.

Z nazwy akcji wynika nazwa metody uruchamianej po wystąpieniu akcji oraz nazwa widoku. Funkcją uruchamianą po wystąpieniu akcji main/hello będzie metoda execute_ hello() klasy Actions modułu main. Widok akcji main/hello zaś będzie zawarty w pliku main/hello.html. Nazwa pliku widoku jest identyczna jak nazwa akcji i ma rozszerzenie .html. Najpierw w klasie Actions modułu main dodajemy pustą metodę execute_hello(). Gotowy plik main/actions.class.php jest przedstawiony na listingu 1.1. Listing 1.1. Plik main/actions.class.php z projektu 1.1 na listingu 1.1. Jest to zamierzone działanie, którego celem jest uniknięcie problemów pojawiających się wówczas, gdy po znaczniku zamykającym występują białe znaki.

Następnie tworzymy plik main/hello.html. W jego treści wprowadzamy komunikat powitalny Hello world!, jak to zostało przedstawione na listingu 1.2. Zwróć uwagę, że kod HTML nie zawiera elementów html, head, title czy body. Jest to tylko fragment strony WWW, który zostanie umieszczony wewnątrz większej całości.

20

Część I  Akcje, widoki, translacje adresów URL i bazy danych

Listing 1.2. Widok akcji main/hello zawarty w pliku main/hello.html Hello world!

Krok trzeci: utworzenie układu witryny WWW Układ generowanej witryny WWW pochodzi z pliku layout.html, zawartego w folderze templates/. W pliku tym umieszczamy zarys kompletnej strony WWW, a więc m.in. znaczniki html, head i title. W treści witryny w dowolnym miejscu wlewamy wynik przetwarzania akcji. Zadanie to realizuje instrukcja:

Kompletny kod HTML/PHP zawarty w pliku templates/layout.html jest przedstawiony na listingu 1.3. Listing 1.3. Szablon templates/layout.html

Pierwszy projekt





Krok czwarty: reguła translacji adresu pierwszy-projekt.html na wykonanie akcji main/hello W kolejnym kroku definiujemy regułę, która spowoduje, że po odwiedzeniu adresu URL pierwszy-projekt.html wykonana zostanie akcja main/hello. Reguła ta jest zapisana w pliku translations.txt i ma następującą postać: /pierwszy-projekt.html

index.php?module=main&action=hello

Plik translations.txt jest plikiem tekstowym, w którym każdy wiersz zawiera dwie kolumny: przyjazny adres URL oraz wewnętrzny adres URL. W powyższej linijce adresem przyjaznym jest adres: /pierwszy-projekt.html

adresem wewnętrznym zaś: index.php?module=main&action=hello

Adresy przyjazne są dowolnymi napisami. W miejsce adresu /pierwszy-projekt.html możesz użyć adresu /pierwszy/projekt.html, /pierwszy/projekt/nowy/index.html lub dowolnego innego. Natomiast adres wewnętrzny wskazuje skrypt index.php i definiuje

Rozdział 1.  Hello world — pierwsza aplikacja korzystająca z MVC

21

dwie zmienne: module oraz action. Zmienna module jest nazwą modułu, a action — nazwą akcji, która ma zostać wykonana. Przedstawiona reguła: /pierwszy-projekt.html

index.php?module=main&action=hello

powoduje, że po otrzymaniu żądania /pierwszy-projekt.html kontroler wykona akcję hello modułu main. Podobnie reguła: /a/b/c.html

index.ph?module=inny&action=projekt

powoduje, że po otrzymaniu żądania /a/b/c.html kontroler wykona akcję inny/projekt. Jak widać na listingu 1.4, w pliku translations.txt warto dodać regułę, w której adresem przyjaznym jest /. Dzięki temu strona WWW będzie widoczna od razu po odwiedzeniu odpowiedniego folderu, bez konieczności wpisywania adresu pierwszy-projekt.html. Listing 1.4. Reguły translacji zawarte w pliku translations.txt /pierwszy-projekt.html /

index.php?module=main&action=hello index.php?module=main&action=hello

Krok piąty: skrypt index.php Jedyną czynnością, którą należy wykonać w skrypcie index.php, jest uruchomienie kontrolera MVC. Należy więc dołączyć odpowiednie klasy, utworzyć obiekt $controller i wywołać jego metodę dispatch(). Kompletny skrypt index.php został przedstawiony na listingu 1.5. Listing 1.5. Skrypt index.php error_reporting(E_ALL); ini_set('display_errors', 1); set_include_path( '../scripts' . PATH_SEPARATOR . '../scripts/include' . PATH_SEPARATOR . get_include_path() ); require_once 'controller.class.php'; $controller = new Controller(); $controller->dispatch();

Dwie pierwsze instrukcje: error_reporting(E_ALL); ini_set('display_errors', 1);

włączają wyświetlanie komunikatów diagnostycznych. Dzięki nim — bez względu na konfigurację PHP — błędy w skryptach będą wyświetlane w przeglądarce. Ułatwi to ewentualne ich wyszukiwanie.

Część I  Akcje, widoki, translacje adresów URL i bazy danych

22

Funkcja set_include_path() wywołana na początku skryptu index.php zmienia ścieżki poszukiwań. Dzięki niej oraz dzięki mechanizmowi automatycznego ładowania klas zmniejszymy ilość niezbędnych instrukcji require_once. Instrukcja: set_include_path( '../scripts' . PATH_SEPARATOR . '../scripts/include' . PATH_SEPARATOR . get_include_path() );

powoduje odczytanie bieżących ścieżek dostępu zdefiniowanych parametrem include_ path w pliku php.ini. Następnie do odczytanych ścieżek dołączamy ścieżki ../scripts oraz ../scripts/include i otrzymany napis przekazujemy jako parametr do funkcji set_ include_path(). Instrukcja ta dołącza więc do bieżących ścieżek poszukiwań dwie ścieżki: ../scripts oraz ../scripts/include. Głównym zadaniem skryptu index.php jest uruchomienie kontrolera MVC. Po dołączeniu klasy Controller: require_once 'controller.class.php';

tworzymy obiekt $controller i wywołujemy jego metodę dispatch(): $controller = new Controller(); $controller->dispatch();

Metoda dispatch() zajmie się przetworzeniem żądania HTTP, wykonaniem metody execute_hello() oraz przetworzeniem widoków layout.html i hello.html. Dokument HTML uzyskany po przetworzeniu widoków zostanie wysłany do przeglądarki.

Pliki, które należy utworzyć Pełne zestawienie plików, które należy utworzyć, wykonując projekt 1.1, jest przedstawione na rysunku 1.1. Ich pełna zawartość zaś jest przedstawiona na listingach 1.1, 1.2, 1.3, 1.4 oraz 1.5. Rysunek 1.1. Pliki, które należy samodzielnie utworzyć, wykonując projekt 1.1

Rozdział 1.  Hello world — pierwsza aplikacja korzystająca z MVC

23

Zwróć uwagę na strukturę folderów. Kod skryptu index.php jest zawarty w folderze www/, zaś wszystkie pozostałe pliki — w folderze scripts/. Folder scripts/ jest dalej podzielony na foldery modules/ oraz templates/. W folderze modules/ zawarte są wszystkie moduły aplikacji. Każdy moduł jest zawarty w osobnym folderze, którego nazwa jest taka sama jak nazwa modułu.

Uruchomienie projektu W celu uruchomienia omawianego projektu do plików przedstawionych na rysunku 1.1 należy dodać pliki kontrolera MVC. Wykorzystany kontroler jest zaimplementowany z wykorzystaniem kilku dodatkowych klas oraz funkcji zawartych w plikach: actionsbase.class.php, controller.class.php, helpers.inc.php, phpview.class.php, urltranslator.class.php, view.class.php. Niezbędne są także dwa pliki .htaccess: jeden umieszczamy w folderze www/, a drugi — w folderze scripts/, oraz funkcje pomocnicze z folderu include/. Pełne zestawienie plików tworzących projekt 1.1 jest przedstawione na rysunku 1.2. Rysunek 1.2. Komplet plików tworzących projekt 1.1

Plik www/.htaccess zawiera reguły, które przekierowują wszystkie żądania HTTP do skryptu index.php: DirectoryIndex index.php RewriteEngine on RewriteRule .* index.php

Natomiast rolą pliku scripts/.htaccess jest ochrona kodu PHP aplikacji przed niepowołanym dostępem. Reguła:

Część I  Akcje, widoki, translacje adresów URL i bazy danych

24

Order allow,deny Deny from all

wyłącza widoczność zawartości folderu scripts/ protokołem HTTP. Jedynym folderem projektu pierwszego, który uda Ci się odwiedzić przeglądarką WWW, jest folder www/. Pozostałe foldery, np. scripts/modules/, w ogóle nie będą widoczne w przeglądarce, co zostało przedstawione na rysunku 1.3. Rysunek 1.3. Reguły z pliku scripts/.htaccess wyłączają widoczność folderu scripts/ w przeglądarce

Przebieg wykonania Po wejściu do folderu www/ przedstawionego na rysunku 1.3 ujrzymy witrynę z rysunku 1.4. Rysunek 1.4. Witryna wyświetlana po odwiedzeniu folderu www/ z rysunku 1.3

Rozdział 1.  Hello world — pierwsza aplikacja korzystająca z MVC

25

Wyświetlenie witryny z rysunku 1.4 jest wynikiem następujących zdarzeń: po wejściu do folderu www/ widocznego na rysunku 1.3 przeglądarka wysyła do serwera żądanie: GET /projekt-01-01/www/ HTTP/1.1

Reguła: RewriteRule .*

index.php

zawarta w pliku /projekt-01-01/www/.htaccess, powoduje, że żądanie to jest skierowane do skryptu /projekt-01-01/www/index.php przedstawionego na listingu 1.5. W skrypcie tym uruchamiamy kontroler MVC. Kontroler najpierw wykonuje translację adresu URL. Z adresu URL otrzymanego w żądaniu HTTP: GET /projekt-01-01/www/ HTTP/1.1

usuwana jest nazwa folderu, w którym znajduje się skrypt index.php, czyli /projekt-01-01/ www. Po odcięciu przedrostka: /projekt-01-01/www

z adresu /projekt-01-01/www/

zostaje adres bieżącego żądania: jeden znak /. Następnie kontroler przeszukuje plik translations.txt w poszukiwaniu adresu przyjaznego /. Odnajduje regułę: /

index.php?module=main&action=hello

Na podstawie tej reguły kontroler ładuje klasę Actions modułu main (zawartą w pliku modules/main/actions.class.php), po czym uruchamia metodę execute_hello(). Po wykonaniu tej metody przetwarzany jest szablon templates/layout.html, w treści którego dołączony jest widok akcji main/hello (zawarty w pliku modules/main/hello.html). Kod HTML otrzymany po przetworzeniu szablonu jest wysyłany jako odpowiedź do przeglądarki.

Ćwiczenie 1.1 Rozpoczynając pracę od pliku cw-01-01-start.zip, wykonaj samodzielnie projekt 1.1.

Ćwiczenie 1.2 Rozpoczynając pracę od pliku cw-01-01-start.zip, wykonaj samodzielnie projekt, który będzie prezentował jedną stronę WWW z tekstem Lorem ipsum. Zadanie rozwiąż w taki sposób, by w aplikacji pojawił się moduł my oraz akcja my/tekst. Adresem strony prezentującej tekst Lorem ipsum ma być wyłącznie napis lorem.html.

26

Część I  Akcje, widoki, translacje adresów URL i bazy danych

Ćwiczenie 1.3 Wykonaj aplikację, która będzie zawierała trzy strony WWW o adresach: kot.html, lis.html oraz pies.html. Na każdej ze stron ma się pojawiać jeden wyraz: KOT, LIS lub PIES. W aplikacji tej zdefiniuj moduły kot, lis i pies i trzy akcje kot/pierwsza, lis/druga oraz pies/trzecia. Zadanie rozwiąż tak, by każda ze stron była dostępna pod dwoma różnymi adresami URL:  kot.html oraz moj/maly/kotek.html;  pies.html oraz moj/duzy/piesek.html;  list.html oraz nie/moj/lisek.

Zadanie wykonaj, rozpoczynając pracę od pliku cw-01-01-start.zip. Po wykonaniu zadania odwiedź wszystkie sześć adresów URL.

Rozdział 2.

Dołączanie zewnętrznych zasobów .css, .jpg, .js Pierwszym problemem, jaki dotyczy zewnętrznych zasobów, jest reguła: RewriteRule .*

index.php

zawarta w pliku www/.htaccess. Przekazuje ona wszystkich żądania HTTP do skryptu index.php. Jeśli więc w folderze www/ umieścimy plik foto.jpg, to i tak nie uda nam się go zobaczyć w przeglądarce WWW. Po odwiedzeniu adresu www/foto.jpg żądanie HTTP zostanie bowiem skierowane do pliku index.php. Musimy więc zdefiniować wyjątki, które spowodują, że niektóre żądania HTTP nie będą przekazywane do skryptu index.php. Najwygodniejszym rozwiązaniem jest utworzenie folderu img/ i umieszczenie w nim — obok pliku foto.jpg — pliku .htaccess o zawartości: RewriteEngine off

Spowoduje to wyłączenie przekierowań HTTP dla wszystkich plików zawartych w folderze img/. W podobny sposób rozwiążemy problem stylów CSS, umieszczając je w folderze css/ i wyłączając mod_rewrite. Innym rozwiązaniem problemu przekierowań jest użycie reguł warunkowych. Reguła poprzedzona warunkiem: RewriteCond %{REQUEST_URI} !\.css$ RewriteRule .* index.php

przekierowuje do skryptu index.php wszystkie żądania z wyjątkiem zakończonych rozszerzeniem .css.

Drugim problemem dotyczącym zewnętrznych plików dołączanych do strony WWW są ścieżki dostępu. Co się stanie, gdy do witryny dołączymy style z pliku style.css, po czym zmienimy przyjazny adres URL? Style staną się niedostępne. Jeśli w aplikacji zdefiniujemy akcję strona/glowna i określimy translację adresu przyjaznego następująco:

Część I  Akcje, widoki, translacje adresów URL i bazy danych

28 /strona-glowna.html

index.php?module=strona&action=glowna

to po zmianie powyższej reguły na: /strona/glowna.html

index.php?module=strona&action=glowna

style dołączone znacznikiem:

z powodu braku odwołania do folderu nadrzędnego przy użyciu dwóch kropek1 będą niedostępne. W celu uniezależnienia folderu dostępu do zasobów od stosowanych przyjaznych URL wykorzystamy zmienną $path_prefix prowadzącą do folderu, w którym znajduje się skrypt index.php. Za ustalenie wartości zmiennej $path_prefix odpowiada kontroler, mamy więc do niej dostęp w szablonach bez konieczności pisania żadnego kodu PHP. Jeśli style CSS dołączymy, wykorzystując zmienną $path_prefix:





Akcja fraszka/show odpowiada za wyświetlenie tekstu wybranej fraszki. Do identyfikacji fraszki użyjemy zmiennej URL o nazwie slug. Jej wartością będzie napis slug utworzony na podstawie tytułu fraszki. Zatem wewnętrzny URL dla fraszki Do gościa przyjmie postać: index.php?module=fraszka&action=show&slug=do_goscia

a dla fraszki Na swoje księgi: index.php?module=fraszka&action=show&slug=na_swoje_ksiegi

Wartość zmiennej slug zawartej w adresie URL jest dostępna w tablicy $_GET pod indeksem slug. A zatem pierwszą czynnością wykonaną w metodzie execute_show() modułu fraszka będzie sprawdzenie, czy została podana poprawna zmienna URL: if ( isset($_GET['slug']) && str_ivslug($_GET['slug']) && in_array($_GET['slug'], $this->controller->slugi) ) { ... } else { $this->execute_404(); }

Rozdział 5.  Pre- i postprzetwarzanie

65

Warunek powyższej instrukcji if sprawdza, czy zmienna $_GET['slug']:  istnieje (funkcja isset());  składa się z dozwolonych znaków i jej długość nie przekracza 255 znaków (funkcja str_ivslug()1);  czy podana wartość występuje w tablicy $this->controller->slugi2 (funkcja in_array()).

Jeśli którykolwiek z powyższych warunków nie jest spełniony, to wywołujemy metodę execute_404(), która spowoduje wyświetlenie błędu 404. Jeśli natomiast warunki były spełnione, to wywołując funkcję array_search(), ustalamy indeks podanego napisu slug w tablicy $this->controller->slugi: $index = array_search($_GET['slug'], $this->controller->slugi);

Na podstawie ustalonego indeksu za pomocą funkcji file() odczytujemy plik z treścią fraszki. Nazwa pliku jest dostępna w zmiennej3: $this->controller->menu[$index]['nazwapliku']

Po odczytaniu pliku z treścią fraszki usuwamy pierwszy wiersz pliku, konwertujemy fraszkę z tablicy napisów w jeden napis i przekazujemy do widoku jako zmienną o nazwie tresc: $tresc = file($this->controller->menu[$index]['nazwapliku']); $tresc[0] = ''; $tresc = implode('', $tresc); $this->set('tresc', $tresc);

Przetwarzanie kończymy, przekazując do widoku także tytuł fraszki: $this->set('tytul', $this->controller->menu[$index]['tytul']);

Podsumowując, z metody execute_show() do widoku show.html są przekazane dwa napisy. Pierwszy z nich nazywa się tresc i zawiera tekst fraszki. Drugi nazywa się tytul i zawiera tytuł fraszki. W przedstawionym na listingu 5.6 widoku drukujemy wartości dwóch zmiennych: $tytul oraz $tresc. Wartość zmiennej $tytul jest drukowana tak jak dotychczas:

Wydruk zmiennej $tresc zaś wykorzystuje dodatkowo metodę nl2br():

Dzięki temu w treści fraszki znaki złamania wiersza zostaną poprzedzone znacznikami
. 1

Funkcja str_ivslug() jest zawarta w pliku walidacja.inc.php.

2

Tablicę $this->controller->slugi utworzyliśmy w metodzie preActions().

3

Tablica $this->controller->menu została utworzona w metodzie preActions().

66

Część I  Akcje, widoki, translacje adresów URL i bazy danych

Kolejnym plikiem, który musimy wykonać, jest przedstawiony w zarysie na listingu 5.7 układ witryny layout.html. Listing 5.7. Plik layout.html projektu 5.1









  • Treść witryny jest dołączana przez omówioną w poprzednich rozdziałach instrukcję include, zawartą w sekcji div. Nowym elementem układu jest wykonane przy użyciu listy numerowanej ol/li menu witryny. Każda pozycja listy ol jest jednym elementem menu. Naszym zadaniem jest wygenerowanie menu zbliżonego do:

  • Na nabożną
  • Raki
  • ...

    Menu to powstaje na podstawie tablicy $menu przekazanej do szablonu w metodzie preActions(). Każdy element tablicy $menu zawiera informacje o jednej opcji menu. Zatem tablicę $menu przetwarzamy iteracyjnie w pętli foreach:

    ...

    Na podstawie kolejnego jej elementu zawartego w zmiennej $opcja drukujemy tytuł:

    oraz wewnętrzny adres URL: index.php?module=fraszka&action=show&slug=

    W ten sposób powstanie element li zawierający hiperłącze z wewnętrznym adresem URL oraz tytułem fraszki, np.:


  • Do gościa



  • Rozdział 5.  Pre- i postprzetwarzanie

    67

    Adresy wewnętrzne zostaną na zakończenie przetwarzania kontrolera przekonwertowane do postaci przyjaznej. Pozostaje więc nam już tylko zdefiniowanie reguł translacji adresów URL. W pliku translations.txt umieszczamy trzy reguły przedstawione na listingu 5.8. Listing 5.8. Reguły translacji adresów URL w projekcie 5.1 /index.html / /REGEXP1.html

    index.php?module=fraszka&action=show&slug=do_goscia index.php?module=fraszka&action=show&slug=do_goscia index.php?module=fraszka&action=show&slug=REGEXP1

    Pierwsza reguła powoduje, że adres index.html zostanie przekierowany do strony o adresie wewnętrznym: index.php?module=fraszka&action=show&slug=do_goscia

    Zatem po odwiedzeniu strony index.html ujrzymy treść fraszki identyfikowanej za pomocą napisu do_goscia. Będzie to oczywiście fraszka zatytułowana Do gościa. Druga reguła powoduje, że strona z tekstem fraszki Do gościa będzie wyświetlana po odwiedzeniu folderu www/. Najbardziej skomplikowaną regułą jest reguła trzecia. Napis REGEXP1 w niej zawarty jest synonimem wyrażenia regularnego: ([^\/" &]+)

    Wyrażenie regularne: ([^\/" &]+)

    zawiera:  przechwytywanie ();  negację zbioru znaków [^];  cytowanie ukośnika odwrotnym ukośnikiem; kombinacja dwóch znaków \/ jest rozumiana jako jeden znak / pozbawiony swego specjalnego znaczenia (zwykle jest on ogranicznikiem całego wyrażenia regularnego);  kwantyfikator + pozwalający na dowolną, ale większą od zera, liczbę wystąpień poprzedzającego go znaku. Zatem pasuje ono do dowolnego ciągu cyfr, liter i innych znaków różnych od /" &. Na przykład pasuje do całego napisu do_goscia i spowoduje przechwycenie go.

    Wyrażenie to jest wstawiane w miejsce napisów REGEXP1 w regule trzeciej. Reguła wejściowa: /REGEXP1.html

    zostanie przekształcona do postaci: /([^\/" &]+).html

    Po dopasowaniu do adresu URL zawartego w bieżącym żądaniu, np. /na_nabozna.html, spowoduje ona przechwycenie fragmentu na_nabozna. Przechwycony fragment będzie wykorzystany przy tworzeniu adresu wewnętrznego. W adresie: index.php?module=fraszka&action=show&slug=REGEXP1

    68

    Część I  Akcje, widoki, translacje adresów URL i bazy danych

    napis REGEXP1 zostanie zamieniony na napis przechwycony przez wyrażenie regularne, tj. na_nabozna. W ten sposób powstanie adres wewnętrzny: index.php?module=fraszka&action=show&slug=na_nabozna

    Czyli użycie adresu przyjaznego /na_nabozna.html spowoduje wyświetlenie strony o adresie wewnętrznym: index.php?module=fraszka&action=show&slug=na_nabozna

    Analogicznie, adres przyjazny /raki.html będzie przekształcony na adres wewnętrzny: index.php?module=fraszka&action=show&slug=raki

    a adres /na_swoje_ksiegi.html — na adres: index.php?module=fraszka&action=show&slug=na_swoje_ksiegi

    Opisana konwersja wykorzystująca wyrażenie regularne będzie wykonywana przez kontroler w dwóch kierunkach. Nadchodzące żądanie zawierające adres przyjazny, np. /raki.html, będzie przekierowane do strony: index.php?module=fraszka&action=show&slug=raki

    a adres wewnętrzny występujący w generowanym kodzie HTML: index.php?module=fraszka&action=show&slug=raki

    zostanie zastąpiony adresem przyjaznym /raki.html.

    Ćwiczenie 5.1 Uruchom projekt 5.1 zapisany w pliku projekt-05-01.zip, a następnie w przeglądarce podaj błędny adres odwołujący się do folderu www/ (np. www/lorem/ipsum/dolor/sit.html). Aplikacja powinna wyświetlić stronę błędu 404. Dzięki wykorzystaniu mechanizmu preprzetwarzania na stronie błędu 404 powinieneś zauważyć menu umożliwiające nawigację po witrynie.

    Ćwiczenie 5.2 Rozpoczynając pracę od pliku cw-05-02-start.zip, wykonaj projekt 5.1.

    Projekt 5.2. Fraszki — szablony Smarty Wykonaj projekt 5.1, stosując szablony Smarty.

    Rozdział 5.  Pre- i postprzetwarzanie

    69

    Kod projektu 5.2 będzie się różnił od projektu 5.1 następującymi szczegółami:  pliki layout.html oraz modules/fraszka/show.html wykonamy, stosując Smarty;  w klasie FraszkiController nadpiszemy konstruktor.

    Konstruktor klasy FraszkiController z projektu 5.2 jest przedstawiony na listingu 5.9. Listing 5.9. Zarys klasy FraszkiController z projektu 5.2 class FraszkiController extends Controller { public function __construct() { $opcje = array( 'viewClass' => 'SmartyView' ); parent::__construct($opcje); } public function preActions() { ... } }

    W konstruktorze tworzymy tablice opcji $opcje, po czym wywołujemy konstruktor z klasy bazowej: parent::__construct($opcje);

    Dzięki pokryciu konstruktora skrypt index.php z projektu 5.2 jest identyczny jak skrypt index.php z projektu 5.1. Tworzymy w nim instancję klasy FraszkiController i wywołujemy metodę dispatch(): $controller = new FraszkiController(); $controller->dispatch();

    Nie musimy do konstruktora przekazywać opcji zmieniających klasę przetwarzania widoków na SmartyView, gdyż zadanie to jest wykonane w nadpisanym konstruktorze. Szablon layout.html z projektu 5.2 jest w zarysie przedstawiony na listingu 5.10. Listing 5.10. Zarys układu layout.html z projektu 5.2

    {foreach from=$menu item=opcja}


  • {$opcja.tytul}

  • {/foreach}

    Część I  Akcje, widoki, translacje adresów URL i bazy danych

    70

    {include file="../modules/$module/$action.html"}

    Menu przekazane do widoku wewnątrz metody preActions() przetwarzamy iteracyjnie za pomocą funkcji foreach: {foreach from=$menu item=opcja} ... {/foreach}

    Zmienna $opcja jest w kolejnych obrotach pętli elementem tablicy $menu. Jest to tablica dwuwymiarowa, w której indeksami są napisy slug oraz tytul. Wydruk tytułu fraszki w szablonie PHP przedstawionym na listingu 5.7 przyjmował postać:

    W Smarty indeks tablicy asocjacyjnej dołączamy do nazwy tablicy, stosując kropkę: {$opcja.tytul}

    Podobnie w celu wydrukowania adresu wewnętrznego należy wykorzystać składową $opcja['slug'], co w Smarty zapiszemy następująco:

    Ostatnim plikiem, który należy zmodyfikować, jest plik modules/fraszka/show.html. Jest on przedstawiony na listingu 5.11. Listing 5.11. Widok modules/fraszka/show.html projektu 5.2 {$tytul}

    {$tresc|nl2br}



    Do wydrukowania treści fraszki wykorzystujemy modyfikator nl2br. Zapis: {$tresc|nl2br}

    powoduje przekształcenie zmiennej $tresc modyfikatorem nl2br, co spowoduje poprzedzenie wszystkich znaków złamania wiersza znacznikami
    .

    Ćwiczenie 5.3 Rozpoczynając pracę od pliku cw-05-03-start.zip, wykonaj projekt 5.2.

    Rozdział 6.

    Translacja adresów URL Adresy URL możemy podzielić, stosując dwa niezależne kryteria. Pierwszym jest poznany już podział na adresy przyjazne oraz adresy wewnętrzne. Przykładem adresu przyjaznego jest: na_nabozna.html

    Odpowiadającym mu adresem wewnętrznym w projekcie 5.1 był adres: index.php?module=fraszka&action=show&slug=na_nabozna

    Drugim kryterium podziału URL jest ich bezwzględność. Adres URL może być bezwzględny, np.: http://phppp.gajdaw.pl/projekty/36-06/a-wczora-z-wieczora.html

    lub względny: css/style.css

    Pewnym szczególnym rodzajem adresów względnych są adresy rozpoczynające się od ukośnika: /css/style.css

    Bezwzględny adres URL rozpoczyna się od nazwy schematu, np. http lub ftp. Przykładami takich adresów są: http://helion.pl ftp://sunsite.icm.edu.pl

    Adresy: /css/style.css css/style.css ./css/style.css

    są adresami względnymi. Szczegółowy opis zagadnień dotyczących URL znajdziesz w specyfikacji RFC 3986 dostępnej pod adresem ftp://ftp.rfc-editor.org/in-notes/ rfc3986.txt.

    72

    Część I  Akcje, widoki, translacje adresów URL i bazy danych

    Tworząc witryny WWW, niejednokrotnie będziesz wykorzystywał każdy z wymienionych trzech rodzajów adresów, a więc:  adresy bezwzględne (np. http://helion.pl);  adresy względne rozpoczynające się od znaku innego niż ukośnik, w szczególności

    od kropki (np. img/foto.html lub ./img/foto.html);  adresy względne rozpoczynające się od ukośnika (np. /css/style.css).

    Każdy z powyższych adresów ma swoje zalety i w pewnych sytuacjach okazuje się przydatny. Adresy bezwzględne będziemy musieli stosować w plikach sitemap.xml. Specyfikacja sitemap.xml nie dopuszcza stosowania innych rodzajów adresów. Zatem umiejętność posłużenia się bezwzględnymi URL będzie — w przypadku generowania mapy sitemap.xml — konieczna. Adresy względne, rozpoczynające się od znaku innego niż ukośnik, np. css/style.css, są jedynymi rodzajami adresów, których możesz użyć w stronach WWW zapisywanych w spakowanych archiwach (tj. np. w plikach .zip). Jeśli myślisz o przygotowaniu spakowanego archiwum, które po rozpakowaniu w dowolnym folderze zachowa poprawność hiperłączy, to musisz zastosować względne URL rozpoczynające się od znaku innego niż ukośnik, na przykład css/style.css. Pewnym szczególnym przypadkiem takiego adresu jest adres ./css/style.css. Ostatni rodzaj adresów, czyli adresy względne rozpoczynające się od ukośnika, np. /css/style.css, jest bardzo wygodny w przypadku publikowania witryny w internecie. Umieszczając w układzie witryny opublikowanej na serwerze odwołanie:

    możesz mieć pewność, że style zawsze zostaną odnalezione, bez względu na to, na której podstronie serwisu się znajdziesz. Nawet jeśli użytkownik poda nieistniejący adres zawierający wiele folderów: /a/b/c/zly/adres/url.html

    to na generowanej stronie błędu 404 odwołanie do stylów CSS, w przypadku użycia adresu /css/style.css, będzie poprawne. Oczywiście w miejsce adresu /css/style.css możesz użyć bezwzględnego URL http://example.net/css/style.css, jednak adres ten jest o wiele dłuższy. Rozpatrując kryterium względny/bezwzględny, mamy więc trzy rodzaje adresów URL, które w dalszej części oznaczymy umownie jako absolute, root oraz relative:  absolute — adresy bezwzględne;  root — adresy względne rozpoczynające się od znaku ukośnika;  relative — adresy względne rozpoczynające się od znaku innego niż ukośnik.

    Podsumowując, adresy URL możemy podzielić, uwzględniając dwa kryteria:  przyjazny/wewnętrzny,  absolute/root/relative.

    Rozdział 6.  Translacja adresów URL

    73

    Opisywany kontroler MVC pozwala na wybór rodzajów adresów URL dwoma niezależnymi opcjami o nazwach pathType oraz friendlyUrls. Poprawnymi wartościami opcji pathType są napisy: absolute, root oraz relative. Opcja friendlyUrls przyjmuje wartości logiczne true lub false. Jeśli kontroler $c utworzymy, podając następujące opcje: $opcje = array( 'pathType' => 'absolute', 'friendlyUrls' => false, ); $c = new Controller($opcje);

    to adresy URL w generowanym dokumencie HTML będą adresami nieprzyjaznymi i bezwzględnymi. W przypadku użycia opcji: $opcje = array( 'pathType' => 'root', 'friendlyUrls' => true, ); $c = new Controller($opcje);

    generowane będą przyjazne adresy URL rozpoczynające się od ukośnika. Ustawieniami domyślnymi kontrolera są opcje 'pathType' => 'relative' 'friendlyUrls' => true

    Zatem wywołanie: $c = new Controller();

    jest równoważne wywołaniu: $opcje = array( 'pathType' => 'relative', 'friendlyUrls' => true, ); $c = new Controller($opcje);

    Projekt 6.1. Kolędy Wykorzystując pliki tekstowe z tekstami kolęd, pliki .png, .mus oraz .pdf prezentujące ich nuty oraz dodatkowy plik 00lista.log z indeksem wszystkich kolęd, wykonaj witrynę pt. Kolędy. Menu witryny ma zawierać tytuły kolęd. Jako adresów stron użyj napisów zawartych w ostatniej kolumnie pliku 00lista.log.

    Pierwszy wiersz pliku 00lista.log jest następujący: A wczora z wieczora|a-wczora-z-wieczora

    74

    Część I  Akcje, widoki, translacje adresów URL i bazy danych

    Wynika z niego, że dane kolędy zatytułowanej A wczora z wieczora są zapisane w plikach: a-wczora-z-wieczora.txt a-wczora-z-wieczora.mus a-wczora-z-wieczora.pdf a-wczora-z-wieczora.png mini/a-wczora-z-wieczora.png

    W aplikacji wystąpią dwie akcje: main/404 oraz koleda/show. W celu wykonania aplikacji należy:  nadpisać metodę preActions(), która przekaże do szablonu dane potrzebne

    do wykonania menu;  zaimplementować metodę execute_show() modułu koleda;  wykonać dwa szablony layout.html i show.html;  zdefiniować translacje adresów URL.

    W celu nadpisania metody preActions() aplikacji, definiujemy nową klasę KoledyController. Klasa ta jest przedstawiona na listingu 6.1. Listing 6.1. Metoda preActions() projektu 6.1 class KoledyController extends Controller { public function preActions() { $tmp = string2VArray(file_get_contents('../scripts/dane/00lista.log')); $this->dane = $tmp['items']; $this->set('menu', $this->dane); } }

    W metodzie preActions() odczytujemy plik 00lista.log i przekształcamy go w wielowymiarową tablicę. Tablica dwuwymiarowa, która powstaje przez pokrojenie pliku 00lista.log, jest dostępna w zmiennej $tmp['items']. Zostaje ona przypisana do właściwości $dane kontrolera oraz przekazana do widoków. Metoda execute_show() akcji koleda/show jest widoczna na listingu 6.2. Listing 6.2. Metoda execute_show() akcji koleda/show public function execute_show() { if ( isset($_GET['slug']) && str_ivslug($_GET['slug']) && in_array($_GET['slug'], $this->controller->dane[1]) ) { $nr = array_search($_GET['slug'], $this->controller->dane[1]); $tekst = file_get_contents('koledy/' . $this->controller->dane[1][$nr] . '.txt'); $this->set('tekst', $tekst); $nuty = file_exists('koledy/' . $this->controller->dane[1][$nr] . '.mus'); $this->set('nuty', $nuty);

    Rozdział 6.  Translacja adresów URL

    }

    75

    $this->set('slug', $this->controller->dane[1][$nr]); $this->set('tytul', $this->controller->dane[0][$nr]); } else { $this->execute_404(); }

    W metodzie tej najpierw sprawdzamy obecność i poprawność zmiennej $_GET['slug']. Główną częścią tego testu jest sprawdzenie, czy podana wartość występuje w tablicy $this->controller->dane[1] utworzonej w metodzie preActions(): in_array($_GET['slug'], $this->controller->dane[1])

    Jeśli podana wartość zmiennej slug jest poprawna, to ustalamy jej indeks w tablicy zawierającej wszystkie wartości slug: $nr = array_search($_GET['slug'], $this->controller->dane[1]);

    a następnie odczytujemy i przekazujemy do widoku tekst kolędy: $tekst = file_get_contents('koledy/' . $this->controller->dane[1][$nr] . '.txt'); $this->set('tekst', $tekst);

    Sprawdzamy, czy wśród danych znajdą się nuty do wybranej kolędy1: $nuty = file_exists('koledy/' . $this->controller->dane[1][$nr] . '.mus');

    po czym do szablonu przekazujemy informację, czy wybrana kolęda ma nuty, wartość slug oraz tytuł: $this->set('nuty', $nuty); $this->set('slug', $this->controller->dane[1][$nr]); $this->set('tytul', $this->controller->dane[0][$nr]);

    Przechodzimy do przygotowania widoków. W pliku layout.html umieszczamy pętlę foreach, która przetworzy tablicę $menu przekazaną do widoków w metodzie preActions() w menu. Zarys widoku jest przedstawiony na listingu 6.3. Listing 6.3. Plik layout.html z projektu 6.1



  • {$fotka}

    ";

    Tak utworzony kod XML zapisujemy do pliku: file_put_contents('fotka.xml', $xml);

    Ćwiczenie 31.1 Napisz skrypt PHP, który obraz fotka.jpg umieści w dokumencie fotka.xml wewnątrz elementu obraz.

    Dekodowanie base64 W celu odczytania zakodowanego obrazu i wysłania go do przeglądarki najpierw przetwarzamy dokument XML. Do parsingu kodu XML możemy wykorzystać klasę SimpleXML: $xml = simplexml_load_file('fotka.xml');

    Rozdział 31.  Skompresowane dokumenty XML zawierające dane binarne

    491

    Zawartość znaczników jest dostępna w zmiennej $xml->obraz. Treść zmiennej dekodujemy i wysyłamy do przeglądarki: echo base64_decode($xml->obraz);

    W ten sposób do przeglądarki możemy wysłać dowolne dane binarne odczytane z dokumentu XML.

    Ćwiczenie 31.2 Napisz skrypt PHP, który wyśle do przeglądarki obraz JPG zawarty w dokumencie fotka.xml.

    Kompresja danych Do kompresji pojedynczego pliku z wykorzystaniem biblioteki zlib należy wykorzystać trzy funkcje: gzopen(), gzwrite() oraz gzclose(). Po odczytaniu danych, które mają być poddane kompresji: $plk = file_get_contents('dane.txt');

    tworzymy nowe archiwum o nazwie dane.gz: $gzfile = gzopen('dane.gz', 'w9');

    Drugi parametr funkcji gzopen() ustala tryb otwarcia. Tryb ten może być do zapisu (w) lub do odczytu (r). Dodatkowa liczba ustala poziom kompresji. Parametr w9 oznacza otwarcie pliku w trybie do zapisu i ustalenie stopnia konwersji na 9, czyli na najwyższy możliwy poziom. Jeśli tworzenie archiwum nie powiedzie się, to zmienna $gzfile przyjmie wartość false: if ($gzfile === false) { die('Blad tworzenia pliku .xml.gz'); }

    W przypadku pomyślnego utworzenia pliku dane.gz zapisujemy w nim treść odczytaną z pliku: gzwrite($gzfile, $plk);

    a następnie zamykamy: gzclose($gzfile);

    W bieżącym folderze powstanie plik dane.gz, który będzie zawierał skompresowane dane z pliku dane.txt.

    Część IV  Formaty danych

    492

    Ćwiczenie 31.3 Napisz skrypt PHP, który zawartość pliku dane.txt zapisze w postaci skompresowanej w pliku dane.gz.

    Dekompresja danych Do odczytu skompresowanego pliku dane.gz służą funkcje gzopen(), gzread() oraz gzclose(). Najpierw otwieramy plik w trybie do odczytu i sprawdzamy powodzenie operacji otwarcia: $gzfile = gzopen('dane.gz', 'r'); if ($gzfile === false) { exit(); }

    Następnie funkcją gzread() odczytujemy całą spakowaną zawartość: $dane = ''; while (!gzeof($gzfile)) { $dane .= gzread($gzfile, 10000); }

    Na zakończenie zamykamy plik: gzclose($gzfile);

    a rozpakowane informacje wysyłamy do przeglądarki: echo $dane;

    Ćwiczenie 31.4 Napisz skrypt PHP, który zawartość pliku dane.gz odczyta, rozpakuje i wyśle do przeglądarki.

    Ćwiczenie 31.5 Napisz skrypt PHP, który zdjęcie fotka.jpg umieści w spakowanym pliku XML o nazwie fotka.xml.gz. Rozwiązanie ćwiczenia jest przedstawione na listingu 31.1. Listing 31.1. Rozwiązanie ćwiczenia 31.5 $plk = file_get_contents('fotka.jpg'); $fotka = base64_encode($plk); $xml =

    Rozdział 31.  Skompresowane dokumenty XML zawierające dane binarne

    493

    "

    {$fotka}

    "; $gzfile = gzopen('fotka.xml.gz', 'w9'); if ($gzfile === false) { die('Blad tworzenia pliku .xml.gz'); } gzwrite($gzfile, $xml); gzclose($gzfile);

    Ćwiczenie 31.6 Napisz skrypt PHP, który zdjęcie zawarte w dokumencie fotka.xml.gz wyśle do przeglądarki. Rozwiązanie ćwiczenia jest przedstawione na listingu 31.2. Listing 31.2. Rozwiązanie ćwiczenia 31.6 header('Content-Type: image/jpg'); $gzfile = gzopen('fotka.xml.gz', 'r'); if ($gzfile === false) { exit(); } $xml = ''; while (!gzeof($gzfile)) { $xml .= gzread($gzfile, 10000); } gzclose($gzfile); $xml = simplexml_load_string($xml); echo base64_decode($xml->obraz);

    Projekt 31.1. Format danych systemu do publikowania artykułów Zdefiniuj format danych dla systemu do publikowania artykułów. Użyj plików tekstowych oraz plików binarnych. Pojedynczy artykuł powinien być zapisany w HTML i może zawierać dowolną liczbę ilustracji, listingów oraz tabel. Ponadto do artykułu będą dołączone: pliki z przykładami, oprogramowanie oraz bibliografia w postaci listy adresów URL. Rozwiązanie zaprojektuj w taki sposób, by ułatwić automatyczną numerację ilustracji, listingów oraz tabel.

    Część IV  Formaty danych

    494

    Pojedynczy artykuł będzie zawarty w osobnym folderze o dowolnej nazwie i będzie się składał z następujących plików:  article.txt,  date.txt,  introduction.txt,  title.txt

    oraz  addresses.txt,  download.txt,  examples.txt,  figures.txt,  frames.txt,  listings.txt,  tables.txt.

    Pliki z pierwszej grupy zawierają pojedyncze dane. W pliku article.txt umieścimy treść artykułu, w pliku date.txt — datę publikacji, plik introduction.txt będzie zawierał streszczenie, a title.txt — tytuł artykułu. Każdy z plików drugiej serii, czyli addresses.txt, download.txt, examples.txt, figures.txt, frames.txt, listings.txt oraz tables.txt, zawiera listę pozycji. W pliku addresses.txt znajduje się bibliografia (tj. zestawienie adresów URL). Plik download.txt zawiera zestawienie programów dołączonych do artykułu, w pliku example.txt są wymienione przykłady dołączone do artykułu. Kolejne pliki: figures.txt, frames.txt, listings.txt oraz tables.txt, zawierają zestawienie ilustracji, ramek, listingów oraz tabel. Każdy z plików zawierających listę pozycji jest plikiem tekstowym zawierającym kilka kolumn, w którym jeden wiersz zawiera dane jednego rekordu. Do podziału kolumn stosujemy znak |. Na przykład w pliku figures.txt znajdziemy opis: Pierwszy wykres w Google Chart API|png Modyfikacja tła i grubości linii|png Wielokrotne serie danych i markery|jpg

    Wynika z niego, że w artykule występują trzy ilustracje. Pierwsza z nich jest zawarta w pliku 1.png i ma podpis Pierwszy wykres w Google Chart API. Druga ilustracja, z pliku 2.png, będzie podpisana Modyfikacja tła i grubości linii. Ostatnia z ilustracji będzie pochodziła z pliku 3.jpg. Jej podpisem będzie tekst Wielokrotne serie danych i markery. Numer ilustracji w artykule oraz nazwa pliku graficznego są zgodne z numeracją wierszy w pliku figures.txt. Plik examplex.txt zawiera listę przykładów dołączonych do artykułu: Statyczny plik.xml|1-1-statyczny-plik-xml.zip Generowanie dokumentu XML|1-2-echo-header.zip Generowanie dokumentu XML na podstawie tablicy|2-1-tablica.zip

    Rozdział 31.  Skompresowane dokumenty XML zawierające dane binarne

    495

    Każdy przykład jest opisany przez etykietę (np. Statyczny plik .xml) oraz nazwę pliku (np. 1-1-statyczny-plik.xml.zip). Ilustracje, przykłady, programy, listingi, ramki oraz tabelki dołączone do artykułu będą zawarte w osobnych folderach: download/, examples/, figures/, frazes/, listings/, tables/.

    Umieszczanie ilustracji, listingów, ramek i tabel w treści artykułu Treść artykułu zawarta w pliku article.txt będzie napisana w języku HTML. W miejsce rysunków, listingów, ramek oraz tabel użyte zostaną specjalne znaczniki: #####{$figures[x]}##### #####{$frames[x]}##### #####{$listings[x]}##### #####{$tables[x]}#####

    Literę x w powyższych znacznikach należy zastąpić numerem. Na przykład w celu wstawienia ilustracji numer 7 pomiędzy dwa akapity lorem ipsum, użyjemy znacznika: ...

    Lorem ipsum...

    #####{$figures[7]}#####

    Lorem ipsum...

    ...

    Projekt 31.2. Konwersja artykułu z formatu tekstowego do spakowanego pliku XML Napisz skrypt PHP, który artykuł zapisany w formacie opisanym w poprzednim projekcie przekonwertuje w pojedynczy plik .xml.gz, zawierający komplet informacji związanych z artykułem.

    Główną wadą formatu tekstowego jest to, że składa się on z wielu plików. Będzie to utrudniało zarówno kopiowanie artykułów pomiędzy serwerami, jak i publikowanie ich. Rozwiązaniem tych problemów jest spakowany dokument XML. Format taki zapewnia łatwy dostęp do poszczególnych elementów artykułu, a zarazem jest wygodny do kopiowania. Konwersję dokumentu wykonamy, definiując klasę TXTArticle, która będzie zawierała metody odpowiedzialne za parsing plików tekstowych oraz za wygenerowanie i zapisanie do pliku spakowanego dokumentu XML. Wykorzystując klasę TXTArticle, skrypt

    Część IV  Formaty danych

    496

    konwertujący wszystkie artykuły z folderu arts/ do formatu .xml.gz przyjmie postać taką jak na listingu 31.3. Listing 31.3. Konwersja artykułów z formatu tekstowego do formatu .xml.gz $plks = glob('arts/*'); foreach ($plks as $plk) { $art = new TXTArticle($plk); $art->saveXml('xml/' . basename($plk) . '.xml'); }

    Zarys klasy TXTArticle jest przedstawiony na listingu 31.4. W klasie tej definiujemy konstruktor oraz metody loadArticle(), loadDate(), loadIntroduction(), loadFigures() itd. odpowiedzialne za parsing odpowiednich plików tekstowych. Metody do odczytu plików article.txt, date.txt, title.txt, introduction.txt sprowadzają się do odczytania zawartości pojedynczego pliku. W pozostałych metodach load() należy, tak jak w przedstawionej na listingu 31.4 metodzie loadFigures(), dokonać krojenia pliku tekstowego. Listing 31.4. Zarys klasy TXTArticle class TXTArticle { ... public function __construct($ADirectory) { $this->directory = $ADirectory; $this->loadArticle(); $this->loadDate(); $this->loadIntroduction(); $this->loadTitle(); $this->loadFigures(); $this->loadListings(); $this->loadFrames(); $this->loadTables(); $this->loadExamples(); $this->loadDownload(); $this->loadAddresses(); } ... protected function loadArticle() { $filename = $this->directory . '/article.txt'; if (file_exists($filename)) { $this->article = trim(file_get_contents($filename)); } } ... protected function loadFigures()

    Rozdział 31.  Skompresowane dokumenty XML zawierające dane binarne

    497

    { $this->figures_count = 0; $this->figures = array(); $filename = $this->directory . '/figures.txt'; if (file_exists($filename)) { $tmp = trim(file_get_contents($filename)); $d = string2HArray($tmp); $this->figures_count = $d['rows']; for ($i = 0; $i < $this->figures_count; $i++) { $tmp_figure = array(); $tmp_figure['no'] = $i + 1; $tmp_figure['ext'] = $d['items'][$i][1]; $tmp_figure['filename'] = $tmp_figure['no'] . '.' . $tmp_figure['ext']; $tmp_figure['caption'] = $d['items'][$i][0]; $tmp_figure['image'] = file_get_contents( $this->directory . '/figures/' . $tmp_figure['filename'] ); $tmp_figure['image'] = base64_encode($tmp_figure['image']); $this->figures[$i + 1] = $tmp_figure; } } } ... public function getXml() { $serializer = new XML_Serializer(); $options = array( 'addDecl' => true, 'indent' => ' ', 'rootName' => 'artykul', 'encoding' => 'utf-8', 'defaultTagName' => 'item', ); $serializer->setOptions($options); $serializer->serialize($this); $this->xml = $serializer->getSerializedData(); return $this->xml; } public function saveXml($filename, $compress = true) { if ($compress) { if (substr($filename, -3) != '.gz') { $filename .= '.gz'; } $gzfile = gzopen($filename, 'w9'); if ($gzfile === false) { throw new Exception('TxtArticle::saveXML() exception'); } if ($this->xml == '') { $this->getXml();

    Część IV  Formaty danych

    498 } gzwrite($gzfile, $this->xml); gzclose($gzfile); } else { if ($this->xml == '') { $this->getXml(); } file_put_contents($filename, $this->xml); } } }

    Metoda getXml(), wykorzystując klasę XML_Serializer, konwertuje zawartość obiektu $this do formatu XML. Natomiast ostatnia z metod, saveXml(), odpowiada za zapisanie skompresowanego kodu XML do pliku o podanej nazwie. Po uruchomieniu skryptu z listingu 31.3 w folderze xml/ powstaną dokumenty .xml.gz. Każdy ze spakowanych plików będzie zawierał komplet danych dotyczących pojedynczego artykułu.

    Ćwiczenie 31.7 Napisz skrypt z projektu 31.2, który przekonwertuje artykuły zawarte w folderze arts/ z formatu tekstowego do formatu .xml.gz.

    Ćwiczenie 31.8 Zmodyfikuj ćwiczenie 31.7 w taki sposób, by wszystkie artykuły były zapisane w jednym pliku artykuly.xml.gz.

    Projekt 31.3. System publikacji artykułów w postaci witryny WWW Opracuj aplikację, która będzie służyła do publikowania artykułów zawartych w plikach .xml.gz w postaci witryny WWW. Zadanie wykonaj w taki sposób, by artykuły były poddane stronicowaniu. Każdy punkt artykułu oznaczony znacznikami ma stanowić kolejną stronę artykułu. Dla każdego artykułu przygotuj także wersję przeznaczoną do wydruku. Bez względu na to, na której stronie artykułu czytelnik się znajduje, zawsze powinien mieć możliwość wydrukowania kompletnego tekstu artykułu.

    Rozdział 31.  Skompresowane dokumenty XML zawierające dane binarne

    499

    Baza danych Baza danych do projektu 31.3 będzie zawierała trzy tabele przedstawione na rysunku 31.1. Tabela article jest przeznaczona na artykuły. Każdy artykuł, oprócz tytułu, daty publikacji i wstępu, będzie miał pola: toc oraz onepage. W polu toc umieścimy kod HTML spisu treści, a pole onepage będzie zawierało kompletną treść artykułu bez podziału na strony. Pole onepage zostanie wykorzystane do drukowania artykułu. Tabela page będzie zawierała poszczególne strony tekstu artykułów, a w tabeli file znajdą się pliki binarne do pobrania. Rysunek 31.1. Struktura bazy danych z projektu 31.1

    Propel i dostęp tylko do wybranych kolumn tabeli Rekordy tabeli article zawierają znaczne ilości danych. Każdy rekord będzie zawierał: kompletną treść artykułu przeznaczoną do wydruku, kod HTML spisu treści, listę przykładów, programów oraz adresów. Jeśli do wydrukowania listy tytułów artykułów wykorzystamy kod: //w akcji $artykuly = ArticlePeer::doSelect(); //w widoku



    wówczas z bazy danych pobierzemy kompletną treść wszystkich artykułów. Jest to bardzo duże marnotrawienie przepustowości pomiędzy bazą danych a skryptem PHP. W celu wyeliminowania zbędnego transferu danych z bazy do skryptu należy w zapytaniach SQL pobrać wyłącznie wybrane kolumny tabeli article. W powyższym przykładzie wystarczy kolumna title.

    Część IV  Formaty danych

    500

    Za pobranie wybranych kolumn tabeli article odpowiada przedstawiona na listingu 31.5 metoda podajArtykuly() klasy ArticlePeer. Listing 31.5. Metoda podajArtykuly() klasy ArticlePeer static public function podajArtykuly() { $c = new Criteria(); $c->clearSelectColumns(); $c->addSelectColumn(ArticlePeer::TITLE); $c->addSelectColumn(ArticlePeer::INTRODUCTION); $c->addSelectColumn(ArticlePeer::DATE); $c->addSelectColumn(ArticlePeer::SLUG); $rs = ArticlePeer::doSelectStmt($c); return $rs->fetchAll(); }

    W celu pobrania z tabeli article czterech kolumn title, introduction, date oraz slug należy najpierw z kryteriów usunąć wszystkie pobierane kolumny: $c = new Criteria(); $c->clearSelectColumns();

    a następnie dodać kolumny, które mają być zawarte w klauzuli select zapytania SQL: $c->addSelectColumn(ArticlePeer::TITLE); $c->addSelectColumn(ArticlePeer::INTRODUCTION); $c->addSelectColumn(ArticlePeer::DATE); $c->addSelectColumn(ArticlePeer::SLUG);

    Po ustaleniu kryteriów wykonujemy zapytanie select i odbieramy zwrócone wyniki w postaci tablicy asocjacyjnej: $rs = ArticlePeer::doSelectStmt($c); $tmp = $rs->fetchAll();

    Tablica $tmp będzie tym razem zwykłą tablicą asocjacyjną, a nie — jak to miało miejsce w przypadku metody doSelect() — tablicą obiektów klasy Article. W tablicy $tmp pod indeksem 0 znajdziemy dane pierwszego artykułu. W celu odczytania tytułu, wstępu, daty publikacji oraz identyfikatora slug stosujemy indeksy TITLE, INTRODUCTION, DATE oraz SLUG: echo echo echo echo

    $tmp[0]['TITLE']; $tmp[0]['INTRODUCTION']; $tmp[0]['DATE']; $tmp[0]['SLUG'];

    W metodzie przedstawionej na listingu 31.5 wynik działania funkcji fetchAll() przekazujemy na zewnątrz jako wynik działania metody: return $rs->fetchAll();

    Rozdział 31.  Skompresowane dokumenty XML zawierające dane binarne

    501

    Wypełnianie bazy danych W celu wypełnienia bazy danych artykułami zapisanymi w formacie .xml.gz należy najpierw zaimplementować dwie operacje:  odczyt, rozpakowanie i parsing dokumentu .xml.gz;  przetworzenie treści artykułu: osadzenie ilustracji, listingów, tabelek oraz

    pokrojenie artykułu na strony.

    Parsing artykułu w formacie .xml.gz Za konwersję dokumentu .xml.gz w tablicę asocjacyjną odpowiada klasa XMLArticle, której zarys jest przedstawiony na listingu 31.6. Listing 31.6. Zarys klasy XMLArticle class XMLArticle { private $xml = ''; public $a; public function __construct($filename) { $this->load($filename); $this->unserialize(); } public function load($filename) { $gzfile = gzopen($filename, 'r'); if ($filename === false) { throw new Exception('XMLArticle::load() exception'); } $this->xml = ''; while (!gzeof($gzfile)) { $this->xml .= gzread($gzfile, 10000); } gzclose($gzfile); } public function unserialize() { $unserializer = new XML_Unserializer(); $options = array( 'forceEnum' => array('item'), ); $unserializer->setOptions($options);

    }

    $unserializer->unserialize($this->xml, false); $this->a = $unserializer->getUnserializedData();

    public function getFiguresCount() {

    Część IV  Formaty danych

    502

    }

    return $this->a['figures_count'];

    public function getFigure($i) { return $this->a['figures']['item'][$i - 1]; } public function getListingsCount() { return $this->a['listings_count']; } public function getListing($i) { return $this->a['listings']['item'][$i - 1]; } ... }

    Klasa XMLArticle zawiera konstruktor, metody load() i unserialize() oraz metody zwracające liczbę elementów danego typu (np. liczbę listingów — metoda getListingsCount()) i element o zadanym numerze (np. listing nr x — metoda getListing(x)). W treści metody load()do odczytania i rozpakowania pliku .xml.gz wykorzystujemy bibliotekę zlib. Wypakowana zawartość pliku zostaje zapisana we właściwości $this->xml. Metoda unserialize(), bazując na klasie XML_Unserializer, konwertuje kod XML zawarty we właściwości $this->xml w tablicę asocjacyjną. Otrzymana tablica jest zapisana we właściwości $this->a. Pozostałe metody, czyli m.in. getLisgingsCount() oraz getListing(), zwracają liczbę elementów oraz odpowiedni fragment tablicy asocjacyjnej $this->a. Po wywołaniu: $obj = new XMLArticle('2008-08-google-chart-api.xml.gz'); $tmp = $obj->getListing(3);

    zmienna $tmp będzie tablicą asocjacyjną zawierającą komplet informacji o listingu numer 3, a instrukcje: $obj = new XMLArticle('2008-07-mi-propel-porady.xml.gz'); $img = $obj->getFigure(2);

    spowodują pobranie do zmiennej $img tablicy asocjacyjnej z kompletem informacji na temat ilustracji numer 2. Dane te będą zawierały podpis, numer oraz cały plik graficzny (napis zakodowany funkcją base64_encode()).

    Przetwarzanie treści artykułu Treść artykułu, która w projekcie 31.2 została odczytana z pliku article.txt i umieszczona w kodzie XML, zawiera akapity podzielone elementami h3 na punkty oraz specjalne znaczniki umieszczające w treści m.in. listingi i ilustracje. Przykładowy fragment artykułu jest przedstawiony na listingu 31.7.

    Rozdział 31.  Skompresowane dokumenty XML zawierające dane binarne

    503

    Listing 31.7. Fragment kodu źródłowego artykułu Pierwszy wykres w Google Chart API

    Po umieszczeniu na stronie WWW ...

    #####{$figures[1]}#####

    W tak prosty sposób...

    Działanie Google Chart API ...

    Wówczas przeglądarka Firefox...

    #####{$figures[2]}##### Adresy URL

    Analizując adres...



    Artykuł w formacie z listingu 31.7 należy przetworzyć na cztery sposoby. Po pierwsze, należy osadzić w nim w miejsce znaczników: #####{$figures[x]}##### #####{$frames[x]}##### #####{$listings[x]}##### #####{$tables[x]}#####

    kod HTML rysunków, ramek, listingów i tabel. Po drugie, należy wygenerować spis treści artykułu. Po trzecie, treść artykułu należy podzielić na poszczególne strony. Ostatnim sposobem przetworzenia artykułu źródłowego będzie wygenerowanie jednostronicowego dokumentu HTML zawierającego kompletną treść artykułu. Dokument jednostronicowy będzie wykorzystany do przygotowania operacji wydruku artykułu. Te cztery zadania realizuje klasa HTMLArticle, której zarys jest przedstawiony na listingu 31.8. Listing 31.8. Zarys klasy HTMLArticle class HTMLArticle { private $art; public $pages; public $html; public $singlepagearticle; public $pagedarticle; public function __construct($filename) { $this->art = new XMLArticle($filename); $this->setUrl(); $this->html = array( 'figures' => array(), 'listings' => array(), 'tables' => array(), 'frames' => array(), );

    }

    $this->processFLFTHTML(); $this->processEDANumbering(); $this->processHTML(); $this->processSinglepage(); $this->processPages();

    Część IV  Formaty danych

    504

    public function processFLFTHTML() { for ($i = 1; $i art->getFiguresCount(); $i++) { $this->html['figures'][$i] = $this->getHTMLFigure($i); } for ($i = 1; $i art->getListingsCount(); $i++) { $this->html['listings'][$i] = $this->getHTMLListing($i); } for ($i = 1; $i art->getFramesCount(); $i++) { $this->html['frames'][$i] = $this->getHTMLFrame($i); }

    }

    for ($i = 1; $i art->getTablesCount(); $i++) { $this->html['tables'][$i] = $this->getHTMLTable($i); }

    public function processHTML() { $tmps = new SmartyString(); $tmp = $this->art->getArticle(); $tmps->addTemplate('content.tpl', $tmp); $tmps->assign('figures', $this->html['figures']); $tmps->assign('listings', $this->html['listings']); $tmps->assign('frames', $this->html['frames']); $tmps->assign('tables', $this->html['tables']); $tmps->left_delimiter = '#####{'; $tmps->right_delimiter = '}#####'; }

    $this->html['article'] = $tmps->fetch('str:content.tpl');

    public function processSinglepage() { $this->singlepagearticle = array(); $toc_array = getTableOfContents($this->html['article']); $this->singlepagearticle['toc'] = getTableOfContentsAsString($toc_array); $this->singlepagearticle['text'] = replaceChapters($toc_array, $this->html['article']);

    }

    $this->singlepagearticle['title'] $this->singlepagearticle['introduction'] $this->singlepagearticle['date'] $this->singlepagearticle['examples'] $this->singlepagearticle['addresses'] $this->singlepagearticle['download']

    = = = = = =

    $this->art->getTitle(); $this->art->getIntroduction(); $this->art->getDate(); $this->html['examples']; $this->html['addresses']; $this->html['download'];

    public function getHTMLFigure($ANo) { $z = new Smarty(); $z->assign('figure', $this->art->getFigure($ANo)); return $z->fetch('figure.tpl');

    Rozdział 31.  Skompresowane dokumenty XML zawierające dane binarne

    505

    } public function getHTMLListing($ANo) { $z = new Smarty(); $z->assign('listing', $this->art->getListing($ANo)); return $z->fetch('listing.tpl'); } public function processPages() { $this->paged = array(); $this->pages = array(); $this->paged['title'] $this->paged['introduction'] $this->paged['date'] $this->paged['examples'] $this->paged['addresses'] $this->paged['download'] $tablicaTOC

    = = = = = =

    $this->art->getTitle(); $this->art->getIntroduction(); $this->art->getDate(); $this->html['examples']; $this->html['addresses']; $this->html['download'];

    = getTableOfContents($this->html['article']);

    $this->paged['toc'] = getTableOfContentsAsStringPages($tablicaTOC, $this->url); $newContents = replaceChaptersPages($tablicaTOC, $this->html['article']); $podziel = preg_split( "/(.*)/Uis", $newContents ); $this->pages_count = count($tablicaTOC); for ($i = 1; $i pages_count; $i++) { $r_tekst $r_tytul $r_numer $r_tekst

    = = = =

    trim($podziel[$i]); $tablicaTOC[$i]['title']; $i; "{$r_numer}. {$r_tytul}" . $r_tekst;

    $this->pages[$i] = trim($r_tekst); } } public function setUrl() { } }

    Wszystkie wymienione cztery kroki przetwarzania odbywają się w konstruktorze klasy HTMLArticle. Przetwarzanie rozpoczynamy odczytaniem, rozpakowaniem i konwersją kodu XML w tablicę asocjacyjną. Po wykonaniu instrukcji: $this->art = new XMLArticle($filename);

    Część IV  Formaty danych

    506

    właściwość $this->art będzie obiektem klasy XMLArticle, który zapewni wygodny dostęp do wszystkich informacji dotyczących artykułu (m.in. treści, liczby ilustracji oraz szczegółowych danych każdej ilustracji). Konwersja pseudoznaczników #####{…}##### w odpowiedni kod HTML sprowadza się do wywołania trzech metod: $this->processFLFTHTML(); $this->processEDANumbering(); $this->processHTML();

    Pierwsza z nich przetwarza dane źródłowe rysunków (F — figures), listingów (L — listings), ramek (F — frames) oraz tabel (T — tables) w odpowiadający im kod HTML. W tablicy $this->html, w której w konstruktorze tworzymy puste składowe figures, listings, frames oraz tables, znajdą się kody HTML odpowiednich elementów. Kolejna metoda processEDANumbering() ustali numerację tabel z przykładami (E — examples), oprogramowaniem (D — download) oraz adresami (A — addresses). Ostatnia z trzech powyższych metod, czyli processHTML(), realizuje wymianę pseudoznaczników #####{…}##### na odpowiedni kod HTML. W treści metody processHTML() wykorzystujemy klasę SmartyString, która pozwala na przetwarzanie szablonu Smarty zawartego w napisie. Szablonem jest treść artykułu odczytana z pliku .xml.gz przez klasę XML. Treść ta jest zwracana przez metodę getArticle() klasy XMLArticle. W celu ustalenia, że wynik metody getArticle() jest szablonem Smarty, wykonujemy instrukcje: $tmps = new SmartyString(); $tmp = $this->art->getArticle(); $tmps->addTemplate('content.tpl', $tmp);

    Po przekazaniu do szablonu zmiennych: $tmps->assign('figures', $this->html['figures']); $tmps->assign('listings', $this->html['listings']); $tmps->assign('frames', $this->html['frames']); $tmps->assign('tables', $this->html['tables']);

    oraz zmianie ograniczników zmiennych szablonu: $tmps->left_delimiter = '#####{'; $tmps->right_delimiter = '}#####';

    przetwarzamy szablon, a wynik przetwarzania zapisujemy we właściwości $this-> html['article']: $this->html['article'] = $tmps->fetch('str:content.tpl');

    W ten sposób otrzymamy kod HTML kompletnego artykułu. Teraz kod ten należy przetworzyć w dokument jednostronicowy zawierający spis treści oraz pokroić na oddzielne strony i przygotować spis treści dokumentu stronicowanego. Te dwa zadania wykonujemy za pomocą metod: $this->processSinglepage(); $this->processPages();

    Rozdział 31.  Skompresowane dokumenty XML zawierające dane binarne

    507

    Treść metody processSinglepage() bazuje na omówionych w rozdziale 24. funkcjach getTableOfContents(), getTableOfContentsAsString() i replaceChapters(). Tworzenie jednostronicowego dokumentu ze spisem treści przebiega podobnie jak w projekcie 24.1. W metodzie processPages(), której zadaniem jest podział artykułu na strony, wykorzystujemy wyrażenie regularne: /(.*)/Uis

    Wywołując funkcję preg_split(): $podziel = preg_split( "/(.*)/Uis", $newContents );

    w zmiennej $podziel otrzymamy poszczególne strony artykułu. Strony te zostają umieszczone w tablicy $this->pages. Dzięki klasie HTMLArticle mamy dostęp do:  dokumentu jednostronicowego: kodu HTML zawierającego spis treści i kompletny

    tekst artykułu;  dokumentu podzielonego na strony, przy czym w osobnych zmiennych

    dostępne są:  kod HTML spisu treści;  kod HTML poszczególnych stron artykułu.

    Skrypt wstaw.php Zarys skryptu wypełniającego bazę danych z rysunku 31.1 danymi z plików .xml.gz jest przedstawiony na listingu 31.9. Listing 31.9. Zarys skryptu wstaw.php z projektu 31.1 $plks = glob('xml/*'); foreach ($plks as $plk) { $art = new HTMLArticle($plk); $artykul = new Article(); $artykul->setTitle($art->paged['title']); $artykul->setIntroduction($art->paged['introduction']); $artykul->setToc($art->paged['toc']); $artykul->setSlug(html2slug($art->paged['title'])); $artykul->setDate($art->paged['date']); $artykul->setOnepage($art->singlepagearticle['toc'] . $art->singlepagearticle['text']); $artykul->setAddresses($art->paged['addresses']); $artykul->setDownload($art->paged['download']); $artykul->setExamples($art->paged['examples']); $artykul->save();

    Część IV  Formaty danych

    508 foreach ($art->pages as $k=>$str_page) { $page = new Page(); $page->setPage($str_page); $page->setNumber($k); $page->setArticle($artykul); $page->save(); }

    foreach ($art->getFigures() as $figure) { $file = new File(); $file->setData(base64_decode($figure['image'])); $file->setSlug($figure['filename']); $file->setMime($figure['ext']); $file->setArticle($artykul); $file->save(); } ... }

    Wszystkie pliki z folderu xml/ przetwarzamy w pętli foreach. Na podstawie nazwy pliku tworzymy obiekt klasy HTMLArticle. Obiekt ten będzie zawierał komplet informacji o artykule. Następnie tworzymy nowy obiekt klasy Article (klasa ta została wygenerowana przez Propel dla tabeli article), ustalamy wartości jego składowych i zapisujemy w bazie danych. Dwie następne pętle z listingu 31.9 odpowiadają za przetworzenie stron artykułu oraz zawartych w nim ilustracji. Strony artykułu zapisujemy — przy użyciu klasy Page — w tabeli page, a ilustracje — korzystając z klasy File — w tabeli file. Zwróć uwagę, że dane binarne obrazu zostają przed przesłaniem do bazy danych zdekodowane: $file->setData(base64_decode($figure['image']));

    oraz że na podstawie rozszerzenia pliku ustalamy wartość kolumny mime: $file->setMime($figure['ext']);

    Pozwoli to na wysłanie odpowiedniego nagłówka odpowiedzi HTTP w akcji odpowiedzialnej za wysyłanie obrazu pobranego z bazy danych. W podobny sposób w tabeli file umieszczamy wszystkie przykłady do pobrania oraz oprogramowanie.

    Aplikacja Po przygotowaniu bazy danych z artykułami wykonanie aplikacji nie powinno przysporzyć wielu kłopotów. W aplikacji wystąpią dwa moduły: article oraz file. Pierwszy z nich będzie zawierał akcje prezentujące dane artykułu, a drugi będzie odpowiadał za wysyłanie do przeglądarki odpowiedniego pliku.

    Rozdział 31.  Skompresowane dokumenty XML zawierające dane binarne

    509

    Akcją strony głównej projektu będzie article/list. W akcji tej pobieramy z bazy danych listę tytułów artykułów zawartych w bazie danych. W celu zmniejszenia transferu z bazy danych do skryptu PHP w kodzie akcji wykorzystujemy opisaną metodę podaj Artykuly(), która z bazy danych pobiera tylko wybrane kolumny tabeli article. Prezentację pojedynczego artykułu podzielimy na następujące akcje:  article/show;  article/page;  article/print;  article/examples;  article/download;  article/addresses.

    Akcja show odpowiada za prezentację spisu treści artykułu. Jej kod jest przedstawiony na listingu 31.10. Po utworzeniu na podstawie zmiennej slug obiektu $artykul tworzymy nowy obiekt klasy Pager. Obiekt ten będzie odpowiadał za wskaźnik pozwalający na wybór pojedynczej strony artykułu. Do widoku akcji trafiają dwie zmienne: $artykul oraz $pager. Listing 31.10. Kod akcji article/show public function execute_show() { if ( isset($_GET['slug']) && str_ivslug($_GET['slug']) && ($artykul = ArticlePeer::retrieveBySlug($_GET['slug'])) ) { $this->set('artykul', $artykul); $c = new Criteria(); $c->add(PagePeer::ARTICLE_ID, $artykul->getArticleId()); $pager = new Pager('Page', 1, $c, 10); $pager->assignRecords(); $pager->setBaseURL( 'index.php?module=article&action=page&slug=' . $artykul->getSlug() . '&page=' ); $this->set('pager', $pager); } else { $this->execute_404(); } }

    Część IV  Formaty danych

    510

    Akcja article/page odpowiada za prezentację pojedynczej strony artykułu. Walidacji poddajemy zmienne slug oraz page i na ich podstawie tworzymy obiekty $artykul i $page. Obiekt $page tworzymy, wywołując statyczną metodę retrieveByArtNr(), którą należy zdefiniować w klasie PagePeer. Jeśli utworzenie obiektów $artykul i $page powiedzie się, to do szablonu przekazujemy trzy obiekty: $artykul, $page oraz odpowiedzialny za stronicowanie $pager. Kod akcji article/page jest przedstawiony na listingu 31.11. Listing 31.11. Kod akcji article/page public function execute_page() { if ( isset($_GET['slug']) && str_ivslug($_GET['slug']) && ($artykul = ArticlePeer::retrieveBySlug($_GET['slug'])) && isset($_GET['page']) && str_ivslug($_GET['page']) && ($page = PagePeer::retrieveByArtNr($artykul, $_GET['page'])) ) { $this->set('artykul', $artykul); $this->set('page', $page); $c = new Criteria(); $c->add(PagePeer::ARTICLE_ID, $artykul->getArticleId()); $pager = new Pager('Page', 1, $c, 10); $pager->setPage($_GET['page']); $pager->assignRecords(); $pager->setBaseURL( 'index.php?module=article&action=page&slug=' . $artykul->getSlug() . '&page=' ); $this->set('pager', $pager); } else { $this->execute_404(); }

    }

    Pozostałe akcje modułu article różnią się od akcji show wyłącznie szablonem. Zatem w treści ich metod (np. w metodzie execute_print() akcji article/print) wywołujemy metodę execute_show(): public function execute_print() { $this->execute_show(); }

    Ćwiczenie 31.9 Wykonaj projekt 31.3. Pracę rozpocznij od pliku cw-31-09-start.zip.

    Rozdział 32.

    Czego powinieneś nauczyć się z części czwartej? Wykonanie ćwiczeń i projektów opisanych w części czwartej pozwoli na opanowanie kilku formatów zapisu danych. Oprócz omówionych wielokrotnie w poprzednich częściach plików tekstowych wykorzystaliśmy formaty XML oraz XLS. Rozdział 26. stanowił wprowadzenie do przetwarzania dokumentów XML. Pliki XML możesz odczytywać, wykorzystując klasę SimpleXML. Zwolni Cię to z konieczności krojenia napisów na tablice, jak to ma miejsce w przypadku plików tekstowych. Odpowiednio przygotowany dokument XML będzie automatycznie przekształcony na drzewo obiektów, w którym znajdziesz wartości zawarte w poszczególnych elementach XML w postaci właściwości obiektu. Przetwarzając obiekt zwrócony przez funkcję simplexml_load_file(), możesz w bardzo prosty sposób wygenerować dokument HTML lub utworzyć plik tekstowy zawierający dane z pliku XML. Ćwiczenia wykonane w tym rozdziale zapoznały Cię z dwoma formatami XML. Jednym z nich jest format stosowanym przez Narodowy Bank Polski do publikowania kursów walut, drugim zaś — format wykorzystany przez wydawnictwo Helion do publikowania informacji o bieżącej ofercie. Kolejny rozdział zapoznał Cię z najprostszą techniką generowania kodu XML. Jeśli stosujesz Framework MVC oraz system ORM, wówczas generowanie dokumentu XML na postawie danych pobranych z bazy sprowadza się do zmodyfikowania widoku akcji. Zamiast znaczników HTML w widoku umieszczamy znaczniki XML. W ten sposób w projekcie 27.1 wykonaliśmy mapę witryny sitemap.xml oraz kanał rss.xml. Dodatkowo, analizując projekt poświęcony kursom walut, dowiedziałeś się, jak na stronach WWW umieszczać wykresy, korzystając z usługi Google Charts. Tematem rozdziału 28. było przetwarzanie kodu XML w tablice asocjacyjne. Taka technika pracy z kodem XML znacznie upraszcza implementację importu oraz eksportu danych. Zaletą wykorzystania omówionych klas XML_Serializer oraz XML_Unserializer

    Część IV  Formaty danych

    512

    jest między innymi to, że klasy te automatycznie zajmą się formatowaniem wynikowego kodu XML oraz zabezpieczaniem danych zawartych w tablicy m.in. poprzez cytowanie znaków < i > w postaci < oraz >. Jeśli opanujesz opcje konfigurujące pracę tych dwóch klas, to będziesz dysponował bardzo wygodnym narzędziem, które pracę z kodem XML zredukuje do operowania tablicami asocjacyjnymi. Opisane w tym rozdziale przekształcenia wiele w jeden oraz jeden w wiele pokazują, w jak prosty sposób możesz listę plików XML, z których każdy definiuje jeden obiekt, przekształcić w jeden plik definiujący listę obiektów. Przekształcenie w odwrotnym kierunku jest równie proste. Zamiana wielu plików w pojedynczy plik okaże się istotna wówczas, gdy będziemy operowali tysiącami plików. W projekcie 28.6 klasa XML_Serializer została wykorzystana do wygenerowania kanału RSS. Mapa witryny została wykonana z wykorzystaniem klasy File_Sitemap z archiwum PEAR. Rozdział 29. opisuje, w jaki sposób w PHP możesz operować dokumentami arkusza kalkulacyjnego MS Excel. Pliki .xls mogą być m.in. wykorzystane do wypełniania bazy danych. Rozwiązanie takie zostało zilustrowane w projekcie 29.2. Formaty TXT, XML oraz XLS mogą być wykorzystywane zamiennie. Rozdział 30. pokazuje, w jaki sposób można zaimplementować konwersję pomiędzy tymi trzema formatami. Aplikacja opisane w tym rozdziale zawiera połączenie trzech metod opisanych w części trzeciej:  tabele, których zawartość może być sortowana względem dowolnych kolumn;  stronicowanie;  przewijanie rekordów następny/poprzedni.

    Ostatni z rozdziałów części czwartej ilustruje użycie spakowanego formatu XML, w którym umieszczono dane binarne. Zaletą takiego formatu jest to, że komplet danych dotyczących jednego artykułu jest zawarty w jednym pliku. Przykładowy projekt wyjaśnia, w jaki sposób możemy zautomatyzować proces publikacji artykułu w serwisie WWW.

    Skorowidz ###PATH_PREFIX###, 92, 228 $_GET, 64, 346 $path_prefix, 28, 29, 32, 92 &, 78 htaccess, 23, 25, 27 __construct(), 69 __toString(), 198, 209, 247, 291 , 247 href, 282 , 30 , 28, 268 , 225 33 ⅓, 332 baza danych, 333 dublowanie identyfikatorów slug, 333 kontekstowe stronicowanie rekordów, 348 numeracja stron, 340 Pager, 335 prezentacja rekordów poddanych stronicowaniu, 345 stronicowanie, 335 widok wskaźnika stronicowania, 343

    A Actions, 19 set(), 41 ActionsBase, 19, 36 addAscendingOrderByColumn(), 132, 136 AddAttribute(), 388 AddChild(), 388 addDescendingOrderByColumn(), 132 AddType, 76 adres URL, 20, 71 ###PATH_PREFIX###, 92 $path_prefix, 92 bezwzględny, 71, 72

    dwukierunkowość konwersji, 78 konwersja, 78 konwersja przy użyciu funkcji pomocniczych, 81 przyjazny, 20, 71, 72, 73 root, 71, 72 translacja wyjściowa, 80 wewnętrzny, 20, 71, 72, 78 włączanie translacji wyjściowych, 80 wyłączanie translacji wyjściowych, 80 względny, 71, 72 zmienne, 83 akcje, 19 list, 236 nazwy, 19 show, 236 analiza nagłówka HTTP, 38 analiza ścieżek w kodzie HTML, 31 analiza zawartości plików tekstowych, 250 Angaże (szablony PHP, Propel), 248 aplikacja, 261 baza danych, 249 filtry konwertujące generowany kod HTML, 260 hiperłącza kontekstowe, 263 kolumna slug, 248 menu kontekstowe, 264 pliki tekstowe, 250 prezentacja tablicy obiektów, 262 walidacja zmiennych URL, 259 warstwa M, 251 widoki częściowe, 262 zapytania SQL, 255 złączenia, 252 Aparaty foto (Doctrine, PHP), 208 aplikacja, 212 wstawianie rekordów do bazy danych, 211

    514

    PHP, MySQL i MVC. Tworzenie witryn WWW opartych na bazie danych

    Aparaty foto (Propel, PHP), 202 aplikacja, 206 model, 202 warstwa M, 202 wypełnianie bazy danych, 205 aplikacje MVC, 17 kontroler, 17 model, 17 pliki, 22 przebieg wykonania, 24 sterowanie przebiegiem wykonania, 17 warstwa C, 17 widok, 17 architektura MVC, 17 arkusze kalkulacyjne, 449 arra2txt(), 476 array(), 77, 407, 459 array_1dim_to_2dimH(), 261, 305 array_1dim_to_2dimV(), 366 array_map(), 164, 458 array_search(), 65, 75 array_unique(), 459 array2xls(), 474, 475 array2xml(), 471, 473 Artykuły, 372 aplikacja, 381 baza danych, 373 kolorowanie składni, 380 parse_article(), 374 tworzenie spisu treści, 378 wypełnianie bazy danych, 373 asXML(), 387, 388 atrybuty elementu, 391 atrybuty href, 227 atrybuty src, 227 attributes(), 388, 391 AUTO INCREMENT, 98 autoinkrementacja klucza głównego, 99 Autokomis, 460 aplikacja, 465 wypełnianie bazy danych, 460 autoload, 105 automatyczne generowanie identyfikatorów slug dla rekordów o zdublowanych tytułach, 333 automatyczne ładowanie klas, 22

    B base64, 490 dekodowanie, 490 kodowanie, 490 base64_decode(), 489 base64_encode(), 489, 490, 502

    BasePeer::TYPE_COLNAME, 199 BasePeer::TYPE_FIELDNAME, 199 BasePeer::TYPE_NUM, 199 BasePeer::TYPE_PHPNAME, 199 BasePeer::TYPE_STUDLYPHPNAME, 199 baza danych, 95 czyszczenie zawartości, 197 Doctrine, 100 edytor wizualny, 95 identyfikacja rekordów, 146 konwencje nazewnicze, 97 MySQL, 95 projekt, 110 projektowanie, 95 Propel, 100 relacje, 157 relacje n:m, 181 sortowanie rekordów, 132, 134 tabele, 97 tworzenie, 110, 117, 137 warunkowe wstawianie nieistniejących obiektów, 200 wizualne projektowanie, 95 wstawianie rekordów, 211 wybieranie pojedynczego rekordu, 145 wybieranie rekordów z tabeli w zadanym porządku, 131 wypełnianie, 110, 117 wyzwalacze, 363 zapisywanie obrazów, 215 zapisywanie plików binarnych, 218 zapytania SQL, 255 złączenia, 252 bezwzględny adres URL, 71 biblioteka jQuery, 307 BLOB, 224 błędne adresy URL, 35 błędy 404, 35 breadcrumb, 287, 310 buforowanie wydruku, 299

    C children(), 388, 389 chmura tagów, 357 HTML_TagCloud, 358 słowa kluczowe, 358 conf.ini, 106 Content-Type, 217, 220 Controller, 18 create-db.bat, 103 create-db-filled.bat, 103, 113 Criteria, 146

    Skorowidz

    515

    CSS, 48, 51, 54 kolory, 54 text-align, 51 CSS Zen Garden, 234 customOutputTranslations(), 260 Czcionki projektów CSS Zen Garden (Propel, PHP), 234 aplikacja, 235 list, 236 menu główne witryny, 240 show, 236 tytuły stron, 240 widoki akcji list oraz show, 237 czyszczenie zawartości bazy danych, 197

    D dane binarne, 489 tekstowe, 467 XLS, 470 dane XML, 469 opis witryny WWW, 410 data, 42, 45 Data i godzina, 42 szablony PHP, 42 szablony Smarty, 45 date(), 42 db-frame-tool, 101 definiowanie ograniczeń klucza obcego, 271 dekodowanie base64, 490 dekompresja danych, 492 dispatch(), 21, 69 Doctrine, 95, 100, 101, 116, 120 generowanie klas dostępu do bazy, 106, 116 klasy, 107 konwersja obiektu w tablicę, 198 metody, 107 PHP, 141 plik konfiguracyjny, 106 projekt bazy danych, 116 relacje 1:n, 160 relacje n:m, 183 rozszerzanie funkcjonalności klas, 209 rozszerzanie właściwości klas, 174 sortowanie rekordów, 134 sortowanie rekordów stojących w relacji n m, 193 użycie klas, 108 wybieranie pojedynczego rekordu, 147 zapytania, 109 Doctrine Query Language, 109 Doctrine_Query, 109 doDeleteAll(), 197

    dokumenty XML, 387 atrybuty elementu, 391 dane binarne, 489 dostęp do atrybutów, 391 dostęp do węzłów drzewa, 389 drukowanie, 406 drzewo, 387 elementy, 387 generowanie, 403, 405 język XPath, 395 kanały RSS, 411 kompresja, 489 konwersja w tablicę, 436 Książki wydawnictwa Helion, 397 Kursy walut, 395 lista identycznych elementów, 390 mapa witryny, 410 modyfikacja drzewa, 388 prolog, 404, 405 przetwarzanie, 387 przetwarzanie wszystkich elementów, 391 rodzeństwo, 390 SimpleXML, 387 SimpleXMLElement, 387, 388 tworzenie obiektu SimpleXMLElement, 388 wielokrotne zagnieżdżenia, 392 wyszukiwanie danych, 388 zagnieżdżenia elementów, 392 zapytania XPath, 388, 395 dołączanie stylów CSS, 28 dołączanie zewnętrznych zasobów, 27 przekierowanie HTTP, 27 style CSS, 28 ścieżki dostępu, 27 DOMDocument, 388 dopasowanie do adresu URL, 67 doSelect(), 131, 132, 136 doSelectOne(), 145 dostęp do bazy danych, 99 Propel, 102 dostęp do wybranych kolumn tabeli, 499 dostęp do zasobów, 28 DQL, 109 DROP TRIGGER IF EXISTS, 364 drukowanie kodu XML, 406 dublowanie identyfikatorów slug, 333 dwukierunkowość konwersji adresów, 78

    E echo, 406 edytor wizualny bazy danych, 95 efekt rollover, 307 encje, 61

    516

    PHP, MySQL i MVC. Tworzenie witryn WWW opartych na bazie danych

    endforeach, 114 error_reporting(), 21 Excel XLS, 449 execute(), 256 execute_x(), 41, 59 explode(), 164

    F fetch(), 256 fetchAll(), 256 fetchArray(), 175 file(), 51, 65, 458 file_exists(), 75, 362 file_get_contents(), 54, 301, 362, 490, 491 file_put_contents(), 409 Filmy (Doctrine, PHP), 189 Filmy (Doctrine, PHP, sortowanie), 194 Filmy (Propel, PHP), 184 aplikacja, 187 baza danych, 184 Filmy (Propel, PHP, sortowanie), 192 filtr prezentujący początkowe litery rekordów, 351 filtry konwertujące generowany kod HTML, 260 flush(), 299 FOR EACH ROW, 364 foreach, 57, 111, 114 format danych dane tekstowe, 467 Propel XML, 100 XLS, 470 XML, 387, 469 YAML, 100 Format danych systemu do publikowania artykułów, 493 fotografie podążające za wskaźnikiem myszki, 307 Fraszki, 60 szablony Smarty, 68 friendlyUrls, 80 fromArray(), 198 funkcje __toString(), 198 array(), 77, 407, 459 array_1dim_to_2dimH(), 305 array_1dim_to_2dimV(), 366 array_map(), 164, 458 array_search(), 65, 75 array_unique(), 459 array2xls(), 474 base64_decode(), 489 base64_encode(), 489, 490 date(), 42 error_reporting(), 21 explode(), 164 file(), 51, 65, 458

    file_exists(), 75, 362 file_get_contents(), 54, 301, 362, 490, 491 file_put_contents(), 409 flush(), 299 get_file_list(), 361 gzclose(), 491, 492 gzopen(), 491, 492 gzread(), 492 gzwrite(), 491 header(), 217, 297, 405 html2slug(), 61 htmlDeleteTag(), 376 htmlGetFirstMatch(), 376 htmlGetTagsContent(), 375, 376 htmlSetFirstMatch(), 376 ImageCopyResized(), 300 imagejpeg(), 301 implode(), 419, 459 in_array(), 65, 89 ini_set(), 21 isset(), 65, 89, 150 mb_internal_encoding(), 355 mb_strlen(), 355 nl2br(), 47 ob_flush(), 299 ob_get_clean(), 301 ob_start(), 301 parse_filename(), 362 parse_ini_file(), 297 pathinfo(), 149 preg_match(), 377 search_files(), 361 set_include_path(), 22 set_time_limit(), 297 shuffle(), 137, 149 simplexml_load_file(), 387, 390, 393, 490 simplexml_load_string(), 387, 388 sort(), 459 str_ievpifr(), 89 str_ivslug(), 65, 89, 150, 231 str_replace(), 381 string2HArray(), 54, 111, 399 string2slug(), 61 string2VArray(), 54, 399 trim(), 251, 430, 459 uncomment_and_trim(), 251 urldecode(), 355

    G GD, 295, 300 gd_thumbnail_obj(), 295 gd_watermark_obj(), 300 generator ORM, 101

    Skorowidz

    517

    generowanie identyfikatory slug dla rekordów o zdublowanych tytułach, 333 klasy dostępu do bazy, 102, 106, 110, 116, 135, 141 statyczny dokument sitemap xml, 447 Generowanie danych autokomisu, 455 generowanie dokumentów XML, 403, 405 echo, 406 pliki tekstowe, 408 tablice, 407 GET, 25 get_file_list(), 361 getCurrentSort(), 90 getDocNamespaces(), 388 getFirstPageURL(), 344 getName(), 388 getNamespaces(), 388 getPreviousPageURL(), 344 getSerializedData(), 423 godzina, 42, 45 Google Chart API, 418, 420 gzclose(), 491, 492 gzopen(), 491, 492 gzread(), 492 gzwrite(), 491

    H header(), 217, 297, 405 Hello world!, 18 hiperłącza, 247, 268 link w nagłówku strony WWW, 285 następny/poprzedni, 276 przewijanie rozdziałów, 283 hiperłącza kontekstowe, 263 href, 227, 228 HTML_TagCloud, 358, 367 html2slug(), 61 HTMLArticle, 503, 507 htmlDeleteTag(), 376 htmlGetFirstMatch(), 376 htmlGetTagsContent(), 375, 376 htmlSetFirstMatch(), 376 HTTP, 24 HTTPLiveHeaders, 38, 404 HYDRATE_RECORD, 210

    I identyfikacja rekordów w bazie danych, 146 IF, 318 ImageCopyResized(), 300 imagejpeg(), 301 ImgPeer, 362

    Imiona, 351 komponent wyświetlający alfabet, 353 kontrolka z listą liter, 355 layout html, 355 prezentacja liter rozpoczynających się od wybranej litery na stronie WWW, 354 wybieranie alfabetu liter, 352 implementacja sortowalnych tabelek HTML, 320 implode(), 419, 459 in_array(), 65, 89 Indeks, 267 indeksy UNIQUE, 248, 250 index.php, 21 informacje sumaryczne, 291 ini_set(), 21 INSERT, 364 insertIfNotExists(), 200, 222, 317 INT, 98 invertCurrentSort(), 90 isset(), 65, 89, 150

    J JavaScript, 307 jednowymiarowa tablica indeksowana, 426 język DQL, 109 Smarty, 42 XPath, 395 jQuery, 307 justify, 51 justowanie tekstu, 51

    K kanały RSS, 411, 444 Kursy walut, 412 katalog Open Clipart, 358 klasy Actions, 19 Controller, 18 SimpleXML, 387 SimpleXMLElement, 388 Spreadsheet_Excel_Reader, 449, 454 Spreadsheet_Excel_Writer, 452, 453 XML_Serializer, 423, 431 XML_Unserializer, 436 klasy dostępu do bazy, 102, 106 Doctrine, 106 Propel, 102 Klasyfikacja zwierząt, 441 akcje, 443 generowanie statycznego dokumentu sitemap.xml, 447 kanał RSS, 444

    518

    PHP, MySQL i MVC. Tworzenie witryn WWW opartych na bazie danych

    Klasyfikacja zwierząt main/drzewo, 444 moduły, 443 wypełnianie bazy danych, 442 klucz główny, 97 klucz obcy, 97, 252, 270 ograniczenia, 270 kod XML, 387 kodowanie base64, 490 kodowanie utf-8, 61, 76 kodowanie znaków, 355 Kolekcja płyt DVD z fotografiami, 288 aplikacja, 302 baza danych, 290 breadcrumb, 310 efekt rollover, 307 fotografie podążające za wskaźnikiem myszki, 307 klasy dostępu do bazy, 291 ograniczenia czasowe skryptu, 297 opcje konfiguracyjne, 297 przewijanie kategorii, 306 przewijanie zdjęć, 306 tabela zdjęć, 305 translacja adresów, 304 wskaźnik położenia, 310 wskaźniki następny/poprzedni, 306 wypełnianie bazy danych rekordami, 295 znak wodny, 300 Kolędy, 73 kolorowanie składni, 380 kolory CSS, 54 szablony Smarty, 56 kolumna slug, 248 kompresja danych, 491 komunikaty diagnostyczne, 21 kontekstowe hiperłącza do stron ze szczegółowymi informacjami, 247 kontekstowe stronicowanie rekordów, 348 kontroler, 17, 18 Kontynenty, państwa, miasta (Doctrine, PHP), 173 aplikacja, 178 wstawianie rekordów, 176 Kontynenty, państwa, miasta (Propel, PHP), 162 akcje modułu kontynent, 169 akcje modułu miasto, 171 aplikacja, 167 baza danych, 163 index.php, 172 moduł kontynent, 169 moduł miasto, 171 translacja adresów, 172

    układ witryny, 172 widoki modułu kontynent, 169 widoki modułu miasto, 171 konwencje nazewnicze, 97 konwersja dokument XML w tablicę, 436 format XML, 439 obiekt w napis, 198 pliki mwb do formatu Doctrine YML, 101 pliki mwb do formatu Propel XML, 100 pliki tekstowe do formatu XLS, 453 pliki tekstowe do formatu XML, 409 pliki XLS do formatu tekstowego, 454 pliki z danymi, 467 tablica w kod XML, 423 konwersja adresów URL, 78 funkcje pomocnicze, 81 konwersja w generowanych stronach WWW, 79 Konwersja artykułu z formatu tekstowego do spakowanego pliku XML, 495 Konwersja formatu TXT do formatu XLS, 474 Konwersja formatu TXT do formatu XML, 470 Konwersja formatu XLS do formatu TXT, 478 Konwersja formatu XLS do formatu XML, 480 Konwersja formatu XML do formatu TXT, 476 Konwersja formatu XML do formatu XLS, 477 Konwersja jeden-w-wiele, 439 Konwersja pliku mecze.txt, 432 Konwersja pliku nobel.txt, 431 Konwersja pliku tcs.txt, 434 Konwersja wiele-w-jeden, 440 Książki wydawnictwa Helion, 397 Kursy walut, 395, 412 adres dokumentów XML, 412 aplikacja, 415 kanały RSS, 412, 415 mapa witryny, 416 projekt bazy danych, 413 wykresy kursów walut, 418 wypełnianie bazy danych, 413

    L layout html, 20 LEFT(), 352 Ligi piłkarskie, 84 link, 268 list, 233, 236 lista słów kluczowych, 365 LiveHTTPHeaders, 221

    Ł ładowanie klas, 22

    Skorowidz

    519

    M main, 19 mapa witryny, 410, 416 max_allowed_packet, 224 mb_internal_encoding(), 355 mb_strlen(), 355 menu główne witryny, 240 menu kontekstowe, 264 MIME, 217, 221 miniatury ilustracji, 273 mod_rewrite, 27, 30 model, 17, 95 model bazy danych, 102 model MVC, 17 Model-View-Controller, 17 moduły, 19 mouseover, 309 Multibyte, 355 MVC, 17 kontroler, 17 model, 17, 95 warstwa C, 17 warstwa M, 17, 95 warstwa V, 17 widok, 17 MySQL, 95 MySQL Workbench, 95 konwersja bazy danych, 100 myszka, 307

    N nagłówek 404, 35 nagłówki HTTP, 38 nakładanie znaków wodnych, 300 Następny, 267 nazwy, 97 akcje, 19 pliki, 362 nl2br, 70 nl2br(), 47 NotH (Doctrine, PHP), 229 aplikacja, 230 wstaw.php, 230 NotH (Propel, PHP), 221 aplikacja, 224 rozwijane menu pionowe, 226 tytuły stron, 225 wstaw.php, 223

    O ob_flush(), 299 ob_get_clean(), 301 ob_start(), 301

    obiekt GD, 295, 301 obiekty, 108 konwersja w napis, 198 obrazy, 215, 300, 301, 359 ochrona kodu PHP, 23 odczytywanie fragment kodu HTML, 376 pliki XLS, 449 wiele arkuszy XLS, 451 oglądanie strony błędu, 38 ograniczenia czasowe skryptu, 297 ograniczenia kluczy obcych, 270 Ojciec i syn, 47 szablony PHP, 47 szablony Smarty, 49 okienko pop-up, 307 On Delete, 270 On Update, 270 opcje konfiguracyjne, 297 Open Clipart, 358 aplikacja, 365 baza danych, 359 chmura słów kluczowych obrazu, 368 chmura wszystkich słów kluczowych, 367 HTML_TagCloud, 367 ImgPeer, 362 lista słów kluczowych, 365 pliki graficzne, 361 waga słów kluczowych, 363 wypełnianie bazy danych, 360 zestaw słów kluczowych, 366 oprogramowanie ORM, 99 ORM, 95, 100 ORM Propel, 42 Ostatni, 267 outputTranslations, 80

    P Pager, 335 parse_filename(), 362 parse_ini_file(), 297 parse_txt(), 471 parse_xml(), 476 parsing atrybutów, 437 artykuły w formacie .xml.gz, 501 partial(), 282 pathinfo(), 149 PCRE, 377 PEAR, 358 PEAR::OLE, 452 PEAR::Spreadsheet_Excel_Writer, 452 Peer, 131, 132 doDeleteAll(), 197 doSelect(), 131 doSelectOne(), 145

    520

    PHP, MySQL i MVC. Tworzenie witryn WWW opartych na bazie danych

    PHP, 21 PHP. Praktyczne projekty, 269 hiperłącza link zawarte w nagłówku strony WWW, 285 hiperłącza następny/poprzedni, 276 klasy dostępu do bazy, 271 klucz obcy, 270 miniatury ilustracji, 273 moduł spistresci, 274 prezentacja odsyłaczy następny/poprzedni dla tabeli, 281 przewijanie rozdziałów, 283 tytuły stron WWW, 272 wskaźniki następny/poprzedni dla tabeli rozdzial, 280 PHP-ExcelReader, 449 phpMyAdmin, 112 Pierwszy, 267 Piłka nożna — sezon 2002/2003, 312 aplikacja, 320 baza danych, 313 implementacja sortowalnych tabelek HTML, 320 sortowanie nazw klubów, 320 sortowanie wyników sezonu, 321 sortowanie złączeń dla wielokrotnych kluczy, 314 TabelaKlubow, 320, 324 TabelaMeczow, 323, 324 TabelaWynikow, 321, 324 widoki prezentujące tabelki HTML, 327 wielokrotne klucze obce z tej samej tabeli, 314 wypełnianie bazy danych, 317 zestawienie meczów, 322 pl_win2utf8(), 450 pliki, 22 css, 27 graficzne, 361 ini, 297 jpg, 27 js, 27 nazwy, 362 sprawdzanie istnienia, 75 tekstowe, 73, 250, 467 XLS, 449 XML, 403 zapisywanie kodu XML, 409 PNG, 359 polskie znaki diakrytyczne, 61 połączenie z bazą danych, 463 Poprzedni, 267 pop-up, 307 porządek sortowania, 132 postActions(), 59

    postprzetwarzanie, 59 prase_txt(), 471 preActions(), 59, 74, 261 preg_match(), 377 prepare(), 256 preprzetwarzanie, 59 prezentacja liter rozpoczynających się od wybranej litery na stronie WWW, 354 prezentacja tablicy obiektów, 262 prezentacja zawartości bazy danych, 114, 118 prezentacja zdjęć JPG zapisanych w bazie danych na stronie WWW, 216 prezentacja zestawu słów kluczowych, 357 projekt bazy danych, 110, 135 projektowanie bazy danych, 95 prolog XML, 404, 405 Propel, 42, 95, 100, 102, 104, 109, 119 dostęp do wybranych kolumn tabeli, 499 generowanie klas dostępu do bazy, 102, 110 klasy, 104 konwersja obiektu w tablicę, 198 metody, 104 PHP, 134 porządek sortowania, 178 projekt bazy danych, 110 relacje 1:n, 158 relacje n:m, 182 sortowanie rekordów, 132 sortowanie rekordów stojących w relacji n:m, 192 typy indeksacji tablic, 199 użycie klas, 105 Propel XML, 100 protokół HTTP, 24 przebieg wykonania, 24 przekazywanie danych do widoku, 41 przekierowanie żądań HTTP, 23, 27 przekształcanie elementów tablicy danych w atrybuty, 428 przetwarzanie dokumenty XML, 387 widoki, 42 żądania HTTP, 17 przewijanie zawartości witryny WWW, 267 przyjazne adresy URL, 20, 73 publikowanie zawartości bazy danych w postaci witryny WWW, 233

    R registerXPathNamespace(), 388 reguły translacji adresów URL, 30 reguły warunkowe, 27

    Skorowidz

    521

    relacje, 157 1 n, 157, 315 relacje n m, 181 Doctrine, 183 Propel, 182 sortowanie rekordów, 192, 193 require_once(), 22 RewriteCond, 27 RewriteEngine, 27, 30 RewriteRule, 27 RGB, 54 rodzaje adresów URL, 77 rollover, 307 rozmiar pól BLOB, 224 rozszerzanie właściwości klas generowanych przez Doctrine, 174 rozwijane menu pionowe, 226 RSS, 411

    S schema xml, 101 schema.yml, 101 search_files(), 361 SELECT DISTINCT, 352 serialize(), 423 set(), 41 set_include_path(), 22 set_time_limit(), 297 setOption(), 425 setOutputEncoding(), 449 short_open_tag, 405 show, 233, 236 shuffle(), 137, 149 SimpleXML, 387, 388 __construct(), 388 AddAttribute(), 388 AddChild(), 388 asXML(), 388 attributes(), 388 children(), 388 getDocNamespaces(), 388 getName(), 388 getNamespaces(), 388 registerXPathNamespace(), 388 simplexml_import_dom(), 388 simplexml_load_file(), 388 simplexml_load_string(), 388 xpath(), 388 simplexml_import_dom(), 388 simplexml_load_file(), 387, 388, 390, 393, 490 simplexml_load_string(), 387, 388 SimpleXMLElement, 387, 388, 389

    Site navigation bar, 268 sitemap xml, 410, 417, 447 skompresowane dokumenty XML, 489 słownik, 134, 141 Słownik (Doctrine, PHP), 141 Słownik (Propel, PHP), 134 Smarty, 42 smarty_function_url(), 82 SmartyView, 69 sort(), 90, 459 sortowanie rekordy stojące w relacji n m, 192, 193 tabele HTML, 311, 320 względem dowolnej kolumny, 85 złączenia dla wielokrotnych kluczy, 314 sortowanie rekordów, 132, 134 Doctrine, 134 porządek sortowania, 132 Propel, 132 spis treści, 371 tworzenie, 378 Spreadsheet_Excel_Reader, 449, 454 read(), 449 setOutputEncoding(), 449 Spreadsheet_Excel_Writer, 452, 453 src, 227, 228 statyczne pliki XML, 403 Stefan Żeromski: Zmierzch, 50 szablony PHP, 50 szablony Smarty, 53 sterowanie przebiegiem wykonania aplikacji, 17 str_ievpifr(), 89, 340 str_ivslug(), 65, 89, 150, 231 str_replace(), 381 strGetSort(), 90 string2HArray(), 54, 111, 399 string2slug(), 60, 61, 465 string2VArray(), 54, 399 strInvertSort(), 90 strona błędu, 35, 38 strona WWW, 20 stronicowanie, 331 implementacja, 335 kontekstowe, 348 numeracja stron, 340 prezentacja rekordów, 345 wskaźnik, 343 wskaźnik bieżącej strony, 331 style CSS, 28, 48 SVG, 359 SyntaxHighlighter, 380 system ORM, 100

    522

    PHP, MySQL i MVC. Tworzenie witryn WWW opartych na bazie danych

    System publikacji artykułów w postaci witryny WWW, 498 akcje, 509 aplikacja, 508 article/page, 510 article/show, 509 baza danych, 499 dostęp do wybranych kolumn tabeli, 499 HTMLArticle, 503, 507 parsing artykułu w formacie xml.gz, 501 przetwarzanie treści artykułu, 502 wstaw.php, 507 wypełnianie bazy danych, 501 XMLArticle, 501, 505 szablony, 41 szablony PHP, 42, 47, 50 data, 42 Doctrine, 116 godzina, 42 Propel, 109 szablony Smarty, 42, 45, 49, 53, 68 data, 45 Doctrine, 120 godzina, 45 kolory CSS, 56 Propel, 119 wtyczki, 82

    Ś ścieżki dostępu, 27, 31

    T tabele, 97 relacje 1:n, 157 relacje n:m, 181 tworzenie, 97 wybieranie rekordów w zadanym porządku, 131 złączenia, 252 tabele HTML, 305 sortowanie, 311 tablica opcji, 426 tablice, 54, 407, 459 tablice asocjacyjne, 55, 257, 424 tags cloud, 357 Tatry (szablony PHP, Doctrine), 116 Tatry (szablony Smarty, Doctrine), 120 Tatry (szablony Smarty, Propel), 119 text-align, 51 toArray(), 198 transformacje tablic w XML, 423 atrybuty, 428 jednowymiarowa tablica indeksowana, 426 konwersja pliku mecze.txt, 432

    konwersja pliku nobel.txt, 431 konwersja pliku tcs.txt, 434 opcje, 425 przekształcenia, 430 tablica asocjacyjna, 424 wielowymiarowe tablice indeksowane, 427 wybiórcze stosowanie atrybutów, 429 XML_Serializer, 423 XML_Unserializer, 436 translacja adresów URL, 20, 30, 37, 71, 304 ###PATH_PREFIX###, 92 $path_prefix, 92 adresy w generowanych stronach WWW, 79 dwukierunkowość konwersji, 78 funkcje pomocnicze, 81 translacja wyjściowa, 80 wtyczki Smarty, 82 zmienne, 83 Treny (Doctrine, PHP), 153 Treny (Propel, PHP), 147 identyfikacja trenu wewnątrz akcji tren/show, 151 trim(), 251, 430, 459 try, 191 Turniej Czterech Skoczni, 398 aplikacja, 400 baza danych, 398 tworzenie akcje, 19 baza danych, 110, 117, 137 moduły, 19 obiekty, 108 pliki XLS, 452 relacje 1:n, 157 relacje n:m, 181 spis treści, 378 tabele, 97 układ witryny WWW, 20 TXTArticle, 495 typ MIME, 217, 218, 221 tytuły stron, 225, 240, 272

    U układ witryny WWW, 20 uncomment_and_trim(), 251 unikatowość kolumny slug, 248 UNIQUE, 248, 250 unserialize(), 437, 502 URL, 20 url(), 81 urldecode(), 355 uruchamianie generator ORM, 101 projekt, 23

    Skorowidz

    523

    usuwanie fragmenty kodu HTML, 376 znaczniki HTML, 61 utf-8, 61, 355

    V viewClass, 42

    W waga słów kluczowych, 363 walidacja zmiennych URL, 259 warunkowe wstawianie nieistniejących obiektów, 200 wewnętrzny adres URL, 20 while, 335 widok, 17, 41, 75 wielokrotne wykorzystanie widoku, 201 widok częściowy, 201, 262 widok wskaźnika stronicowania, 343 wielokrotne klucze obce z tej samej tabeli, 314 wielokrotne wykorzystanie widoku, 201 wielowymiarowe tablice indeksowane, 427 wizualne projektowanie bazy danych, 95 Wlazł kotek na schody…, 28 wskaźnik myszki, 307 wskaźnik położenia, 287, 310 separator elementów, 288 wskaźnik stronicowania, 343 wstawianie rekordów do bazy danych, 176, 211 wtyczki Smarty, 82 www, 24 wybór litery, 351 wybór pojedynczego rekordu, 145 Doctrine, 147 wybór rekordów z tabeli w zadanym porządku, 131 wykonanie zapytania, 256 wykresy, 418 Google Chart API, 418 kursy walut, 418 wyniki rozgrywek piłkarskich, 84 wyniki zapytania SQL, 256 wypełnianie bazy danych, 110, 117, 137 wyrażenia regularne, 67, 377 tryb leniwy, 377 wysyłanie danych binarnych z bazy do przeglądarki, 220 wysyłanie stron WWW, 17 wyświetlanie komunikatów diagnostycznych, 21 wyznaczanie statystycznych informacji sumarycznych, 291 wyzwalacze, 363 względny adres URL, 71

    X XLS, 449, 470 konwersja pliku tekstowego, 453 konwersja pliku XLS do formatu tekstowego, 454 odczyt kilku arkuszy, 451 odczytywanie danych, 449 Spreadsheet_Excel_Reader, 449 Spreadsheet_Excel_Writer, 452 tworzenie pliku, 452 wysyłanie arkusza do przeglądarki, 453 zapisywanie danych, 452 XML, 387, 469 XML_Serializer, 423, 431, 474 getSerializedData(), 423 opcje, 425 serialize(), 423 setOption(), 425 XML_SERIALIZER_OPTION_XML_DECL_ ENABLED, 425 XML_Unserializer, 423, 436, 476, 502 odczyt pliku, 437 opcje, 438 parsing atrybutów, 437 unserialize(), 437 XML_UNSERIALIZER_OPTION_ ATTRIBUTES_PARSE, 437 XMLArticle, 501, 505 XPath, 388, 395 xpath(), 388, 395

    Y YAML, 100

    Z zapisywanie dane XLS, 452 kod XML do pliku, 409 obrazy w bazie danych, 215 pliki binarne, 215, 218 zapytania SQL, 255 XPath, 388, 395 zawartość bazy danych, 138 zestaw słów kluczowych, 366 Zestawienia artykułów „Magazynu INTERNET”, 480 aplikacja, 483 autor/list, 484 autor/show, 486

    524

    PHP, MySQL i MVC. Tworzenie witryn WWW opartych na bazie danych

    baza danych, 481 stronicowana tabelka HTML, 484 zliczanie artykułów, 482 zewnętrzne zasoby, 27 zlib, 491 złączenia, 248, 252 zmienne, 41 adres URL, 83 znak wodny, 300 zrzut zawartości bazy danych, 113

    Ż żądania HTTP, 17, 23, 25 Żółta Turnia, 36

    Dodatkowe materiały Dodatkowe materiały do książki można znaleźć pod adresem: ftp://ftp.helion.pl/przyklady/aplphp.zip Rozmiar pliku: 741 MB Materiały zawierają:  Oprogramowanie:  Apache 2.2.14  PHP 5.2.13  MySQL 5.1.44  phpMyAdmin 3.2.5  MySQL Workbench 5.1.18a  Propel 1.3  Doctrine 1.1.6  Smarty 2.6.26  Szczegółową instrukcję instalacji oprogramowania w systemach:  Windows XP  Windows Vista  Windows 7  Wszystkie listingi zawarte w książce  Kompletny kod wszystkich omówionych projektów  Dla każdego ćwiczenia plik startowy, od którego należy rozpocząć pracę

    Wszystkie projekty zostały szczegółowo przetestowane na platformie Windows z wykorzystaniem wymienionego oprogramowania w podanych powyżej wersjach. Każdy z projektów jest dostępny w postaci spakowanego archiwum .zip, które oprócz kodu źródłowego zawiera także kod SQL tworzący odpowiednią bazę danych. Utworzenie bazy danych wybranego projektu na lokalnym serwerze MySQL sprowadza się do uruchomienia pliku wsadowego .bat. Materiał jest przygotowany w postaci witryny WWW, co ułatwi wyszukiwanie rozdziałów, projektów, ćwiczeń oraz listingów. Strona opisująca pojedynczy projekt zawiera:  Zrzut ekranowy prezentujący wygląd rozwiązania w przeglądarce  Plik .zip zawierający kompletne rozwiązanie  Hiperłącze do strony dostępnej w Internecie, prezentującej działający projekt Działanie wszystkich projektów prezentuje witryna http://php-mysql-mvc.gajdaw.pl.