← Lekcje
PHP · lekcja 26

Strona, która
Was pamięta

Dzisiaj:

  1. Dlaczego serwer zapomina Was między jednym kliknięciem a drugim?
  2. Sesja: session_start(), $_SESSION, session_destroy()
  3. Ciasteczko: setcookie(), $_COOKIE i czas życia
  4. Ć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

  1. Z jakiej tablicy odbieramy dane formularza wysłanego metodą post?
  2. Dlaczego empty("0") to pułapka przy polu na liczbę?
  3. 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.

Przeglądarka żądanie 1: form.php wysyła imię: Jan Przeglądarka żądanie 2: welcome.php nic nie wysyła Serwer, skrypt nr 1 $_POST["userName"] = "Jan" skrypt kończy się, zmienne znikają Serwer, skrypt nr 2 $userName nie istnieje „a kto to właściwie pyta?” Potrzebny łącznik sesja: dane leżą na serwerze ciasteczko: dane leżą w przeglądarce plik: dane leżą na dysku serwera
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.

Przeglądarka PHPSESSID=8f3a1c... sam numerek, żadnych danych wysyła numerek przy każdym żądaniu numerek Serwer, dane sesji $_SESSION["userName"] = "Jan" $_SESSION["visitCount"] = 3 tu leżą prawdziwe wartości Trzy polecenia session_start(); zawsze na początku pliku $_SESSION["userName"] = "Jan"; session_destroy(); kasuje dane całej 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.

Skrypt PHP, żądanie 1 setcookie("visitCount", 3, ...) w nagłówkach Przeglądarka visitCount = 3 plik na komputerze użytkownika żyje do: time() + 60*60*24*30 po tym czasie znika sama odsyła sama Skrypt PHP, żądanie 2 $_COOKIE["visitCount"] Bez haseł i danych wrażliwych to plik na cudzym komputerze

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

PytanieSesjaCiasteczko
Gdzie leżą dane?Na serwerze; przeglądarka ma sam identyfikatorW 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 identyfikatorTak, to plik na jego komputerze
Do czego pasuje?Zalogowany użytkownik, koszyk, dane na czas wizytyWybrany język, tryb ciemny, rozpoznanie powracającej przeglądarki
Jak się do nich sięga?session_start(), potem $_SESSIONsetcookie() do zapisu, $_COOKIE do odczytu
PHP Manual: function.session-start.php, function.session-destroy.php, function.setcookie.php, reserved.variables.session.php, reserved.variables.cookies.php
Część 5 · Kod na żywo

Imię z formularza i licznik wejść

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 sesji
session_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 ciasteczka
session_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
PHP Manual: function.session-start.php, function.setcookie.php, reserved.variables.session.php, reserved.variables.cookies.php
Część 6 · Trzeci sposób

Zapis do pliku: dane przeżywają wszystko

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”.

file_put_contents ("counter.txt", "7") file_get_contents ("counter.txt") counter.txt 7 plik na dysku serwera wspólny dla wszystkich Bez flagi: plik zostaje nadpisany od zera file_put_contents(f, text) Z flagą FILE_APPEND: dopisuje na końcu file_put_contents(f, text, FILE_APPEND)
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?

  1. session.choiceId = 4;
  2. session.choiceId = {4};
  3. $_SESSION[4] = choiceId;
  4. $_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

  1. zliczanie liczby odwiedzin strony.
  2. wyświetlenie ciasteczka z zapisaną zmienną.
  3. zapisanie do ciasteczka wartości 1 za każdym odświeżeniem witryny.
  4. 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ą

  1. 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.
  2. 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).
  3. Utwórz page-two.php: session_start(), powitanie echo "Witaj, " . $_SESSION["userName"];.
  4. 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.
  5. 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.
  6. 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ę

  1. Gdzie leżą dane sesji, a gdzie dane ciasteczka?
  2. W którym miejscu pliku muszą stać session_start() i setcookie()?
  3. 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 lekcjiW produkcjiStatus
$_SESSION zapisywana jako plik na jednym serwerzeSesje 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 ciasteczkuLiczenie po stronie serwera; ciasteczko służy do rozpoznania przeglądarki, nie do liczenia.zmienione
file_put_contents() jako miejsce na daneBaza 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.”)