PHP i baza danych: mysqli krok po kroku, PDO, SQL injection i hasła

INF.03 · teoria
autor: redakcja · 08.09.2026
Cztery kroki skryptu łączącego PHP z MySQL: mysqli_connect, mysqli_query, pętla z mysqli_fetch_array i mysqli_close. Funkcje ze ściągi CKE, wypisywanie wyników w liście i w tabeli, obrona przed SQL injection zapytaniem przygotowanym, hasła w password_hash oraz biblioteka PDO. Lekcja 12.8 kursu INF.03.

[ INF.03: PYTANIA Z TEGO DZIAŁU ]

Bi­blio­te­ka mysqli (MySQL Im­pro­ved, ulep­szo­ny MySQL) to zestaw funk­cji PHP, któ­ry­mi skrypt łączy się z ser­we­rem bazy danych, wysyła za­py­ta­nia SQL i od­bie­ra wier­sze wyniku. Na eg­za­mi­nie prak­tycz­nym jest to osobno oce­nia­ny re­zul­tat: arkusz mówi wprost, że skrypt „łączy się z ser­we­rem ba­zo­da­no­wym na lo­cal­host, użyt­kow­nik root bez hasła, baza danych o nazwie eg­za­min" i że „na końcu dzia­ła­nia skrypt zamyka po­łą­cze­nie z ser­we­rem". W części pi­sem­nej wra­ca­ją py­ta­nia o nazwy i ko­lej­ność pa­ra­me­trów tych funk­cji, o to, która z nich po­bie­ra po­je­dyn­czy wiersz, oraz o ataki na apli­ka­cję in­ter­ne­to­wą, z SQL in­jec­tion na czele.

Cztery kroki skryp­tu z bazą

Skrypt ba­zo­da­no­wy zawsze ma ten sam szkie­let: połącz, za­py­taj, prze­czy­taj wier­sze, za­mknij. Każdy krok to jedna funk­cja z tabeli do­łą­czo­nej do ar­ku­sza.
Cztery kroki skryptu mysqli: połączenie, zapytanie, pętla czytająca wiersze jako tablicę z kluczami 0 i nazwa, na końcu zamknięcie połączenia
mysqli_connect (POŁĄCZ) otwie­ra po­łą­cze­nie i przyj­mu­je cztery pa­ra­me­try w stałej ko­lej­no­ści: adres ser­we­ra, nazwę użyt­kow­ni­ka, hasło i nazwę bazy. Dla śro­do­wi­ska XAMPP z ar­ku­sza są to ko­lej­no 'localhost', 'root', '' oraz 'egzamin', a puste apo­stro­fy na trze­cim miej­scu znaczą konto bez hasła. Funk­cja oddaje iden­ty­fi­ka­tor po­łą­cze­nia, który każda na­stęp­na funk­cja do­sta­je jako pierw­szy ar­gu­ment. Bazę można też wybrać osobno, przez mysqli_select_db($polaczenie, 'egzamin'). Nie­uda­ne po­łą­cze­nie oddaje false, a powód opi­su­je mysqli_connect_error, więc spraw­dza się to od razu i kończy skrypt funk­cją die (UMRZYJ). Pol­skie znaki wy­ma­ga­ją jesz­cze jed­ne­go wier­sza: mysqli_set_charset($polaczenie, 'utf8mb4') usta­wia ko­do­wa­nie roz­mo­wy z ser­we­rem, bez niego za­miast liter ze zna­ka­mi dia­kry­tycz­ny­mi po­ja­wia­ją się na stro­nie py­taj­ni­ki.
mysqli_query (ZAPYTAJ) wysyła jedno za­py­ta­nie SQL. Dla SELECT oddaje wynik, czyli zestaw wier­szy cze­ka­ją­cych na odczyt, a dla INSERT, UPDATE i DELETE oddaje samo true albo false, bo tam nie ma czego czytać. Wynik nie jest jesz­cze danymi: wier­sze wyj­mu­je z niego po jednym mysqli_fetch_array, a gdy wier­szy już nie ma, funk­cja oddaje null i pętla while sama się kończy.
Wiersz z mysqli_fetch_array ma dwa kom­ple­ty kluczy naraz: numery kolumn li­czo­ne od zera oraz nazwy kolumn, więc ten sam pro­dukt czyta się jako $w[0] i $w[1] albo przez $w['nazwa'] i $w['cena']. Który kom­plet po­wsta­nie, roz­strzy­ga drugi pa­ra­metr: MYSQLI_NUM daje same numery, MYSQLI_ASSOC same nazwy, a MYSQLI_BOTH oba i to jest war­tość do­myśl­na. Krócej robią to samo mysqli_fetch_row, która daje ta­bli­cę in­dek­so­wa­ną, i mysqli_fetch_assoc, która daje aso­cja­cyj­ną. Na koniec mysqli_close zwal­nia po­łą­cze­nie i to ten wiersz arkusz spraw­dza jako ostat­ni punkt re­zul­ta­tu.
<?php $polaczenie = mysqli_connect('localhost', 'root', '', 'egzamin'); if (!$polaczenie) { die('Blad polaczenia: ' . mysqli_connect_error()); } mysqli_set_charset($polaczenie, 'utf8mb4'); $wynik = mysqli_query($polaczenie, 'SELECT nazwa, cena FROM produkt'); while ($w = mysqli_fetch_array($wynik)) { echo '<li>' . $w['nazwa'] . ', ' . $w['cena'] . ' zł</li>'; } mysqli_close($polaczenie);
Skrypt wy­pi­su­je jedną po­zy­cję <li> dla każ­de­go wier­sza tabeli produkt, a po ostat­nim wier­szu zamyka po­łą­cze­nie.

