Ćwiczenie: dwie podstrony, powitanie po imieniu i licznik wejść
Podstawa programowa technik informatyk 351203, INF.03.5(4) „programuje skrypty wykonywane po stronie serwera”, kryteria weryfikacji 6 „korzysta z funkcji do obsługi plików” i 7 „korzysta z funkcji do obsługi ciasteczek (ang. Cookies) oraz sesji”
Rozgrzewka · 3 minuty
Rozgrzewka: formularz, baza i błędy
Z jakiej tablicy odbieramy dane formularza wysłanego metodą post?
Dlaczego empty("0") to pułapka przy polu na liczbę?
Dlaczego do pliku z połączeniem z bazą lepiej pasuje require niż include?
Część 1 · Dlaczego strona zapomina
Serwer nie pamięta poprzedniej strony
Każde kliknięcie w link to osobne żądanie do serwera, a po odesłaniu strony serwer kończy pracę tego skryptu i zapomina wszystko, co w nim policzył. To jest jak okienko w urzędzie, przy którym za każdym razem siada ktoś inny: znów trzeba się przedstawić. Dlatego imię wpisane w formularz na jednej podstronie samo z siebie nie pojawi się na drugiej. Potrzebny jest mechanizm, który przeniesie tę informację między żądaniami.
PHP Manual: sessions („Sessions are a simple way to store data for individual users against a unique session ID. This can be used to persist state information between page requests.”, php.net/manual/en/session.examples.basic.php)
Część 2 · Sesja
Sesja: dane zostają na serwerze
session_start() „creates a session or resumes the current one”: zakłada nową sesję albo wraca do tej, która już trwa. Dane wkładamy do tablicy $_SESSION, czyli „an associative array containing session variables available to the current script”. Sesja to szatnia w kinie: kurtka zostaje na serwerze, a przeglądarka dostaje numerek (identyfikator sesji) i pokazuje go przy każdym kolejnym żądaniu. session_destroy() niszczy wszystkie dane bieżącej sesji.
Ciekawostka: dane sesji domyślnie leżą na serwerze jako zwykłe pliki. PHP Manual: „By default, PHP uses the internal files save handler which is set by session.save_handler. This saves session data on the server at the location specified by the session.save_path configuration directive.”
PHP Manual: function.session-start.php („creates a session or resumes the current one”, „To use cookie-based sessions, session_start() must be called before outputting anything to the browser.”), reserved.variables.session.php, function.session-destroy.php („destroys all of the data associated with the current session”) · php.net/manual/en/
Część 3 · Ciasteczko
Ciasteczko: dane w przeglądarce
Ciasteczko (ang. cookie) to mała porcja danych, którą serwer każe zapisać przeglądarce, a przeglądarka odsyła ją przy każdym kolejnym żądaniu do tej strony. Zapisujemy je funkcją setcookie(), a odczytujemy z tablicy $_COOKIE, czyli „an associative array of variables passed to the current script via HTTP Cookies”. Trzeci argument to moment wygaśnięcia jako znacznik czasu: time() + 60*60*24*30 to trzydzieści dni.
Dwie reguły bezpieczeństwa. Pierwsza z PHP Manual o wartości ciasteczka: „This value is stored on the clients computer; do not store sensitive information”, więc hasło nigdy nie trafia do ciasteczka. Druga to opcja httponly: „When true the cookie will be made accessible only through the HTTP protocol. This means that the cookie won't be accessible by scripting languages, such as JavaScript”, dzięki czemu skrypt wstrzyknięty na stronę nie przeczyta ciasteczka.
PHP Manual: function.setcookie.php („defines a cookie to be sent along with the rest of the HTTP headers”, „cookies must be sent before any output from the script”, „time()+60*60*24*30 will set the cookie to expire in 30 days”, opis parametrów value i httponly), reserved.variables.cookies.php · php.net/manual/en/
Część 4 · Co wybrać
Sesja kontra ciasteczko
Pytanie
Sesja
Ciasteczko
Gdzie leżą dane?
Na serwerze; przeglądarka ma sam identyfikator
W przeglądarce użytkownika
Jak długo żyją?
Do zamknięcia przeglądarki albo do session_destroy()
Do czasu podanego w trzecim argumencie setcookie()
Czy użytkownik może je podejrzeć i zmienić?
Nie, widzi tylko identyfikator
Tak, to plik na jego komputerze
Do czego pasuje?
Zalogowany użytkownik, koszyk, dane na czas wizyty
Wybrany język, tryb ciemny, rozpoznanie powracającej przeglądarki
Imię z formularza (metoda post z lekcji o formularzach) wkładam do sesji, a licznik wejść trzymam w ciasteczku. Obie linie z session_start() i setcookie() stoją przed jakimkolwiek echo, bo jedno i drugie wysyła nagłówki.
// page-one.php: formularz i zapis imienia do sesjisession_start();
if (!empty($_POST["userName"])) { $_SESSION["userName"] = $_POST["userName"]; }
echo'<form action="page-one.php" method="post"><input name="userName"><button>Zapisz</button></form>';
echo'<a href="page-two.php">Przejdź dalej</a>';
// page-two.php: powitanie z sesji i licznik z ciasteczkasession_start();
if (!isset($_COOKIE["visitCount"])) { $visitCount = 1; }
else { $visitCount = intval($_COOKIE["visitCount"]) + 1; }
setcookie("visitCount", $visitCount, time() + 60 * 60 * 24 * 30);
echo"Witaj, " . $_SESSION["userName"] . "! To Twoje wejście numer " . $visitCount;
// po trzecim wejściu: Witaj, Jan! To Twoje wejście numer 3
Sesja znika po zamknięciu przeglądarki, ciasteczko po upływie swojego czasu, a jedno i drugie dotyczy tylko jednego użytkownika. Gdy dane mają zostać na dobre i być wspólne dla wszystkich, zapisujemy je do pliku na dysku serwera. file_put_contents() „is identical to calling fopen(), fwrite() and fclose() successively to write data to a file” i zwraca liczbę zapisanych bajtów, a file_get_contents() „reads entire file into a string”.
PHP Manual: function.file-put-contents.php („If filename does not exist, the file is created. Otherwise, the existing file is overwritten, unless the FILE_APPEND flag is set.”, „returns the number of bytes that were written to the file, or false on failure”), function.file-get-contents.php („Reads entire file into a string”) · php.net/manual/en/
Egzamin INF.03
Tak pytają na egzaminie
1. W jaki sposób w języku PHP należy ustawić zmienną sesji o nazwie choiceId na wartość 4?
session.choiceId = 4;
session.choiceId = {4};
$_SESSION[4] = choiceId;
$_SESSION["choiceId"] = 4;
2.if (!isset($_COOKIE["visits"])) $counter = 1; else $counter = intval($_COOKIE["visits"]) + 1; setcookie("visits", $counter); Efektem wielokrotnego wykonania kodu PHP jest
zliczanie liczby odwiedzin strony.
wyświetlenie ciasteczka z zapisaną zmienną.
zapisanie do ciasteczka wartości 1 za każdym odświeżeniem witryny.
zapisanie danych do ciasteczka jedynie przy pierwszym uruchomieniu strony.
CKE, EE.09, styczeń 2022, zadanie 9 · CKE, EE.09, styczeń 2022, zadanie 37
Ćwiczenie przy komputerze · 15 minut
Ćwiczenie: dwie podstrony, które Was pamiętają
W folderze swojego serwera (np. htdocs) utwórz page-one.php: session_start() w pierwszej linii, formularz z jednym polem name="userName", method="post", action="page-one.php", pod nim łącze do page-two.php.
W page-one.php zapisz odebrane imię do sesji: $_SESSION["userName"] = $_POST["userName"]; (tylko gdy pole nie jest puste, sprawdź empty() jak na lekcji o formularzach).
W page-two.php dołóż licznik wejść w ciasteczku: gdy $_COOKIE["visitCount"] nie istnieje, ustaw 1, w przeciwnym razie poprzednia wartość plus 1; zapisz przez setcookie() na 30 dni i wypisz numer wejścia. setcookie() musi stać przed każdym echo.
Sprawdź w przeglądarce: localhost/page-one.php, wpisz imię, przejdź dalej, odśwież trzy razy. Potem zamknij całą przeglądarkę i wejdź od razu na page-two.php: zanotuj w komentarzu w kodzie, co zniknęło, a co zostało.
Zostaw oba pliki obok siebie w folderze kursu. Dla chętnych: uruchom je jeszcze raz w domu i sprawdź, po ilu dniach licznik z ciasteczka się wyzeruje.
$_POST i empty(): lekcje o przetwarzaniu formularza
Na koniec
Sprawdź się
Gdzie leżą dane sesji, a gdzie dane ciasteczka?
W którym miejscu pliku muszą stać session_start() i setcookie()?
Dlaczego hasła użytkownika nigdy nie zapisujemy w ciasteczku?
To zamyka temat pamiętania użytkownika między podstronami i cały kurs PHP.
odpowiedzi zgodne z PHP Manual (function.session-start.php, function.setcookie.php)
Poza szkołą
A jak to wygląda w produkcji?
Na lekcji
W produkcji
Status
$_SESSION zapisywana jako plik na jednym serwerze
Sesje trzymane w Redisie albo w bazie, bo ta sama aplikacja pracuje na kilku serwerach naraz.
rozszerzane
setcookie("visitCount", $count, time() + ...)
To samo wywołanie plus flagi httponly, secure i samesite przy każdym ciasteczku.
rozszerzane
Licznik odwiedzin trzymany w ciasteczku
Liczenie po stronie serwera; ciasteczko służy do rozpoznania przeglądarki, nie do liczenia.
zmienione
file_put_contents() jako miejsce na dane
Baza danych; plik zostaje na logi i na to, co użytkownik sam wysłał.
zastępowane
PHP Manual: function.setcookie.php (opcje httponly, secure), session.security.ini.php („Almost all applications must use the httponly attribute for the session ID cookie.”)