Добавить в корзинуПозвонить
Найти в Дзене
Belhak

Как сделать сайт на php

Это фундаментальное пошаговое руководство (эквивалент 10 страниц печатного текста) разработано для программистов, желающих научиться создавать динамические веб-сайты на чистом PHP (Native PHP) без использования готовых CMS (WordPress, Joomla) и тяжелых фреймворков. В ходе этого руководства мы создадим модульный, структурированный сайт-визитку с динамическими страницами, рабочей формой обратной связи, базой данных и панелью администратора для управления контентом. Прежде чем написать первую строку кода, необходимо понять, как устроен типичный динамический сайт и как он взаимодействует с сервером. В старой школе PHP для каждой страницы создавался свой файл: index.php, about.php, contacts.php. Это приводило к дублированию кода.
Современный подход использует концепцию Единой точки входа. Абсолютно все запросы пользователя идут на один файл — index.php. Этот файл анализирует адресную строку URL и, исходя из запроса, подключает нужные блоки данных. Создайте в вашей рабочей директории (наприм
Оглавление

Подробное руководство по созданию веб-сайта на PHP с нуля

Это фундаментальное пошаговое руководство (эквивалент 10 страниц печатного текста) разработано для программистов, желающих научиться создавать динамические веб-сайты на чистом PHP (Native PHP) без использования готовых CMS (WordPress, Joomla) и тяжелых фреймворков.

В ходе этого руководства мы создадим модульный, структурированный сайт-визитку с динамическими страницами, рабочей формой обратной связи, базой данных и панелью администратора для управления контентом.

Страница 1: Архитектура веб-приложений и проектирование сайта

Прежде чем написать первую строку кода, необходимо понять, как устроен типичный динамический сайт и как он взаимодействует с сервером.

Статический vs Динамический сайт

  • Статический сайт (HTML/CSS): Сервер просто берет готовый файл .html с жесткого диска и отправляет его браузеру пользователя. Если на сайте 100 страниц, вам нужно создать 100 отдельных файлов. Если меняется дизайн шапки, менять ее придется в 100 файлах.
  • Динамический сайт (PHP/MySQL): Пользователь запрашивает страницу. Сервер запускает PHP-скрипт. Скрипт «собирает» страницу на лету: запрашивает текст из базы данных, берет шаблон шапки и подвала, склеивает их и отдает браузеру чистый HTML.

Принцип единой точки входа (Front Controller)

В старой школе PHP для каждой страницы создавался свой файл: index.php, about.php, contacts.php. Это приводило к дублированию кода.
Современный подход использует концепцию
Единой точки входа. Абсолютно все запросы пользователя идут на один файл — index.php. Этот файл анализирует адресную строку URL и, исходя из запроса, подключает нужные блоки данных.

Структура нашего проекта

Создайте в вашей рабочей директории (например, C:\www\mysite\ или в папке вашего локального сервера) следующую структуру файлов и папок:

mysite/

├── config/
│ └── db.php # Настройки подключения к базе данных

├── includes/
│ ├── header.php # Шапка сайта (HTML-верстка)
│ ├── footer.php # Подвал сайта (HTML-верстка)
│ └── functions.php # Вспомогательные PHP-функции

├── templates/
│ ├── home.php # Шаблон главной страницы
│ ├── about.php # Шаблон страницы "О нас"
│ ├── contact.php # Шаблон страницы контактов
│ └── 404.php # Страница ошибки

├── assets/
│ ├── css/
│ │ └── style.css # Стили сайта
│ └── js/
│ └── main.js # Скрипты JavaScript

├── admin/
│ ├── index.php # Главная страница админки
│ └── login.php # Авторизация в админку

└── index.php # Единая точка входа (главный файл)

Страница 2: Верстка и создание модульной структуры (Шаблонизация)

Сделаем так, чтобы нам не приходилось дублировать HTML-код меню и подвала на каждой странице. Разделим стандартный макет на независимые части.

1. Создаем includes/header.php

Этот файл отвечает за начало HTML-документа, подключение стилей и верхнюю навигацию.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php echo $pageTitle ?? 'Мой PHP Сайт'; ?></title>
<link rel="stylesheet" href="/assets/css/style.css">
</head>
<body>
<header class="site-header">
<div class="container">
<div class="logo">PHP.WebDev</div>
<nav class="main-nav">
<ul>
<li><a href="index.php?page=home">Главная</a></li>
<li><a href="index.php?page=about">О нас</a></li>
<li><a href="index.php?page=contact">Контакты</a></li>
</ul>
</nav>
</div>
</header>
<main class="main-content">
<div class="container">

2. Создаем includes/footer.php

Этот файл закрывает открытые теги и содержит информацию об авторских правах с динамическим выводом текущего года.

</div>
</main>
<footer class="site-footer">
<div class="container">
<p>&copy; <?php echo date('Y'); ?> PHP.WebDev. Все права защищены.</p>
</div>
</footer>
<script src="/assets/js/main.js"></script>
</body>
</html>

3. Базовые стили assets/css/style.css

Добавьте минимальное оформление, чтобы сайт выглядел аккуратно.

* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: Arial, sans-serif; color: #333; line-height: 1.6; }
.container { width: 80%; max-width: 1200px; margin: 0 auto; }
.site-header { background: #2c3e50; color: #fff; padding: 20px 0; }
.site-header .container { display: flex; justify-content: space-between; align-items: center; }
.main-nav ul { display: flex; list-style: none; }
.main-nav ul li { margin-left: 20px; }
.main-nav ul li a { color: #fff; text-decoration: none; font-weight: bold; }
.main-content { padding: 40px 0; min-height: 70vh; }
.site-footer { background: #34495e; color: #fff; text-align: center; padding: 20px 0; margin-top: 40px; }
.error-msg { color: red; margin-bottom: 15px; }
.success-msg { color: green; margin-bottom: 15px; }

Страница 3: Маршрутизация (Routing) и создание контентных страниц

Теперь настроим файл index.php. Он будет принимать параметр page из URL (например, index.php?page=about) и отдавать пользователю нужную страницу.

Создаем контентные шаблоны

Перед настройкой роутера создадим контентные файлы в папке templates/.

  • templates/home.php<h1>Добро пожаловать на наш сайт!</h1>
    <p>Это главная страница, написанная на PHP. Здесь будет размещен основной контент.</p>
  • templates/about.php<h1>О нашей компании</h1>
    <p>Мы команда разработчиков, создающая качественные веб-приложения на чистом PHP.</p>
  • templates/404.php<h1>Ошибка 404</h1>
    <p>К сожалению, запрашиваемая страница не найдена.</p>
    <a href="index.php?page=home">Вернуться на главную</a>

Настройка ядра роутинга в index.php

Этот файл связывает всё воедино. Мы используем «белый список» (White List) страниц из соображений безопасности, чтобы злоумышленник не смог подключить системные файлы сервера через URL.

<?php
// Включаем отображение ошибок для этапа разработки
ini_set('display_errors', 1);
error_reporting(E_ALL);

// Получаем имя страницы из параметров URL, по умолчанию - 'home'
$page = $_GET['page'] ?? 'home';

// Список разрешенных страниц (Белый список)
$allowedPages = [
'home' => ['template' => 'templates/home.php', 'title' => 'Главная страница'],
'about' => ['template' => 'templates/about.php', 'title' => 'О нас'],
'contact' => ['template' => 'templates/contact.php', 'title' => 'Контакты']
];

// Проверяем, существует ли запрашиваемая страница в белом списке
if (array_key_exists($page, $allowedPages)) {
$template = $allowedPages[$page]['template'];
$pageTitle = $allowedPages[$page]['title'];
} else {
// Если страницы нет, отдаем 404 ошибку
header("HTTP/1.0 404 Not Found");
$template = 'templates/404.php';
$pageTitle = 'Страница не найдена';
}

// Собираем страницу из модулей
require_once 'includes/header.php';
require_once $template;
require_once 'includes/footer.php';

Теперь, если вы запустите встроенный сервер (php -S localhost:8000) и покликаете по меню, ссылки начнут работать, подгружая контент без перезагрузки структуры шапки и подвала.

Страница 4: Обработка форм и валидация данных (Форма контактов)

Формы — главный способ получения данных от пользователя. Напишем безопасный обработчик для страницы контактов.

1. Создаем шаблон формы в templates/contact.php

Форма будет отправлять данные на этот же адрес методом POST.

<h1>Напишите нам</h1>

<?php
// Вывод сообщений об ошибках или успехе, если они переданы из обработчика
if (!empty($errors)) {
foreach ($errors as $error) {
echo "<p class='error-msg'>$error</p>";
}
}
if (isset($successMessage)) {
echo "<p class='success-msg'>$successMessage</p>";
}
?>

<form action="index.php?page=contact" method="POST" style="max-width: 500px; display: flex; flex-direction: column; gap: 15px;">
<div>
<label for="username">Ваше имя:</label>
<input type="text" id="username" name="username" style="width: 100%; padding: 8px;" value="<?php echo htmlspecialchars($_POST['username'] ?? ''); ?>">
</div>
<div>
<label for="email">E-mail:</label>
<input type="email" id="email" name="email" style="width: 100%; padding: 8px;" value="<?php echo htmlspecialchars($_POST['email'] ?? ''); ?>">
</div>
<div>
<label for="message">Сообщение:</label>
<textarea id="message" name="message" rows="5" style="width: 100%; padding: 8px;"><?php echo htmlspecialchars($_POST['message'] ?? ''); ?></textarea>
</div>
<button type="submit" style="padding: 10px; background: #2c3e50; color: #fff; border: none; cursor: pointer;">Отправить</button>
</form>

2. Добавляем логику обработки в index.php

Вставим код обработки перед выводом header.php, чтобы при необходимости мы могли делать редиректы или обрабатывать сессии. Изменим логику для страницы contact в index.php:

// Переменные для хранения ошибок и статуса обработки формы
$errors = [];
$successMessage = null;

// Если форма была отправлена методом POST
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $page === 'contact') {

// Извлекаем данные и очищаем их от лишних пробелов
$username = trim($_POST['username'] ?? '');
$email = trim($_POST['email'] ?? '');
$message = trim($_POST['message'] ?? '');

// Валидация (проверка заполнения и корректности данных)
if (empty($username)) {
$errors[] = 'Пожалуйста, введите ваше имя.';
}

if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = 'Укажите корректный адрес электронной почты.';
}

if (strlen($message) < 10) {
$errors[] = 'Сообщение должно содержать не менее 10 символов.';
}

// Если ошибок нет - обрабатываем данные
if (empty($errors)) {
// В реальном проекте здесь будет отправка email или запись в БД.
// Имитируем успешную отправку:
$successMessage = "Спасибо, $username! Ваше сообщение успешно отправлено.";

// Очищаем POST данные, чтобы форма обнулилась
$_POST = [];
}
}

Важно по безопасности: Функция htmlspecialchars() используется при выводе данных обратно в форму. Она превращает опасные HTML-теги (например, <script>) в безопасные сущности (&lt;script&gt;), защищая сайт от XSS-атак (межсайтового скриптинга).

Страница 5: Работа с базой данных (MySQL и PDO)

Для хранения динамических страниц и записей блога нам понадобится база данных. Будем использовать расширение PDO (PHP Data Objects). Это современный стандарт, обеспечивающий защиту от SQL-инъекций.

Создание базы данных и таблицы

Зайдите в вашу панель управления БД (phpMyAdmin или аналогичную среду) и выполните следующий SQL-запрос для создания структуры:

CREATE DATABASE IF NOT EXISTS `my_php_site` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE `my_php_site`;

-- Таблица страниц сайта
CREATE TABLE IF NOT EXISTS `pages` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`slug` VARCHAR(50) NOT NULL UNIQUE,
`title` VARCHAR(255) NOT NULL,
`content` TEXT NOT NULL,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;

-- Наполняем таблицу тестовыми данными
INSERT INTO `pages` (`slug`, `title`, `content`) VALUES
('home', 'Главная страница', 'Приветствуем вас на нашем динамическом сайте, который работает на базе СУБД MySQL!'),
('about', 'О нас', 'Данные этой страницы полностью загружены из таблицы MySQL с помощью технологии PDO.'),
('contact', 'Контакты', 'Свяжитесь с нами. Форма ниже проверяет данные на сервере.');

Подключение к БД: config/db.php

Создадим класс/скрипт подключения. Мы упакуем подключение в блок try-catch для перехвата возможных ошибок.

<?php
$host = 'localhost';
$db = 'my_php_site';
$user = 'root'; // Ваш логин от БД (в XAMPP/OpenServer обычно root)
$pass = ''; // Ваш пароль от БД (в OpenServer обычно пустая строка или root)
$charset = 'utf8mb4';

$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // Выбрасывать исключения при ошибках
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // Возвращать данные в виде ассоциативных массивов
PDO::ATTR_EMULATE_PREPARES => false, // Отключаем эмуляцию подготовленных запросов
];

try {
$pdo = new PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {
// В реальном проекте нельзя выводить $e->getMessage() пользователям, пишите в логи.
die("Ошибка подключения к базе данных: " . $e->getMessage());
}

Страница 6: Перенос контента в БД и динамический вывод

Теперь перепишем наш index.php так, чтобы он не хранил страницы в жестком коде, а забирал их из созданной таблицы.

Обновленный index.php со сбором данных из БД

<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);

// Подключаем файл конфигурации БД
require_once 'config/db.php';

// Определяем текущую страницу
$page = $_GET['page'] ?? 'home';

// Подготавливаем безопасный SQL-запрос для поиска страницы по ее 'slug'
$stmt = $pdo->prepare("SELECT * FROM pages WHERE slug = :slug");
$stmt->execute(['slug' => $page]);
$pageData = $stmt->fetch();

// Если страница найдена в БД
if ($pageData) {
$pageTitle = $pageData['title'];
$pageContent = $pageData['content'];
} else {
header("HTTP/1.0 404 Not Found");
$pageTitle = 'Страница не найдена';
$pageContent = '<h1>404 Кажется, такой страницы нет</h1><p>Проверьте корректность ссылки.</p>';
}

// Логика обработки формы обратной связи (оставляем только для страницы contact)
$errors = [];
$successMessage = null;
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $page === 'contact') {
$username = trim($_POST['username'] ?? '');
$email = trim($_POST['email'] ?? '');
$message = trim($_POST['message'] ?? '');

if (empty($username)) $errors[] = 'Введите имя.';
if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) $errors[] = 'Некорректный email.';
if (strlen($message) < 10) $errors[] = 'Короткое сообщение.';