Funk­cje mysqli ze ściągi CKE

Arkusz do­łą­cza do za­da­nia tabelę „Wybór funk­cji języka PHP do ob­słu­gi bazy MySQL i MariaDB", więc nazw nie trzeba pa­mię­tać co do znaku, ale trzeba wie­dzieć, co która robi i co oddaje.
Funk­cja
Co robi
Zwraca
mysqli_connect
otwie­ra po­łą­cze­nie z ser­we­rem bazy
iden­ty­fi­ka­tor po­łą­cze­nia albo false
mysqli_connect_error
opi­su­je powód nie­uda­ne­go po­łą­cze­nia
tekst ko­mu­ni­ka­tu
mysqli_select_db
wy­bie­ra bazę na otwar­tym po­łą­cze­niu
true albo false
mysqli_set_charset
usta­wia ko­do­wa­nie znaków w roz­mo­wie z ser­we­rem
true albo false
mysqli_query
wysyła jedno za­py­ta­nie SQL
wynik dla SELECT, true albo false dla zmian
mysqli_fetch_array
po­bie­ra ko­lej­ny wiersz wyniku
ta­bli­cę z nu­me­ra­mi i na­zwa­mi kolumn
mysqli_fetch_assoc
po­bie­ra ko­lej­ny wiersz wyniku
ta­bli­cę z na­zwa­mi kolumn
mysqli_fetch_row
po­bie­ra ko­lej­ny wiersz wyniku
ta­bli­cę z nu­me­ra­mi kolumn od zera
mysqli_num_rows
liczy wier­sze po­bra­ne­go wyniku
liczbę wier­szy
mysqli_num_fields
liczy ko­lum­ny po­bra­ne­go wyniku
liczbę kolumn
mysqli_affected_rows
liczy wier­sze zmie­nio­ne ostat­nim za­py­ta­niem
liczbę wier­szy
mysqli_insert_id
podaje klucz ostat­nio wsta­wio­ne­go wier­sza
liczbę z ko­lum­ny au­to­ma­tycz­nej
mysqli_error
opi­su­je błąd ostat­niej ope­ra­cji
tekst ko­mu­ni­ka­tu
mysqli_close
zamyka po­łą­cze­nie z ser­we­rem
true

