PHP / Архитектура
PHP для начинающих: как работает серверный код и что изучать первым
Введение в современный PHP 8.4: цикл HTTP-запроса, установка, первый скрипт, структура проекта, безопасность и учебный маршрут.
Содержание статьи
PHP — серверный язык программирования. Браузер не получает исходный PHP-код: веб-сервер передаёт запрос приложению, PHP выполняет программу, а клиенту возвращается готовый HTTP-ответ — обычно HTML или JSON.
Браузер → HTTP-запрос → веб-сервер → PHP-приложениеБраузер ← HTTP-ответ ← веб-сервер ← HTML или JSONЭто отличие от JavaScript, который обычно выполняется в браузере и работает с уже загруженной страницей.
Для чего используют PHP
PHP подходит для:
- динамических страниц и CMS;
- обработки форм;
- работы с базами данных;
- административных интерфейсов;
- JSON API;
- консольных команд, импорта и миграций;
- серверной интеграции с почтой и внешними сервисами.
Язык не определяет архитектуру автоматически. Безопасность и поддерживаемость зависят от структуры проекта, валидации, прав, SQL и конфигурации окружения.
Установка
Для обучения нужна актуальная поддерживаемая версия PHP, в этом руководстве — PHP 8.4+. Проверьте CLI:
php -vНа Windows можно использовать локальное серверное окружение или официальный бинарный пакет; на Linux и macOS — пакетный менеджер или контейнер. Важно, чтобы CLI и веб-сервер использовали ожидаемую версию и одинаковый набор нужных расширений.
Проверьте модули:
php -mДля учебных примеров часто нужны mbstring, pdo и конкретный PDO-драйвер, например pdo_sqlite.
Первый скрипт
Создайте public/index.php:
<?phpdeclare(strict_types=1);$name = 'мир';?><!doctype html><html lang="ru"><head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Первый PHP-скрипт</title></head><body> <h1>Привет, <?= htmlspecialchars($name, ENT_QUOTES, 'UTF-8') ?>!</h1></body></html>Запустите локальный сервер из корня проекта:
php -S 127.0.0.1:8000 -t publicОткройте http://127.0.0.1:8000/. Встроенный сервер предназначен для разработки, не для публичной эксплуатации.
Почему web-root должен быть отдельным
Безопасная базовая структура:
project/├── public/│ └── index.php├── src/├── templates/├── config/└── storage/Веб-сервер направляется только на public/. Исходный код, конфигурация, база SQLite и логи остаются вне публичного каталога.
Не храните секреты в репозитории. Используйте переменные окружения или игнорируемый локальный файл конфигурации.
Как PHP получает запрос
Суперглобальные массивы содержат данные окружения:
$_GET— параметры query string;$_POST— тело обычной HTML-формы;$_FILES— загруженные файлы;$_COOKIE— cookies;$_SERVER— метод, путь и серверные сведения;$_SESSION— серверное состояние сессии после её запуска.
Все внешние значения недоверенные:
$query = is_string($_GET['q'] ?? null) ? trim($_GET['q']) : '';if (mb_strlen($query) > 100) { http_response_code(422); exit('Слишком длинный запрос.');}Нельзя считать тип и формат правильными только потому, что форма отправляет строку.
Генерация ответа
PHP управляет статусом и заголовками до вывода тела:
http_response_code(404);header('Content-Type: text/html; charset=UTF-8');echo '<h1>Страница не найдена</h1>';После начала вывода заголовки обычно уже нельзя изменить. Поэтому контроллер сначала обрабатывает запрос, затем выбирает статус и шаблон.
Для redirect:
header('Location: /articles', true, 303);exit;exit предотвращает случайное продолжение выполнения.
Работа с базой через PDO
$database = new PDO('sqlite:' . dirname(__DIR__) . '/storage/app.sqlite', null, null, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,]);$statement = $database->prepare( 'SELECT id, title FROM articles WHERE status = :status ORDER BY id DESC');$statement->execute(['status' => 'published']);$articles = $statement->fetchAll();Значения передаются параметрами. SQL-строку нельзя собирать конкатенацией с $_GET или $_POST.
Основы безопасности
На старте закрепите правила:
- валидировать каждый внешний ввод по типу, длине, формату и allowlist;
- использовать prepared statements;
- экранировать недоверенный текст при выводе в HTML;
- защищать изменяющие запросы CSRF-токеном;
- проверять права на сервере;
- хранить пароли через
password_hash(), а не обычный хеш; - размещать загрузки под сгенерированными именами и никогда не исполнять их как PHP;
- не показывать исключения, SQL и секреты пользователю;
- использовать HTTPS и безопасные cookie;
- поддерживать PHP и зависимости в актуальном состоянии.
Архитектурные роли
По мере роста разделяйте обязанности:
- точка входа принимает HTTP-запрос;
- маршрутизатор выбирает контроллер;
- контроллер координирует сценарий;
- валидатор проверяет ввод;
- модель или репозиторий работает с данными;
- сервис выполняет внешний эффект;
- шаблон только отображает подготовленные значения.
Не создавайте все папки заранее. Выносите роль, когда она появилась в реальном сценарии.
Что изучать по порядку
- Синтаксис, типы, массивы, условия, циклы и функции.
- HTTP, формы, статусы и заголовки.
- Валидация и контекстное экранирование.
- PDO, SQL, ограничения и транзакции.
- Сессии, cookies, CSRF и аутентификация.
- Файлы, JSON и обработка исключений.
- Классы, интерфейсы и композиция.
- Маршрутизация, миграции, тесты и развёртывание.
После каждой темы создавайте небольшой связный сценарий и проверяйте ошибочные состояния. Прочитанный синтаксис без практики быстро забывается.
Что запомнить
PHP получает HTTP-запрос на сервере и формирует ответ. Начните с небольшого приложения с отдельным public/, строгими типами и явной валидацией. Безопасная работа с вводом, SQL и выводом важнее раннего знакомства с большим фреймворком.