if (empty($errors)) {
$successMessage = "Спасибо, данные проверены!";
$_POST = [];
}
}

// Выводим интерфейс
require_once 'includes/header.php';

// Печатаем контент, полученный из базы данных
echo "<div>" . $pageContent . "</div>";

// Если это страница контактов, то ниже контента принудительно выводим форму
if ($page === 'contact') {
require_once 'templates/contact.php';
}

require_once 'includes/footer.php';

Страница 7: Механизм сессий и авторизация пользователей

Чтобы закрыть панель администратора от посторонних глаз, нам потребуется механизм отслеживания состояния пользователя. Для этого в PHP используются Сессии (Sessions).

Создание таблицы пользователей

Добавим в базу данных таблицу для хранения администраторов. Пароли в БД обязательно должны храниться в зашифрованном виде (хэш-код).

CREATE TABLE IF NOT EXISTS `users` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`username` VARCHAR(50) NOT NULL UNIQUE,
`password` VARCHAR(255) NOT NULL
) ENGINE=InnoDB;

-- Пароль 'admin123' хэшируем встроенной функцией PHP password_hash()
-- Сгенерируем хэш и вставим пользователя (ниже указан стандартный хэш для admin123)
INSERT INTO `users` (`username`, `password`) VALUES
('admin', '$2y$10$mC7p7V16W0gVbWfS9fNfDu6U9CPhv7NlzfXmD0L7qD7.I5vKWhuW2');