Wy­pi­sa­nie wy­ni­ków: lista i tabela

Wzór wyniku podaje arkusz, a skrypt ma go od­two­rzyć co do prze­cin­ka. Dwa naj­częst­sze wzory to lista nu­me­ro­wa­na i wier­sze tabeli, a dane biorą się z tabeli produkt w bazie sklep, tej samej co w dziale o za­py­ta­niach SELECT.
<?php $p = mysqli_connect('localhost', 'root', '', 'sklep'); $wynik = mysqli_query($p, 'SELECT nazwa, cena FROM produkt ORDER BY cena'); echo '<ol>'; while ($w = mysqli_fetch_assoc($wynik)) { echo '<li>' . $w['nazwa'] . ', ' . $w['cena'] . ' zł</li>'; } echo '</ol>'; mysqli_close($p);
1. Kabel HDMI, 25 zł 2. Mysz, 45 zł 3. Klawiatura, 120 zł 4. Monitor 24, 650 zł 5. Monitor 27, 990 zł
Numery po­zy­cji rysuje prze­glą­dar­ka, bo znacz­nik <ol> nu­me­ru­je sam: skrypt wy­pi­su­je wy­łącz­nie <li>, a ko­lej­ność bierze się z klau­zu­li ORDER BY, nie z kodu PHP. Gdy za­py­ta­nie nie znaj­dzie nic, pętla nie wykona się ani razu i lista zo­sta­nie pusta, dla­te­go przed nią spraw­dza się mysqli_num_rows($wynik).
Drugi wzór wy­peł­nia tabelę. Tu wy­god­niej­sza jest mysqli_fetch_row: numery kolumn od­po­wia­da­ją ko­lej­no­ści z SELECT.
<?php $p = mysqli_connect('localhost', 'root', '', 'sklep'); $sql = 'SELECT nazwa, kategoria, sztuk FROM produkt WHERE sztuk > 0'; $wynik = mysqli_query($p, $sql); echo '<table>'; while ($w = mysqli_fetch_row($wynik)) { echo '<tr><td>' . $w[0] . '</td><td>' . $w[1] . '</td><td>' . $w[2] . '</td></tr>'; } echo '</table>'; mysqli_close($p);
Klawiatura akcesoria 15 Monitor 24 monitory 4 Monitor 27 monitory 2
Trzy wier­sze, a nie pięć: Mysz ma zero sztuk, więc odpada na wa­run­ku, a Kabel HDMI ma w ko­lum­nie sztuk war­tość NULL, której żadne po­rów­na­nie nie speł­nia. Gdy wzór łączy dane z dwóch tabel, na przy­kład imię klien­ta obok nazwy pro­duk­tu, robi to za­py­ta­nie ze złą­cze­niem JOIN, a PHP nadal tylko prze­pi­su­je wier­sze do znacz­ni­ków.

Dane z for­mu­la­rza i SQL in­jec­tion

