PHP, MySQL i javascript. Wprowadzenie. wyd. IV

Tytuł oryginału: Learning PHP, MySQL & JavaScript, 4th Edition Tłumaczenie: Piotr Cieślak ISBN: 978-83-283-0845-9 © 2015 Helion S.A. Authorized Polish...

13 downloads 74 Views 22MB Size



Rysunek 26.4. Edytowanie profilu użytkownika

620



Rozdział 26. Zastosowanie wszystkich omówionych technologii

members.php Korzystając z pliku members.php (przykład 26.9), użytkownicy będą mogli wyszukiwać innych użytkowników i dodawać ich do grona znajomych (albo ich z tego grona usuwać). Ten program działa w dwóch trybach. Pierwszy powoduje wymienienie wszystkich użytkowników oraz ich relacji z Tobą, zaś drugi wyświetla profil użytkownika. Przykład 26.9. members.php "; if (isset($_GET['view'])) { $view = sanitizeString($_GET['view']); if ($view == $user) $name = "Twoje"; else $name = "$view"; echo "

Profil użytkownika $name

"; showProfile($view); echo "" . "Wyświetl wiadomości: $name.

"; die("
"); } if (isset($_GET['add'])) { $add = sanitizeString($_GET['add']); $result = queryMysql("SELECT * FROM friends WHERE user='$add' AND friend='$user'"); if (!$result->num_rows) queryMysql("INSERT INTO friends VALUES ('$add', '$user')"); } elseif (isset($_GET['remove'])) { $remove = sanitizeString($_GET['remove']); queryMysql("DELETE FROM friends WHERE user='$remove' AND friend='$user'"); } $result = queryMysql("SELECT user FROM members ORDER BY user"); $num = $result->num_rows; echo "

Inni użytkownicy

    "; for ($j = 0 ; $j < $num ; ++$j) { $row = $result->fetch_array(MYSQLI_ASSOC); if ($row['user'] == $user) continue; echo "
  • " . $row['user'] . "";

    Funkcje



    621

    $follow = "follow"; $result1 = queryMysql("SELECT * FROM friends WHERE user='" . $row['user'] . "' AND friend='$user'"); $t1 = $result1->num_rows; $result1 = queryMysql("SELECT * FROM friends WHERE user='$user' AND friend='" . $row['user'] . "'"); $t2 = $result1->num_rows; if (($t1 + $t2) > 1) echo " ↔ jesteście znajomymi"; elseif ($t1) echo " ← Ty obserwujesz"; elseif ($t2) { echo " → obserwuje Ciebie"; $follow = "odwzajemnij"; } if (!$t1) echo " [$follow]"; else echo " [usuń]"; } ?>


Wyświetlanie profilu użytkownika Plik zaczyna się od kodu związanego z drugim z wymienionych trybów. Najpierw sprawdzana jest zmienna view z tablicy GET. Jeśli zmienna ta istnieje, to znaczy, że użytkownik chce wyświetlić czyjś profil. Program spełnia to żądanie przy użyciu funkcji showProfile, a przy okazji wyświetla odsyłacze do znajomych użytkownika oraz otrzymane wiadomości.

Dodawanie i usuwanie znajomych Następnie sprawdzane są kolejne dwie zmienne z tablicy GET, a mianowicie add i remove. Jeśli jedna z nich ma wartość, to będzie to nazwa innego użytkownika do dodania albo usunięcia z listy znajomych. Operacja ta polega na wyszukaniu bieżącego użytkownika w tabeli friends w bazie danych MySQL i dodaniu do tej tabeli (lub usunięciu z niej) odpowiedniej nazwy. Oczywiście wszystkie przesyłane zmienne są najpierw poddawane czyszczeniu przy użyciu funkcji sanitizeString, aby można było bezpiecznie używać ich w komunikacji z bazą MySQL.

Wyświetlanie listy wszystkich użytkowników Ostatnia część omawianego pliku zawiera zapytanie SQL powodujące wyświetlenie wszystkich użytkowników. Ich liczba trafia do zmiennej $num (w wierszu kodu tuż przed nagłówkiem). Następnie za pomocą pętli for przetwarzani są wszyscy użytkownicy. Program pobiera informacje na ich temat i weryfikuje zawartość tabeli friends, aby sprawdzić, czy są obserwowani przez bieżącego użytkownika, czy też może sami go obserwują. Jeśli ktoś obserwuje kogoś i zarazem jest przez niego obserwowany, to taka relacja zostaje zaklasyfikowana jako znajomość. Jeśli bieżący użytkownik obserwuje innego, zmienna $t1 ma niezerową wartość. Jeśli inny użytkownik serwisu obserwuje bieżącego, zmienna $t2 jest różna od zera. Na podstawie tych

