Programowanie po stronie serwera (PHP)
Składnia języka, przesyłanie danych (metody GET i POST), zarządzanie sesjami, obsługa plików, łączenie aplikacji webowej z bazą danych (mysqli), bezpieczeństwo.
Wstęp: PHP to miejsce, w którym arkusz INF.03 zamienia się w aplikację
W części praktycznej PHP pojawia się zawsze w tej samej roli: masz formularz w HTML, bazę danych przygotowaną przez CKE i musisz je połączyć. Odebrać dane, sprawdzić je, zapytać bazę, wyświetlić wynik. Część pisemna dokłada pytania, które trzeba znać z pamięci — różnicę między metodami GET i POST, działanie sesji, sposób łączenia z bazą. Ten artykuł prowadzi dokładnie tą drogą: od pierwszego znacznika PHP aż do zabezpieczenia zapytania przed atakiem.
📋 Spis treści
Aplikacja webowa
- Osadzanie kodu i składnia
Kod PHP wykonuje się na serwerze, a do przeglądarki trafia już tylko wynik —
czysty HTML. To najważniejsza różnica względem JavaScriptu i najczęstsze
pytanie w części pisemnej. Plik musi mieć rozszerzenie .php,
inaczej serwer potraktuje go jak zwykły dokument i pokaże kod jako tekst.
<?php $imie = "Anna"; echo "Witaj, " . $imie; // sklejanie kropką echo "<p>Witaj, $imie</p>"; // zmienna rozwija się w cudzysłowie ?>
W cudzysłowie zmienne są rozwijane do swojej wartości, w apostrofie nie.
echo '$imie'
wypisze dosłownie $imie, a nie „Anna". To ulubione pytanie w teście.
- Zmienne, typy i tablice
Nazwa zmiennej zaczyna się od dolara i nie deklaruje się jej typu — PHP ustala go sam na podstawie przypisanej wartości. Na egzaminie liczą się przede wszystkim tablice, bo to w nich przychodzą dane z formularza i wyniki z bazy.
$liczby = [4, 8, 15]; // tablica indeksowana
$osoba = ["imie" => "Anna", "wiek" => 17]; // tablica asocjacyjna
echo $liczby[0]; // 4
echo $osoba["imie"]; // Anna
echo count($liczby); // 3
foreach ($osoba as $klucz => $wartosc) {
echo "$klucz: $wartosc<br>";
}Tablica asocjacyjna to dokładnie ta struktura, w której dostaniesz wiersz z bazy danych, a kluczami będą nazwy kolumn. Warto się z nią oswoić, bo to fundament ostatniego zadania w arkuszu.
- Warunki, pętle i funkcje
if ($wiek >= 18) {
echo "Pełnoletni";
} elseif ($wiek >= 13) {
echo "Nastolatek";
} else {
echo "Dziecko";
}
for ($i = 1; $i <= 5; $i++) {
echo $i;
}
function podatek($kwota, $stawka = 0.23) {
return $kwota * $stawka;
}
echo podatek(1000); // 230Wartość domyślna parametru — jak $stawka = 0.23 —
pozwala wywołać funkcję z jednym argumentem. Parametry z wartością domyślną
muszą stać na końcu listy, inaczej PHP zgłosi błąd.
- Formularze: GET i POST
To serce większości zadań praktycznych. Formularz w HTML wskazuje plik PHP i metodę przesyłania, a PHP odbiera dane z odpowiedniej tablicy nadrzędnej.
<!-- formularz.html -->
<form action="wynik.php" method="post">
<input type="text" name="imie">
<button type="submit">Wyślij</button>
</form>
<!-- wynik.php -->
<?php
if (isset($_POST["imie"])) {
echo "Witaj, " . htmlspecialchars($_POST["imie"]);
}
?>| Cecha | GET | POST |
|---|---|---|
| Gdzie są dane | w adresie URL | w treści żądania |
| Widoczność | widoczne dla użytkownika | niewidoczne w pasku |
| Limit długości | ograniczony | praktycznie brak |
| Typowe zastosowanie | wyszukiwarka, filtr, link | logowanie, wysyłka pliku |
POST nie jest szyfrowany — jest tylko mniej widoczny. Dane idą otwartym tekstem, dopóki połączenie nie działa po HTTPS. Odpowiedź „POST jest bezpieczny, bo szyfruje dane" jest błędna.
- Sesje i ciasteczka
HTTP nie pamięta niczego między jednym żądaniem a kolejnym. Sesja to mechanizm, który pozwala rozpoznać tego samego użytkownika — dane trzyma serwer, a przeglądarka dostaje tylko identyfikator sesji.
<?php session_start(); // MUSI być przed jakimkolwiek wyjściem $_SESSION["uzytkownik"] = "anna"; // zapis echo $_SESSION["uzytkownik"]; // odczyt session_destroy(); // wylogowanie ?>
Sesja przechowuje dane na serwerze i znika po zamknięciu przeglądarki. Ciasteczko zapisuje dane u użytkownika i może przetrwać tygodniami. Do logowania używa się sesji, do zapamiętania preferencji — ciasteczka.
Najczęstszy błąd praktyczny: wywołanie session_start() po
wypisaniu czegokolwiek na stronę — choćby pustej linii przed znacznikiem PHP.
Skutkuje to komunikatem o wysłanych już nagłówkach.
- Obsługa plików
// zapis do pliku (FILE_APPEND dopisuje zamiast nadpisywać)
file_put_contents("dane.txt", "nowa linia\n", FILE_APPEND);
// odczyt całego pliku do tablicy linii
$linie = file("dane.txt", FILE_IGNORE_NEW_LINES);
foreach ($linie as $linia) {
echo $linia . "<br>";
}Bez flagi FILE_APPEND każdy
zapis kasuje poprzednią zawartość pliku. Jeśli zadanie mówi o dopisywaniu
kolejnych wpisów, brak tej flagi oznacza utratę punktu.
- Połączenie z bazą danych (mysqli)
Ostatnia część arkusza praktycznie zawsze wymaga pobrania danych z bazy i wypisania ich na stronie. Schemat jest niezmienny: połącz się, sprawdź błąd, ustaw kodowanie, wykonaj zapytanie, przejdź wynik pętlą.
<?php
$polaczenie = new mysqli("localhost", "root", "", "sklep");
if ($polaczenie->connect_errno) {
die("Błąd połączenia: " . $polaczenie->connect_error);
}
$polaczenie->set_charset("utf8");
$wynik = $polaczenie->query("SELECT nazwa, cena FROM produkty");
while ($wiersz = $wynik->fetch_assoc()) {
echo "<p>" . $wiersz["nazwa"] . " — " . $wiersz["cena"] . " zł</p>";
}
$polaczenie->close();
?>Wszystkie bazy w arkuszach CKE mają polskie nazwy. Bez ustawienia kodowania zamiast ogonków zobaczysz znaki zapytania — a egzaminator zauważy to od razu.
- Bezpieczeństwo
Część pisemna pyta o to regularnie, a w praktycznej dobre nawyki nic nie kosztują. Trzy zagrożenia trzeba znać z nazwy i umieć wskazać obronę.
SQL Injection — wstrzyknięcie kodu SQL przez pole formularza. Obrona: zapytania przygotowane (
prepareibind_param) zamiast sklejania zapytania z tekstu.XSS — wstrzyknięcie skryptu, który wykona się u innego użytkownika. Obrona:
htmlspecialchars()przy każdym wypisywaniu danych od użytkownika.Hasła zapisane jawnie — nigdy nie trzyma się ich w postaci czytelnej. Obrona:
password_hash()przy zapisie ipassword_verify()przy logowaniu.
// zapytanie przygotowane - dane nigdy nie trafiają do treści zapytania
$stmt = $polaczenie->prepare("SELECT * FROM uzytkownicy WHERE login = ?");
$stmt->bind_param("s", $_POST["login"]);
$stmt->execute();
$wynik = $stmt->get_result();- Podział kodu: include i require
Arkusz INF.03 prawie zawsze każe zbudować witrynę z kilku podstron o wspólnym wyglądzie. Kopiowanie nagłówka do każdego pliku to strata czasu i pewny sposób na rozjechanie się stopki na jednej z podstron. Zamiast tego wyciągasz powtarzalne fragmenty do osobnych plików i dołączasz je jedną linijką.
// polaczenie.php - dane dostępowe w jednym miejscu
<?php
$polaczenie = new mysqli("localhost", "root", "", "egzamin");
$polaczenie->set_charset("utf8mb4");
?>
// index.php - dołączamy i korzystamy
<?php
require_once "polaczenie.php"; // bez bazy strona nie ma sensu -> require
include "naglowek.php"; // ozdoba -> include wystarczy
?>
<main>Treść podstrony</main>
<?php include "stopka.php"; ?>include — gdy pliku nie ma, PHP zgłasza ostrzeżenie i wykonuje skrypt dalej. Reszta strony się wyświetli.
require — gdy pliku nie ma, PHP zgłasza błąd krytyczny i przerywa skrypt. Nic poniżej się nie wykona.
Końcówka _once (include_once,
require_once) pilnuje,
żeby ten sam plik nie został dołączony dwa razy. Przy pliku z definicjami funkcji
to jedyny bezpieczny wariant — drugie dołączenie oznaczałoby próbę zdefiniowania
tej samej funkcji ponownie i błąd krytyczny.
Połączenie z bazą i pliki z funkcjami dołączaj przez require_once.
Nagłówek, menu i stopkę — przez include. Dołączany plik dziedziczy
wszystkie zmienne z miejsca wywołania, więc $polaczenie z
polaczenie.php jest widoczne w każdym pliku, który go dołączył.
- Funkcje tekstowe i liczby
Dane z formularza i z bazy przychodzą jako tekst i prawie zawsze trzeba je pociąć, skleić albo sformatować przed wyświetleniem. To zestaw, który wystarcza na cały arkusz.
| Funkcja | Co robi | Przykład i wynik |
|---|---|---|
| strlen() | długość w bajtach | strlen("02070803628") → 11 |
| substr() | wycina fragment | substr($pesel, 0, 2) → "02" |
| str_replace() | podmienia tekst | str_replace(" ", "-", "kurs php") → "kurs-php" |
| trim() | obcina spacje z brzegów | trim(" Anna ") → "Anna" |
| explode() | tekst → tablica | explode(";", "Anna;Kowalska")[1] → "Kowalska" |
| implode() | tablica → tekst | implode(", ", $tab) → "Anna, Kowalska" |
| ucfirst() | wielka pierwsza litera | ucfirst("anna") → "Anna" |
| number_format() | formatuje liczbę | number_format(12345.678, 2, ",", " ") → "12 345,68" |
Funkcje strlen,
substr i
strtoupper liczą
bajty, a polska litera w UTF-8 zajmuje dwa. Dlatego:
strlen("Zażółć gęślą jaźń") → 26
mb_strlen("Zażółć gęślą jaźń", "UTF-8") → 17
Gdy w tekście mogą wystąpić polskie znaki, używaj wersji z przedrostkiem
mb_: mb_strlen,
mb_substr,
mb_strtoupper.
Na nazwiskach i nazwach produktów to jest różnica między poprawnym a rozsypanym wynikiem.
round($cena, 2) zwraca
liczbę, więc 19.90 wyświetli się jako „19.9". Gdy zadanie mówi „dwa miejsca po przecinku",
użyj number_format($cena, 2, ",", " ") albo
printf("%.2f", $cena) — one
dokładają brakujące zero.
- Daty i czas
Baza trzyma daty w formacie RRRR-MM-DD,
a arkusz zwykle prosi o wyświetlenie ich „po polsku" albo o policzenie różnicy
między dwiema datami. Obie rzeczy załatwia się jedną linijką.
<?php
// dzisiejsza data
echo date("Y-m-d"); // 2026-08-16
echo date("d.m.Y H:i"); // 16.08.2026 09:30
// data z bazy w polskim formacie
$zBazy = "2026-01-14";
echo date("d.m.Y", strtotime($zBazy)); // 14.01.2026
// przesuwanie daty
echo date("Y-m-d", strtotime("$zBazy +7 days")); // 2026-01-21
// różnica dwóch dat w dniach
$od = new DateTime("2026-01-14");
$do = new DateTime("2026-06-01");
echo $od->diff($do)->days; // 138
?>| Znak | Znaczenie | Przykład |
|---|---|---|
| d / j | dzień z zerem / bez zera | 05 / 5 |
| m / n | miesiąc z zerem / bez zera | 01 / 1 |
| Y / y | rok czterocyfrowy / dwucyfrowy | 2026 / 26 |
| H : i : s | godzina, minuta, sekunda | 09:30:00 |
| N | dzień tygodnia (1 = poniedziałek) | 3 |
- Wysyłanie plików na serwer
Zadania typu „dodaj formularz pozwalający wgrać zdjęcie produktu" wracają w arkuszach regularnie. Cała rzecz opiera się na trzech elementach, z których pierwszy najłatwiej przeoczyć.
<!-- 1. formularz MUSI mieć enctype, inaczej przyjdzie sama nazwa pliku -->
<form action="wyslij.php" method="post" enctype="multipart/form-data">
<input type="file" name="zdjecie">
<input type="submit" value="Wyślij">
</form>
// 2. wyslij.php - odbiór, sprawdzenie, przeniesienie
<?php
if (isset($_FILES["zdjecie"]) && $_FILES["zdjecie"]["error"] === 0) {
$nazwa = $_FILES["zdjecie"]["name"];
$tymczas = $_FILES["zdjecie"]["tmp_name"];
$rozmiar = $_FILES["zdjecie"]["size"];
$dozwolone = ["jpg", "jpeg", "png", "gif"];
$rozsz = strtolower(pathinfo($nazwa, PATHINFO_EXTENSION));
if (!in_array($rozsz, $dozwolone)) {
echo "Niedozwolony typ pliku.";
} elseif ($rozmiar > 2 * 1024 * 1024) {
echo "Plik większy niż 2 MB.";
} else {
// 3. przeniesienie z katalogu tymczasowego na docelowy
move_uploaded_file($tymczas, "zdjecia/" . $nazwa);
echo "Wysłano plik: " . $nazwa;
}
}
?>Brak
enctype="multipart/form-data"— tablica$_FILESzostaje pusta i skrypt zachowuje się, jakby nikt nic nie wysłał.Nieistniejący katalog docelowy.
move_uploaded_filenie tworzy folderów — jeśli w projekcie nie ma kataloguzdjecia/, funkcja zwróci fałsz i plik zniknie razem z końcem skryptu.Zaufanie rozszerzeniu z nazwy. Sprawdzenie
pathinfoodsiewaskrypt.php, ale prawdziwe zabezpieczenie sprawdza też typ MIME (mime_content_type) i nadaje własną nazwę pliku. Na egzaminie wystarczy zwykle biała lista rozszerzeń, ale warto wiedzieć dlaczego.
Co z tego wraca na egzaminie
- Odebranie danych z formularza i wypisanie ich na stronie — praktycznie w każdym arkuszu.
- Połączenie z bazą i wyświetlenie wyniku zapytania w pętli.
- Różnica między GET a POST — pytanie zamknięte w części pisemnej.
- Rola sesji przy logowaniu i miejsce wywołania
session_start(). - Wskazanie zagrożenia i sposobu obrony przy podanym fragmencie kodu.
- Wspólny nagłówek i stopka na kilku podstronach —
includezamiast kopiowania. - Różnica
includekontrarequire— pytanie zamknięte. - Wyświetlenie daty z bazy w formacie
d.m.Yi ceny z dwoma miejscami po przecinku. - Formularz wysyłania pliku z walidacją rozszerzenia.
Zapytania SQL, które tu wykonujesz, opisaliśmy osobno w dziale Język zapytań SQL, a gotowy schemat skryptu znajdziesz w pewniaku Skrypt PHP pobierający dane z bazy.
Przebieg sesji, co zabrać na salę, plan pracy na 150 minut i lista rzeczy, na których najczęściej przepadają punkty.
Przygotowanie do INF.03
Nie chcesz przerabiać tego sam?
Prowadzimy indywidualne przygotowanie do kwalifikacji INF.03 — PHP, SQL, HTML i CSS na prawdziwych arkuszach z poprzednich sesji. Zobacz program i cenę.
Zobacz kurs INF.03Zdajesz też maturę? Dla technika informatyka informatyka rozszerzona to najbliższy wybór — połowę materiału masz już przerobioną na kwalifikacjach. Zobacz przygotowanie do matury z informatyki →