Trzeci skrypt ar­ku­sza bierze war­tość z pola for­mu­la­rza wy­sła­ne­go metodą POST do tej samej strony i wsta­wia ją do klau­zu­li WHERE. War­tość czeka w ta­bli­cy $_POST pod klu­czem równym atry­bu­to­wi name pola, co opi­su­je lekcja o for­mu­la­rzach w PHP. Wersja na­pi­sa­na wprost jest dziu­ra­wa.
<?php $p = mysqli_connect('localhost', 'root', '', 'sklep'); $kategoria = $_POST['kategoria']; $sql = "SELECT nazwa, cena FROM produkt WHERE kategoria = '$kategoria'"; $wynik = mysqli_query($p, $sql); while ($w = mysqli_fetch_assoc($wynik)) { echo '<li>' . $w['nazwa'] . ', ' . $w['cena'] . ' zł</li>'; } mysqli_close($p);
SQL in­jec­tion (wstrzyk­nię­cie SQL) to atak po­le­ga­ją­cy na wpi­sa­niu w pole for­mu­la­rza znaków, które za­my­ka­ją war­tość i do­pi­su­ją do za­py­ta­nia własny wa­ru­nek. Skrypt skleja za­py­ta­nie z na­pi­sów, więc apo­strof wpi­sa­ny przez użyt­kow­ni­ka prze­sta­je być danymi i staje się skład­nią. Wpis ' OR '1'='1 daje wa­ru­nek kategoria = '' OR '1'='1', praw­dzi­wy dla każ­de­go wier­sza, więc lista po­ka­zu­je całą tabelę za­miast jednej ka­te­go­rii, a ten sam chwyt w for­mu­la­rzu lo­go­wa­nia prze­pusz­cza in­tru­za bez hasła. Wpis '; DROP TABLE produkt; -- zamyka apo­strof, do­kle­ja drugą in­struk­cję i zna­kiem ko­men­ta­rza -- unie­waż­nia resztę wier­sza: mysqli_query wykona tylko jedno po­le­ce­nie i takie za­py­ta­nie od­rzu­ci, ale mysqli_multi_query usunie tabelę na­praw­dę.
Obroną jest za­py­ta­nie przy­go­to­wa­ne (prepared statement): do ser­we­ra idzie naj­pierw sam wzo­rzec ze zna­ka­mi za­py­ta­nia w miej­scu war­to­ści, a war­to­ści osobno, więc serwer zna struk­tu­rę po­le­ce­nia, zanim zo­ba­czy dane, i żaden apo­strof jej już nie zmieni. mysqli_prepare przy­go­to­wu­je wzo­rzec, mysqli_stmt_bind_param pod­sta­wia war­to­ści, mysqli_stmt_execute wy­ko­nu­je, a mysqli_stmt_get_result oddaje wynik do znanej już pętli. Drugi pa­ra­metr wią­za­nia to typy ko­lej­nych war­to­ści: s dla napisu, i dla liczby cał­ko­wi­tej, d dla liczby z czę­ścią dzie­sięt­ną.
<?php $p = mysqli_connect('localhost', 'root', '', 'sklep'); $kategoria = $_POST['kategoria']; $minimum = (int) $_POST['sztuk']; $sql = 'SELECT nazwa, cena FROM produkt WHERE kategoria = ? AND sztuk >= ?'; $zapytanie = mysqli_prepare($p, $sql); mysqli_stmt_bind_param($zapytanie, 'si', $kategoria, $minimum); mysqli_stmt_execute($zapytanie); $wynik = mysqli_stmt_get_result($zapytanie); while ($w = mysqli_fetch_assoc($wynik)) { echo '<li>' . $w['nazwa'] . ', ' . $w['cena'] . ' zł</li>'; } mysqli_close($p);
Wy­pi­sa­na lista wy­glą­da tak samo jak wcze­śniej, tylko apo­strof wpi­sa­ny w pole trafia do bazy jako zwykły znak i ni­cze­go nie zmie­nia. Mi­ni­mum, które da się zrobić bez za­py­tań przy­go­to­wa­nych: liczbę rzu­tu­je się na typ cał­ko­wi­ty za­pi­sem (int) $_POST['id'], a napis prze­pusz­cza przez mysqli_real_escape_string($p, $_POST['kategoria']), która po­prze­dza apo­stro­fy uko­śni­kiem. War­tość prze­pusz­czo­na przez tę funk­cję nadal wymaga apo­stro­fów wokół siebie w za­py­ta­niu.
Wstrzyk­nię­cie SQL nie jest je­dy­nym ata­kiem przez pole for­mu­la­rza. XSS (Cross Site Scrip­ting, skrypt między wi­try­na­mi) polega na wpi­sa­niu w pole znacz­ni­ka <script> z kodem JavaScript, który wykona się w prze­glą­dar­ce każ­de­go, kto potem otwo­rzy stronę z tą war­to­ścią, i wy­krad­nie na przy­kład cia­stecz­ko z iden­ty­fi­ka­to­rem sesji. Obroną jest htmlspecialchars($tekst), które za­mie­nia znaki <, >, & i cu­dzy­słów na encje, więc znacz­nik wy­świe­tla się jako tekst, za­miast się wy­ko­nać. Trzeci atak, CSRF (Cross Site Re­qu­est For­ge­ry, fał­szo­wa­nie żą­da­nia), pod­su­wa za­lo­go­wa­ne­mu użyt­kow­ni­ko­wi ukryty for­mu­larz wy­sy­ła­ją­cy żą­da­nie do cudzej apli­ka­cji, a broni się przed nim lo­so­wym znacz­ni­kiem za­pi­sa­nym w sesji.
Pu­łap­ka: wa­li­da­cja HTML5 i spraw­dza­nie w JavaScript to wygoda dla użyt­kow­ni­ka, nie za­bez­pie­cze­nie: żą­da­nie da się wysłać z po­mi­nię­ciem strony, więc dane spraw­dza się jesz­cze raz w skryp­cie po stro­nie ser­we­ra.