622



Rozdział 26. Zastosowanie wszystkich omówionych technologii

wartości po nazwach poszczególnych użytkowników serwisu jest wyświetlany odpowiedni tekst, określający relację (jeśli taka zachodzi) względem bieżącego użytkownika. Pomocniczą ilustracją tych relacji są symbole. Podwójna strzałka oznacza, że użytkownicy są znajomymi. Strzałka skierowana w lewą stronę symbolizuje, że bieżący użytkownik obserwuje innego. Zaś strzałka skierowana w prawo jest wyświetlana przy tych użytkownikach serwisu, którzy obserwują bieżącego. Wreszcie w zależności od tego, czy bieżący użytkownik obserwuje innego, wyświetlany jest odsyłacz umożliwiający dodanie (albo usunięcie) danego członka serwisu do (z) grona obserwowanych lub znajomych. Po otwarciu programu z przykładu 26.9 w przeglądarce będzie on wyglądał podobnie jak na rysunku 26.5. Zauważ, że bieżący użytkownik może obserwować innego, którego dotąd nie obserwował, a jeśli ktoś inny obserwuje jego, może odwzajemnić się i dodać go do grona znajomych. Jeśli bieżący użytkownik obserwuje innego, może usunąć go z grona.

Rysunek 26.5. Obsługa modułu Znajomi Na serwerze produkcyjnym, na którym byłyby tysiące albo nawet setki tysięcy użytkowników serwisu, zapewne musiałbyś zdecydowanie zmodyfikować ten program, aby umożliwić przeszukiwanie bazy pod kątem treści tekstu O mnie, wyświetlanie listy użytkowników z podziałem na strony (by nie tworzyć jednej długiej listy) i tak dalej.

friends.php Moduł służący do obsługi znajomości nosi nazwę friends.php i został przedstawiony w przykładzie 26.10. Program ten analizuje zawartość tabeli friends podobnie jak members.php, ale tylko pod kątem jednego użytkownika. Następnie wyświetla on wszystkich wspólnych znajomych oraz użytkowników obserwowanych przez niego i obserwujących go.

Funkcje



623

Przykład 26.10. friends.php $view's"; $name2 = "$view - jej/jego"; $name3 = "$view "; } echo "
"; // Usuń komentarz z poniższej linii, jeśli chcesz wyświetlić profil użytkownika // showProfile($view); $followers = array(); $following = array(); $result = queryMysql("SELECT * FROM friends WHERE user='$view'"); $num = $result->num_rows; for ($j = 0 ; $j < $num ; ++$j) { $row = $result->fetch_array(MYSQLI_ASSOC); $followers[$j] = $row['friend']; } $result = queryMysql("SELECT * FROM friends WHERE friend='$view'"); $num = $result->num_rows; for ($j = 0 ; $j < $num ; ++$j) { $row = $result->fetch_array(MYSQLI_ASSOC); $following[$j] = $row['user']; } $mutual $followers $following $friends

= = = =

array_intersect($followers, $following); array_diff($followers, $mutual); array_diff($following, $mutual); FALSE;

