PHP с нуля: веб-разработка и интеграция с ИИ

Курс проведёт вас от базового синтаксиса PHP до разработки веб-приложений и работы с внешними API. Вы научитесь подключать ИИ-модели (например, через OpenAI-совместимые API), строить чат-функции и применять векторный поиск для RAG-сценариев.

1. Введение в PHP и настройка окружения

Введение в PHP и настройка окружения

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

В этом курсе мы начнём с базовой настройки окружения и первого запуска PHP, чтобы дальше уверенно перейти к веб-разработке, работе с базами данных, API и интеграции с ИИ-сервисами.

Что такое PHP и как он работает

Где выполняется PHP

Код PHP обычно выполняется на сервере, а не в браузере. Это главное отличие от JavaScript, который часто работает внутри браузера.

!Схема показывает, что PHP выполняется на сервере и возвращает результат в браузер

Ключевые понятия простыми словами

  • Интерпретатор PHP — программа, которая читает ваш PHP-код и выполняет его.
  • Сервер — программа, которая принимает запросы от браузера и отдаёт ответы. Для разработки подойдёт даже встроенный сервер PHP.
  • Локальная разработка — когда вы запускаете проект на своём компьютере, не публикуя его в интернет.
  • CLI — запуск программ из командной строки (Terminal на macOS/Linux, PowerShell/Windows Terminal на Windows). PHP можно запускать как для веба, так и из CLI.
  • Что нужно установить для старта

    Минимальный набор:

  • PHP (желательно актуальную версию из ветки 8.x)
  • Редактор кода
  • (Скоро понадобится) Composer — менеджер зависимостей для PHP-проектов
  • Рекомендуемый редактор кода:

  • Visual Studio Code — бесплатный, популярный, удобный для PHP
  • Полезное расширение для VS Code:

  • PHP Intelephense — подсказки кода, навигация, базовая проверка
  • Установка PHP

    Ниже несколько рабочих вариантов. Выберите один — тот, который проще для вашей системы.

    Windows

    #### Вариант A: XAMPP (проще всего для новичка)

    XAMPP ставит сразу PHP и сервер Apache.

  • Скачайте установщик с сайта XAMPP.
  • Установите XAMPP.
  • Запустите панель XAMPP и включите Apache.
  • Папка сайта обычно: C:\xampp\htdocs.
  • Плюсы:

  • быстро стартовать
  • Минусы:

  • среда «монолитная», позже многие переходят на Composer + встроенный сервер или Docker
  • #### Вариант B: Установка PHP отдельно

    Это удобнее для обучения современному подходу (CLI + встроенный сервер).

  • Скачайте PHP для Windows с сайта PHP.
  • Распакуйте архив, например в C:\php.
  • Добавьте C:\php в переменную окружения Path, чтобы команда php работала из терминала.
  • macOS

  • Установите Homebrew (если ещё не установлен) по инструкции: Homebrew.
  • Установите PHP:
  • Linux (Ubuntu/Debian)

  • Обновите списки пакетов:
  • Установите PHP:
  • Примечание: в репозиториях может быть не самая свежая версия. Для старта это нормально, но в курсе мы будем ориентироваться на PHP 8.x.

    Проверка установки

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

    Вы должны увидеть версию PHP и служебную информацию. Если команда не найдена, значит PHP не установлен или не добавлен в PATH.

    Первый проект и первый запуск

    Создайте папку проекта, например php-course и внутри файл index.php.

    Содержимое index.php:

    Запуск через встроенный сервер PHP

  • Откройте терминал в папке проекта.
  • Запустите сервер:
  • Откройте в браузере:
  • http://localhost:8000
  • Вы увидите текст Привет, PHP!.

    Что здесь произошло

  • php -S запустил локальный веб-сервер для разработки.
  • Когда браузер запросил /, сервер отдал файл index.php.
  • PHP выполнил код и вернул результат в ответ.
  • Как устроен проект на старте

    Минимальная структура может быть такой:

  • php-course/
  • - index.php

    Позже, когда мы начнём собирать более серьёзные приложения и подключать библиотеки, структура станет богаче (появятся папки src, public, файлы конфигурации и Composer-зависимости).

    Установка Composer (подготовка к следующим темам)

    Composer нужен, чтобы устанавливать внешние библиотеки и автозагружать классы в проектах. Это стандарт де-факто в PHP.

    Сайт Composer:

  • Composer
  • Проверка после установки:

    Если команда не найдена:

  • на Windows проверьте, что установщик Composer добавил его в PATH
  • на macOS/Linux убедитесь, что установка завершилась без ошибок
  • Типичные проблемы и быстрые решения

  • Команда php не найдена
  • - PHP не установлен или не добавлен в PATH. - Решение: переустановить или добавить путь к PHP в переменные окружения.

  • Порт занят при запуске php -S localhost:8000
  • - Другой процесс уже использует порт 8000. - Решение: выбрать другой порт, например:

  • Открывается список файлов вместо выполнения PHP
  • - Вы открыли index.php как файл напрямую (file:///...), а не через сервер. - Решение: запускать через php -S ... и открывать http://localhost:....

    Что дальше по курсу

    Дальше мы:

  • разберём синтаксис PHP и базовые конструкции
  • научимся принимать данные от пользователя (формы, параметры URL)
  • перейдём к базам данных и API
  • подготовим основу для интеграции с ИИ: HTTP-запросы, работа с JSON, ключи доступа, обработка ошибок
  • 2. Синтаксис PHP: типы, условия, циклы, функции

    Синтаксис PHP: типы, условия, циклы, функции

    В прошлой статье вы установили PHP и запустили первый файл через встроенный сервер php -S. Теперь разберём базовый синтаксис языка: какие бывают типы данных, как писать условия и циклы, как создавать функции. Это фундамент, без которого дальше невозможно уверенно обрабатывать запросы, работать с JSON и вызывать внешние API (включая ИИ-сервисы).

    Как писать PHP-код

    PHP-код обычно находится в файлах с расширением .php и начинается с <?php.

    Несколько практических правил:

  • Каждое выражение обычно заканчивается ;.
  • Комментарии бывают однострочные // и многострочные / ... /.
  • Имена переменных начинаются с name = "Аня";
  • echo age = 20; title = "PHP"; nothing = null;

    var_dump(price, isAdmin, name = "Маша";

    echo "Привет, name'; // Привет, first = "Иван"; first . " " . colors = ["red", "green", "blue"];

    echo user = [ "id" => 10, "name" => "Аня", "is_admin" => false, ];

    echo payload = [ "model" => "gpt-4.1-mini", "input" => [ ["role" => "user", "content" => "Привет!"], ], ];

    var_dump(a + a . a == a === a && x ?? "default" |

    ?? часто используется при разборе входных данных.

    switch

    Подходит, когда нужно сравнить одно значение с набором вариантов.

    Важно: без break выполнение продолжится в следующий case.

    match в PHP 8+

    match часто удобнее switch:

  • сравнение строгое, как ===
  • не нужен break
  • возвращает значение
  • Документация: match.

    !Блок-схема показывает, как работает ветвление if/else

    Циклы

    Циклы позволяют выполнять код многократно.

    for

    Используется, когда заранее известны границы.

    while

    Выполняется, пока условие истинно.

    do...while

    Отличие в том, что тело выполнится хотя бы один раз.

    foreach для массивов

    Самый частый цикл в PHP.

    Для ассоциативного массива:

    break и continue

  • break завершает цикл.
  • continue пропускает текущую итерацию.
  • Функции

    Функция — это именованный блок кода, который можно вызывать много раз.

    Объявление и вызов

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

  • string text, string prefix . " " . host, int useTls): string
  • { return port . " tls=" . (numbers): int { numbers as total += total; }

    echo sum(1, 2, 3); php <?php

    squared = array_map(function (int n * numbers);

    var_dump(factor = 10; scaled = array_map(fn (int n * numbers);

    var_dump(x = 10;

    function demo(): void { // echo x не определён внутри функции x; }

    demo(); php <?php

    ids = [1, 2, 3];

    id) use (prefix . ids);

    var_dump(user): string { user["name"] ?? "(без имени)"; user["age"] ?? null;

    age === null) ? "возраст неизвестен" : ("возраст " . name . ", " . users = [ ["name" => "Аня", "age" => 20], ["name" => "Петя"], ];

    foreach (u) { echo formatUser($u); } ``

    Что дальше

    Следующий шаг после синтаксиса — научиться принимать ввод пользователя и данные запроса: параметры URL, формы, JSON. Это напрямую ведёт к веб-разработке и к интеграциям с ИИ, где вы будете:

  • собирать массивы с данными запроса
  • превращать их в JSON
  • отправлять HTTP-запросы
  • разбирать ответы и обрабатывать ошибки
  • 3. Работа с данными: массивы, строки, файлы, JSON, HTTP

    Работа с данными: массивы, строки, файлы, JSON, HTTP

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

  • структурировать данные в массивах
  • обрабатывать строки
  • читать и писать файлы
  • кодировать и декодировать JSON
  • отправлять HTTP-запросы к внешним API
  • Это напрямую подготовит вас к интеграции с ИИ: почти все ИИ-сервисы принимают запросы по HTTP и используют JSON для тела запроса и ответа.

    !Схема показывает, как данные проходят через HTTP и JSON между клиентом, вашим PHP и внешним API

    Массивы как основной формат данных

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

    Документация: Массивы в PHP

    Частые операции со списками

    Частые операции со словарями

    Безопасное чтение значений

    Частая ошибка новичков: обращаться к ключу, которого нет. Безопаснее использовать ??.

    Строки: очистка, сборка, разбиение

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

    Конкатенация и шаблоны

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

  • explode
  • implode
  • Важный нюанс: длина строки и UTF-8

    Если вы работаете с русским текстом, то strlen считает байты, а не символы. Для корректного подсчёта символов используйте mb_strlen.

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

  • strlen
  • mb_strlen
  • Документация: file_exists

    Запись файла целиком

    Частая практика: хранить данные в JSON-файле

    JSON: кодирование, декодирование, обработка ошибок

    JSON в PHP обычно превращается в массивы, а затем обратно.

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

  • json_encode
  • json_decode
  • json_encode: из массива в JSON-строку

    Полезные флаги:

  • JSON_UNESCAPED_UNICODE не превращает русские символы в \uXXXX
  • JSON_PRETTY_PRINT делает красивое форматирование для чтения человеком
  • json_decode: из JSON-строки в массив

    Если передать вторым аргументом true, вы получите ассоциативные массивы, а не объекты.

    Важные практики для API и ИИ-интеграций

  • Всегда ставьте таймауты (CURLOPT_TIMEOUT), иначе запрос может зависнуть
  • Проверяйте HTTP-статус, а не только факт, что запрос выполнился
  • Логируйте ответы при ошибках, но не логируйте секреты (API-ключи)
  • Обрабатывайте JSON-ошибки, особенно если работаете с внешними сервисами
  • Что дальше

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

    Вы будете разбирать:

  • параметры URL
  • данные форм
  • JSON-тела входящих запросов
  • И затем объедините это с темой этой статьи: будете принимать данные, превращать их в JSON и отправлять в внешние API, включая ИИ-сервисы.

    4. Веб-разработка на PHP: формы, сессии, куки, безопасность

    Веб-разработка на PHP: формы, сессии, куки, безопасность

    В прошлых статьях вы научились писать базовый PHP-код, работать с массивами и JSON, а также отправлять HTTP-запросы к внешним API. Теперь сделаем следующий шаг к реальной веб-разработке: научимся принимать данные от пользователя (как это делает любая форма), хранить состояние между запросами (сессии и куки) и делать всё это безопасно.

    Ключевая идея: HTTP-запросы по своей природе не помнят прошлые действия пользователя. Поэтому состояние (например, логин) обычно реализуют через сессии и куки.

    !Как формы, куки и сессии связывают несколько HTTP-запросов в одно пользовательское взаимодействие

    Как PHP получает данные запроса

    Когда пользователь отправляет данные (через форму, ссылку или API-клиент), PHP получает их через суперглобальные массивы.

    Основные источники:

  • _POST — данные тела запроса для application/x-www-form-urlencoded и multipart/form-data
  • _SERVER — информация о запросе и окружении
  • Документация:

  • Суперглобальные переменные
  • _POST
  • _SERVER
  • Быстрый локальный стенд

    Запустите встроенный сервер (как в первой статье):

    Создайте файл index.php и временно выводите базовую информацию о запросе:

    Формы на практике: GET и POST без HTML-разметки

    В браузере данные формы обычно уезжают на сервер как GET или POST. В этой статье мы сфокусируемся на серверной части: как эти данные читать, проверять и обрабатывать. (HTML-разметку формы мы не приводим, чтобы сосредоточиться на PHP и HTTP.)

    GET: параметры в URL

    Запрос вида:

  • http://localhost:8000/search.php?q=php&limit=5
  • Будет доступен в q = limitRaw = limit = filter_var(limit === false) { q = trim(q\n"; echo "limit=_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'POST') { echo "Use POST\n"; exit; }

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

    email);

    if (!filter_var(password) < 8) { echo "Password too short\n"; exit; }

    echo "OK: email=_GET, _COOKIE могут быть любыми. Практика:

  • проверяйте наличие ключей через ??
  • валидируйте тип и формат
  • задавайте значения по умолчанию
  • XSS: опасность вывода пользовательского текста

    XSS возникает, когда вы выводите пользовательский ввод так, что браузер интерпретирует его как код. Даже если вы не пишете сложные интерфейсы, правило простое:

  • если выводите пользовательский текст, применяйте экранирование
  • В PHP для экранирования в HTML-контексте обычно используют htmlspecialchars.

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

  • htmlspecialchars
  • Важно понимать: htmlspecialchars не делает ввод “безопасным навсегда”, он делает конкретный вывод безопаснее в конкретном контексте.

    Полезный справочник по риску:

  • OWASP: Cross Site Scripting Prevention Cheat Sheet
  • Сессии: как хранить состояние между запросами

    Сессия — это данные на стороне сервера, привязанные к пользователю. Связь обычно делается через cookie с идентификатором сессии.

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

  • Сессии
  • session_start
  • Минимальный пример

    session_demo.php:

    php <?php

    declare(strict_types=1);

    setcookie( 'theme', 'dark', [ 'expires' => time() + 3600, 'path' => '/', 'secure' => false, 'httponly' => true, 'samesite' => 'Lax', ] );

    echo "Cookie set\n"; php <?php

    declare(strict_types=1);

    _COOKIE['theme'] ?? 'light';

    echo "theme=_SESSION['csrf'])) { _SESSION['csrf'] . "\n"; php <?php

    declare(strict_types=1);

    session_start();

    if ((token = expected = expected === '' || !hash_equals(token)) { echo "CSRF failed\n"; exit; }

    echo "Action allowed\n"; bash curl -c cookies.txt http://localhost:8000/csrf_issue.php bash curl -b cookies.txt -X POST -d "csrf=ВАШ_ТОКЕН" http://localhost:8000/csrf_action.php ``

    Минимальный чек-лист безопасности для новичка

  • используйте === и ??, чтобы избегать неожиданностей с типами и отсутствующими ключами
  • валидируйте вход (filter_var, ручные проверки длины и формата)
  • не выводите пользовательский текст без экранирования (htmlspecialchars)
  • защищайте “опасные” POST-операции CSRF-токеном
  • после логина обновляйте id сессии (session_regenerate_id(true))
  • включайте флаги cookie: httponly и samesite, а на продакшене — secure
  • Как это связано с интеграцией с ИИ

    Когда вы начнёте вызывать ИИ-API из веб-приложения, эти навыки станут основой:

  • вы будете принимать текст пользователя через GET или POST
  • хранить параметры пользователя (например, выбранную модель или историю диалога) в $_SESSION`
  • защищать “дорогие” операции (вызов API, списание лимита) через CSRF-токен
  • аккуратно обрабатывать и выводить ответы модели, не создавая XSS-рисков
  • В следующих шагах курса эти элементы будут объединяться: обработка входа пользователя, работа с JSON и HTTP, а затем вызовы внешних API (в том числе ИИ) с корректной обработкой ошибок и безопасностью.

    5. Базы данных: SQL, PDO, CRUD, миграции и проектирование

    Базы данных: SQL, PDO, CRUD, миграции и проектирование

    В прошлых статьях вы научились обрабатывать входные данные, работать с JSON и отправлять HTTP-запросы к внешним API. Следующий обязательный шаг для реальных веб-приложений — база данных: хранить пользователей, настройки, заказы, историю запросов к ИИ, лимиты и логи.

    В этой статье вы разберёте:

  • что такое реляционная база данных и зачем нужен SQL
  • как подключаться к БД в PHP через PDO
  • как делать CRUD (Create, Read, Update, Delete)
  • что такое миграции и как вести схему БД в порядке
  • базовые правила проектирования таблиц и связей
  • !Общая картина: где находится база данных и как PHP к ней обращается

    Что такое база данных и почему чаще всего это SQL

    База данных (БД) — это система хранения данных, где вы можете:

  • записывать данные надолго
  • быстро искать и сортировать
  • связывать данные между сущностями (пользователь → его заказы)
  • гарантировать целостность (например, чтобы заказ не ссылался на несуществующего пользователя)
  • В веб-разработке часто используются реляционные БД: PostgreSQL, MySQL/MariaDB, SQLite. Они используют язык запросов SQL.

    SQL — это язык, которым вы:

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

  • Документация PHP: PDO
  • Документация PHP: PDOStatement
  • Документация SQLite
  • Документация MySQL 8.0
  • Минимальная модель данных: таблица и строки

    Таблица — как таблица в Excel, но с правилами.

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

  • первичный ключ (primary key) — уникальный идентификатор строки (обычно id)
  • ограничения (например, email уникален)
  • Пример SQL для таблицы пользователей:

    Пояснения простыми словами:

  • PRIMARY KEY — гарантирует уникальность идентификатора
  • AUTOINCREMENT — id увеличивается автоматически (в SQLite)
  • NOT NULL — поле обязательно
  • UNIQUE — нельзя создать двух пользователей с одинаковым email
  • > В разных СУБД типы и автогенерация id оформляются по-разному. Идея одна: первичный ключ должен быть уникальным.

    PDO в PHP: один интерфейс для разных баз

    PDO (PHP Data Objects) — стандартный способ работы с БД в PHP.

    Плюсы:

  • поддерживает разные БД (SQLite, MySQL, PostgreSQL)
  • умеет подготовленные запросы (это основная защита от SQL-инъекций)
  • даёт удобный интерфейс для транзакций и обработки ошибок
  • Подключение к SQLite (самый простой старт)

    SQLite хранит базу в одном файле — это удобно для обучения.

    Создадим db.php:

    Что важно:

  • PDO::ATTR_ERRMODE = PDO::ERRMODE_EXCEPTION — ошибки БД становятся исключениями (их проще ловить)
  • PDO::ATTR_DEFAULT_FETCH_MODE = PDO::FETCH_ASSOC — результаты по умолчанию как ассоциативные массивы
  • Подключение к MySQL (пример)

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

  • password_hash
  • PDO::lastInsertId
  • Read: получить пользователя по email

    fetch() возвращает одну строку или false.

    Update: обновить email

    Связи между таблицами: внешние ключи

    Как только данных становится больше одной таблицы, появляется необходимость связывать данные.

    Пример: пользователь делает запросы к ИИ. Это отдельная сущность.

    Таблица запросов к ИИ

    Что означает FOREIGN KEY:

  • ai_requests.user_id должен ссылаться на реально существующий users.id
  • это помогает сохранять целостность данных
  • !Пример проектирования: связь «один ко многим»

    Чтение связанных данных: JOIN

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

    Проектирование таблиц: практические правила для новичка

    Выбирайте “сущности” и их границы

    Начните с вопроса: какие данные вы храните долго?

    Примеры сущностей для приложения с ИИ:

  • users — пользователи
  • ai_requests — запросы к ИИ (prompt, модель, ответ, стоимость, время)
  • api_keys или user_settings — настройки пользователя
  • rate_limits — лимиты, если вы считаете запросы
  • Первичные ключи и внешние ключи

    Практические правила:

  • у каждой таблицы должен быть первичный ключ (id)
  • связи оформляйте через внешние ключи (user_id)
  • Ограничения целостности

    Ограничения делают данные чище:

  • NOT NULL для обязательных полей
  • UNIQUE для уникальных значений (email)
  • Индексы

    Индекс ускоряет поиск, но замедляет вставку и обновление.

    Базовые идеи:

  • часто фильтруете по email → индекс/уникальность на email
  • часто выбираете запросы пользователя → индекс на ai_requests.user_id
  • В MySQL/PostgreSQL индексы создаются явно (CREATE INDEX ...). В SQLite часть индексов появляется автоматически из PRIMARY KEY и UNIQUE, но дополнительные индексы тоже можно создавать.

    Нормализация “на пальцах”

    Нормализация — это не хранить дублирующиеся данные там, где они не нужны.

    Плохой пример:

  • хранить user_email прямо в ai_requests (вы потом меняете email — и вам надо обновить тысячи строк)
  • Хороший пример:

  • хранить user_id и получать email через JOIN
  • Безопасность: SQL-инъекции и аккуратная работа с ошибками

    SQL-инъекция

    SQL-инъекция — это когда пользовательский ввод ломает SQL-запрос и позволяет атакующему выполнить лишнюю команду.

    Практическое правило:

  • никогда не вставляйте пользовательский ввод в SQL строковой конкатенацией
  • используйте prepare + execute с параметрами
  • Что логировать

    Полезно логировать:

  • факт ошибки
  • код ошибки и контекст (какой обработчик, какой пользователь)
  • Нельзя логировать:

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

    Когда вы начнёте вызывать ИИ-API из PHP (через HTTP и JSON, как в прошлых темах), база данных позволит:

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

  • Принять текст пользователя через POST.
  • Записать запрос в ai_requests.
  • Вызвать внешний ИИ-API.
  • Сохранить ответ в ai_requests.response_text.
  • Показать результат пользователю.
  • Что дальше

    Следующий логичный шаг после БД — собрать всё вместе в небольшое веб-приложение:

  • форма ввода текста
  • сохранение пользователя/сессии
  • запись запросов и ответов в БД
  • вызов внешнего API по HTTP
  • Именно в таком виде обычно выглядит практическая интеграция с ИИ в реальном проекте.

    6. ООП и современный PHP: Composer, автозагрузка, тестирование

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

    Вы уже умеете писать PHP-скрипты, обрабатывать HTTP-ввод, работать с JSON и ходить в базу через PDO. Следующий шаг к реальной разработке (в том числе к интеграции с ИИ) — писать код так, чтобы он:

  • был разбит на понятные модули
  • подключал внешние библиотеки стандартным способом
  • автоматически подгружал классы
  • проверялся тестами
  • Это и есть основа современного PHP-проекта: ООП, Composer, автозагрузка и тестирование.

    !Диаграмма показывает, как Composer создаёт vendor и автозагрузчик, как PHP подключает autoload.php и как тесты используют те же классы

    Что такое ООП в контексте веб-приложения

    ООП (объектно-ориентированное программирование) — это способ организовать код вокруг сущностей (объектов) и их поведения.

    В веб-разработке ООП особенно полезно, когда вы:

  • отделяете бизнес-логику от HTTP-слоя
  • переиспользуете код (например, клиент для внешнего API)
  • изолируете зависимости (БД, HTTP-клиент, конфиги)
  • пишете тесты на логику без запуска сервера
  • Класс и объект

    Класс — это “чертёж”. Объект — конкретный экземпляр.

    Пример сущности, которая форматирует и валидирует входные данные запроса к ИИ:

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

  • namespace App; — помещает класс в пространство имён (помогает не конфликтовать названиями)
  • final — запрещает наследование (часто упрощает поддержку)
  • readonly — свойство можно присвоить только в конструкторе (удобно для неизменяемых данных)
  • declare(strict_types=1); — включает строгий режим типов в файле
  • Документация:

  • Пространства имён в PHP
  • Классы и объекты в PHP
  • Инкапсуляция и публичный интерфейс

    Инкапсуляция — это когда вы скрываете детали реализации и оставляете наружу только нужные методы.

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

  • контроллер/обработчик HTTP знает только “вызови метод сервиса”, а не детали SQL/HTTP
  • менять реализацию внутри класса можно без переписывания всего приложения
  • Зависимости и внедрение зависимостей

    В приложении почти всегда есть внешние “ресурсы”:

  • PDO-подключение к БД
  • HTTP-клиент для API
  • конфигурация (ключи, URL)
  • Хорошая практика: передавать такие вещи в конструктор, а не создавать внутри метода.

    Что проверяем:

  • нормализацию ввода (trim)
  • отказ от некорректного ввода (исключение)
  • Запуск тестов:

    Если всё настроено правильно, PHPUnit найдёт тесты в tests/ и выполнит их.

    Практическая связка с ИИ-интеграциями

    В дальнейшем, когда вы будете вызывать ИИ-API, типичная архитектура на ООП будет выглядеть так:

  • AiClient — класс, который делает HTTP-запросы и возвращает результат
  • AiService — класс, который готовит промпт, выбирает модель, обрабатывает ошибки
  • AiRequestRepository — класс, который сохраняет запросы и ответы в БД
  • Composer поможет подключить готовые библиотеки (например, HTTP-клиенты), автозагрузка позволит не писать ручные require, а тесты дадут уверенность, что подготовка JSON и обработка ошибок не сломались.

    Что дальше

    Дальше курс обычно переходит к сборке мини-приложения, где всё объединяется:

  • веб-форма принимает текст
  • сервисный слой готовит запрос
  • клиент отправляет HTTP-запрос к внешнему API
  • результат сохраняется в БД
  • тесты покрывают ключевую логику (валидация, форматирование, парсинг)
  • 7. Интеграция с ИИ: API, промптинг, чат, функции, RAG и векторы

    Интеграция с ИИ: API, промптинг, чат, функции, RAG и векторы

    Вы уже умеете:

  • принимать данные от пользователя (формы, JSON)
  • отправлять HTTP-запросы и разбирать JSON
  • хранить данные в БД через PDO
  • организовывать код через ООП и Composer
  • Теперь соберём это в практическую картину интеграции с ИИ: как вызывать ИИ по API, как делать чат, как подключать функции (tools), и как добавлять свои данные через RAG с векторами.

    !Общая архитектура интеграции ИИ в PHP-приложение

    Общая архитектура: где живёт ИИ в вашем приложении

    Типичный поток запроса в веб-приложении:

  • Пользователь отправляет текст (POST-форма или JSON).
  • PHP валидирует ввод и применяет правила безопасности.
  • Приложение при необходимости читает историю диалога из сессии/БД.
  • Приложение формирует JSON-запрос к ИИ-провайдеру и отправляет его по HTTP.
  • Приложение проверяет HTTP-статус, разбирает JSON-ответ.
  • Результат сохраняется в БД (логи, история, метрики, кэш) и возвращается пользователю.
  • Важное правило: API-ключ всегда хранится на сервере. Браузер не должен его видеть.

    ИИ API: ключи, окружение, ошибки и таймауты

    ИИ-интеграции почти всегда выглядят одинаково на уровне протоколов:

  • HTTP-запрос (обычно POST)
  • заголовки, включая Authorization
  • JSON-тело
  • JSON-ответ
  • Документация OpenAI (как пример реального API):

  • Документация OpenAI API
  • Где хранить API-ключ

    Практика для разработки:

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

  • vlucas/phpdotenv
  • Минимальные практики надёжности

  • всегда ставьте таймауты на HTTP-запросы
  • проверяйте HTTP-статус (2xx — успех)
  • не логируйте секреты (ключи, токены)
  • аккуратно обрабатывайте не-JSON ответы (ошибки, HTML от прокси и т.д.)
  • Минимальный вызов модели по HTTP (PHP + cURL + JSON)

    Ниже пример запроса к OpenAI Responses API.

  • endpoint: https://api.openai.com/v1/responses
  • документация: Responses API
  • Файл ai_demo.php:

    php <?php

    declare(strict_types=1);

    session_start();

    if (!isset(_SESSION['chat'] = []; }

    function chatAdd(string content): void { role, 'content' => _SESSION['chat']) > 20) { _SESSION['chat'], -20); } }

    chatAdd('user', 'Привет!'); sql CREATE TABLE chat_messages ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER NOT NULL, role TEXT NOT NULL, content TEXT NOT NULL, created_at TEXT NOT NULL ); php <?php

    declare(strict_types=1);

    function openaiEmbedding(string text): array { payload = [ 'model' => 'text-embedding-3-small', 'input' => ch = curl_init(ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', 'Authorization: Bearer ' . payload, JSON_UNESCAPED_UNICODE), CURLOPT_TIMEOUT => 20, ]);

    ch); if (err = curl_error(ch); throw new RuntimeException('cURL error: ' . status = (int) curl_getinfo(ch);

    if (status >= 300) { throw new RuntimeException('HTTP error ' . body); }

    body, true, 512, JSON_THROW_ON_ERROR);

    data['data'][0]['embedding'] ?? null; if (!is_array(vec; }

    function cosineSimilarity(array b): float { na = 0.0; n = min(count(b)); for (i < i++) { a[y = (float) i]; x * na += x; y * na === 0.0 || dot / (sqrt(nb)); } sql CREATE TABLE doc_chunks ( id INTEGER PRIMARY KEY AUTOINCREMENT, doc_id INTEGER NOT NULL, chunk_text TEXT NOT NULL, embedding_json TEXT NOT NULL, created_at TEXT NOT NULL ); ``

    А дальше:

  • при загрузке документа разбить его на чанки
  • посчитать эмбеддинг каждого чанка
  • сохранить chunk_text и embedding_json
  • при запросе пользователя посчитать эмбеддинг запроса
  • перебрать чанки, посчитать similarity, взять top-k
  • Этот подход будет медленным на больших объёмах данных, но отлично объясняет идею.

    Как делают в продакшене

    Для больших данных используют специализированный поиск:

  • PostgreSQL с расширением векторов: pgvector
  • Идея та же, но “поиск ближайших” делает база данных.

    Как собрать RAG-контекст и отправить в модель

    Практика подготовки контекста:

  • Найдите top-k фрагментов.
  • Соберите единый блок “Контекст” (обычно с разделителями).
  • В промпте явно попросите отвечать только на основе контекста.
  • Пример текста инструкции:

  • system: “Отвечай только на основе контекста. Если в контексте нет ответа — скажи, что данных недостаточно.”
  • Организация кода по-взрослому: классы и тесты

    Когда интеграция растёт, полезно разделить ответственность:

  • AiClient — HTTP-вызовы (cURL/Guzzle), обработка статусов и JSON
  • PromptBuilder — сбор промпта из правил, истории и RAG-контекста
  • EmbeddingClient — получение эмбеддингов
  • ChunkRepository — чтение/запись чанков и эмбеддингов в БД
  • ChatService` — бизнес-логика диалога
  • Это напрямую продолжает тему ООП, Composer и PHPUnit из прошлой статьи.

    Итог

    Теперь у вас есть полная “карта” интеграции с ИИ в PHP:

  • API-вызов по HTTP + JSON с таймаутами и проверкой статусов
  • промптинг как способ сделать ответы стабильнее
  • чат как управление историей (сессии/БД)
  • tools/function calling как мост между моделью и вашим кодом
  • RAG как способ подключить ваши документы через векторы и поиск
  • Следующий практический шаг курса — собрать мини-приложение: форма ввода → сохранение запроса → RAG-поиск → вызов модели → сохранение ответа → отображение результата.