Utwórz bazę sklep oraz tabelę produkty z przykładowymi danymi.
CREATE DATABASE IF NOT EXISTS sklep;
USE sklep;
CREATE TABLE IF NOT EXISTS produkty (
id INT AUTO_INCREMENT PRIMARY KEY,
nazwa VARCHAR(100) NOT NULL,
cena DECIMAL(10,2) NOT NULL
);
INSERT INTO produkty (nazwa, cena) VALUES
('Mysz gamingowa RGB', 79.99),
('Klawiatura mechaniczna', 199.99),
('Monitor 24"', 599.00),
('Słuchawki bezprzewodowe', 129.90),
('Laptop 15"', 2999.99);
Możesz dodać więcej kolumn, np. opis, kategoria, stan_magazynu.
db.php – połączenie z baząStwórz plik db.php z połączeniem do bazy danych (mysqli) i ustawieniem kodowania.
<?php
$host = 'localhost';
$user = 'root';
$pass = '';
$db = 'sklep';
$conn = new mysqli($host, $user, $pass, $db);
if ($conn->connect_error) {
die("Błąd połączenia: " . $conn->connect_error);
}
$conn->set_charset("utf8mb4");
Na serwerze produkcyjnym używaj oddzielnego użytkownika MySQL z ograniczonymi uprawnieniami.
index.php – wyświetlanie listy produktówWyświetl wszystkie produkty z bazy na stronie głównej sklepu, dbając o poprawne formatowanie i zabezpieczenie HTML.
<?php
require_once 'db.php';
?>
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Sklep internetowy</title>
</head>
<body>
<h1>Lista produktów</h1>
<?php
$sql = "SELECT id, nazwa, cena FROM produkty";
$result = $conn->query($sql);
if ($result && $result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
$id = (int)$row['id'];
$nazwa = htmlspecialchars($row['nazwa'], ENT_QUOTES, 'UTF-8');
$cena = number_format((float)$row['cena'], 2, ',', ' ');
echo "<div>";
echo "<strong>{$nazwa}</strong> - {$cena} zł";
echo " (ID: {$id})";
echo "</div>";
}
} else {
echo "Brak produktów.";
}
$conn->close();
?>
</body>
</html>
search.php – wyszukiwanie produktów (prepared)Dodaj stronę, która wyszukuje produkty po fragmencie nazwy. Użyj prepared statements, aby uniknąć SQL injection.
<?php
require_once 'db.php';
?>
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Wyszukiwanie produktów</title>
</head>
<body>
<h1>Wyszukiwanie produktów</h1>
<form method="get">
Wyszukaj produkt:
<input type="text" name="query">
<button type="submit">Szukaj</button>
</form>
<?php
if (isset($_GET['query'])) {
$query = trim($_GET['query']);
if ($query !== '') {
$like = "%" . $query . "%";
$stmt = $conn->prepare("SELECT id, nazwa, cena FROM produkty WHERE nazwa LIKE ?");
$stmt->bind_param("s", $like);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
$nazwa = htmlspecialchars($row['nazwa'], ENT_QUOTES, 'UTF-8');
$cena = number_format((float)$row['cena'], 2, ',', ' ');
echo "<div>Produkt: {$nazwa} - Cena: {$cena} zł</div>";
}
} else {
echo "Brak produktów spełniających kryteria.";
}
$stmt->close();
} else {
echo "Podaj frazę do wyszukania.";
}
}
$conn->close();
?>
</body>
</html>
klienci – przechowywanie użytkownikówStwórz tabelę użytkowników, w której hasło będzie przechowywane w postaci hash.
CREATE TABLE klienci (
id INT AUTO_INCREMENT PRIMARY KEY,
login VARCHAR(50) NOT NULL UNIQUE,
haslo VARCHAR(255) NOT NULL
);
register.php – rejestracja z password_hash + preparedPrzy rejestracji hasło powinno być haszowane funkcją password_hash(), a dane wstawiane prepared statementem.
<?php
session_start();
require_once 'db.php';
$info = "";
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["zarejestruj"])) {
$login = trim($_POST["login"] ?? "");
$haslo = $_POST["haslo"] ?? "";
if ($login === "" || $haslo === "") {
$info = "Uzupełnij login i hasło.";
} else {
$hash = password_hash($haslo, PASSWORD_DEFAULT);
$stmt = $conn->prepare("INSERT INTO klienci (login, haslo) VALUES (?, ?)");
$stmt->bind_param("ss", $login, $hash);
if ($stmt->execute()) {
$info = "Zarejestrowano użytkownika: " . htmlspecialchars($login, ENT_QUOTES, 'UTF-8');
} else {
$info = "Błąd rejestracji (login może być zajęty).";
}
$stmt->close();
}
}
?>
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Rejestracja</title>
</head>
<body>
<h1>Rejestracja</h1>
<form method="post">
Login: <input type="text" name="login"><br>
Hasło: <input type="password" name="haslo"><br>
<input type="submit" name="zarejestruj" value="Zarejestruj się">
</form>
<?php
if ($info !== "") {
echo "<p>" . htmlspecialchars($info, ENT_QUOTES, 'UTF-8') . "</p>";
}
?>
</body>
</html>
login.php – logowanie z password_verify + preparedPrzy logowaniu pobierz hash hasła z bazy przez prepared statement i sprawdź go funkcją password_verify().
<?php
session_start();
require_once 'db.php';
$komunikat = "";
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["zaloguj"])) {
$login = trim($_POST["login"] ?? "");
$haslo = $_POST["haslo"] ?? "";
if ($login === "" || $haslo === "") {
$komunikat = "Podaj login i hasło.";
} else {
$stmt = $conn->prepare("SELECT id, haslo FROM klienci WHERE login = ?");
$stmt->bind_param("s", $login);
$stmt->execute();
$result = $stmt->get_result();
if ($result && $result->num_rows === 1) {
$u = $result->fetch_assoc();
if (password_verify($haslo, $u["haslo"])) {
$_SESSION["klient_id"] = (int)$u["id"];
$_SESSION["login"] = $login;
$komunikat = "Zalogowano jako " . htmlspecialchars($login, ENT_QUOTES, 'UTF-8');
} else {
$komunikat = "Błędne hasło.";
}
} else {
$komunikat = "Nie znaleziono użytkownika.";
}
$stmt->close();
}
}
?>
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Logowanie</title>
</head>
<body>
<h1>Logowanie</h1>
<form method="post">
Login: <input type="text" name="login"><br>
Hasło: <input type="password" name="haslo"><br>
<input type="submit" name="zaloguj" value="Zaloguj się">
</form>
<?php
if ($komunikat !== "") {
echo "<p>" . htmlspecialchars($komunikat, ENT_QUOTES, 'UTF-8') . "</p>";
}
?>
</body>
</html>
Dodaj do strony z produktami formularz „Dodaj do koszyka” i przechowuj koszyk w tablicy sesyjnej.
<?php
session_start();
require_once 'db.php';
if (!isset($_SESSION["koszyk"])) {
$_SESSION["koszyk"] = [];
}
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["produkt_id"])) {
$id = (int)$_POST["produkt_id"];
$_SESSION["koszyk"][$id] = ($_SESSION["koszyk"][$id] ?? 0) + 1;
echo "Dodano produkt do koszyka.<br>";
}
?>
W pętli z produktami dodaj do każdego produktu przycisk z ukrytym produkt_id.
<form method="post">
<input type="hidden" name="produkt_id" value="<?= $id ?>">
<button type="submit">Dodaj do koszyka</button>
</form>
zamowienia i zamowienia_produktyUtwórz tabele do przechowywania zamówień oraz produktów w zamówieniu.
CREATE TABLE zamowienia (
id INT AUTO_INCREMENT PRIMARY KEY,
klient_id INT,
data_zamowienia DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE zamowienia_produkty (
zamowienie_id INT,
produkt_id INT,
ilosc INT
);
Po kliknięciu „Złóż zamówienie” zapisz dane z koszyka w tabelach zamowienia i zamowienia_produkty.
<?php
session_start();
require_once 'db.php';
if (!isset($_SESSION["klient_id"])) {
die("Tylko zalogowany użytkownik może złożyć zamówienie.");
}
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["zloz"]) && !empty($_SESSION["koszyk"])) {
$klient_id = (int)$_SESSION["klient_id"];
$stmtZ = $conn->prepare("INSERT INTO zamowienia (klient_id) VALUES (?)");
$stmtZ->bind_param("i", $klient_id);
$stmtZ->execute();
$zamowienie_id = $stmtZ->insert_id;
$stmtZ->close();
$stmtP = $conn->prepare(
"INSERT INTO zamowienia_produkty (zamowienie_id, produkt_id, ilosc) VALUES (?, ?, ?)"
);
foreach ($_SESSION["koszyk"] as $pid => $ilosc) {
$pid = (int)$pid;
$ilosc = (int)$ilosc;
$stmtP->bind_param("iii", $zamowienie_id, $pid, $ilosc);
$stmtP->execute();
}
$stmtP->close();
$_SESSION["koszyk"] = [];
echo "Zamówienie złożone!";
}
?>
<form method="post">
<input type="submit" name="zloz" value="Złóż zamówienie">
</form>
Wyświetl wszystkie zamówienia z nazwą klienta i listą produktów (JOIN kilku tabel).
<?php
require_once 'db.php';
$sql = "SELECT z.id, k.login, z.data_zamowienia,
p.nazwa, zp.ilosc
FROM zamowienia z
JOIN klienci k ON z.klient_id = k.id
JOIN zamowienia_produkty zp ON zp.zamowienie_id = z.id
JOIN produkty p ON p.id = zp.produkt_id
ORDER BY z.id DESC";
$res = $conn->query($sql);
$last_id = null;
while ($row = $res->fetch_assoc()) {
if ($row["id"] != $last_id) {
echo "<h3>Zamówienie #" . $row["id"] . " przez "
. htmlspecialchars($row["login"], ENT_QUOTES, 'UTF-8')
. " (" . $row["data_zamowienia"] . ")</h3>";
$last_id = $row["id"];
}
$nazwa = htmlspecialchars($row["nazwa"], ENT_QUOTES, 'UTF-8');
echo "- {$nazwa} x " . (int)$row["ilosc"] . "<br>";
}
$conn->close();
?>
Dodaj token CSRF do formularzy modyfikujących dane (np. rejestracja, dodawanie produktu).
<?php
session_start();
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
?>
<form method="post">
<input type="hidden" name="csrf_token"
value="<?= htmlspecialchars($_SESSION['csrf_token'], ENT_QUOTES, 'UTF-8') ?>">
... reszta formularza ...
</form>
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!hash_equals($_SESSION['csrf_token'] ?? '', $_POST['csrf_token'] ?? '')) {
die("Nieautoryzowany dostęp.");
}
// Przetwarzanie formularza...
}
?>
Dodaj indeks na kolumnie nazwa w tabeli produkty, aby przyspieszyć wyszukiwanie.
CREATE INDEX idx_nazwa ON produkty (nazwa);
Portal edukacyjny © 2026 – Sklep PHP + SQL (wersja edukacyjna, bezpieczne wzorce kodu)