Файл авторизации: admin/login.php

Сессии запускаются функцией session_start(). Она должна быть вызвана до любого вывода HTML в браузер.

<?php
session_start();
require_once '../config/db.php';

$error = '';

// Если пользователь уже авторизован, перенаправляем в админку
if (isset($_SESSION['admin_logged'])) {
header('Location: index.php');
exit;
}

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

if (!empty($username) && !empty($password)) {
// Ищем пользователя в БД
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username");
$stmt->execute(['username' => $username]);
$user = $stmt->fetch();

// Проверяем хэш пароля с помощью встроенной функции
if ($user && password_verify($password, $user['password'])) {
// Записываем маркер авторизации в сессию
$_SESSION['admin_logged'] = $user['username'];
header('Location: index.php');
exit;
} else {
$error = 'Неверное имя пользователя или пароль!';
}
} else {
$error = 'Заполните все поля!';
}
}
?>
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Вход в панель управления</title>
<link rel="stylesheet" href="../assets/css/style.css">
</head>
<body style="display: flex; justify-content: center; align-items: center; height: 100vh; background: #f4f6f9;">
<div style="background: #fff; padding: 30px; border-radius: 5px; box-shadow: 0 0 10px rgba(0,0,0,0.1); width: 320px;">
<h2 style="margin-bottom: 20px; text-align: center;">Вход в Админку</h2>
<?php if($error): ?>
<p class="error-msg"><?php echo $error; ?></p>
<?php endif; ?>
<form action="login.php" method="POST" style="display: flex; flex-direction: column; gap: 15px;">
<input type="text" name="username" placeholder="Логин" required style="padding: 10px;">
<input type="password" name="password" placeholder="Пароль" required style="padding: 10px;">
<button type="submit" style="padding: 10px; background: #2c3e50; color: white; border: none; cursor: pointer;">Войти</button>
</form>
</div>
</body>
</html>