Hasła użyt­kow­ni­ków i dane do­stę­po­we

Hasła nigdy nie leżą w bazie w po­sta­ci wpi­sa­nej przez użyt­kow­ni­ka. Za­pi­su­je się skrót kryp­to­gra­ficz­ny (hash), czyli wynik prze­li­cze­nia hasła funk­cją, której nie da się od­wró­cić. Robi to password_hash($haslo, PASSWORD_DEFAULT): do­kła­da losową do­miesz­kę (salt, sól), liczy skrót po­wol­nym al­go­ryt­mem i oddaje napis dłu­go­ści około 60 znaków, więc ko­lum­na w bazie po­trze­bu­je typu VARCHAR(255). To samo hasło za­pi­sa­ne dwa razy daje dwa różne skróty, więc skró­tów nie po­rów­nu­je się znak po znaku: robi to password_verify($haslo, $skrot), która oddaje true albo false.
<?php session_start(); $login = $_POST['login']; $zapytanie = mysqli_prepare($p, 'SELECT haslo FROM uzytkownik WHERE login = ?'); mysqli_stmt_bind_param($zapytanie, 's', $login); mysqli_stmt_execute($zapytanie); $w = mysqli_fetch_assoc(mysqli_stmt_get_result($zapytanie)); if ($w && password_verify($_POST['haslo'], $w['haslo'])) { $_SESSION['login'] = $login; }
Po udanym spraw­dze­niu skrypt za­pi­su­je login w ta­bli­cy $_SESSION, a ko­lej­ne pod­stro­ny pytają tylko, czy ten wpis ist­nie­je. Me­cha­nizm sesji opi­su­je lekcja o pli­kach, cia­stecz­kach i se­sjach. Funk­cje md5 i sha1 do haseł nie nadają się od dawna: liczą się bardzo szybko, nie mają do­miesz­ki, a dla po­pu­lar­nych haseł gotowe ta­bli­ce skró­tów oddają hasło od ręki. Dane do­stę­po­we do bazy trzyma się w osob­nym pliku do­łą­cza­nym przez include, poza ka­ta­lo­giem pu­blicz­nym ser­we­ra, żeby nikt nie pobrał ich ad­re­sem, i w tym samym miej­scu trzyma się kopię za­pa­so­wą bazy.

PDO i inne spo­so­by po­łą­cze­nia

