PHP до уровня Middle: от основ до профессиональной разработки

Курс последовательно ведёт от базового синтаксиса PHP к уверенной разработке веб-приложений. Вы изучите ООП, работу с базами данных, тестирование, безопасность и практики современной разработки, необходимые для уровня Middle.

1. Основы PHP и работа с HTTP

Основы PHP и работа с HTTP

Зачем PHP и что значит работа с HTTP

PHP — это серверный язык программирования: код выполняется на сервере, а в браузер уходит результат (обычно HTML/JSON).

HTTP — это протокол, по которому браузер (клиент) отправляет запросы на сервер, а сервер возвращает ответы. Большая часть веб-разработки на PHP — это:

  • Прочитать данные запроса (URL, параметры, заголовки, тело)
  • Выполнить бизнес-логику (проверки, вычисления, работа с базой данных)
  • Сформировать корректный HTTP-ответ (статус, заголовки, тело)
  • !Схема жизненного цикла HTTP-запроса в веб-приложении на PHP

    Как запустить PHP локально

    Для первых шагов достаточно встроенного сервера PHP.

  • Установите PHP (например, через пакетный менеджер или сборку).
  • В папке проекта создайте файл index.php.
  • Запустите сервер командой:
  • Откройте в браузере http://localhost:8000.
  • Официальная документация по встроенному серверу: PHP Built-in web server

    Синтаксис PHP: минимум, без которого нельзя

    Теги PHP и вывод

    PHP-код в файлах обычно пишется внутри <?php ... ?>. Для вывода используйте echo.

    Переменные и типы

    Переменные начинаются с name = "Alice"; // строка isAdmin = false; // логический тип numbers = [10, 20, 30]; numbers[0]; // 10 echo arr) — количество элементов

  • isset(arr) — существует ли ключ (даже если значение null)
  • Документация: PHP Arrays

    Управляющие конструкции

    Условия и циклы:

    php <?php _GET['q'] ?? ''; _GET['limit'] ?? 10);

    echo "Query: " . limit; php <?php _SERVER['REQUEST_METHOD'] ?? 'GET'; _SERVER['REQUEST_URI'] ?? '/';

    echo "Method: uri";

    Здесь:

  • php://input — поток с телом запроса
  • json_decode(..., true) — декодировать JSON в ассоциативный массив
  • Документация: PHP json_decode

    Cookies и сессии

    Cookie — маленькая строка, которую сервер просит браузер сохранить и отправлять обратно в следующих запросах.

    В PHP cookies доступны в _COOKIE['theme'] ?? 'no theme'; php <?php session_start();

    _SESSION['user_id']; php <?php _POST['email'] ?? ''); email);

    if (email, FILTER_VALIDATE_EMAIL)) { http_response_code(422); echo 'Invalid email'; exit; }

    echo 'OK'; php <?php _GET['name'] ?? ''); name, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');

    echo $safe; `

    Документация: PHP htmlspecialchars

    CSRF

    CSRF — это атака, когда браузер пользователя отправляет запрос (например, POST) на сайт без осознанного действия пользователя.

    Типичная защита — CSRF-токен: случайная строка в форме, которую сервер проверяет при отправке.

    На уровне основ запомните:

  • Изменяющие операции лучше делать через POST/PUT/PATCH/DELETE, а не через GET`
  • Для форм и cookie-сессий понадобится CSRF-защита (мы сделаем её позже в курсе)
  • Итоги

    В этой статье вы изучили базовые строительные блоки:

  • Основы синтаксиса PHP: переменные, массивы, условия, циклы, функции, подключение файлов
  • Модель HTTP: запрос и ответ, методы, заголовки, статус-коды
  • Как PHP читает данные запроса через суперглобальные массивы и как формирует ответ
  • Почему данные запроса нужно валидировать и как начать думать о безопасности
  • В следующих материалах курса мы будем развивать эти идеи: аккуратная структура проекта, обработка ошибок, более чистая архитектура, работа с базой данных и создание API.

    2. ООП, исключения и архитектурные принципы

    ООП, исключения и архитектурные принципы

    Связь с предыдущей темой

    В прошлой статье вы научились принимать HTTP-запрос в PHP, читать данные из _POST, php://input, выставлять заголовки, статус-коды и делать простой роутинг.

    Проблема такого подхода в том, что по мере роста проекта:

  • index.php превращается в большой файл с ветвлениями
  • валидация, бизнес-логика и работа с данными смешиваются
  • ошибки обрабатываются несистемно
  • В этой статье вы изучите три опоры, которые выводят PHP-проекты на уровень уверенной профессиональной разработки:

  • ООП в PHP: как структурировать код через классы и объекты
  • исключения: как обрабатывать ошибки предсказуемо
  • архитектурные принципы: как разделять ответственность и управлять зависимостями
  • ООП простыми словами

    Объектно-ориентированное программирование — это способ проектировать код вокруг объектов.

  • Класс — это описание того, каким будет объект (шаблон)
  • Объект — это конкретный экземпляр класса (созданный по шаблону)
  • ООП помогает:

  • группировать данные и операции над ними в одном месте
  • прятать детали реализации и выдавать наружу простой интерфейс
  • подменять реализации (например, для тестов)
  • Документация: PHP Classes and Objects

    Класс, свойства, методы, конструктор

    Пример простого класса User.

    Что здесь важно:

  • __construct(...)конструктор, вызывается при создании объекта
  • private int this — ссылка на текущий объект
  • final class — запрет наследования от класса (полезно, когда вы хотите зафиксировать поведение)
  • Видимость: public, protected, private

    Видимость определяет, откуда можно обратиться к свойству/методу.

  • public — доступно отовсюду
  • protected — доступно внутри класса и его наследников
  • private — доступно только внутри класса
  • Практическое правило для начала:

  • данные внутри объекта чаще делайте private
  • наружу давайте методы (например, getEmail() и changeEmail()), чтобы контролировать изменения
  • Такой подход называется инкапсуляция: объект сам защищает свои данные.

    Value Object: как хранить данные безопаснее

    Во веб-разработке много данных, которые выглядят как строки, но имеют правила: email, телефон, UUID, цена, валюта.

    Value Object (объект-значение) — небольшой объект, который:

  • хранит одно значение
  • проверяет корректность
  • предоставляет понятные методы
  • Пример Email.

    Подключение:

    Преимущество: у вас появляется единое место, где решается, какой статус-код и какое сообщение вернуть.

    Архитектурные принципы: как не утонуть в коде

    Архитектура — это договорённость о том, как устроен проект: какие слои существуют и кто за что отвечает.

    Цель архитектурных принципов:

  • сделать код предсказуемым
  • упростить изменения
  • уменьшить количество скрытых зависимостей
  • SOLID на практическом уровне

    SOLID — набор принципов, которые помогают держать код в форме.

    Документация-обзор: SOLID

    #### Single Responsibility Principle

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

    Плохой сигнал:

  • класс одновременно валидирует запрос, пишет в базу и формирует JSON
  • Хороший ориентир:

  • контроллер читает вход и вызывает сервис
  • сервис содержит бизнес-логику
  • репозиторий работает с хранилищем (например, БД)
  • #### Dependency Inversion Principle

    Инверсия зависимостей: высокоуровневая логика (сервисы) не должна зависеть от деталей (как именно пишем в БД).

    На практике это означает:

  • зависеть от интерфейсов
  • передавать зависимости через конструктор (dependency injection)
  • Пример:

    Контроллер и сервис

    Что вы получаете архитектурно:

  • контроллер не знает, откуда берутся данные пользователя
  • сервис не знает, как формируется HTTP-ответ
  • ошибки переводятся в исключения, а HTTP-слой решает, что вернуть клиенту
  • Итоги

    Вы собрали важный переход от «скриптов» к профессиональной разработке:

  • поняли базовые элементы ООП в PHP: класс, объект, свойства, методы, видимость, интерфейсы
  • научились использовать исключения для централизованной обработки ошибок
  • познакомились с архитектурными принципами (SOLID, KISS, DRY, YAGNI) и типичной слоистой структурой веб-приложения
  • Дальше в курсе мы будем усиливать эти идеи: нормальный роутинг, контейнер зависимостей, более строгая валидация, работа с БД, тестирование и построение устойчивого API.

    3. Данные: SQL, PDO, транзакции и миграции

    Данные: SQL, PDO, транзакции и миграции

    Связь с предыдущими темами

    В предыдущих статьях вы научились принимать HTTP-запросы, валидировать ввод, формировать HTTP-ответы, а также структурировать код через ООП, исключения и слои (контроллеры, сервисы, репозитории).

    Следующий шаг к уровню Middle — уверенная работа с данными:

  • понимать, как устроены таблицы и запросы SQL
  • безопасно выполнять запросы из PHP через PDO
  • делать изменения данных атомарно через транзакции
  • эволюционировать схему базы предсказуемо через миграции
  • !Как SQL и PDO обычно вписываются в слоистую архитектуру

    Что такое SQL и зачем он нужен

    SQL — язык для работы с реляционными базами данных (например, MySQL или PostgreSQL). В реляционной модели данные хранятся в таблицах.

    Таблица похожа на таблицу в Excel:

  • строка — один объект (например, один пользователь)
  • колонка — одно поле (например, email)
  • Чаще всего SQL нужен, чтобы:

  • создавать структуру хранения (таблицы, индексы)
  • читать данные (запросы SELECT)
  • изменять данные (INSERT, UPDATE, DELETE)
  • Полезные справочники:

  • PostgreSQL Documentation
  • MySQL 8.0 Reference Manual
  • Минимальная схема: таблицы, ключи и связи

    Представим, что мы делаем простой сервис с пользователями и их задачами.

    Пример таблиц

    Что здесь важно:

  • PRIMARY KEY — главный уникальный идентификатор строки
  • UNIQUE — запрещает дубликаты (например, одинаковые email)
  • FOREIGN KEY — связь между таблицами (задача принадлежит пользователю)
  • Нормальная практика именования

  • таблицы во множественном числе: users, tasks
  • первичный ключ почти всегда id
  • внешние ключи: user_id, order_id
  • булевы поля: is_done, is_active
  • CRUD: базовые операции SQL

    CRUD — это Create, Read, Update, Delete.

    Create: INSERT

    Read: SELECT

    Update: UPDATE

    Delete: DELETE

    Фильтрация, сортировка, лимиты

    WHERE

    WHERE отбирает строки по условию.

    ORDER BY

    LIMIT и OFFSET

    Обычно применяются для пагинации.

    JOIN: как читать связанные данные

    JOIN — способ получить данные из нескольких таблиц в одном запросе.

    Пример: получить задачи вместе с email владельца.

    Как это читать:

  • FROM tasks t — берём таблицу tasks и называем её коротко t
  • JOIN users u ON ... — присоединяем строки пользователей по условию связи
  • в SELECT можно выбрать колонки из обеих таблиц
  • Индексы: как ускорять запросы

    Индекс — структура данных, которая помогает базе быстрее находить строки.

    Простой ориентир:

  • если вы часто ищете по колонке в WHERE (например, tasks.user_id) — индекс полезен
  • если колонка уникальна (email) — UNIQUE обычно уже подразумевает индекс
  • Пример индекса:

    Важно помнить:

  • индексы ускоряют чтение
  • но могут замедлять запись (каждый INSERT/UPDATE/DELETE должен обновлять индекс)
  • PDO: безопасная работа с базой из PHP

    PDO — стандартный слой доступа к БД в PHP. Он умеет работать с разными СУБД через драйверы.

    Документация:

  • PHP PDO
  • PHP PDOStatement
  • Почему не стоит склеивать SQL строками

    Опасный код:

    Проблема: пользователь может подставить в email кусок SQL.

    Правильный подход — подготовленные выражения (prepared statements).

    Подключение к базе и базовые настройки

    Правила, которые стоит запомнить:

  • SQL содержит плейсхолдер :email
  • реальные значения передаются отдельно в execute([...])
  • PDO сам корректно экранирует и подставляет значения
  • INSERT и получение id

    Способ зависит от базы.

    Для PostgreSQL удобно использовать RETURNING.

    Для MySQL часто используют lastInsertId():

    Документация:

  • PHP PDO::lastInsertId
  • UPDATE и количество затронутых строк

    Почему здесь транзакция важна:

  • если миграция частично выполнилась, а запись в schema_migrations не произошла, вы получите несогласованное состояние
  • транзакция делает применение миграции более надёжным
  • Практические правила миграций

  • миграции должны быть детерминированными: одинаковый результат на любом окружении
  • не редактируйте уже применённые миграции на проде: создавайте новую миграцию
  • храните миграции в репозитории вместе с кодом
  • применяйте миграции автоматически при деплое (или через CI)
  • Как это соединить в веб-приложении

    Типовой поток запроса, который создаёт задачу:

  • контроллер читает JSON и валидирует поля
  • сервис открывает транзакцию
  • репозитории создают записи (tasks), при необходимости читают/проверяют users
  • сервис коммитит транзакцию
  • контроллер возвращает 201 Created
  • Это продолжает линию курса: мы делаем код расширяемым и предсказуемым, отделяя HTTP от бизнес-логики и от работы с хранилищем.

    Итоги

    Вы освоили основу работы с данными на уровне, который ожидается от Middle:

  • SQL: CRUD, фильтрация, сортировки, JOIN, индексы
  • PDO: подключение, prepared statements, безопасная подстановка параметров, чтение результатов
  • транзакции: beginTransaction/commit/rollBack, когда и зачем применять
  • миграции: как версионировать изменения схемы и применять их предсказуемо
  • Дальше по курсу это станет фундаментом для более серьёзных тем: проектирование схемы, надёжные доменные операции, тестирование, оптимизация запросов и построение устойчивого API.

    4. Современная экосистема: Composer, PSR, фреймворки

    Современная экосистема: Composer, PSR, фреймворки

    Связь с предыдущими темами

    В прошлых статьях вы:

  • принимали HTTP-запросы и формировали HTTP-ответы
  • строили код через ООП, исключения и слои (контроллеры, сервисы, репозитории)
  • подключали базу данных через SQL и PDO, использовали транзакции и миграции
  • Чтобы уверенно расти до уровня Middle, нужно освоить экосистему PHP: как подключать библиотеки, как писать код в общепринятом стиле и как использовать фреймворки, не теряя понимания того, что происходит внутри.

    Эта статья про три ключевых компонента современной PHP-разработки:

  • Composer — менеджер зависимостей и автозагрузчик
  • PSR — стандарты, которые позволяют библиотекам работать вместе
  • Фреймворки — готовая инфраструктура для веб-приложений
  • !Как Composer, PSR-4 и пакеты связываются в одном проекте

    Composer

    Что такое зависимость и пакет

    Зависимость — внешняя библиотека, без которой ваш проект не работает или которую вы используете для удобства.

    Пакет — опубликованная библиотека (набор файлов с кодом), которую можно подключить в проект.

    В PHP пакеты чаще всего устанавливают через Composer — стандартный менеджер зависимостей.

    Официальный сайт и документация: Composer

    Каталог пакетов: Packagist

    Зачем Composer в реальной разработке

    Composer решает две базовые задачи:

  • устанавливает и обновляет библиотеки
  • подключает классы автоматически через автозагрузку
  • Без Composer вы быстро приходите к хаосу из ручных require и копирования чужого кода в проект.

    Основные файлы Composer

    #### composer.json

    Это описание вашего проекта:

  • какие пакеты нужны
  • какие версии подходят
  • как настроить автозагрузку
  • Пример минимального composer.json:

    #### composer.lock

    Это зафиксированные версии зависимостей.

    Практическое правило команды:

  • composer.json задаёт какие версии разрешены
  • composer.lock фиксирует какие версии реально установлены
  • Именно composer.lock помогает получить одинаковые зависимости на ноутбуке разработчика, на CI и на проде.

    Установка и обновление зависимостей

    Базовые команды:

  • composer install — установить зависимости строго по composer.lock
  • composer update — подобрать новые версии в рамках ограничений из composer.json и обновить composer.lock
  • Рекомендация для повседневной работы:

  • на сервере и в CI почти всегда используется composer install
  • composer update делают осознанно, обычно отдельным изменением, чтобы контролировать обновления
  • Версионирование и ограничения версий

    Composer использует правила семантического версионирования (идея в том, что версии вида MAJOR.MINOR.PATCH отражают масштаб изменений).

    Документация: Composer: Versions and constraints

    Практический смысл ограничений:

  • ^2.0 обычно означает: можно обновляться в пределах 2.x, но не на 3.0
  • фиксировать версию впритык (например, 2.3.1) стоит редко, когда есть веская причина
  • require и require-dev

    Зависимости делятся на две группы:

  • require — нужно для работы приложения в проде
  • require-dev — нужно для разработки (тесты, линтеры, статанализ)
  • Примеры dev-инструментов:

  • тестирование: PHPUnit
  • статический анализ: PHPStan
  • автоматическое форматирование: PHP CS Fixer
  • Для уровня Middle важно понимать: инструменты качества кода — часть экосистемы и процесса разработки.

    Автозагрузка классов

    Composer генерирует файл vendor/autoload.php. Его обычно подключают один раз в точке входа.

    Пример public/index.php:

    Теперь классы из src/ и из vendor/ будут подгружаться автоматически.

    PSR-4 в Composer: как классы сопоставляются с файлами

    Если у вас настройка:

    то класс App\Http\Response должен лежать примерно здесь:

  • src/Http/Response.php
  • После изменения настроек автозагрузки нужно выполнить:

    Документация: Composer: Autoloading

    Мини-практика: подключаем логгер через Composer

    Одна из типичных задач в веб-приложении — логировать ошибки.

    Установим популярный логгер Monolog:

    Использование:

    ``php <?php

    declare(strict_types=1);

    require __DIR__ . '/vendor/autoload.php';

    use Monolog\Logger; use Monolog\Handler\StreamHandler;

    logger->pushHandler(new StreamHandler(__DIR__ . '/app.log', Logger::INFO));

    _SERVER и php://input напрямую

  • затем делали свой Request и Response
  • PSR-7 предлагает общий контракт, чтобы библиотека роутинга, middleware и ваш код говорили на одном языке
  • Если вы используете фреймворк или микрофреймворк, вы часто косвенно используете эти стандарты.

    PSR-11: контейнер зависимостей

    Контейнер — это объект, который умеет выдавать нужные зависимости (например, PDO, репозитории, сервисы) по запросу.

    Стандарт контейнера: PSR-11

    Связь с прошлой статьёй про Dependency Injection:

  • вы продолжаете передавать зависимости через конструктор
  • контейнер помогает собирать граф объектов в одной точке и не делать это вручную во всех местах
  • Фреймворки

    Что такое фреймворк

    Фреймворк — это набор готовых компонентов и правил, который берёт на себя инфраструктуру приложения.

    Обычно фреймворк предоставляет:

  • роутинг
  • контроллеры и слой HTTP
  • контейнер зависимостей
  • обработку ошибок
  • валидацию
  • работу с базой (в разной степени)
  • миграции и инструменты для CLI
  • Фреймворк не отменяет знания базовых вещей из прошлых статей. Наоборот: чтобы не быть junior, который умеет только нажимать кнопки, важно понимать, как это устроено внутри.

    Два самых популярных фреймворка

    | Фреймворк | Сильные стороны | Когда часто выбирают | | --- | --- | --- | | Laravel | высокая скорость разработки, богатая экосистема | продуктовая разработка, CRUD, быстрый старт | | Symfony | модульность, строгая архитектура, сильные компоненты | крупные системы, сложная доменная логика, долгоживущие проекты |

    Официальные источники:

  • Laravel Documentation
  • Symfony Documentation
  • Что фреймворк делает с вашим кодом

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

    Если вспомнить слои из прошлой статьи:

  • Router и Request/Response чаще всего уже есть
  • Controller остаётся точкой, где вы превращаете HTTP во вызов сервиса
  • Service и Repository остаются вашими: там живут правила и SQL (через PDO или ORM)
  • То есть ваш опыт с архитектурой, исключениями и транзакциями отлично переносится.

    Middleware: полезная техника из экосистемы

    Middleware — это шаг обработки запроса, который можно вставить в цепочку.

    Типичные middleware:

  • аутентификация
  • логирование
  • ограничение частоты запросов (rate limit)
  • CORS
  • обработка ошибок
  • Идея middleware особенно формализована в PSR-15, но встречается и в других реализациях.

    Когда фреймворк не нужен

    Фреймворк — не обязательная цель, а инструмент. Бывают ситуации, когда он избыточен:

  • очень маленький проект
  • внутренний скрипт или CLI-утилита
  • сервис, где важна минимальная зависимость и контроль над каждым слоем
  • Но даже тогда Composer и PSR почти всегда нужны.

    Как выбирать фреймворк и не попасть в ловушку

    Выбор зависит от контекста, но есть практичные критерии:

  • есть ли в команде опыт поддержки выбранного стека
  • насколько важна скорость разработки против гибкости
  • как выглядит экосистема пакетов вокруг фреймворка
  • насколько легко тестировать код и не смешивать HTTP с бизнес-логикой
  • И главный ориентир для Middle: вы должны уметь объяснить, как ваш код проходит путь от HTTP-запроса до SQL-запроса и обратно, независимо от того, фреймворк это или самописный каркас.

    Как связать всё вместе с тем, что вы уже сделали в курсе

    Если представить развитие вашего учебного приложения:

  • Вы начали с одного index.php и _POST.
  • Затем выделили Controller, Service, Repository, добавили исключения.
  • Добавили PDO, транзакции и миграции.
  • Теперь подключаете библиотеки через Composer.
  • Начинаете ориентироваться в PSR и понимаете, почему интерфейсы важны.
  • Переходите к фреймворку, где инфраструктура уже есть, но принципы остаются прежними.
  • Так и выглядит путь от основ до уверенного Middle: вы не просто пишете PHP-код, вы строите поддерживаемую систему в индустриальном окружении.

    Итоги

    Вы освоили базовые элементы современной экосистемы PHP:

  • Composer как стандарт управления зависимостями, автозагрузкой и воспроизводимостью окружения через composer.lock
  • PSR как общий язык для стиля кода, автозагрузки и взаимодействия библиотек (логирование, HTTP, middleware, контейнер)
  • роль фреймворков и то, как они накладываются на знакомую вам слоистую архитектуру
  • Дальше по курсу логично углубляться в практику: DI-контейнер, конфигурация, логирование, тестирование, а затем собрать полноценное API или веб-приложение на одном из фреймворков с хорошей архитектурой.

    5. Качество и продакшен: тестирование, безопасность, деплой

    Качество и продакшен: тестирование, безопасность, деплой

    Связь с предыдущими темами

    Ранее в курсе вы научились:

  • принимать и формировать HTTP-запросы и ответы
  • разделять код на слои (контроллер, сервис, репозиторий), использовать ООП и исключения
  • работать с данными через SQL, PDO, транзакции и миграции
  • подключать зависимости через Composer и ориентироваться в PSR
  • Следующий шаг до уровня Middle: сделать так, чтобы приложение было предсказуемым, безопасным и готовым к продакшену. Это означает:

  • ошибки ловятся и диагностируются
  • изменения проверяются тестами и анализаторами
  • секреты не хранятся в коде
  • деплой повторяемый и контролируемый
  • !Как изменение проходит путь от коммита до продакшена

    Качество: что это в PHP-проекте

    Качество в веб-приложении обычно сводится к трём вещам:

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

  • тесты на ключевую бизнес-логику
  • автоматическая проверка стиля и типизации
  • безопасная обработка ввода и правильная работа с сессиями
  • понятный процесс деплоя (включая миграции)
  • Тестирование

    Зачем тесты, если можно проверить руками

    Ручная проверка не масштабируется:

  • легко забыть сценарий
  • сложно проверить регрессии
  • невозможно быстро убедиться, что рефакторинг ничего не сломал
  • Тесты дают быстрое подтверждение, что ключевые правила системы не нарушились.

    Виды тестов и что ими проверять

    | Вид теста | Что проверяет | Что обычно мокают/подменяют | Скорость | | --- | --- | --- | --- | | Unit | один класс или функция | БД, сеть, время | высокая | | Integration | связку компонентов | минимум подмен, чаще реальная БД | средняя | | End-to-end | приложение целиком через HTTP | ничего, это “почти прод” | низкая |

    Практическая рекомендация для учебного проекта из этого курса:

  • unit-тестами покрыть сервисы и Value Object
  • интеграционными тестами покрыть репозитории (PDO + реальная схема)
  • end-to-end ограничить парой smoke-тестов, если вообще делать
  • !Пирамида тестов и баланс по количеству

    Как архитектура из прошлых статей помогает тестировать

    Если у вас:

  • контроллер отвечает только за HTTP
  • сервис содержит бизнес-правила
  • репозиторий содержит SQL и PDO
  • то тестирование становится проще:

  • сервис тестируется без HTTP и без БД
  • репозиторий тестируется отдельно, на подготовленной базе
  • Главный принцип: чем меньше у тестируемого кода скрытых зависимостей, тем проще тесты.

    Unit-тест на сервис: пример

    Представим сервис, который создаёт задачу и требует валидный заголовок.

    Unit-тест делает репозиторий “фейковым”, чтобы не трогать БД.

    php <?php

    pdo->prepare('SELECT id, email FROM users WHERE email = :email'); email]); php <?php

    userInput, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); php <?php

    session_start();

    if (!isset(_SESSION['csrf'] = bin2hex(random_bytes(16)); }

    _POST['csrf'] ?? ''; if (!hash_equals(token)) { http_response_code(403); echo 'CSRF validation failed'; exit; } php <?php

    password, PASSWORD_DEFAULT);

    if (!password_verify(hash)) { // неверный пароль } php <?php

    session_set_cookie_params([ 'httponly' => true, 'secure' => true, 'samesite' => 'Lax', ]);

    session_start(); php <?php

    session_regenerate_id(true); php <?php

    declare(strict_types=1);

    try { // обработка запроса } catch (InvalidArgumentException e) { // здесь должен быть логгер http_response_code(500); echo 'Internal Server Error'; } ```

    Итоги

    Теперь у вас есть набор практик, которые отличают “код работает у меня” от “код живёт в продакшене”:

  • тестирование: unit и integration как основа уверенных изменений
  • автоматические проверки: статический анализ и единый стиль
  • безопасность: защита от SQL-инъекций, XSS, CSRF, правильная работа с паролями и сессиями
  • продакшен-подход: конфигурация через окружение, логирование, health-check, повторяемый деплой и миграции
  • Эти навыки напрямую усиливают всё, что вы уже сделали в курсе: слои, исключения, PDO и Composer превращаются в основу приложения, которое можно поддерживать и развивать как инженерный продукт.