Страница 8: Создание Системы управления контентом (Панель администратора)

Теперь создадим файл admin/index.php. Здесь администратор сможет просматривать список страниц и редактировать их контент, меняя информацию на основном сайте в один клик.

Панель управления admin/index.php

<?php
session_start();
require_once '../config/db.php';

// Защита: если сессия пуста, выкидываем пользователя на страницу входа
if (!isset($_SESSION['admin_logged'])) {
header('Location: login.php');
exit;
}

// Логика обработки выхода (Logout)
if (isset($_GET['action']) && $_GET['action'] === 'logout') {
session_destroy();
header('Location: login.php');
exit;
}

// Получаем все страницы для вывода в таблицу
$stmt = $pdo->query("SELECT id, slug, title FROM pages");
$pages = $stmt->fetchAll();
?>
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Панель управления</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; background: #f9f9f9; }
table { width: 100%; border-collapse: collapse; margin-top: 20px; background: #fff; }
th, td { border: 1px solid #ddd; padding: 12px; text-align: left; }
th { background-color: #2c3e50; color: white; }
.btn { padding: 6px 12px; text-decoration: none; color: white; background: #3498db; border-radius: 3px; }
.btn-logout { background: #e74c3c; float: right; }
</style>
</head>
<body>
<header>
<a href="index.php?action=logout" class="btn btn-logout">Выйти из системы</a>
<h1>Панель администратора</h1>
<p>Добро пожаловать, администратор <strong><?php echo htmlspecialchars($_SESSION['admin_logged']); ?></strong>!</p>
</header>

<main>
<h3>Список текстовых страниц сайта</h3>
<table>
<thead>
<tr>
<th>ID</th>
<th>Slug (URL-адрес)</th>
<th>Заголовок страницы</th>
<th>Действия</th>
</tr>
</thead>
<tbody>
<?php foreach ($pages as $p): ?>
<tr>
<td><?php echo $p['id']; ?></td>
<td>/index.php?page=<?php echo htmlspecialchars($p['slug']); ?></td>
<td><?php echo htmlspecialchars($p['title']); ?></td>
<td>
<!-- Ссылка на скрипт редактирования -->
<a href="edit.php?id=<?php echo $p['id']; ?>" class="btn">Редактировать</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<p style="margin-top:20px;"><a href="../index.php" target="_blank">Перейти на сайт &rarr;</a></p>
</main>
</body>
</html>

Страница 9: Модификация данных (Редактор страниц)

Создадим скрипт admin/edit.php, который будет обновлять информацию в базе данных на основе SQL-оператора UPDATE.

<?php
session_start();
require_once '../config/db.php';

if (!isset($_SESSION['admin_logged'])) {
header('Location: login.php');
exit;
}

$id = $_GET['id'] ?? null;
if (!$id) {
die("Не указан ID страницы.");
}

// Загружаем текущие данные страницы
$stmt = $pdo->prepare("SELECT * FROM pages WHERE id = :id");
$stmt->execute(['id' => $id]);
$page = $stmt->fetch();

if (!$page) {
die("Страница с таким ID не найдена.");
}

$success = false;

// Обработка отправки формы сохранения изменений
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$title = trim($_POST['title'] ?? '');
$content = trim($_POST['content'] ?? '');

if (!empty($title) && !empty($content)) {
// Обновляем данные в БД
$updateStmt = $pdo->prepare("UPDATE pages SET title = :title, content = :content WHERE id = :id");
$updateStmt->execute([
'title' => $title,
'content' => $content,
'id' => $id
]);
$success = true;

// Обновляем локальные переменные для вывода в форме актуальных данных
$page['title'] = $title;
$page['content'] = $content;
}
}
?>
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Редактирование страницы</title>
<link rel="stylesheet" href="../assets/css/style.css">
</head>
<body style="padding: 40px; background: #f4f6f9;">
<div style="max-width: 800px; margin: 0 auto; background: #fff; padding: 30px; border-radius: 5px; box-shadow:0 0 10px rgba(0,0,0,0.05)">
<a href="index.php" style="text-decoration:none; color:#3498db;">&larr; Назад в админку</a>
<h2 style="margin: 20px 0;">Редактирование: <?php echo htmlspecialchars($page['slug']); ?></h2>

<?php if ($success): ?>
<p class="success-msg">Изменения успешно сохранены в базе данных!</p>
<?php endif; ?>

<form action="edit.php?id=<?php echo $id; ?>" method="POST" style="display:flex; flex-direction:column; gap:20px;">
<div>
<label style="font-weight:bold; display:block; margin-bottom:5px;">Заголовок страницы:</label>
<input type="text" name="title" value="<?php echo htmlspecialchars($page['title']); ?>" style="width:100%; padding:10px;" required>
</div>
<div>
<label style="font-weight:bold; display:block; margin-bottom:5px;">Контент (HTML разрешен):</label>
<textarea name="content" rows="12" style="width:100%; padding:10px; font-family:Courier, monospace;" required><?php echo htmlspecialchars($page['content']); ?></textarea>
</div>
<button type="submit" style="padding:12px; background:#2ecc71; border:none; color:white; font-size:16px; cursor:pointer; font-weight:bold;">Сохранить изменения</button>
</form>
</div>
</body>
</html>

Страница 10: Безопасность, оптимизация и развертывание (Production)

При переносе написанного PHP-сайта с домашнего компьютера на реальный хостинг (в продакшн) критически важно провести аудит безопасности.

Топ-3 правил безопасности PHP-разработчика

  1. Защита от SQL-инъекций: Никогда не подставляйте переменные в тело SQL-запроса напрямую (например, "SELECT * FROM users WHERE name = '$name'"). Всегда используйте подготовленные запросы (prepare() и плейсхолдеры :placeholder), как мы делали в этом руководстве.
  2. Защита от XSS-атак: Любые текстовые данные, которые ввел пользователь на сайте (или которые администратор добавил через редактор, если там есть риск ввода скриптов), перед выводом в браузер должны прогоняться через функцию htmlspecialchars().
  3. Отключение вывода ошибок на живом сайте: На локальном ПК ошибки помогают разрабатывать код. Но на хостинге вывод системных ошибок (display_errors = On) покажет хакерам пути к файлам и структуры таблиц. В файле php.ini на сервере должно быть:display_errors = Off
    log_errors = On
    error_log = /var/log/php_errors.log

Как залить сайт на сервер (Хостинг)

  1. Купите домен и хостинг: Выберите Linux-хостинг с поддержкой PHP 8.x и MySQL.
  2. Экспорт базы данных: В локальном phpMyAdmin выберите вашу базу данных, нажмите вкладку Экспорт -> Вперед. Вы получите файл .sql.
  3. Импорт базы на хостинге: В панели хостинга создайте новую пустую БД, запишите ее новое имя, пользователя и пароль. Зайдите в удаленный phpMyAdmin и нажмите Импорт, выбрав сохраненный файл .sql.
  4. Загрузка файлов: Подключитесь к вашему хостингу по протоколу FTP/SFTP (через программу FileZilla) и загрузите все папки и файлы вашего проекта в корневую директорию сервера (обычно называется public_html или www).
  5. Настройка конфигурации: Откройте файл config/db.php прямо на сервере и замените локальные доступы к БД (localhost, root, "") на новые данные, которые вам предоставил хостинг при создании базы данных.

✅ Заключение

Вы создали полноценный динамический веб-сайт с собственной CMS на чистом PHP. Этот каркас можно бесконечно масштабировать: добавлять таблицы категорий, блог, комментарии, загрузку файлов изображений и корзину товаров.