Ćwiczenie – Sesje w PHP (INF.03)

Czym jest sesja?

HTTP to protokół bezstanowy – każde żądanie do serwera jest niezależne. Serwer domyślnie nie pamięta, że to ten sam użytkownik co przed chwilą.

Sesja rozwiązuje ten problem. PHP tworzy unikalny identyfikator sesji (losowy ciąg liter i cyfr), zapisuje go w ciasteczku przeglądarki, a na serwerze przechowuje dane powiązane z tym ID. Dzięki temu możesz zapamiętać zalogowanego użytkownika, koszyk zakupów, wyniki quizu itd.

🌐 Przeglądarka

Wysyła zapytanie
+ ciasteczko PHPSESSID=abc123

⚙️ Serwer PHP

Odczytuje ID sesji,
ładuje dane z $_SESSION

💾 Pliki na serwerze

/tmp/sess_abc123
Dane sesji zapisane na dysku
⚠️ Ważna zasada: session_start() musi być pierwszą linią pliku PHP, zanim cokolwiek zostanie wysłane do przeglądarki (żaden echo, żaden HTML, żadna pusta linia przed <?php). Inaczej PHP zwróci błąd: "Cannot send session cache limiter – headers already sent".

1. session_start() i zapisywanie danych

Cel: Uczeń potrafi uruchomić sesję i zapisać w niej dane.
Plik: sesja_start.php
<?php
// UWAGA: session_start() musi być PIERWSZĄ linią, przed jakimkolwiek HTML
session_start();

// Zapisywanie danych w sesji – $_SESSION to tablica asocjacyjna
$_SESSION['uzytkownik'] = 'Jan Kowalski';
$_SESSION['rola']       = 'admin';
$_SESSION['zalogowany'] = true;

echo "Sesja uruchomiona!<br>";
echo "Użytkownik: " . htmlspecialchars($_SESSION['uzytkownik']) . "<br>";
echo "Rola: "       . htmlspecialchars($_SESSION['rola'])       . "<br>";
echo "ID sesji: "   . session_id();  // unikalny identyfikator tej sesji
?>
  
Sesja uruchomiona!
Użytkownik: Jan Kowalski
Rola: admin
ID sesji: a3f7b2c91d4e8f56... (losowy ciąg, unikalny dla każdej przeglądarki)

2. Odczytywanie danych sesji na innej stronie

Cel: Uczeń rozumie, że dane sesji są dostępne na każdej podstronie.
Plik: profil.php
ℹ️ Każdy plik PHP, który chce korzystać z danych sesji, musi zaczynać się od session_start(). Bez tego $_SESSION będzie pustą tablicą.
<?php
session_start();  // bez tego $_SESSION jest puste!

// isset() sprawdza czy klucz istnieje w tablicy $_SESSION
if (!isset($_SESSION['zalogowany']) || $_SESSION['zalogowany'] !== true) {
    // Użytkownik nie jest zalogowany – przenosimy go na stronę logowania
    header("Location: login.php");
    exit;  // ZAWSZE exit po header() – PHP musi przestać wykonywać kod
}

// Tutaj użytkownik na pewno jest zalogowany
$imie = htmlspecialchars($_SESSION['uzytkownik']);
$rola = htmlspecialchars($_SESSION['rola']);

echo "<h2>Cześć, $imie!</h2>";
echo "<p>Twoja rola: <b>$rola</b></p>";
echo "<a href='wyloguj.php'>Wyloguj się</a>";
?>
  

Cześć, Jan Kowalski!

Twoja rola: admin

Wyloguj się

3. session_destroy() – wylogowanie

Cel: Uczeń potrafi poprawnie zakończyć sesję i wylogować użytkownika.
Plik: wyloguj.php
⚠️ Typowy błąd: wywołanie samego session_destroy() nie czyści tablicy $_SESSION w bieżącym żądaniu. Żeby mieć pewność, że dane znikną natychmiast, najpierw nadpisz tablicę pustą, potem niszcz sesję.
<?php
session_start();

// Krok 1: wyczyść tablicę $_SESSION
$_SESSION = [];

// Krok 2: usuń ciasteczko sesji z przeglądarki (opcjonalne, ale dobre praktyka)
if (ini_get("session.use_cookies")) {
    $params = session_get_cookie_params();
    setcookie(
        session_name(), '', time() - 42000,
        $params["path"], $params["domain"],
        $params["secure"], $params["httponly"]
    );
}

// Krok 3: zniszcz dane sesji po stronie serwera
session_destroy();

// Krok 4: przekieruj na stronę główną lub logowania
header("Location: login.php");
exit;
?>
  
Sesja została zakończona. Użytkownik wylogowany i przekierowany na login.php.

4. Licznik wizyt – praktyczny przykład