PDO (PHP Data Ob­jects, obiek­ty danych PHP) to druga stan­dar­do­wa bi­blio­te­ka ba­zo­da­no­wa PHP, obiek­to­wa i wspól­na dla wielu sil­ni­ków. Po­łą­cze­nie tworzy ope­ra­tor new, a rodzaj bazy, adres ser­we­ra i jej nazwę podaje się w jednym na­pi­sie.
<?php $pdo = new PDO('mysql:host=localhost;dbname=egzamin;charset=utf8mb4', 'root', ''); $zapytanie = $pdo->prepare('SELECT nazwa, cena FROM produkt WHERE id = ?'); $zapytanie->execute([5]); $wiersz = $zapytanie->fetch(PDO::FETCH_ASSOC); echo $wiersz['nazwa'];
Skrypt wy­pi­su­je Kabel HDMI, czyli nazwę pro­duk­tu o kluczu 5. War­to­ści podaje się ta­bli­cą prosto w execute, bez osob­ne­go wią­za­nia i bez po­da­wa­nia typów, fetch(PDO::FETCH_ASSOC) oddaje jeden wiersz jako ta­bli­cę aso­cja­cyj­ną, a wszyst­kie naraz fetchAll. Przej­ście na PostgreSQL albo SQLite to zmiana samego napisu z ad­re­sem i na tym polega prze­wa­ga PDO nad mysqli, która ob­słu­gu­je wy­łącz­nie MySQL i MariaDB.
Sama mysqli ma też wersję obiek­to­wą: po­łą­cze­nie tworzy new mysqli('localhost', 'root', '', 'egzamin'), za­py­ta­nie wysyła $polaczenie->query($sql), wiersz oddaje $wynik->fetch_assoc(), a zamyka $polaczenie->close(). Nazwy są te same, tylko za­pi­sa­ne po kropce, i o tę wersję pytają za­da­nia wspo­mi­na­ją­ce pole insert_id. Naj­star­szy zestaw mysql_connect, mysql_query i mysql_fetch_row bez litery i usu­nię­to z PHP 7, choć w ban­kach pytań jesz­cze się po­ja­wia.

Na eg­za­mi­nie

Py­ta­nia pi­sem­ne o po­łą­cze­nie z bazą mają kilka sta­łych kształ­tów. Pierw­szy to pa­ra­me­try: w za­pi­sie mysqli_connect('localhost', 'root', '', 'zwierzaki') idą po kolei adres ser­we­ra, nazwa użyt­kow­ni­ka, hasło i nazwa bazy, więc py­ta­nie o war­tość na trze­cim miej­scu ma od­po­wiedź „hasło użyt­kow­ni­ka". Drugi to wybór funk­cji: pracę z bazą otwie­ra mysqli_connect, a kończy mysqli_close, nie exit, die ani mysqli_commit. Trzeci to rodzaj ta­bli­cy z wier­szem: mysqli_fetch_row oddaje ta­bli­cę in­dek­so­wa­ną, mysqli_fetch_assoc aso­cja­cyj­ną, a mysqli_fetch_array obie naraz. Czwar­ty to liczby: liczbę wier­szy wyniku podaje mysqli_num_rows, liczbę kolumn mysqli_num_fields, a klucz świeżo wsta­wio­ne­go wier­sza mysqli_insert_id. Piąty to za­py­ta­nie w ramce: INSERT INTO dane VALUES (NULL, '$a', '$b', '$c') wsta­wia wiersz, a NULL zo­sta­wia ko­lum­nę klucza au­to­ma­tycz­ne­go ser­we­ro­wi. Szósty to inny silnik: pg_connect łączy z bazą PostgreSQL, nie z MySQL. Siódmy to ko­do­wa­nie pol­skich znaków, za które od­po­wia­da mysqli_set_charset, oraz ko­mu­ni­kat błędu z mysqli_error i jego numer z mysqli_errno. Ósmy to bez­pie­czeń­stwo: atak po­le­ga­ją­cy na wpi­sa­niu w pole for­mu­la­rza frag­men­tu za­py­ta­nia to SQL in­jec­tion, broni przed nim za­py­ta­nie przy­go­to­wa­ne, a hasła za­pi­su­je się skró­tem z password_hash i spraw­dza przez password_verify.
Pu­łap­ka: mysqli_query oddaje wynik, a nie wier­sze. Po­je­dyn­czy wiersz wy­cho­dzi do­pie­ro z mysqli_fetch_array, mysqli_fetch_assoc albo mysqli_fetch_row, wy­wo­ła­nej w pętli, bo jedno wy­wo­ła­nie daje jeden wiersz.
W za­da­niu prak­tycz­nym skrypt po­łą­cze­nia z bazą jest osobno oce­nia­nym re­zul­ta­tem, a jego po­czą­tek jest za każdym razem ten sam: localhost, użyt­kow­nik root, puste hasło, nazwa bazy podana w ar­ku­szu i mysqli_close na końcu. Za­py­ta­nia idą do bazy za­im­por­to­wa­nej wcze­śniej w phpMyAdmin, a wynik ma trafić na stronę do­kład­nie w po­sta­ci ze wzoru: te same prze­cin­ki, ta sama jed­nost­ka, ta sama ko­lej­ność kolumn. Plik .php musi leżeć w ka­ta­lo­gu htdocs i zostać otwar­ty ad­re­sem http://localhost/..., bo prosto z dysku nie wykona się wcale i za­miast listy pro­duk­tów w oknie prze­glą­dar­ki zo­sta­nie kod albo pusta strona.

