PHP для начинающих: с нуля до Junior-разработчика

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

1. Основы PHP и синтаксис: переменные, типы, функции

Основы PHP и синтаксис: переменные, типы, функции

Что такое PHP и где он выполняется

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

Важно понимать базовую идею:

  • Пользователь открывает страницу в браузере.
  • Браузер отправляет HTTP-запрос на сервер.
  • Сервер запускает PHP-код.
  • PHP-код формирует результат (например, HTML) и возвращает его браузеру.
  • > PHP-код выполняется на сервере, а не в браузере. Браузер видит только результат выполнения.

    Официальная документация: PHP Manual (RU)

    Как писать и запускать PHP

    Минимальный пример

    Файл обычно имеет расширение index.php.

    Теги PHP

    * PHP-код пишется внутри <?php ... ?>. * Если файл содержит только PHP-код, закрывающий тег ?> часто опускают (это снижает риск случайного вывода пробелов).

    Инструкции и ;

    Большинство инструкций в PHP заканчиваются точкой с запятой ;.

    Комментарии

    Переменные

    Объявление и присваивание

    В PHP переменные начинаются со знака age = 20; name = "Иван"; name и user * _token * firstName = "Иван"; firstName . " " . name = "Иван"; echo "Привет, name = "Иван"; echo 'Привет, .

    Типы данных

    PHP — язык с динамической типизацией: тип переменной определяется по присвоенному значению.

    ``php <?php x = "10"; // string a = 10; | | Скалярные | float | c = "text"; | | Скалярные | bool | e = [1, 2, 3]; | | Составные | object | (позже в курсе) | | Специальные | null | value = "123";

    var_dump(strNumber = "100";

    strNumber; var_dump(a, int a + name): void { echo "Привет, a, int a + result = sum(2, 3); echo name, string prefix, name, int name (numbers): int { return array_sum(x = 10;

    function showX(): void { // echo у переменной: name = "Иван"; вместо name'. * Путают = (присваивание) и ==/=== (сравнение) — сравнения подробно будут в следующих статьях. * Не понимают, почему переменная «не видна» внутри функции — это область видимости.

    Куда дальше

    В этой статье вы освоили базовый синтаксис PHP, переменные, типы и функции — это фундамент, на который будет опираться всё остальное.

    Дальше логично перейти к:

    * операторам и выражениям (арифметика, сравнение, логика) * условиям if/else и конструкции switch * циклам for/while/foreach

    Эти темы позволят писать управляемую логику, а затем вы перейдёте к массивам, строкам, работе с формами и основам веб-разработки на PHP.

    2. Веб-разработка на PHP: HTTP, формы, сессии, cookies

    Веб-разработка на PHP: HTTP, формы, сессии, cookies

    Как PHP «видит» веб

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

  • входные данные приходят в виде строк (а значит, типы нужно контролировать)
  • данные запроса доступны через массивы (суперглобальные массивы)
  • повторяющуюся логику удобно оформлять в функции (валидация, нормализация, преобразования)
  • Ключевая идея: веб-приложение — это обработка HTTP-запросов и формирование HTTP-ответов.

    !Диаграмма жизненного цикла HTTP-запроса и ответа

    HTTP простыми словами

    HTTP — протокол, по которому клиент (например, браузер) общается с сервером.

    Любое взаимодействие состоит из двух частей:

  • Запрос (request): метод, путь, параметры, заголовки, иногда тело.
  • Ответ (response): статус-код, заголовки, тело.
  • Полезные справочники:

  • HTTP overview (MDN)
  • HTTP response status codes (MDN)
  • Методы HTTP, которые нужны новичку

    | Метод | Для чего обычно используют | Где данные | |---|---|---| | GET | получить страницу или данные | в URL (query string) | | POST | отправить данные (создать/изменить) | в теле запроса |

    Важно: GET и POST — это не про «безопасно/небезопасно», а про смысл операции и способ передачи данных.

    Статус-коды ответа

    | Код | Значение | Пример ситуации | |---|---|---| | 200 | успешно | страница отдана | | 302 | перенаправление | после успешной отправки формы | | 400 | ошибка запроса | невалидные входные данные | | 401 | не авторизован | нужна авторизация | | 403 | запрещено | нет прав | | 404 | не найдено | неверный путь | | 500 | ошибка сервера | исключение/фатальная ошибка |

    Суперглобальные массивы PHP: где лежат данные запроса

    В веб-режиме PHP предоставляет готовые массивы (они доступны «из коробки»):

  • _POST — данные, отправленные методом POST
  • _SESSION — данные сессии (после запуска сессии)
  • _GET
  • URL может выглядеть так:

    /search.php?q=php&page=2

    Тогда в PHP:

    Обратите внимание:

  • если ключа нет, будет ошибка уровня notice, поэтому используйте ?? (оператор объединения с null)
  • значения приходят строками, даже если выглядят как числа
  • Пример: безопасное приведение типов для параметров

    php <?php

    declare(strict_types=1);

    _POST['email'] ?? ''; _POST['password'] ?? '';

    var_dump(password); php <?php

    declare(strict_types=1);

    function isValidEmail(string email = trim(email, FILTER_VALIDATE_EMAIL) !== false; }

    function isNonEmpty(string value) !== ''; }

    _POST['email'] ?? ''; _POST['password'] ?? '';

    email)) { password)) { errors); php <?php

    declare(strict_types=1);

    if (theme = theme;

    Безопасность сессий: базовые правила

  • После входа пользователя обновляйте идентификатор сессии:
  • php <?php

    declare(strict_types=1);

    _GET['name'] ?? ''; name, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');

    echo _GET, _COOKIE, _SERVER.

    Куда дальше

    Теперь вы понимаете, как PHP работает в веб-контексте:

  • что такое HTTP и методы GET/POST`
  • как читать данные запроса через суперглобальные массивы
  • как устроены cookies и сессии
  • почему важны базовые меры безопасности
  • Следующий логичный шаг — углубиться в управляющие конструкции и массивы на практике (условия, циклы, обработка коллекций), потому что обработка форм и запросов почти всегда сводится к разбору массивов данных, проверкам и ветвлениям логики.

    3. Работа с данными: файлы, JSON, MySQL и PDO

    Работа с данными: файлы, JSON, MySQL и PDO

    Зачем это нужно после HTTP, форм, cookies и сессий

    В предыдущих статьях вы научились принимать данные из запроса (_POST) и хранить состояние пользователя через cookies и сессии. Следующий шаг — сохранять данные надолго и обмениваться данными между системами.

    В PHP это чаще всего делают так:

  • Файлы — быстро и просто для логов, конфигов, временных данных
  • JSON — стандартный формат обмена данными и хранения структур
  • MySQL — база данных для надёжного долговременного хранения
  • PDO — универсальный и безопасный способ работать с БД в PHP
  • !Схема показывает, куда в PHP-приложении обычно попадают данные и где они хранятся

    Работа с файлами

    Файл — это самый простой способ сохранить данные на диске сервера. Для новичка важно помнить:

  • путь к файлу считается от текущей папки скрипта (если не указан абсолютный путь)
  • операции чтения/записи могут завершиться ошибкой (нет прав, файла нет, диск недоступен)
  • входные данные из веба — недоверенные, нельзя бездумно превращать их в пути файлов
  • Документация:

  • file_get_contents
  • file_put_contents
  • Быстрое чтение файла целиком

    Добавление в файл (например, лог)

    Чтобы не перетирать файл, используйте флаг FILE_APPEND.

    Чтение и запись построчно (когда файл большой)

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

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

  • fopen
  • fgets
  • fclose
  • Типичные ошибки новичков при работе с файлами

  • чтение/запись без проверок на false
  • запись пользовательского ввода в путь файла (риск подмены пути)
  • использование относительных путей без __DIR__
  • JSON: хранение структур и обмен данными

    JSON — текстовый формат, который описывает объекты и массивы. Его любят в вебе, потому что:

  • его удобно читать человеку
  • он стандартно используется в API
  • в PHP есть встроенные функции для кодирования и декодирования
  • Документация:

  • json_encode
  • json_decode
  • Превращаем массив в JSON

    Разбор ошибок JSON

    Если JSON пришёл «битым», важно увидеть причину.

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

  • json_last_error_msg
  • Пример: храним настройки в JSON-файле

    Почему важно использовать prepared statements

    Если вы склеиваете SQL-строку с пользовательским вводом, вы открываете дверь для SQL-инъекции.

    Неправильно:

    Здесь :email — именованный параметр, а массив в execute — значения параметров.

    INSERT: добавить запись

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

  • password_hash
  • PDO::lastInsertId
  • UPDATE и DELETE: изменить и удалить

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

  • PDOStatement::rowCount
  • Транзакции: когда нужно «всё или ничего»

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

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

  • PDO::beginTransaction
  • PDO::commit
  • PDO::rollBack
  • php <?php

    declare(strict_types=1);

    session_start();

    function isValidEmail(string email = trim(email, FILTER_VALIDATE_EMAIL) !== false; }

    if (email = password = errors = [];

    if (!isValidEmail(errors[] = 'Некорректный email'; }

    if (trim(errors[] = 'Пароль пустой'; }

    if (_SESSION['errors'] = passwordHash = password_hash(stmt = stmt->execute(['email' => passwordHash]);

    $_SESSION['flash'] = 'Регистрация успешна'; header('Location: /login.php'); exit; ```

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

    Куда двигаться дальше

    Вы научились трём ключевым способам работы с данными в PHP:

  • через файловую систему
  • через JSON как формат структур
  • через MySQL, используя PDO и prepared statements
  • Следующие логичные темы для уровня Junior:

  • проектирование таблиц и индексы (как хранить данные правильно)
  • обработка ошибок и логирование
  • архитектура: разбиение кода на слои (контроллеры, сервисы, репозитории)
  • безопасность веб-приложений (XSS, CSRF, управление доступом) на практике
  • 4. ООП в PHP: классы, наследование, интерфейсы, автозагрузка

    ООП в PHP: классы, наследование, интерфейсы, автозагрузка

    Зачем вам ООП после базового PHP, веба и PDO

    В первых темах вы писали PHP как набор инструкций и функций, а затем научились:

  • принимать запросы (_POST), работать с cookies и сессиями
  • валидировать ввод и защищаться от базовых веб-уязвимостей
  • сохранять данные в файлы, JSON и MySQL через PDO
  • Когда логики становится больше, код начинает расползаться по файлам: часть отвечает за валидацию, часть за доступ к БД, часть за вывод, часть за работу с сессией. ООП (объектно-ориентированное программирование) помогает собирать код в понятные блоки ответственности.

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

    Полезные источники:

  • Документация PHP: Классы и объекты
  • Документация PHP: Автозагрузка классов
  • Класс и объект: основная идея

    Класс — это описание (шаблон). Объект — конкретный экземпляр этого шаблона.

    Пример: класс User описывает, какие данные есть у пользователя и что можно с ним делать. Объект new User(...) — конкретный пользователь.

    Минимальный класс

    Здесь:

  • public означает, что свойство доступно снаружи
  • int и string — типы свойств (современный PHP активно использует типизацию)
  • Конструктор и инварианты

    Часто объект должен быть создан сразу в корректном состоянии. Для этого используют конструктор __construct.

    Здесь свойства private, то есть:

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

    Видимость: public, protected, private

    | Модификатор | Доступ откуда | Когда использовать | |---|---|---| | public | отовсюду | публичный API класса | | protected | внутри класса и наследников | когда наследникам нужно использовать деталь реализации | | private | только внутри класса | когда деталь реализации нельзя трогать извне |

    Практическое правило: начинайте с private и повышайте доступность только если есть понятная причина.

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

  • Документация PHP: Область видимости
  • Статические методы и константы класса

    Константы

    Константа класса хранит значение, не привязанное к конкретному объекту.

    static

    static-методы вызываются без создания объекта.

    Практическая оговорка:

  • static удобен для небольших утилит
  • для бизнес-логики чаще лучше обычные объекты и зависимости, потому что их проще тестировать и заменять
  • Наследование: extends, переопределение и final

    Наследование — когда один класс расширяет другой: наследник получает свойства и методы родителя.

    Важная практика: композиция часто лучше наследования

    Наследование удобно, когда отношения реально типа это является.

  • AdminUser является User
  • HttpException является Exception
  • Но если отношения скорее это использует, обычно лучше композиция:

  • UserService использует UserRepository
  • Композиция делает код гибче и уменьшает связность.

    !Схема связей: зависимости через интерфейс и композицию

    Интерфейсы: контракт поведения

    Интерфейс задаёт набор методов, которые класс обязан реализовать. Это способ договориться о поведении без привязки к конкретному классу.

    Смысл разделения:

  • UserRepository отвечает только за SQL и структуру таблиц
  • UserService отвечает за правила регистрации
  • LoggerInterface позволяет заменить логгер без переписывания сервиса
  • Это тот стиль, который потом легко переносится в фреймворки.

    Пространства имён (namespaces): чтобы классы не конфликтовали

    Когда проект растёт, классы с одинаковыми именами начинают конфликтовать. Для этого в PHP есть пространства имён.

    Использование класса из другого пространства имён:

    Что здесь происходит:

  • Вы регистрируете функцию автозагрузки.
  • Когда PHP не находит класс, он вызывает автозагрузчик.
  • Автозагрузчик превращает имя класса в путь к файлу и делает require.
  • Документация:

  • Документация PHP: spl_autoload_register
  • !Пошаговый процесс автозагрузки классов

    Стандарт де-факто: Composer и PSR-4

    В реальных проектах автозагрузку почти всегда делает Composer.

  • вы описываете правило соответствия namespace → папка
  • Composer генерирует файл автозагрузчика
  • Стандарт, по которому обычно строят соответствие, называется PSR-4.

  • PSR-4: Autoloader (PHP-FIG)
  • Composer: Autoloading
  • Пример composer.json:

    Дальше (в терминале):

    И в вашем public/index.php:

    Частые ошибки новичков в ООП

  • Делать все свойства public и менять состояние объекта отовсюду.
  • Смешивать ответственность: класс и валидирует, и ходит в БД, и рисует HTML.
  • Злоупотреблять наследованием там, где лучше композиция.
  • Писать require для каждого файла вместо автозагрузки.
  • Игнорировать пространства имён и получать конфликты имён классов.
  • Куда дальше

    Теперь у вас есть базовый набор инструментов ООП в PHP:

  • классы, свойства, методы, конструкторы и видимость
  • наследование и переопределение
  • интерфейсы как способ писать расширяемый код
  • пространства имён и автозагрузка, включая подход Composer + PSR-4
  • Следующий логичный шаг для уровня Junior — научиться собирать эти знания в структуру проекта: разделять слой HTTP (контроллеры), бизнес-логику (сервисы) и доступ к данным (репозитории), а также аккуратно обрабатывать ошибки и логировать события.

    5. Практика Junior: безопасность, Composer, тестирование, мини-проект

    Практика Junior: безопасность, Composer, тестирование, мини-проект

    Что вы уже умеете и что прокачаем в этой теме

    В предыдущих уроках вы прошли цепочку, которая встречается в реальных PHP-проектах:

  • основы синтаксиса, типов и функций
  • веб-контекст: HTTP, формы, сессии, cookies
  • хранение данных: файлы, JSON, MySQL + PDO
  • ООП: классы, интерфейсы, пространства имён и автозагрузка
  • В этой статье вы соберёте навыки уровня Junior, которые отличают «код, который работает» от «кода, который можно поддерживать»:

  • базовая безопасность веб-приложений по умолчанию
  • Composer как стандарт управления зависимостями и автозагрузкой
  • тестирование логики (минимум, который реально применяют)
  • мини-проект: структура, слои, точки расширения
  • !Схема слоёв мини‑проекта и направлений зависимостей

    Безопасность: минимум, который должен быть в каждом проекте

    Безопасность в PHP — это не «набор трюков», а привычка: любые внешние данные считаем недоверенными, а выход на страницу — потенциально опасным.

    Полезные источники:

  • OWASP Top 10
  • PHP Manual: Security
  • Валидация входа и нормализация

    Данные из _POST почти всегда приходят строками, поэтому вы делаете два шага:

  • нормализация: trim, приведение типов, приведение регистра, удаление лишних пробелов
  • валидация: проверки формата и допустимых значений
  • Пример: аккуратно достать число страницы из pageRaw = page = (int) page < 1) { value): string { return htmlspecialchars(name = name); php <?php

    declare(strict_types=1);

    _POST['email'] ?? '';

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

    stmt->fetch(); php <?php

    declare(strict_types=1);

    password, PASSWORD_DEFAULT);

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

    declare(strict_types=1);

    session_start();

    if (_SESSION['user_id'] = _SESSION['_csrf'])) { _SESSION['_csrf']; }

    function csrfCheck(?string _SESSION['_csrf'])) { return false; }

    if (!is_string(token === '') { return false; }

    return hash_equals(token); } bash composer --version bash composer init json { "name": "app/mini-project", "require": { "php": ">=8.1" }, "autoload": { "psr-4": { "App\\": "src/" } } } bash composer dump-autoload php <?php

    declare(strict_types=1);

    require __DIR__ . '/../vendor/autoload.php'; bash composer require vendor/package bash composer require --dev vendor/package bash composer require --dev phpunit/phpunit php <?php

    declare(strict_types=1);

    namespace App\Contracts;

    interface UserRepositoryInterface { public function findByEmail(string email, string message): void; } php <?php

    declare(strict_types=1);

    namespace App\Services;

    use App\Contracts\LoggerInterface; use App\Contracts\UserRepositoryInterface; use InvalidArgumentException; use RuntimeException;

    final class UserService { public function __construct( private UserRepositoryInterface logger, ) { }

    public function register(string password): int { email);

    if (filter_var(password) === '') { throw new InvalidArgumentException('Пароль пустой'); }

    if (email) !== null) { throw new RuntimeException('Пользователь уже существует'); }

    password, PASSWORD_DEFAULT); this->users->create(hash);

    id);

    return usersByEmail = []; private int email): ?array { return email] ?? null; }

    public function create(string passwordHash): int { this->id++; email] = ['id' => email, 'hash' => id; } }

    final class NullLogger implements LoggerInterface { public function info(string service = new UserService(new InMemoryUsers(), new NullLogger());

    service->register('not-an-email', 'secret'); }

    public function testRegisterCreatesUser(): void { id = this->assertSame(1, _SERVER['REQUEST_URI'].

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

    Это не «идеально», но это хороший учебный шаг: вы видите границы между HTTP и логикой.

    Сервисный слой: правила вместо скриптов

    Рекомендуемая практика:

  • всё, что можно назвать «правилами», выносить в сервисы
  • сервисы получают зависимости (репозитории, логгеры) через конструктор
  • Примеры сервисов мини-проекта:

  • AuthService: регистрация, вход, работа с сессией
  • NotesService: создать заметку, удалить заметку, получить список
  • Репозитории: только доступ к данным

    Репозитории инкапсулируют PDO и SQL:

  • UserRepositoryPdo
  • NoteRepositoryPdo
  • Такой код проще:

  • тестировать (можно подменить интерфейс)
  • переписать (например, поменять структуру таблиц)
  • Шаблоны: безопасный вывод и CSRF

    Пример фрагмента формы (только идея):

  • выводить значения через e(...)
  • добавлять скрытое поле _csrf
  • CSRF-токен вы берёте из функции csrfToken() и вставляете в форму.

    Чеклист «готовности» мини-проекта

  • везде, где выводится пользовательский текст, используется htmlspecialchars
  • все SQL-запросы с пользовательскими параметрами сделаны через prepare
  • все формы, которые меняют данные, защищены CSRF-токеном
  • после успешного POST используется паттерн POST-Redirect-GET
  • Composer подключён, классы грузятся через PSR-4
  • есть хотя бы 2 теста на сервисный слой
  • Куда двигаться дальше после этой практики

    Когда мини-проект собран и работает, вы уже близки к Junior-уровню. Следующие логичные шаги:

  • добавить централизованную обработку ошибок и логирование
  • добавить конфигурацию окружения (например, параметры БД) через отдельный конфиг
  • подключить статический анализатор и форматтер (когда почувствуете потребность)
  • перейти на фреймворк (Laravel или Symfony), чтобы увидеть те же принципы на «боевом» каркасе