if (sizeof($mutual)) { echo "$name2 znajomości
    "; foreach($mutual as $friend) echo "
  • $friend"; echo "
"; $friends = TRUE; }

624 

Rozdział 26. Zastosowanie wszystkich omówionych technologii

if (sizeof($followers)) { echo "$name2 grono obserwatorów
    "; foreach($followers as $friend) echo "
  • $friend"; echo "
"; $friends = TRUE; } if (sizeof($following)) { echo "$name3 obserwuje(sz)
    "; foreach($following as $friend) echo "
  • $friend"; echo "
"; $friends = TRUE; } if (!$friends) echo "
Nie masz jeszcze żadnych znajomości.

"; echo "" . "$name2 wiadomości"; ?>



Wszyscy obserwujący bieżącego użytkownika trafiają do tablicy o nazwie $followers, zaś osoby, które obserwuje bieżący użytkownik — do tablicy $following. Następnie za pomocą sprytnej instrukcji wyodrębniani są ci, który zarówno obserwują bieżącego użytkownika, jak i są przez niego obserwowani: $mutual = array_intersect($followers, $following);

Funkcja array_intersect wyszukuje wszystkich użytkowników występujących w obydwu tablicach i zwraca nową tablicę tylko z tymi użytkownikami. Tablica ta jest przechowywana w zmiennej o nazwie $mutual. Dzięki temu pojawia się możliwość zastosowania funkcji array_ diff na tablicach $followers i $following, by zawierały one tylko tych użytkowników, którzy nie są znajomymi (czyli tymi, którzy obserwują się nawzajem): $followers = array_diff($followers, $mutual); $following = array_diff($following, $mutual);

W rezultacie w tablicy $mutual znajdują się tylko znajomi, w tablicy $followers tylko obserwujący użytkownika (z wyłączeniem znajomych), zaś w tablicy $following tylko obserwowani (z wyłączeniem znajomych). Uzbrojeni w te tablice możemy bez trudu wyświetlić każdą grupę użytkowników z osobna, co ilustruje rysunek 26.6. Funkcja PHP sizeof zwraca liczbę elementów w tablicy; tutaj użyłem jej tylko do uruchomienia kodu, gdy tablica ma niezerowy rozmiar (co oznacza istnienie znajomego należącego do danej kategorii). Zauważ, że dzięki zmiennym $name1, $name2 oraz $name3 zastosowanym w odpowiednich miejscach kod „wie”, kiedy przeglądasz listę własnych znajomych, i zwraca się bezpośrednio do Ciebie („Twoje…”, „Ty…”), zamiast wyświetlać Twoją nazwę w serwisie. Jeśli chcesz, aby na tym ekranie wyświetlał się także profil użytkownika, możesz usunąć z kodu stosowny komentarz.

Funkcje



625

Rysunek 26.6. Wyświetlanie znajomych i osób obserwowanych/obserwujących

messages.php Ostatnim spośród głównych modułów serwisu jest messages.php (przykład 26.11). Program rozpoczyna się od sprawdzenia zmiennej text pod kątem przesłania wiadomości. Jeśli wiadomość istnieje, trafia do tabeli messages w bazie danych. Wraz z nią jest zapisywana wartość pm, która decyduje o tym, czy wiadomość jest prywatna, czy publiczna. Wartość 0 oznacza wiadomość publiczną, zaś 1 wiadomość prywatną. Przykład 26.11. messages.php
626



Rozdział 26. Zastosowanie wszystkich omówionych technologii

} if ($view != "") { if ($view == $user) $name1 = $name2 = "Twoje"; else { $name1 = "$view - jej/jego"; $name2 = "$view - jej/jego"; } echo "

$name1 wiadomości

"; showProfile($view); echo <<<_END
Poniżej wpisz treść wiadomości:

Publiczna Prywatna

_END; if (isset($_GET['erase'])) { $erase = sanitizeString($_GET['erase']); queryMysql("DELETE FROM messages WHERE id=$erase AND recip='$user'"); } $query = "SELECT * FROM messages WHERE recip='$view' ORDER BY time DESC"; $result = queryMysql($query); $num = $result->num_rows; for ($j = 0 ; $j < $num ; ++$j) { $row = $result->fetch_array(MYSQLI_ASSOC); if ($row['pm'] == 0 || $row['auth'] == $user || $row['recip'] == $user) { echo date('M jS \'y g:ia:', $row['time']); echo " " . $row['auth']. " "; if ($row['pm'] == 0) echo "pisze: "" . $row['message'] . "" "; else echo "szepcze: "" . $row['message']. "" "; if ($row['recip'] == $user) echo "[usuń]"; echo "
"; } } } if (!$num) echo "
Brak wiadomości.

";

Funkcje



627

echo "
Odśwież wiadomości"; ?>



Następnie jest wyświetlany profil użytkownika oraz formularz wpisywania wiadomości wraz z przyciskami wyboru, umożliwiającymi nadanie wiadomości statusu prywatnej albo publicznej. Poniżej są wyświetlane wiadomości, w zależności od tego, czy są prywatne, czy publiczne. Publiczne mogą widzieć wszyscy użytkownicy, ale prywatne są widoczne tylko dla nadawcy i odbiorcy. Za to wszystko odpowiadają dwa zapytania do bazy MySQL. Ponadto wiadomości prywatne można odróżnić po słowie szepcze, a poza tym są one wyświetlane kursywą. Na koniec program wyświetla odsyłacze umożliwiające odświeżenie listy wiadomości (w razie gdyby w międzyczasie dotarł kolejny list) i wyświetlenie znajomych użytkownika. Ponownie użyłem sztuczki ze zmiennymi $name1 oraz $name2, aby przy wyświetlaniu własnego profilu zamiast nazwy użytkownika pojawiało się słowo Twoje. Rezultat działania tego programu został pokazany na rysunku 26.7. Zauważ, że użytkownicy przeglądający własne wiadomości mogą usuwać te niepożądane przy użyciu specjalnych odsyłaczy.

Rysunek 26.7. Moduł wiadomości

628 

Rozdział 26. Zastosowanie wszystkich omówionych technologii

logout.php Ostatnim składnikiem naszego serwisu społecznościowego będzie przykład 26.12, czyli plik logout.php. Odpowiada on za wyświetlenie strony informującej o zakończeniu sesji i usunięcie wszelkich powiązanych z tą sesją danych i ciasteczek. Rezultat uruchomienia tego programu został pokazany na rysunku 26.8. Program prosi użytkownika o kliknięcie odsyłacza, który spowoduje wyświetlenie strony głównej dla niezalogowanych gości, bez kategorii widocznych tylko dla użytkowników serwisu. Oczywiście w JavaScripcie albo w PHP można byłoby napisać fragment kodu automatyzujący przekierowanie (dzięki czemu proces wylogowania wyglądałby bardziej elegancko). Przykład 26.12. logout.php Wylogowanie odbyło się poprawnie. Proszę " . "kliknąć tutaj, aby odświeżyć stronę."; } else echo "

" . "Nie możesz się wylogować, ponieważ nie jesteś zalogowany."; ?>



Rysunek 26.8. Strona wylogowania

styles.css Przykład 26.13 to arkusz stylów użyty na potrzeby tego projektu. Zadeklarowano w nim pewną liczbę reguł dla następujących elementów:

Funkcje



629

*

Za pomocą selektora uniwersalnego zdefiniowana została domyślna rodzina fontów oraz ich wielkość dla całego projektu.

body

Określa szerokość okna z projektem, wyśrodkowuje stronę w poziomie, zmienia kolor tła i powoduje wyświetlenie ramki.

html

Określa kolor tła sekcji HTML.

img

Wszystkie obrazki są wyświetlane w ramkach, z cieniem i marginesem po prawej stronie.

li a oraz .button

Usuwa podkreślenia z odsyłaczy we wszystkich znacznikach znajdujących się w elementach
  • oraz we wszystkich elementach klasy button. li a:hover oraz .button:hover

    Określa kolor wyświetlania elementów
  • oraz elementów klasy button po wskazaniu ich kursorem myszy. .appname

    Określa właściwości nagłówka (któremu przypisano klasę appname) z uwzględnieniem wyśrodkowania, zmiany koloru tła i tekstu, rodziny fontów, wielkości znaków oraz odstępów.

    .fieldname

    Określa szerokość elementów korzystających z klasy fieldname i nadaje im właściwość float.

    .main

    Powoduje wcięcie elementów tej klasy.

    .info

    Ta klasa służy do wyświetlania ważnych informacji. Określa ona kolor tła i tekstu, definiuje obramowanie i odstępy oraz powoduje wcięcie elementów, do których została przypisana.

    .menu li oraz .button

    Te deklaracje gwarantują, że wszystkie elementy
  • oraz klasy button zostaną wyświetlone w trybie inline, będą miały właściwe odstępy, ramki oraz kolor tła i tekstu. Ponadto reguły te definiują wartość prawego marginesu, zaokrąglone rogi i cień, co daje efekt w postaci przycisku. .subhead

    Eksponuje wybrane fragmenty tekstu.

    .taken, .available, .error oraz .whisper

    Te deklaracje definiują kolory i fonty używane do wyświetlania różnego rodzaju informacji. #logo

    Te reguły definiują logo w formie tekstowej na potrzeby przeglądarek niezgodnych z HTML5, w których logo nie zostanie wygenerowane w zwykły sposób.

    Przykład 26.13. styles.css * { font-family:verdana,sans-serif; font-size :14pt;

    630



    Rozdział 26. Zastosowanie wszystkich omówionych technologii

    } body { width :700px; margin :20px auto; background:#f8f8f8; border :1px solid #888; } html { background:#fff } img { border :1px solid black; margin-right :15px; -moz-box-shadow :2px 2px 2px #888; -webkit-box-shadow:2px 2px 2px #888; box-shadow :2px 2px 2px #888; } li a, .button { text-decoration:none; } li a:hover, .button:hover { color:green; } .appname { text-align :center; background :#eb8; color :#40d; font-family:helvetica; font-size :20pt; padding :4px; } .fieldname { float:left; width:120px; } .main { margin-left:40px; } .info { background :lightgreen; color :blue; border :1px solid green; padding :5px 10px; margin-left:40px; } .menu li, .button { display :inline; padding :4px 6px;

    Funkcje



    631

    border :1px solid #777; background :#ddd; color :#d04; margin-right :8px; border-radius :5px; -moz-box-shadow :2px 2px 2px #888; -webkit-box-shadow:2px 2px 2px #888; box-shadow :2px 2px 2px #888; } .subhead { font-weight:bold; } .taken, .error { color:red; } .available { color:green; } .whisper { font-style:italic; color :#006600; } #logo { font-family:Georgia; font-weight:bold; font-style:italic; font-size :97px; }

    javascript.js I wreszcie ostatni plik to kod JavaScript (przykład 26.14), który zawiera funkcje O, S i C używane w wielu przykładach w tej książce, a także fragment powodujący wygenerowanie graficznego logo serwisu przy użyciu elementu canvas HTML5, zgodnie ze wskazówkami podanymi w rozdziale 23. Przykład 26.14. javascript.js canvas context context.font context.textBaseline image image.src

    = = = = = =

    O('logo') canvas.getContext('2d') 'bold italic 97px Georgia' 'top' new Image() 'robin.gif'

    image.onload = function() { gradient = context.createLinearGradient(0, 0, 0, 89) gradient.addColorStop(0.00, '#faa') gradient.addColorStop(0.66, '#f00') context.fillStyle = gradient context.fillText( "R bin's Nest", 0, 0)

    632



    Rozdział 26. Zastosowanie wszystkich omówionych technologii

    context.strokeText("R bin's Nest", 0, 0) context.drawImage(image, 64, 32) } function O(i) { return typeof i == 'object' ? i : document.getElementById(i) } function S(i) { return O(i).style } function C(i) { return document.getElementsByClassName(i) }

    I to by było na tyle, jak mawiają niektórzy. Jeśli zrealizujesz własny projekt z użyciem powyższego kodu albo kodu dowolnego z przykładów podanych w poprzednich rozdziałach, jeśli uda Ci się z tej książki w ten czy inny sposób skorzystać — to bardzo się cieszę, że mogłem pomóc, i zarazem dziękuję za jej przeczytanie. Zanim jednak wypróbujesz nowo zdobyte umiejętności podczas realizowania własnych projektów, zajrzyj do dodatków w dalszej części książki, zawierają one bowiem wiele potencjalnie przydatnych informacji.

    Funkcje



    633

    634 

    Rozdział 26. Zastosowanie wszystkich omówionych technologii

    DODATEK A

    Odpowiedzi na pytania kontrolne

    Odpowiedzi na pytania z rozdziału 1. 1. Serwer WWW (taki jak Apache), interpreter języka skryptowego działający po stronie ser-

    wera (PHP), baza danych (MySQL) oraz język skryptowy działający po stronie przeglądarki (JavaScript).

    2. To skrót od nazwy HyperText Markup Language. Używa się go w odniesieniu do stron WWW, z uwzględnieniem tekstu i znaczników.

    3. Podobnie jak niemal wszystkie silniki baz danych MySQL obsługuje instrukcje w języku

    o nazwie Structured Query Language (SQL). SQL to po prostu sposób komunikacji użytkowników z MySQL („użytkownikiem” może być też program PHP).

    4. PHP działa na serwerze, podczas gdy JavaScript funkcjonuje po stronie programu klienc-

    kiego. PHP może się komunikować z bazą danych w celu przechowywania i pozyskiwania informacji, ale nie może modyfikować zawartości wyświetlanej strony internetowej w dynamiczny, interaktywny sposób. Zalety i możliwości JavaScriptu są dokładnie odwrotne.

    5. To skrót od nazwy Cascading Style Sheets, opisującej standard reguł umożliwiających zmianę wyglądu i układu elementów w dokumencie HTML.

    6. Chyba najciekawszymi spośród nowych elementów opisanych w HTML5 są:
    , ,