Cel: Uczeń rozumie, że sesja persystuje między żądaniami.
Plik: licznik.php
Klasyczny przykład – ile razy użytkownik odświeżył stronę w tej samej sesji (czyli zanim zamknie przeglądarkę lub wyloguje się).
<?php
session_start();

// Jeśli klucz nie istnieje – ustawiamy go na 0
if (!isset($_SESSION['wizyty'])) {
    $_SESSION['wizyty'] = 0;
}

// Zwiększamy licznik przy każdym wejściu na stronę
$_SESSION['wizyty']++;

echo "Odwiedziłeś tę stronę " . $_SESSION['wizyty'] . " razy w tej sesji.";
echo "<br><a href=''>Odśwież</a>";
echo " | <a href='wyloguj.php'>Resetuj licznik (wyloguj)</a>";
?>
  
Odwiedziłeś tę stronę 3 razy w tej sesji.
Odśwież | Resetuj licznik (wyloguj)

5. Projekt: Proste logowanie przez sesję

Cel: Uczeń potrafi zbudować system logowania oparty na sesji.
Pliki: login.php + panel.php + wyloguj.php
📁 Struktura projektu: Hasło porównujemy przez password_verify() – nigdy nie przechowuj haseł jako zwykłego tekstu!
<?php
// login.php
session_start();

// Jeśli już zalogowany – nie ma sensu pokazywać formularza
if (isset($_SESSION['zalogowany']) && $_SESSION['zalogowany'] === true) {
    header("Location: panel.php");
    exit;
}

$blad = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $login = trim($_POST['login'] ?? '');
    $haslo = trim($_POST['haslo'] ?? '');

    // W prawdziwej aplikacji pobierasz użytkownika z bazy MySQL przez PDO
    // Tu dla uproszczenia mamy zahardkodowane dane testowe
    $uzytkownicy = [
        'admin' => password_hash('haslo123', PASSWORD_DEFAULT),
        'jan'   => password_hash('qwerty',   PASSWORD_DEFAULT),
    ];

    if (isset($uzytkownicy[$login]) && password_verify($haslo, $uzytkownicy[$login])) {
        // Dane poprawne – zapisujemy w sesji
        $_SESSION['zalogowany']  = true;
        $_SESSION['uzytkownik']  = $login;

        header("Location: panel.php");
        exit;
    } else {
        $blad = "Nieprawidłowy login lub hasło.";
    }
}
?>
<!DOCTYPE html>
<html lang="pl"><head><meta charset="UTF-8"><title>Logowanie</title></head>
<body>
  <h2>Logowanie</h2>
  <?php if ($blad): ?>
    <p style="color:red"><?= htmlspecialchars($blad) ?></p>
  <?php endif; ?>
  <form method="POST">
    Login: <input type="text"     name="login" required><br>
    Hasło: <input type="password" name="haslo" required><br>
    <button type="submit">Zaloguj się</button>
  </form>
  <p>Testowe dane: login <b>admin</b>, hasło <b>haslo123</b></p>
</body></html>
  
<?php
// panel.php
session_start();

// Strażnik – jeśli nie zalogowany, wróć na login
if (!isset($_SESSION['zalogowany']) || $_SESSION['zalogowany'] !== true) {
    header("Location: login.php");
    exit;
}
?>
<!DOCTYPE html>
<html lang="pl"><head><meta charset="UTF-8"><title>Panel</title></head>
<body>
  <h2>Panel użytkownika</h2>
  <p>Zalogowany jako: <b><?= htmlspecialchars($_SESSION['uzytkownik']) ?></b></p>
  <p>Ta strona jest dostępna tylko po zalogowaniu.</p>
  <a href="wyloguj.php">Wyloguj się</a>
</body></html>
  
  • Użytkownik wchodzi na login.php i podaje login + hasło
  • PHP sprawdza dane przez password_verify()
  • Jeśli poprawne – zapisuje $_SESSION['zalogowany'] = true i przekierowuje
  • Na każdej chronionej podstronie sprawdzamy czy sesja istnieje
  • wyloguj.php czyści sesję i wraca na login.php

Podsumowanie – ściągawka sesji PHP

Funkcja / składnia Co robi Kiedy używać
session_start() Uruchamia lub wznawia sesję Pierwsza linia każdego pliku korzystającego z sesji
$_SESSION['klucz'] = wartość Zapisuje dane w sesji Po zalogowaniu, przy zapisie koszyka itp.
$_SESSION['klucz'] Odczytuje dane z sesji Na każdej podstronie gdzie potrzebujesz tych danych
isset($_SESSION['klucz']) Sprawdza czy klucz istnieje Przed odczytaniem – unikasz błędu "undefined index"
unset($_SESSION['klucz']) Usuwa jeden klucz z sesji Gdy chcesz wyczyścić tylko część danych
$_SESSION = [] Czyści całą tablicę sesji Na początku wylogowania
session_destroy() Niszczy dane sesji na serwerze Na końcu wylogowania, po wyczyszczeniu tablicy