Ściąga

Zapis
Znaczy
mysqli_connect('localhost', 'root', '', 'egzamin')
serwer, użyt­kow­nik, hasło, baza
mysqli_select_db($p, 'egzamin')
wybór bazy na otwar­tym po­łą­cze­niu
mysqli_connect_error()
powód nie­uda­ne­go po­łą­cze­nia
mysqli_set_charset($p, 'utf8mb4')
ko­do­wa­nie pol­skich znaków
mysqli_query($p, $sql)
wysyła za­py­ta­nie, oddaje wynik SELECT
mysqli_fetch_array($w)
wiersz z klu­cza­mi licz­bo­wy­mi i na­zwa­mi kolumn
mysqli_fetch_assoc($w)
wiersz z na­zwa­mi kolumn
mysqli_fetch_row($w)
wiersz z nu­me­ra­mi kolumn od zera
mysqli_num_rows($w)
liczba wier­szy wyniku
mysqli_num_fields($w)
liczba kolumn wyniku
mysqli_affected_rows($p)
liczba wier­szy zmie­nio­nych przez UPDATE
mysqli_insert_id($p)
klucz ostat­nio wsta­wio­ne­go wier­sza
mysqli_error($p)
ko­mu­ni­kat o błę­dzie ostat­niej ope­ra­cji
mysqli_close($p)
za­mknię­cie po­łą­cze­nia, ostat­ni wiersz skryp­tu
mysqli_prepare($p, $sql)
wzo­rzec za­py­ta­nia ze zna­ka­mi za­py­ta­nia
mysqli_stmt_bind_param($z, 'si', $a, $b)
pod­sta­wie­nie war­to­ści, s napis, i liczba
mysqli_real_escape_string($p, $t)
uciecz­ka apo­stro­fów w na­pi­sie z for­mu­la­rza
htmlspecialchars($t)
obrona przed XSS przy wy­pi­sy­wa­niu na stronę
password_hash($h, PASSWORD_DEFAULT)
skrót hasła do za­pi­sa­nia w bazie
password_verify($h, $skrot)
spraw­dze­nie hasła przy lo­go­wa­niu
new PDO('mysql:host=localhost;dbname=egzamin', 'root', '')
po­łą­cze­nie bi­blio­te­ką PDO
$zapytanie->execute([$id])
wy­ko­na­nie za­py­ta­nia PDO z war­to­ścią
$zapytanie->fetch(PDO::FETCH_ASSOC)
jeden wiersz jako ta­bli­ca aso­cja­cyj­na
Pobierz ściągę PDF
ZAWODNIK
egzamin zawodowy INF.02 · INF.03 · INF.04
Serwer Discord
Egzaminy zawodowe IT/Matury/Studia
@yastor
© 2026 Zawodnik · by Yastor
Arkusze i zasady oceniania pochodzą z CKE. Serwis nie jest powiązany z Centralną Komisją Egzaminacyjną.