PHP: полный мануал с примерами, функциями и ООП
Практический мануал PHP: от переменных и читаемого кода до безопасных форм, интеграций, базы данных и ООП на примере магазина. Учебный маршрут, поиск функций, подробные примеры, разбор ошибок и исходники для скачивания.

Дерево руководства
Глава 3 · С нуля → окружение
Установка PHP: от исполнителя до первой локальной страницы
Зачем нужны PHP, терминал и сервер; Windows-сборка, полный путь и PATH, CLI и SAPI, вводный путь Linux/macOS, расширения и первая страница на localhost.
Что устанавливаем: исполнитель PHP, терминал и браузер
Кто передаёт файл исполнителю PHP
Один язык используется в двух маршрутах. Файл выполняет PHP; браузер видит результат ответа.
- CLI: отчёт в терминале
Вы запускаете php hello.php → PHP читает hello.php → echo печатает строку в терминале.
- HTTP: страница в браузере
Браузер запрашивает адрес → сервер передаёт работу PHP → index.php создаёт ответ → браузер получает текст.
Это альтернативные маршруты, не два обязательных этапа. Для первого запуска hello.php веб-сервер не нужен. FPM требует отдельного HTTP-сервера; учебный php -S объединяет локальную HTTP-обработку с PHP.
Вам нужно запустить небольшой скрипт — например, подготовить отчёт — или открыть собственную PHP-страницу. Файл с окончанием .php содержит инструкции. Сам по себе он не выполняется: его читает программа PHP. На Windows это обычно php.exe; в терминале Linux/macOS — исполняемый файл php.
Терминал — окно для команд. Оболочка PowerShell или bash разбирает команду и запускает выбранную программу. Браузер получает ответ по HTTP и показывает его. Он не исполняет PHP-код, лежащий у вас на диске. Текстовый редактор только помогает записать этот код.
| Задача | Кто запускает PHP | Где результат |
|---|---|---|
| Выполнить hello.php | Вы вводите команду в терминале → PHP читает файл | Текст в терминале |
| Открыть PHP-страницу | Браузер → HTTP-сервер → PHP обрабатывает файл | Тело HTTP-ответа в браузере |
| Редактировать исходник | Редактор сохраняет символы в .php | Изменился файл; выполнение ещё не началось |
Можно представить PHP работником, а файл — листом заданий. Терминал передаёт лист напрямую; веб-сервер передаёт его при запросе посетителя. Это модель передачи работы, а не устройство памяти или обещание отдельного процесса на каждый запрос.
Для первых шагов достаточно уметь создавать папку и сохранять текстовый файл. Начнём с готового исполнителя, без базы данных и настройки Apache. Языковой синтаксис первой программы разобран ниже; продолжение — начальные приёмы PHP.
Windows: выбрать сборку и проверить полный путь
Если PHP уже входит в ваш локальный комплект разработки, сначала найдите его php.exe и проверьте версию. Не кладите поверх него другой архив. Для отдельного учебного окружения официальный сайт предлагает Windows-сборки: страница загрузки PHP для Windows. Проверяйте требования именно выбранного файла; эта глава не назначает «самую новую» версию.
При новой ручной установке последовательность такая: выбрать поддерживаемую сборку, проверить её требования и контрольную сумму, распаковать архив в отдельную папку, убедиться в наличии нужного Visual C++ Runtime, затем запустить php.exe по полному пути. Если runtime отсутствует, используйте ссылку Microsoft из официальной инструкции. Не собирайте недостающие DLL с посторонних сайтов.
| Отметка сборки | Что она означает | Как выбирать |
|---|---|---|
| x64 / x86 | Архитектура исполняемого файла | Совместимость с ОС, сервером и DLL; не смешивать архитектуры |
| NTS | Non Thread Safe | Рекомендованный вариант для CLI и FastCGI при соответствующем окружении |
| TS | Thread Safe | Нужен при загрузке PHP модулем в многопоточный Apache на Windows |
| Версия и компилятор | Двоичная совместимость зависимостей | Сверять требования конкретного архива и расширений |
- Распакованный C:\Tools\PHP\php.exe
- PowerShell запускает именно этот файл с -v
- Версия и CLI в выводе → можно переходить к hello.php
& 'C:\Tools\PHP\php.exe' -v
Предусловие: официальный архив уже распакован в C:\Tools\PHP, файл php.exe действительно существует. Замените путь своим. Команда только запускает выбранный PHP для показа версии; не устанавливает его. Первая строка содержит PHP, номер версии и обозначение CLI; остальные сведения зависят от сборки. Это команда PowerShell, не PHP-код.
Знак & — оператор запуска PowerShell. Кавычки сохраняют путь целиком, даже если в нём есть пробелы. Без & выражение в кавычках лишь обозначает строку. Пробел отделяет аргумент -v: он просит показать версию. В PowerShell файл из текущей папки запускают через .\php.exe; запись php не обязана искать его здесь.
Если окно сразу закрывается после двойного щелчка по php.exe, вернитесь в уже открытый терминал. Если появляется ошибка о системной DLL, сначала сверяйте runtime и архитектуру с официальной Windows-инструкцией; дальнейшие PHP-примеры ещё не смогут выполниться.
Почему полный путь работает, а php не найден
PATH — список каталогов, в которых оболочка ищет программы по короткому имени. В нём записывают каталог C:\Tools\PHP, а не C:\Tools\PHP\php.exe. Уже найденный полный путь позволяет работать без изменения PATH. Для учебного начала это удобный способ избежать случайного запуска соседней версии.
Если решите добавить PHP в пользовательский PATH средствами Windows, добавьте одну отдельную запись, сохранив существующие. Откройте новый терминал и заново проверьте путь. Здесь мы PATH не меняем и не предлагаем команду, которая заменяет весь список.
- Вы вводите php
- PowerShell учитывает свои команды и пути поиска
- Проверяем найденный путь и сравниваем версию с прямым запуском
Get-Command php -All
where.exe php
Предусловие: PowerShell открыт после существующей настройки PATH. Get-Command показывает также функции и псевдонимы PowerShell; where.exe ищет исполняемые файлы по своим правилам поиска. Список путей может быть пустым либо содержать несколько установок. Ошибка поиска означает «команда не найдена», а не «PHP нигде нет». Команды ничего не меняют.
Типичная потребность: PHP запускается только из папки локального комплекта — обсуждение на Stack Overflow. Исправление начинается с поиска конкретного исполняемого файла. Переустановка PHP не является обязательным следствием ошибки «команда не найдена».
При нескольких версиях сохраняйте полный путь в своих учебных командах. Проверка php -v без проверки пути может показать исправный, но совсем другой PHP.
Первый файл: что именно передаём исполнителю
Создайте папку C:\PhpLessons и сохраните hello.php. Отключите скрытие расширений в файловом менеджере или проверьте имя в редакторе: hello.php.txt — другой файл. Код для копирования содержит только программу.
| Запись | Смысл |
|---|---|
| <?php | Начало PHP-кода; перед ним в этом файле ничего нет |
| echo | Вывести следующие данные |
| "Проверка PHP: файл выполнен\n" | Строка в двойных кавычках; \n внутри неё — перевод строки |
| ; | Конец этой инструкции |
- hello.php содержит echo
- php.exe читает hello.php
- Терминал показывает строку «Проверка PHP: файл выполнен»
<?php
echo "Проверка PHP: файл выполнен\n";
Ожидаемый результат
Проверка PHP: файл выполнен
Сохраните именно hello.php в UTF-8, без добавочного .txt и без текста перед открывающим тегом. Эта программа печатает одну строку. Она не создаёт сайт, не обращается в сеть и не меняет настройки.
& 'C:\Tools\PHP\php.exe' 'C:\PhpLessons\hello.php'
Ожидаемый результат
Проверка PHP: файл выполнен
Предусловия: php.exe доступен по указанному пути, hello.php содержит предыдущий пример. Первый путь выбирает программу, второй — файл, который она должна выполнить. Текущая папка терминала не определяет ни один из этих двух абсолютных путей.
Закрывающий тег ?> в файле, состоящем только из PHP, можно не ставить. Если PHP пишет Could not open input file, проверяйте путь и имя файла, а не синтаксис echo. Если появляется Parse error, файл найден, но его запись повреждена: например, пропущены кавычка или точка с запятой. Точное сообщение зависит от ошибки и версии.
Не вставляйте команду PowerShell внутрь hello.php и не вставляйте PHP-код прямо в обычную командную строку. Это два разных языка: оболочка выбирает программу, PHP исполняет её исходник.
CLI, модуль и FPM: один язык, разные способы запуска
SAPI — название интерфейса, через который PHP работает с окружением. CLI обслуживает командную строку. Веб-сервер может передавать работу PHP через CGI/FastCGI либо загрузить PHP как модуль. FPM — менеджер процессов FastCGI: он держит PHP-процессы для запросов веб-сервера. Это не самостоятельный браузерный HTTP-сервер.
Сейчас нужно научиться различать эти режимы. Настройка соединения Nginx/Apache с FPM, права сокета и управление пулом — отдельный следующий урок; его не заменяет успешный php -v.
| Способ | Обычно PHP_SAPI | Что важно |
|---|---|---|
| Команда php hello.php | cli | Проверяет выбранный CLI-процесс |
| Встроенный сервер php -S | cli-server | Локальный HTTP-опыт, отдельный SAPI |
| FPM за HTTP-сервером | fpm-fcgi | Пулы и конфигурация могут отличаться от CLI |
| PHP как модуль Apache | apache2handler | PHP загружен в процессы Apache |
<?php
echo "Интерфейс: ", PHP_SAPI, "\n";
Ожидаемый результат
Интерфейс: cli
Запустите файл именно командой php имя-файла.php. PHP_SAPI — встроенное имя с готовым значением, поэтому перед ним нет знака $. echo печатает перечисленные через запятые части. Для встроенного HTTP-сервера значение другое: cli-server; для FPM — fpm-fcgi. Показанный результат относится к CLI.
Встроенная константа PHP_VERSION показывает версию, PHP_BINARY — путь исполняемого файла текущего процесса. Эти сведения дополняют PHP_SAPI; сами по себе они ещё не доказывают, какие расширения и настройки включены. Диагностика конфигурации — в следующей главе.
Увидеть ответ в браузере: только учебная папка на localhost
После CLI-успеха создайте отдельную C:\PhpLessons\public и файл index.php внутри неё. Корень документов — каталог, из которого сервер берёт доступные по HTTP файлы. Поэтому выбираем public с одним учебным файлом, а не весь диск или каталог проекта с настройками.
Минимальная связь HTTP такова: адрес в браузере задаёт получателя запроса; сервер получает запрос и выбирает файл; PHP выполняет код; сервер возвращает результат. Подробный разбор заголовков и тела — в начале главы о HTTP.
- Браузер: http://127.0.0.1:8080/
- Сервер на этом же ПК → public/index.php
- PHP создаёт текст ответа → браузер показывает его
<?php
header('Content-Type: text/plain; charset=UTF-8');
echo "Учебная страница работает\n";
Ожидаемый результат
Учебная страница работает
Полный файл для следующего локального опыта. header — готовая функция PHP: имя перед скобками выбирает действие, строка в скобках задаёт заголовок ответа. Content-Type сообщает браузеру, что ответ — обычный текст в UTF-8. Вызов должен идти до вывода. Здесь проверяется синтаксис; HTTP-ответ, порт и браузер проверяются отдельно по шагам ниже.
& 'C:\Tools\PHP\php.exe' -S 127.0.0.1:8080 -t 'C:\PhpLessons\public'
Предусловия: отдельная учебная папка public содержит только public/index.php из примера, порт 8080 свободен, в этой папке нет паролей, конфигураций и личных файлов. Оставьте терминал открытым; зайдите на http://127.0.0.1:8080/ в браузере этого же компьютера. Ожидаемое тело ответа приведено у index.php. Ctrl+C в терминале останавливает сервер. Это инструкция, сервер при проверке главы не запускался.
-S включает встроенный сервер; 127.0.0.1 означает только этот компьютер, 8080 — выбранный порт. -t задаёт корень документов. Если порт занят, завершите свой прежний учебный процесс либо выберите свободный порт и измените адрес браузера соответственно. Не отключайте для этого защиту компьютера.
Адрес file:///C:/PhpLessons/public/index.php не обращается к серверу и не выполняет PHP. Если видите исходник, проверьте, что открыли именно http://127.0.0.1:8080/. Этот встроенный сервер предназначен для разработки; не открывайте его в публичную сеть и не используйте для обслуживающего посетителей сайта.
Этот пример проверен синтаксически. Проверка реального HTTP-опыта для читателя: запрос возвращает указанный текст; после Ctrl+C тот же адрес перестаёт обслуживаться этим процессом.
Linux: начать с пакета CLI, сохранив границы дистрибутива
В Linux сборку часто устанавливает пакетный менеджер дистрибутива. Он знает зависимости и место файлов. Названия пакетов, версии и каталоги конфигурации у разных дистрибутивов различаются. Здесь разобран вводный путь Debian/Ubuntu; DNF, Alpine, Arch, OpenBSD и сборка из исходников остаются отдельными уроками.
Сначала выясните, есть ли PHP и какой пакет доступен. command -v — вопрос оболочке о пути команды; apt-cache policy — сведения о версии пакета, а не запуск PHP.
- Проверяем существующий php и пакет php-cli
- При необходимости устанавливаем в собственную учебную систему
- php -v и php --ini фиксируют фактический результат
command -v php
apt-cache policy php-cli
Предусловие: личная Debian/Ubuntu-система с настроенными доверенными репозиториями и оболочкой sh/bash. Первая команда показывает уже найденный исполняемый файл либо ничего; вторая — установленную и предлагаемую версии пакета. Это чтение сведений. Здесь и дальше показаны команды для терминала Linux, не PowerShell.
sudo apt update
sudo apt install php-cli
php -v
php --ini
Команды установки предназначены читателю, который вправе менять эту учебную систему, проверил доступную версию и согласен с показанным apt списком изменений. sudo запускает команду с административными правами; apt update обновляет сведения о пакетах, apt install устанавливает пакет и его зависимости. Здесь эти команды не выполнялись. На рабочем сервере нужен отдельный план обновления зависимостей и служб.
php-cli предназначен для командной строки; для этого шага не нужен пакет модуля Apache. Расширения могут поставляться отдельными пакетами. Установка одного php-cli не настраивает сайт. Команды php hello.php затем имеют тот же смысл, что в Windows, но пути выглядят, например, /home/anna/php-lessons/hello.php.
Поставщик дистрибутива может поддерживать исправления в своей версии. Сверяйте ограничения учебного проекта с фактическим php -v; не добавляйте случайный репозиторий только из-за несовпадения номера с чужим скриншотом.
macOS: проверить происхождение PHP, затем пакет
Нельзя рассчитывать на встроенный /usr/bin/php: начиная с macOS Monterey PHP не поставляется вместе с системой. Официальное руководство направляет к пакетным менеджерам и сборке из исходников. Здесь пример с уже установленным Homebrew; его рецепт поддерживает отдельный проект Homebrew.
Поиск существующего PHP полезен и здесь: прежняя установка или другой пакетный менеджер могут уже предоставить команду php. Не смешивайте инструкции Homebrew и MacPorts в одном учебном окружении.
- Homebrew уже установлен
- brew info php: читаем рецепт и зависимости
- После установки php -v и php --ini проверяют выбранный PATH
command -v php
brew info php
Предусловие: Homebrew уже установлен по его официальной инструкции и команда brew доступна. Просмотрите версию, зависимости и пояснения рецепта. Если brew не найден, эти команды не являются инструкцией установки самого Homebrew. Наличие php в PATH проверяется отдельно.
brew install php
php -v
php --ini
Предусловия: собственная учебная система, изучены сведения brew info php, разрешена установка пакетов. Номер PHP зависит от текущего рецепта. Мы не запускаем brew services и не настраиваем веб-сервер. Команды приведены для читателя; установка в рамках проверки главы не выполнялась.
Пути Homebrew зависят от архитектуры и установки, поэтому не копируйте заранее придуманный путь к php.ini. Если php после установки не найден, следуйте пояснениям установленного пакетного менеджера о PATH и заново проверьте command -v php. Автоматический запуск FPM здесь не нужен для выполнения hello.php.
MacPorts, самостоятельная компиляция и историческая настройка PHP, поставлявшегося с прежними macOS, отмечены в реестре дальнейшей работы.
Первый полезный результат в Linux/macOS
После установки пакета не останавливайтесь на номере версии. Через редактор или файловый менеджер создайте php-lessons в своей домашней папке и сохраните hello.php с уже разобранным echo. В Unix-путях разделитель — /, обозначения диска C: здесь нет.
В следующей команде имя php выбирает проверенный исполнитель из PATH. Оболочка заменяет $HOME на домашний каталог пользователя; это её переменная, а не переменная внутри программы PHP. Остаток пути указывает сохранённый файл.
- Домашняя папка → php-lessons/hello.php
- Команда php получает путь к этому файлу
- Терминал показывает ту же проверочную строку
php "$HOME/php-lessons/hello.php"
Ожидаемый результат
Проверка PHP: файл выполнен
Предусловия: в своей домашней папке создайте php-lessons и сохраните в ней hello.php из первого примера; php уже проверен через command -v и php -v. В sh/bash/zsh $HOME означает домашний каталог, кавычки сохраняют путь с пробелами одним аргументом. Текущая папка терминала не важна. Это команда Unix-оболочки, не PHP-код и не PowerShell.
Для браузерного шага создайте внутри php-lessons отдельную public и сохраните туда index.php из раздела локального HTTP-опыта. Правило то же: в public доступны только учебные файлы, а не весь проект. Флаги -S и -t сохраняют свой смысл; отличается запись пути.
php -S 127.0.0.1:8080 -t "$HOME/php-lessons/public"
Предусловия: php выбран и проверен, порт 8080 свободен, внутри php-lessons создана отдельная public только с index.php из локального HTTP-примера. Откройте http://127.0.0.1:8080/ на этом же компьютере; ожидаемый текст — «Учебная страница работает». Для остановки нажмите Ctrl+C. Сервер привязан только к 127.0.0.1; эта команда не выполнялась при проверке главы.
Если hello.php не найден, сверяйте имя и путь; если php не найден, вернитесь к command -v php и инструкции своего менеджера пакетов. Не заменяйте отсутствующий PHP случайной командой из другой платформы.
Расширение PHP, библиотека Composer и отдельная служба
Предположим, проект должен подготовить JSON, обработать изображение или обратиться к базе. Не каждая возможность является частью одного исполняемого файла. Расширение добавляет функции и классы в PHP-процесс; библиотека Composer состоит из кода проекта; сервер базы данных работает отдельной программой.
| Что требуется | Пример | Как проверить |
|---|---|---|
| Расширение PHP | json, intl, pdo_mysql | php -m, php --ri имя, extension_loaded |
| Библиотека проекта | Пакет из composer.json | Установленные зависимости проекта и подключение автозагрузчика |
| Служба вне PHP | Сервер MySQL | Его отдельное состояние и параметры соединения; DLL драйвера не запускает сервер |
- Проекту нужно расширение json
- Текущий PHP проверяет extension_loaded
- json_encode формирует строку для передачи данных
& 'C:\Tools\PHP\php.exe' -m
& 'C:\Tools\PHP\php.exe' --ri json
Первая команда выводит список модулей, вторая — сведения только об одном расширении. json встроено во все поддерживаемые здесь PHP 8.2+; для необязательного расширения, например intl, отсутствие сведений означает, что выбранный процесс его не загрузил. Список CLI не доказывает наличие тех же модулей у сайта.
<?php
echo "JSON загружен: ", extension_loaded('json') ? 'да' : 'нет', "\n";
echo json_encode('Tea'), "\n";
Ожидаемый результат
JSON загружен: да
"Tea"
extension_loaded получает имя расширения и возвращает true либо false. Запись условие ? значение-если-да : значение-если-нет выбирает слово для отчёта. json_encode преобразует строку Tea в JSON-строку с кавычками; это полезно перед передачей данных другому приложению. Здесь нет HTTP-запроса, базы или Composer; json присутствует в PHP 8.2+.
Кавычки вокруг json обозначают передаваемый текст — имя расширения. Скобки запускают готовую функцию. Результат extension_loaded логический: да/нет. Условное выражение в примере переводит его в читаемую строку. Больше о форматах — глава JSON, о пакетах — первые шаги Composer.
extension_dir = "C:/Tools/PHP/ext"
extension = intl
Это фрагмент активного php.ini, не самостоятельный установщик. Предусловия: совместимая сборка PHP содержит php_intl.dll и все её зависимости, они доступны загрузчику; активный файл настроек уже найден. Подключайте расширение один раз, затем проверяйте новый процесс php --ri intl. Загружаемые Zend-расширения используют zend_extension, но встроенные компоненты повторно загружать не надо. Версионное отличие OPcache разобрано сразу ниже.
Версия имеет значение и для OPcache — компонента кэширования скомпилированного кода. В PHP 8.2–8.4 его загружали как Zend-расширение. Начиная с PHP 8.5 OPcache всегда встроен и загружен: отдельные opcache.so/php_opcache.dll больше не создаются, а прежний zend_extension для них выдаёт предупреждение. Поведение кэша по-прежнему регулируют opcache.enable и opcache.enable_cli. Это уточнение из руководства миграции на PHP 8.5; не переносите старую инструкцию загрузки на новую версию.
У Windows DLL расширения должна соответствовать версии PHP, TS/NTS, архитектуре, debug/non-debug и инструментам сборки. Наличие файла само по себе недостаточно: могут отсутствовать зависимые библиотеки. Сообщение PHP Startup о загрузке расширения появляется до выполнения вашего кода. Сверяйте его с официальной инструкцией расширения и запускайте проверку в новом процессе.
Не все расширения поставляются одним способом: часть встроена, часть включается из комплектной DLL, часть устанавливается отдельно. PECL, PIE и параметры компиляции требуют собственных уроков; приведённая запись не заменяет их.
Развитие: одна проверка для нескольких зависимостей
После объявления и вызова функций и условий if ту же проверку удобно оформить один раз. Это необязательная поздняя ступень: для запуска первого файла она не нужна.
function объявляет действие extensionReport. $name — локальное имя полученной строки; string перед ним и после скобок обозначает ожидаемый текст на входе и выходе. ! меняет «загружено» на «не загружено». return возвращает текст вызывающей строке, точка соединяет части текста. Фигурные скобки ограничивают тело действия или ветви.
<?php
function extensionReport(string $name): string
{
if (!extension_loaded($name)) {
return "Не загружено: " . $name;
}
return "Готово: " . $name;
}
echo extensionReport('json'), "\n";
echo extensionReport('lesson_missing_extension'), "\n";
Ожидаемый результат
Готово: json
Не загружено: lesson_missing_extension
Второе имя специально вымышлено для проверяемого отказа. Функция получает имя, один раз проверяет доступность и возвращает сообщение вызывающему коду. Она ничего не устанавливает и не включает. Сначала выполнен минимальный опыт выше; эту ступень изучайте после базовых функций и условий.
Для запуска реального проекта одного красивого сообщения мало: обязательная зависимость должна останавливать работу с ясной причиной. Здесь функция только диагностическая, поэтому не скрывает ошибку установкой на лету. Правило остановки и журналирование проект выбирает отдельно.
Сборка из исходников и php.ini решают разные задачи
Готовый архив или пакет уже скомпилирован. Настройки php.ini управляют тем, что эта сборка умеет настраивать во время запуска. configure используется раньше — при подготовке сборки из исходников на Unix. Это разные этапы, и строка --enable-fpm в php.ini не создаст FPM.
Например, --enable-fpm выбирает сборку FPM, --with-config-file-path задаёт каталог поиска конфигурации по умолчанию, --with-config-file-scan-dir — каталог дополнительных ini. Возможные параметры зависят от версии и выбранных расширений.
| Этап | Что решаем | Проверка |
|---|---|---|
| Компиляция | Какие компоненты собраны и где исходные пути поиска | Справка configure и результат сборки |
| Запуск процесса | Какой php.ini и дополнительные ini прочитаны | php --ini; для сайта — диагностика его SAPI |
| Выполнение файла | Какие разрешённые параметры временно меняются | ini_set и проверка текущего значения |
./configure --help
Предусловие: исходники нужной версии PHP уже получены из официального источника и сценарий configure подготовлен; терминал открыт в этом дереве. Команда показывает справку о параметрах сборки, не устанавливает PHP. Это не команда php.exe и не обязательный шаг для ZIP или системного пакета.
Подготовка компилятора, библиотек, выбор опций каждого расширения и установка результата ещё не разобраны в этой вводной главе. Прежде чем собирать собственный PHP, полезно уверенно пройти готовый CLI-путь и диагностику настроек.
Практика: доказать, что выбран нужный PHP
Задание 1. hello.php открывается в редакторе, но ничего не печатается. Получите строку из примера. Решение: открыть терминал, запустить полный путь к php.exe и передать путь к hello.php. Двойной щелчок по исходнику выбирает связанный редактор, а не гарантирует выполнение.
Задание 2. Команда php -v показывает другую версию, чем ваш комплект. Решение: Get-Command php -All, затем прямой запуск нужного php.exe. Пока пути не установлены, не исправляйте наугад настройки всех установок.
Задание 3. Сайт не видит расширение, хотя php -m его показывает. Сначала назовите два разных процесса. Решение: CLI и веб-SAPI могут читать разные ini и загружать разные модули; проверка CLI не завершает диагностику сайта.
Задание 4. Откройте учебный index.php по HTTP, затем остановите свой сервер Ctrl+C. Вы должны отличить успешный текст ответа от ошибки соединения после остановки. Это ручной HTTP-опыт; синтаксическая проверка файла не подтверждает сетевую часть.
Дальше — поиск и безопасная проверка конфигурации. При переходе к рабочему сайту потребуется отдельная подготовка развёртывания: встроенный сервер не является её заменой.
Перед установкой на другой системе: что должно совпасть
Вам передали PHP-проект, а на новом компьютере он не запускается. Нужна не просто программа с именем php, а исполнитель подходящей версии с нужными расширениями. Сначала запишем три независимых условия: версия языка, способ запуска и возможности. Это позволяет установить ровно то, чего не хватает.
Следующие уроки предполагают собственную учебную систему или виртуальную машину, где вы вправе устанавливать пакеты. Если это сервер организации, сначала выясняют его владельца и порядок изменений. Все команды установки ниже — инструкции для этой отдельной системы; автор их здесь не выполнял. Предшествующая ступень — исполнитель, файл и первый результат.
| Условие | Пример требования проекта | Доказательство |
|---|---|---|
| Язык | PHP не ниже 8.2 | Версия выбранного php, затем запуск проекта |
| Способ работы | CLI-отчёт или сайт через FPM | PHP_SAPI именно этого выполнения |
| Возможность | Расширение json | extension_loaded в этом же процессе |
| Доступ к данным | Прочитать локальный тариф | Успешное чтение с правами пользователя процесса |
- Проверяем выбранный исполнитель
- Сверяем требования отчёта
- Запускаем маленький диагностический файл
- Только затем подключаем реальный проект
<?php
echo version_compare(PHP_VERSION, '8.2.0', '>=') ? "version:ok\n" : "version:too-old\n";
echo extension_loaded('json') ? "json:ok\n" : "json:missing\n";
Ожидаемый результат
version:ok
json:ok
Самостоятельный файл для PHP 8.2+; проверен на 8.5.11. version_compare получает текущую версию, требуемую и знак сравнения строкой. Условие ? : выбирает понятную надпись. Это проверка двух требований; она не доказывает исправность базы, веб-сервера или всей программы.
Сохраните этот файл рядом с hello.php. Вызывайте его тем же полным путём к PHP, которым собираетесь запускать приложение. После установки расширения повторите проверку новым процессом. Старый FPM-worker не обязан мгновенно увидеть установленный пакет.
Задание: requirements.php успешно отработал в терминале, но сайт пишет об отсутствии intl. Какие выводы ещё нельзя делать? Решение: CLI проверил только себя и только json; нужны требования сайта и диагностика его SAPI.
Debian/Ubuntu: пакет PHP, модуль и файл конфигурации
Для первого отчёта достаточно php-cli. Для работы с изображением может потребоваться php-gd, для сайта — отдельный FPM. Пакетный менеджер связывает версии зависимостей; он не знает, что ваш прикладной проект проверен только на конкретной ветке языка.
Перед изменениями выясните установленный и доступный пакеты. apt-cache policy читает сведения из индекса, apt show показывает описание. Слово install в следующем блоке означает уже изменение системы; сначала просмотрите предполагаемую транзакцию.
- apt-cache сообщает кандидата
- Устанавливаем согласованный CLI и нужный модуль
- Новый php -m/--ri подтверждает загрузку
- Для сайта отдельно применяем конфигурацию его службы
apt-cache policy php-cli php-gd
apt show php-cli
apt-get --simulate install php-cli php-gd
Предусловие: Debian/Ubuntu с настроенными репозиториями. simulate показывает план, но не устанавливает пакет. Номера версий и зависимости зависят от выпуска; ожидается читаемый список, не фиксированный текст.
sudo apt update
sudo apt install php-cli php-gd
php -v
php --ini
php --ri gd
Предусловия: выполнена предыдущая проверка, список изменений изучен, владелец разрешил установку. GD выбран здесь для задачи обработки изображения; без такой задачи пакет не нужен. Если поставщик разделяет ветки по именам php8.x-*, берите согласованные пакеты одной ветки, а не смесь метапакета и случайной DLL.
Имена без номера могут быть метапакетами: они выбирают ветку, принятую в выпуске дистрибутива. Каталоги CLI, Apache и FPM могут разделяться. Поэтому факт правки файла в /etc/php ещё не отвечает, какой процесс его прочёл: смотрите --ini и веб-диагностику отдельно.
Если расширение уже добавлено пакетным менеджером через отдельный ini, не дублируйте extension=gd в основном файле. Предупреждение «already loaded» означает повторное подключение, а не потребность установить пакет ещё раз.
Задание: apt сообщает, что php-gd установлен, а ваш php --ri gd не находит модуль. Решение: проверить путь php, ветку пакета, список scan-ini и сообщение старта. Возможно, запускается собственная сборка из /usr/local, которую пакет не настраивал.
DNF: начать с CLI и не обновить весь сервер случайно
DNF используется, например, в Fedora и ряде систем семейства RHEL. У этих систем не обязательно одна версия PHP и не всегда одинаковая политика репозиториев. Для учебного CLI выбираем php-cli; php-fpm — другой компонент, нужный при передаче HTTP-запросов через FastCGI.
dnf info показывает сведения о пакете; --refresh обновляет метаданные репозитория для запроса. Это отличается от dnf upgrade, который меняет установленные пакеты. Установка PHP не требует автоматически соглашаться на полное обновление работающего сервера.
- Смотрим php-cli и репозиторий
- Читаем план установки и зависимости
- Устанавливаем CLI
- Проверяем php -v, --ini и собственный файл
dnf --refresh info php-cli
dnf search php
dnf list --installed 'php*'
Предусловие: система с рабочим DNF и доверенными репозиториями. Кавычки вокруг php* передают шаблон самому DNF, а не разворачивают файлы текущего каталога оболочкой. Последняя команда может не найти установленных PHP-пакетов.
sudo dnf install php-cli php-gd
php -v
php --ini
php --ri gd
Предусловие: пакеты доступны в репозитории выбранного выпуска, права на установку получены. Перед подтверждением прочитайте транзакцию. Команды не выполнены автором. Для одного текстового отчёта php-gd можно не устанавливать; здесь он показывает дополнительную возможность.
В семействах RHEL существуют зависящие от выпуска потоки модулей и сторонние репозитории. Переключение потока — смена набора пакетов, а не редактирование php.ini. Не выдаём dnf module reset/enable за общий шаг для каждой Fedora: сверяйте модель репозиториев конкретной ОС.
После добавления php-fpm не считайте сайт готовым: нужны обработчик HTTP-сервера, адрес FPM и права. После добавления расширения текущий CLI завершается сам, а долгоживущий веб-процесс требует предусмотренного применения новой конфигурации.
Задание: инструкция предлагает dnf update перед каждым запуском PHP. Что из этого обязательно для запуска hello.php? Решение: уже установленный исполнитель запускается без обновления ОС; актуальность и обновление пакетов — отдельная операция с собственным планом.
Alpine: номер ветки есть в имени пакета и команды
В Alpine инструменты распространяются через apk. PHP-пакеты часто включают номер ветки: php83, php84 и соответствующие им расширения. Число 83 в официальном примере означает ветку PHP 8.3, а не номер Alpine. Доступные имена определяет выпуск и включённые репозитории.
Сначала ищем доступную ветку. Далее показан конкретный пример для системы, где найден php83; если у вас другая ветка, последовательно замените суффикс во всех именах пакетов, команд и каталогов. Не добавляйте репозиторий другой версии Alpine ради одного совпадения имени.
| Назначение | Пример для ветки 8.3 |
|---|---|
| CLI-пакет и команда | php83 |
| Менеджер процессов | Пакет php83-fpm |
| Служба OpenRC | php-fpm83: иной порядок суффикса |
| Дополнительные ini | /etc/php83/conf.d/ |
apk search 'php*'
apk info
Предусловие: Alpine с настроенным apk. search ищет пакеты в индексах; info без имени показывает установленные. Ожидается список, конкретные версии здесь не закреплены.
apk update
apk add php83 php83-gd
php83 -v
php83 --ini
php83 --ri gd
Предусловие: собственная учебная система и административная оболочка, в её репозитории действительно есть оба пакета. update обновляет индекс, add устанавливает выбранные компоненты. Здесь ничего не выполняется. Если общий псевдоним php не создан, используйте php83, не угадывайте результат PATH.
Базовый пакет и набор расширений разделены. Менеджер добавляет настройки установленных расширений; перед ручной строкой extension проверьте соответствующий conf.d. Для FPM есть отдельный пакет и жизненный цикл службы; установка CLI не создаёт обработчик Nginx.
Alpine использует собственный набор системных библиотек. Бинарный модуль, собранный для другой Linux-среды, нельзя считать совместимым только из-за совпадения PHP 8.3. Предпочтительны согласованные пакеты выпуска или сборка в его среде.
Задание: php83 -v работает, php не найден. Решение: использовать подтверждённое имя php83 в своих командах, например php83 путь/hello.php. Это не доказывает поломку установленного пакета.
Arch: пакет и включение расширения — разные шаги
Arch развивается как rolling release: пакеты рассчитаны на согласованное актуальное состояние системы. Для учебной установки следуйте модели полного обновления, принятой дистрибутивом. Комбинацию «обновить только индекс и поставить один пакет» нельзя механически переносить с другого менеджера.
Нам нужен php и, для обработки изображения, php-gd. Установка файла расширения и его подключение в ini различаются. В Arch после установки GD нужно проверить запись extension=gd в действующей конфигурации.
- pacman установил совместимый пакет php-gd
- Активный ini содержит единственное подключение extension=gd
- Новый php --ri gd подтверждает загрузку
pacman -Si php
pacman -Ss 'php-'
pacman -Q php
Предусловие: Arch и действующий pacman. -Si читает сведения из синхронизируемой базы, -Ss ищет, -Q спрашивает установленный пакет. Отсутствующий установленный php у последней команды — ожидаемый диагностический случай.
sudo pacman -Syu php php-gd
php -v
php --ini
Предусловия: собственная учебная система, изучены новости/правила обновления Arch, возможные изменения всего набора пакетов допустимы. -Syu не ограничивается PHP. Перед подтверждением читают полный план; эту команду автор не выполнял.
extension=gd
Фрагмент ini для подтверждённого CLI/SAPI. Если строка уже существует закомментированной, уберите её ;, а не создавайте вторую. Затем новый php --ri gd должен показать сведения о GD. Дополнительный ini в используемом conf.d — альтернатива правке основного файла.
Если PHP пишет о несовместимом API модуля, выясните, не собран ли он отдельно или из AUR для другой ветки. Нельзя исправить ABI-несовпадение простым переименованием .so. Согласуйте сборку PHP, заголовки и расширение.
Задание: пакет установлен, но функция GD не существует. Решение: посмотреть --ini, проверить подключение и сообщение старта, выполнить --ri gd. Это отличает отсутствующий пакет от установленного, но не загруженного модуля.
OpenBSD: packages, ports и граница chroot
OpenBSD — отдельная операционная система, а не дистрибутив Linux с другой командой установки. Простой путь — готовые packages, где ядро PHP и расширения разделены. Ports — рецепты сборки, рассчитанные на человека, который уже понимает инструментальную цепочку OpenBSD.
Пакет php может предлагать несколько версий. Сначала выбирают требуемую ветку, затем ставят согласованные расширения и читают сообщение пакета. Не копируйте названия и пути из многолетнего комментария к руководству поверх инструкций установленного выпуска.
- Пакет установил PHP и его конфигурацию
- HTTP-процесс может работать внутри chroot
- Путь /tmp или сокет базы оценивается внутри этой границы
- CLI вне chroot может видеть другие файлы
pkg_info -Q php
pkg_info
Предусловие: OpenBSD с настроенным источником пакетов. -Q ищет доступные имена; без аргументов pkg_info показывает установленные пакеты. Выберите версию по требованиям приложения, не по первому случайному совпадению.
doas pkg_add php
Предусловие: doas настроен администратором и вам разрешена установка; если pkg_add предлагает версии, выберите согласованную ветку. Прочитайте post-install инструкции, расположение конфигурации и исполняемых файлов. Для окружения без doas администратор выполняет операцию своим установленным способом.
Встроенный веб-сервер OpenBSD называется httpd, но это не Apache httpd. Конфигурация Apache с LoadModule не подходит автоматически. При chroot процесс видит ограниченное дерево, часто основанное на /var/www. Файлы сессий, DNS-настройки и Unix-сокет базы должны быть доступны в этом представлении.
Готовые пакеты и ports — альтернативы. Для сборки через ports потребуются соответствующее дерево, flavors и зависимости; прежде чем исключать модуль через flavor, проверьте реальное описание порта выбранного выпуска. Пакеты предпочтительны для первого успешного запуска.
Задание: CLI читает /tmp/cache.txt, а сайт — нет. Возможное объяснение: разные права или chroot; одинаковая строка пути ещё не гарантирует один и тот же видимый файл. Проверяйте контекст процесса вместо выдачи широких прав всему дереву.
macOS с MacPorts: отдельный поставщик и явная версия
Homebrew — не единственный путь. Если ваше окружение уже использует MacPorts, PHP лучше получать через его согласованный набор пакетов. У MacPorts собственный каталог, по умолчанию /opt/local, и версии PHP могут иметь явные имена вроде php85.
До PHP устанавливают подходящие вашему macOS инструменты разработчика и сам MacPorts по его инструкции. Пакетный установщик MacPorts может настраивать окружение. Этот шаг не выполнен автором; здесь не подменяем его командой curl, запускающей неизвестный сценарий.
- MacPorts установлен для вашей macOS
- port info php85 показывает требования и варианты
- Установка выбранного порта
- Полный путь к php85 отделяет его от Homebrew и старого системного PHP
port info php85
port installed
Предусловие: действующий MacPorts; php85 присутствует в его дереве портов. info читает сведения, installed показывает установленное. Если проект требует другую поддерживаемую ветку, сначала найдите её в каталоге портов.
sudo port install php85
/opt/local/bin/php85 -v
/opt/local/bin/php85 --ini
Предусловие: MacPorts установлен в стандартный /opt/local, его рецепт подтверждает имя бинарника php85, разрешена установка. При нестандартном prefix подставьте установленный путь. Глобальный port select и запуск FPM здесь не требуются; используем явную версию.
Дополнительные расширения, FPM и серверный модуль могут быть отдельными портами. Не подключайте к php85 DLL из Windows или модуль Homebrew, даже если он имеет похожее имя. Сначала проверьте собственный порт, ветку и способ включения.
Задание: после установки php85 команда php показывает другую версию. Решение: проверить command -v php и выполнить подтверждённый /opt/local/bin/php85 напрямую. Установка порта не обещает замену всех существующих путей.
Исторический PHP в macOS: сохранить тему, выбрать современный путь
Официальная страница bundled PHP относится к macOS до Monterey. На старой системе можно встретить /usr/bin/php и конфигурацию системного Apache. Это объясняет старые инструкции, но не подтверждает безопасность и актуальность такой версии сегодня.
Сначала прочитайте реальную версию, не включая исторический сервер. Если приложение требует современный PHP, используйте поддерживаемое окружение и отдельный менеджер пакетов либо отдельную сборку. Перезаписывать системные файлы, чтобы повторить старый рецепт, не нужно.
| Обстоятельство | Понятный путь |
|---|---|
| Современная macOS без PHP | Homebrew/MacPorts или осознанная сборка |
| Старая macOS и /usr/bin/php | Инвентаризация версии, план переноса приложения |
| Нужно воспроизвести старое поведение | Изолированное воспроизводимое окружение без публичного обслуживания |
test -x /usr/bin/php
/usr/bin/php -v
Предусловие: диагностика macOS. Первая команда проверяет существующий исполняемый файл и сама ничего не печатает; вторую выполняйте только если проверка успешна. Отсутствие /usr/bin/php на Monterey и новее не является поломкой системы.
Раньше включение PHP-модуля системного Apache связывало его с конкретной поставкой ОС. Современные инструкции установки пакета и FPM описывают другую модель; это не замена одного имени DLL в старом конфиге.
Задание: статья обещает готовый /usr/bin/php, а файла нет. Решение: сопоставить поколение macOS и дату статьи, перейти к современному пакетному уроку. Не искать случайный старый бинарник для копирования в /usr/bin.
Сборка из исходников: от текста программы к своему исполнителю
Готовый пакет подходит большинству первых задач. Своя сборка нужна, когда вы исследуете изменение PHP, необходимый вариант SAPI или параметры, которых нет у поставщика. Заодно вы берёте на себя обновления, зависимости и проверку результата.
Исходники — текст на C, компилятор превращает его в исполняемую программу. configure проверяет окружение и создаёт инструкции сборки; make следует этим инструкциям; make test запускает набор проверок; make install размещает результат по выбранному prefix. Ни один из этих шагов не равен запуску вашего hello.php.
| Компонент | Зачем |
|---|---|
| Компилятор C | PHP 8.0+ требует C99; PHP 8.4+ — C11 |
| GNU make | Выполнить подготовленные правила сборки |
| Заголовки и библиотеки | Нужны именно выбранным возможностям и расширениям |
| autoconf/re2c/bison | Дополнительные инструменты для Git-дерева или изменения генерируемых файлов |
| Отдельный prefix | Не заменить случайно PHP пакетного менеджера |
- Официальный исходный архив нужной версии и проверка происхождения
- configure выбирает CLI и отдельный prefix
- make → make test
- Проверяем собранный sapi/cli/php
- Устанавливаем в выбранное место и снова проверяем по полному пути
./configure --help
Предусловие: терминал открыт в распакованном официальном release-архиве PHP, где configure уже есть. Ожидается список параметров этой версии. Для Git checkout сначала читают README и выполняют подходящий buildconf; отсутствие configure не лечится скачиванием чужого файла.
./configure --disable-all --enable-cli --disable-cgi --prefix="$HOME/php-lessons/runtime" --with-config-file-path="$HOME/php-lessons/runtime/etc"
make
make test
Предусловия: исходное дерево нужной версии, установлен требуемый C toolchain и зависимости выбранных компонентов, prefix принадлежит пользователю и выделен под этот опыт. После каждого шага проверьте успех; не продолжайте после ошибки configure. --disable-all означает минимальную учебную сборку, не готовую среду каждого приложения.
./sapi/cli/php -n -v
./sapi/cli/php -n "$HOME/php-lessons/hello.php"
make install
"$HOME/php-lessons/runtime/bin/php" -n -v
"$HOME/php-lessons/runtime/bin/php" --ini
Предусловия: configure/make завершились успешно, результаты make test рассмотрены, prefix точно соответствует предыдущей команде и не пересекается с действующим PHP. make install здесь меняет только выбранное личное дерево; бездумный sudo не нужен. Успешный hello.php печатает проверочную строку из базовой главы. Эти команды на Unix автором не выполнялись.
Если configure не находит библиотеку, проверьте пакет разработки с заголовками и источник поиска pkg-config. Наличие исполняемой программы библиотеки не гарантирует наличие её заголовков. Если make остановился, разберите первую содержательную ошибку, а не только последнюю строку «Error».
Git-дерево отличается от release-архива: дополнительные генераторы должны соответствовать требованиям ветки. По текущему руководству autoconf нужен 2.68+ для PHP 7.3+, re2c — 1.0.3+ для PHP 8.3+, bison — 3.0+ для PHP 7.4+. Требования конкретной ветки в README имеют приоритет над старым рецептом.
Политики W^X/MPROTECT могут мешать JIT PCRE: выясняют совместимый вариант сборки или официальное правило платформы, а не отключают защиту всей системы. Кросс-компиляция Android toolchain — отдельный неподдерживаемый маршрут по этой странице PHP.net.
Задание: новая сборка установлена в личный prefix, но команда php осталась старой. Решение: это ожидаемо без изменения PATH; проверяйте новый бинарник полным путём. Сосуществование облегчает сравнение и возврат к прежнему окружению.
Компиляция на macOS: та же цепочка, другие SDK и библиотеки
Официальный подраздел компиляции macOS отсылает к Unix-цепочке. Практическая разница — инструменты Apple, SDK и архитектура. Сначала убедитесь, что Command Line Tools доступны; выбранные библиотеки и PHP должны быть одной целевой архитектуры.
Проверка пути разработчика не устанавливает Xcode. Если инструменты отсутствуют, установите совместимую поставку Apple по её инструкции, затем вернитесь к сборке. Смешение Intel-библиотек и arm64-компиляции часто проявляется уже на этапе связывания.
| Проверка | Что узнаём |
|---|---|
| xcode-select -p | Выбранный каталог инструментов разработчика |
| clang --version | Какой компилятор запущен |
| uname -m | Архитектура текущего окружения |
| README выбранного PHP | Что требуется этой ветке языка |
xcode-select -p
clang --version
uname -m
Предусловие: macOS с установленными инструментами разработчика. Команды читают сведения; если инструмента нет, сообщение ошибки само является результатом диагностики. Никакая версия или архитектура заранее не обещана.
Далее примените отдельный prefix и цикл configure → make → make test из предыдущего раздела. Пути Homebrew на разных архитектурах различаются; при поиске зависимостей используйте сведения своего менеджера, не подставляйте наугад /usr/local или /opt/homebrew.
Задание: configure видит библиотеку, но linker отвергает её архитектуру. Решение: сверить архитектуру compiler target, PHP и библиотеки, установить или собрать совместимую зависимость в своём окружении. Простое переименование файла архитектуру не меняет.
Solaris: исторические инструменты и современная проверка пакетов
Страница PHP.net о Solaris сохраняет полезное объяснение инструментария, но упоминает также исторические pkgadd и Solaris 11 Express. Название официального раздела не обещает, что все его старые команды подходят каждому современному выпуску.
Нужно различать две модели: старые SVR4-пакеты с pkgadd и Image Packaging System с командой pkg в Solaris 11. Для своего выпуска сначала читают Oracle-документацию пакетов и список доступных компонентов. Здесь не обещается наличие конкретной современной ветки PHP в вашем репозитории.
- Узнать выпуск и архитектуру
- Выяснить механизм пакетов и доступный toolchain
- Выбрать поддерживаемый пакет либо обоснованную сборку
- Проверить CLI отдельно от серверной интеграции
uname -a
pkg publisher
pkg list -a '*php*'
Предусловие: Solaris 11 с IPS. Команды не устанавливают PHP; -a в pkg list запрашивает также доступные пакеты. Пустой список PHP не разрешает считать случайный сторонний бинарник совместимым.
При сборке понадобятся совместимый компилятор C, make и корректные Unix-инструменты; старое руководство отдельно подчёркивает GNU sed. Дополнительные расширения требуют своих библиотек и заголовков. Факт наличия gcc не доказывает поддержку требуемого PHP стандарта C11.
Современный путь для нового приложения выбирают по поддержке ОС и PHP, доступности обновлений и воспроизводимости. Если нужной поддерживаемой комбинации нет, перенос на подтверждённое окружение — отдельная миграционная задача. Solaris сохраняется в дереве руководства; его описание не маскируется под проверенную на этой Windows машине установку.
Задание: инструкция для Solaris 11 Express предлагает pkgadd, а администратор использует IPS. Решение: сначала установить модель пакетов конкретного выпуска и следовать её документации; не смешивать два способа управления одними файлами.
CLI, CGI и FastCGI: один язык, разные договорённости о запуске
Сохранённый hello.php можно запустить из терминала. Для сайта нужно ещё передать запрос и вернуть ответ браузеру. CGI описывает такой обмен: сервер готовит сведения о запросе и входное тело, запускает обработчик и читает его ответ. FastCGI сохраняет процессы между запросами, уменьшая повторные затраты на запуск.
CLI предназначен для командной строки. CGI/FastCGI-процесс понимает серверный протокол; подмена его обычным CLI только из-за одинакового языка не делает интеграцию корректной. FPM — менеджер процессов FastCGI для Unix. В Windows IIS обычно управляет php-cgi.exe самостоятельно.
Сначала разберём минимальный ответ. header задаёт HTTP-заголовок: тип выдаваемого текста и кодировку. echo печатает тело. Между ними нельзя случайно вывести пробел перед <?php: заголовки должны формироваться до тела. Подробнее — модель запроса и ответа.
- Браузер обращается к веб-серверу
- Сервер находит health.php и передаёт параметры запроса
- PHP формирует заголовок и тело
- Сервер возвращает браузеру HTTP-ответ
<?php
header('Content-Type: text/plain; charset=UTF-8');
echo "Каталог доступен\n";
Ожидаемый результат
Каталог доступен
Самостоятельный PHP-файл. Здесь проверено выполнение CLI и точное тело; header в CLI не доказывает HTTP-заголовок. В отдельной настроенной HTTP-среде запрос /health.php должен дать статус 200, Content-Type text/plain; charset=UTF-8 и это тело. Автор не запускал Apache/FPM/IIS для данного фрагмента.
| Часть запроса | Пример | Что означает |
|---|---|---|
| REQUEST_METHOD | GET | Способ обращения, а не имя PHP-функции |
| QUERY_STRING | page=2 | Часть URL после вопросительного знака |
| CONTENT_TYPE / CONTENT_LENGTH | Тип и размер тела | Нужны для разбора присланного тела |
| SCRIPT_NAME / PATH_INFO | /health.php и дополнительный путь | Разные части пути; наличие зависит от настройки |
| REMOTE_ADDR | Адрес соединения | При прокси это может быть адрес прокси, не посетителя |
| SCRIPT_FILENAME | Физический путь к файлу | Расширение серверного соглашения, не обязательное поле CGI/1.1 |
Не считайте любой ключ $_SERVER обязательным: набор зависит от SAPI и сервера. Программа командной строки не получает HTTP-запрос автоматически. Минимальная диагностика ниже использует ?? — «если слева отсутствует значение или оно null, взять правое». Это не имитация веб-сервера, а явная надпись о другом окружении.
<?php
echo "method:", $_SERVER['REQUEST_METHOD'] ?? 'no-http-request', "\n";
echo "query:", $_SERVER['QUERY_STRING'] ?? '', "\n";
Ожидаемый результат
method:no-http-request
query:
Точный результат относится к чистому CLI без одноимённых переменных окружения. [] выбирает ключ массива сведений, ?? задаёт запасное значение. При настоящем GET /context.php?page=2 ожидаются строки method:GET и query:page=2; такая HTTP-проверка в этой партии не выполнялась.
CGI-исполнитель нельзя публиковать как обычный доступный для скачивания файл или запускать с произвольным переданным посетителем путём. Маршрут URL → существующий разрешённый PHP-файл задаёт сервер. Права обработчика должны позволять чтение кода и только необходимые записи данных.
Упражнение: сервер показывает исходник health.php. Решение: остановить публичную выдачу этого каталога и проверить обработчик PHP. Установка расширения json проблему маршрутизации не исправляет. Если получен 502, исследуйте соединение сервера с FastCGI и журнал процесса; синтаксис PHP может ещё не выполняться.
FPM: зачем нужен pool и куда сервер отправляет запрос
Представьте пункт выдачи с несколькими сотрудниками. Сервер принимает посетителей, а свободный PHP-worker обрабатывает запрос. Pool — группа таких процессов с общими настройками. Модель помогает оценить очередь, но один worker не является отдельным постоянным пользователем: следующий запрос может принадлежать другому посетителю.
Предусловия: выполнен первый CLI-файл, понятны запрос/ответ и права файлов. FPM установлен отдельным пакетом вашей Unix-системы либо собран по следующему уроку. Имена службы и исполняемого файла зависят от поставщика; php-fpm8.5 и php-fpm — возможные разные имена. FPM не является обычным HTTP-сервером: открыть его порт браузером недостаточно.
| Поле pool | Учебное значение | Кто его использует |
|---|---|---|
| [lessons] | Имя группы | FPM при чтении файла |
| user / group | Учётная запись lessons | ОС для прав worker |
| listen | 127.0.0.1:9070 | Сервер при соединении FastCGI |
| pm | ondemand | FPM создаёт процессы при поступлении работы |
| pm.max_children | 2 | Не более двух одновременно работающих процессов этого pool |
[lessons]
user = lessons
group = lessons
listen = 127.0.0.1:9070
listen.allowed_clients = 127.0.0.1
pm = ondemand
pm.max_children = 2
pm.process_idle_timeout = 10s
pm.max_requests = 200
security.limit_extensions = .php
Фрагмент pool-конфигурации, а не php.ini. Предусловия: Linux/Unix с FPM, специально созданная администратором учётная запись lessons и читаемый ею учебный каталог; свободный локальный порт9070, включение этого файла глобальной конфигурацией FPM. Автор пользователя, службу и сокет не создавал. Числа учебные, не рекомендации для произвольной нагрузки.
В записи имя = значение левая часть — директива FPM. [lessons] начинает pool. pm.max_requests перезапускает worker после определённого числа запросов; это не ограничитель частоты обращений клиента. pm.process_idle_timeout относится к ondemand и задаёт ожидание без работы.
Перед включением серверной связи владелец среды проверяет конфигурацию FPM. Проверка -t не заменяет запуск, права файлов и HTTP-запрос. -y выбирает конкретный файл, чтобы случайно не проверить соседнюю установку.
/opt/lessons/php/sbin/php-fpm -t -y /opt/lessons/php/etc/php-fpm.conf
Предусловие: ваша отдельная сборка установлена именно в /opt/lessons/php, global config включает нужный pool. Подставьте реальный путь или имя пакета. Ожидается успешная проверка с exit status0; текст зависит от версии. Команда не запускалась автором.
- FPM принимает собственную конфигурацию
- Сокет или локальный порт доступен серверу
- Worker читает health.php
- HTTP-запрос возвращает заголовок и ожидаемое тело
Для Unix socket на Linux вместо TCP нужны согласованные listen.owner, listen.group и listen.mode: серверу требуется право соединения, worker — отдельные права чтения проекта. Многие BSD-системы допускают соединение независимо от этих socket permissions, поэтому их модель доступа проверяется отдельно. Изменение chmod на777 не объясняет причину ошибки. Для TCP локальный адрес сам по себе не изолирует недоверенные локальные процессы; на общем хостинге проектируйте доступ отдельно.
Два pool не дают полной изоляции недоверенного кода: в частности, один FPM master может разделять OPcache. Для разных владельцев с недоверенным кодом может требоваться разделение процессов/служб или контейнеров с отдельными правами.
Упражнение: сервер ожидает /run/lessons.sock, а pool слушает127.0.0.1:9070. Решение: выбрать один способ и согласовать обе стороны; менять PHP-функцию echo бессмысленно.
Собрать FPM: отдельная опция, отдельные настройки запуска
Наличие собранного CLI не гарантирует наличие FPM. Для собственного сервера к команде configure добавляют --enable-fpm. Ключи ниже определяют возможности сборки; поля pool затем определяют конкретную работу процессов.
Предусловия и последовательность configure → make → make test уже разобраны в сборке в отдельный prefix. Не пересобирайте системный PHP только ради знакомства: сначала выясните, предоставляет ли дистрибутив подходящий пакет php-fpm.
./configure --disable-all --enable-cli --disable-cgi --enable-fpm --prefix="$HOME/php-lessons/fpm"
make
make test
Предусловие: подготовленное дерево release и его зависимости. Минимальная сборка не включает все расширения будущего сайта. Ожидается успешная сборка sapi/fpm/php-fpm; сами процессы здесь не запускаются. Для установки потребуется отдельный обоснованный make install в выбранный prefix.
| Опция configure | Зачем | Граница |
|---|---|---|
| --with-fpm-user / --with-fpm-group | Значения пользователя/группы по умолчанию | Не создают учётную запись ОС; по умолчанию nobody |
| --with-fpm-systemd | Интеграция с systemd | Не создаёт вашу службу и не запускает её |
| --with-fpm-acl | POSIX ACL для сокетов | Требует поддержки и зависимостей платформы |
| --with-fpm-apparmor | Интеграция AppArmor, PHP8.0+ | Профиль и политика ОС настраиваются отдельно |
| --with-fpm-selinux | Интеграция SELinux, PHP8.2+ | Не означает отключение или автоматическое разрешение политики |
После установки найдите поставленные образцы глобальной и pool-конфигурации, задайте существующего пользователя, адрес прослушивания, журналы и нужные расширения. Затем выполните -t с конкретным файлом. Управлять жизненным циклом должен выбранный механизм вашей ОС; systemd, OpenRC и rc.d не взаимозаменяемы.
Задание: configure принят с --with-fpm-user=lessons, а при запуске пользователя нет. Решение: опция задаёт строку конфигурации, не управляет базой пользователей ОС; существование и права учётной записи обеспечивает администратор.
Apache и FPM: разделить раздачу файлов и выполнение PHP
Apache может отдавать картинки самостоятельно, а файлы .php передавать FPM. Для новых Unix-установок текущая страница PHP.net рекомендует именно этот путь через mod_proxy_fcgi, обычно с event MPM. Модуль Apache передаёт работу; он не устанавливает и не запускает FPM.
Предусловия: уже настроен отдельный localhost-виртуальный хост Apache2.4, его DocumentRoot указывает на учебный public, включены mod_proxy и mod_proxy_fcgi; FPM слушает127.0.0.1:9070 из предыдущего примера. Ни один из этих шагов не считается выполненным только потому, что скопирован следующий фрагмент.
- Apache выбирает виртуальный хост и файл
- FilesMatch выбирает окончание .php
- mod_proxy_fcgi обращается к FPM9070
- FPM выполняет health.php и отдаёт ответ
<FilesMatch "\.php$">
SetHandler "proxy:fcgi://127.0.0.1:9070"
</FilesMatch>
Контекст Apache2.4.10+ с требуемыми модулями и согласованным FPM. FilesMatch выбирает имена: \. означает точку, php — окончание, $ — конец имени. Файл photo.php.jpg не подходит. Это часть виртуального хоста, не полный серверный конфиг; права Directory, Listen и DocumentRoot заданы владельцем среды.
Для Unix socket форма назначения отличается: proxy:unix:/run/lessons.sock|fcgi://localhost/ связывает локальный сокет и FastCGI. Путь должен совпадать с listen у FPM, а Apache должен иметь доступ. Не копируйте сокет пакета другой версии.
Проверка по порядку: сначала статический hello.txt из этого DocumentRoot, затем health.php с ожидаемым телом и HTTP-заголовком, затем намеренно отсутствующий missing.php с ошибкой404. Если PHP-код скачивается или показывается текстом, обработчик не назначен: такой каталог нельзя открывать посетителям.
Служебные страницы FPM/status, пинг и развёрнутый phpinfo не должны становиться общедоступными ради проверки. Для первого результата достаточно health.php; удалите диагностический файл после опыта.
Не включайте enablereuse=on по случайному совету: постоянные соединения Apache могут занять процессы FPM. Размеры пулов Apache/FPM и нагрузка согласуются измерениями. Упражнение: статическая страница работает, PHP даёт502. Решение: исследовать путь к backend и журналы FPM/Apache, затем права и имя файла; браузер уже успешно связался с Apache.
Исторический mod_php на Unix: понять существующую установку
Встречается сервер, где PHP встроен в процесс Apache через apache2handler. Это отдельный официальный маршрут, полезный для сопровождения действующей системы. Для новой установки предыдущий урок с FPM обычно даёт более подходящее разделение процессов; наличие mod_php в дереве не является рекомендацией заменить им FPM.
Нужны совместимый Apache, инструменты разработки его модуля и PHP той же архитектуры. apxs — инструмент Apache для сборки/установки расширений сервера. Опция --with-apxs2 связывает сборку PHP с конкретным apxs, поэтому неверный путь может попасть в другую установленную версию Apache.
| Проверяем | Причина |
|---|---|
| Версия Apache | Для apache2handler PHP8.4+ нужен Apache2.4; старые2.0/2.2 завершили поддержку |
| MPM и потокобезопасность | Для обычного NTS mod_php нужен prefork; threaded MPM требует отдельной оценки ZTS и расширений |
| apxs конкретного сервера | У него правильные заголовки и каталог modules |
| Нужные расширения | Они загружаются в тот же процесс сервера |
| Где перечитывается ini | Перезапуск/перезагрузка веб-процессов, не новая вкладка браузера |
./configure --with-apxs2=/opt/lessons/apache/bin/apxs --prefix="$HOME/php-lessons/apache-php"
Контекст: отдельный учебный Apache с существующим apxs по этому пути, совместимые headers/toolchain, выбран MPM. Не полная production-команда и не выполненная сборка. Последующий make install способен записать модуль в каталог Apache: его область прав и резервный возврат проверяют заранее.
LoadModule php_module modules/libphp.so
<FilesMatch "\.php$">
SetHandler application/x-httpd-php
</FilesMatch>
Контекст: совместимый libphp.so действительно установлен в modules этого Apache. Имя файла проверяют по результату сборки. Не включайте параллельно конкурирующее назначение того же .php на FPM.
SetHandler задаёт способ обработки; MIME-тип и исполняемый обработчик — разные вещи. Старые рецепты с AddType могут неожиданно затронуть имена с несколькими расширениями. Для учебной проверки используйте точное окончание .php.
Не включайте публикацию подсвеченного исходника через .phps ради красивого просмотра: исходный PHP способен раскрыть внутренние пути и секреты. Если сайт использует FallbackResource/front controller, порядок выбора обработчика и существования файла требует отдельной настройки Apache; приведённый минимальный пример рассматривает настоящий health.php.
Задание: после переключения Apache на event MPM старый NTS mod_php отказывается работать. Решение: проверять совместимость модели процессов и SAPI; простое переименование libphp.so не делает код потокобезопасным.
Nginx и FPM: проверить существование файла перед передачей
Nginx сам PHP не выполняет: он выбирает файл и передаёт FastCGI-запрос FPM. В официальном дереве PHP сохранено название «Nginx1.4.x»; конкретные старые версии исходников из того примера не следует устанавливать сегодня. Здесь используем модель текущей документации Nginx и свой учебный public.
Предусловия: Nginx установлен в отдельной учебной Unix-среде, каталог /srv/php-lessons/public содержит health.php, FPM-пользователь читает его, backend слушает127.0.0.1:9070. Пример рассчитан на существующие PHP-файлы; маршрутизация приложения через index.php рассматривается отдельно.
server {
listen 127.0.0.1:8080;
server_name localhost;
root /srv/php-lessons/public;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass 127.0.0.1:9070;
}
}
Фрагмент включается в http-контекст своей конфигурации Nginx; порт8080 должен быть свободен. Файл fastcgi_params предоставлен пакетом: проверьте наличие стандартных параметров запроса и отсутствие другого противоречащего SCRIPT_FILENAME. Автор не запускал nginx -t или HTTP; блок требует проверки в целевой системе.
| Строка | Простой смысл |
|---|---|
| listen127.0.0.1:8080 | HTTP доступен через локальный интерфейс этой машины |
| root | Физическая папка файлов; не URL |
| location ~ \.php$ | Правило имён, оканчивающихся на .php |
| try_files $uri =404 | Не передавать отсутствующий файл в FPM |
| SCRIPT_FILENAME | Собрать путь к выполняемому файлу для PHP |
| fastcgi_pass | Адрес FPM, не адрес браузера |
Переменные Nginx со знаком $ — синтаксис Nginx, а не переменные PHP. Фигурные скобки ограничивают блок настроек. include читает файл конфигурации Nginx; это не PHP include. Путь root должен соответствовать реальному размещению файлов; alias и path-info требуют других проверенных правил.
Сначала владелец среды выполняет nginx -t с нужной конфигурацией, затем применяет её принятой командой управления своим Nginx. В браузере отдельной учебной машины запрашивают http://127.0.0.1:8080/health.php и получают «Каталог доступен». Для missing.php ожидается404, для photo.php.jpg правило PHP не выбирается.
В старых рекомендациях встречается cgi.fix_pathinfo=0. Это параметр PHP, а не замена проверке пути и прав; в приложениях с PATH_INFO изменение требует анализа маршрутизации. Не размещайте исполняемый PHP в каталоге, куда посетитель может загрузить произвольный файл.
Упражнение: SCRIPT_FILENAME указывает /srv/old/public/health.php, а root — /srv/php-lessons/public. Решение: согласовать физический путь; переустановка Nginx не исправляет ошибочно составленное имя.
Lighttpd: подключиться к FPM или управлять php-cgi
В небольшом сервисе Lighttpd может отдавать статические файлы и отправлять PHP в FastCGI. Сначала выберите владельца процессов: либо их уже поддерживает FPM, либо Lighttpd запускает php-cgi через bin-path. Совмещать два независимых менеджера для одного сокета не нужно.
Начнём с уже работающего учебного FPM на127.0.0.1:9070. У Lighttpd должен быть собственный локальный listener и document-root с health.php. fastcgi.server связывает расширение .php с адресом обработчика. Скобки группируют список параметров; запись ключ => значение здесь является синтаксисом конфигурации Lighttpd, а не PHP-кодом.
- Lighttpd находит файл в document-root
- mod_fastcgi обращается к уже настроенному FPM
- FPM выбирает worker
- Lighttpd возвращает его ответ
server.modules += ( "mod_fastcgi" )
fastcgi.server = (
".php" => ((
"host" => "127.0.0.1",
"port" => 9070,
"check-local" => "enable"
))
)
Предусловия: Lighttpd1.4 настроен для своего localhost-сайта; модуль ещё не включён повторно; существующий FPM читает тот же каталог. check-local требует реального файла и даёт404 до обращения к backend при его отсутствии. Конфигурацию и HTTP в Lighttpd автор не запускал.
Другой официальный путь — Lighttpd запускает php-cgi. Тогда bin-path задаёт полный путь к исполняемому файлу, socket — отдельный Unix socket, bin-environment — переменные окружения запуска. Не используйте общедоступный предсказуемый /tmp-сокет без анализа прав: каталог runtime должен принадлежать ответственному сервису.
| Настройка в модели php-cgi | Действие | Типичная ошибка |
|---|---|---|
| bin-path | Lighttpd запускает этот php-cgi | Подставлен CLI php или бинарник другой ветки |
| PHP_FCGI_CHILDREN | Число дочерних процессов PHP | Без расчёта перемножили с группами Lighttpd |
| PHP_FCGI_MAX_REQUESTS | Сколько запросов живёт дочерний процесс | Приняли за лимит запросов посетителя |
| min-procs / max-procs | Управление запускаемыми группами | 2 группы ×16 детей дают32 responder |
| spawn-fcgi | Отдельная утилита запуска FastCGI | Одновременно назначили запуск ещё и через bin-path |
Для этого второго варианта сначала прочтите текущий рецепт своего пакета Lighttpd. В официальном PHP-дереве есть также ручной запуск php-cgi с -b и пример внешних backend: это варианты жизненного цикла, а не ещё два обязательных шага. Внешний FastCGI-порт нельзя открывать недоверенной сети; HTTP-авторизация сайта не защищает прямой доступ к нему.
Упражнение: после добавления bin-path число PHP-процессов неожиданно удвоилось. Решение: проверить, кто создаёт группы, количество детей и не продолжает ли работать старый менеджер. Одинаковые порты не превращают две группы в одну. Полная настройка самостоятельного spawn-fcgi с supervisor остаётся отдельной практикой.
LiteSpeed/OpenLiteSpeed: выбрать именно LSPHP и назначить обработчик
LSPHP — PHP, собранный с интерфейсом LiteSpeed. Его отдельный процесс получает работу по LSAPI. Наличие обычного CLI в /usr/bin/php не доказывает, что сайт LiteSpeed использует ту же версию. Здесь особенно полезно записать точный путь обработчика.
В PHP.net сохранён пример PHP5.6 со старым ключом --with-litespeed. Документация поставщика разделяет версии: для PHP7.4+ используют --enable-litespeed, для7.3 и раньше — --with-litespeed. Старое имя раздела и старый номер не выбирают за вас поддерживаемую ветку.
| Что соединяем | Учебная карта |
|---|---|
| Выбранный пакет | lsphp85 соответствующей поддерживаемой ОС |
| Исполнитель | /usr/local/lsws/lsphp85/bin/lsphp при штатном пути этого пакета |
| Handler ID | Уникальное имя php85 в LSWS |
| Handled Suffixes | php — файлы с этим окончанием |
| Настройки процесса | Окружение, число детей, тайм-ауты и права этого обработчика |
/usr/local/lsws/lsphp85/bin/lsphp -v
/usr/local/lsws/lsphp85/bin/lsphp --ini
Предусловие: этот пакет действительно установлен из выбранного доверенного репозитория и использует указанный путь. Ожидается выбранная версия и SAPI litespeed; точные строки зависят от сборки. Ничего не устанавливается этими командами; автор их не выполнял.
Путь для LSWS5.3+: в WebAdmin настраивают PHP handler, его Command и Handled Suffixes, затем применяют изменения и обновляют detached PHP-процессы по инструкции поставщика. В OpenLiteSpeed связь обычно настраивается через External App и Script Handler; экран LSWS нельзя дословно переносить в другую панель.
Если собираете из исходников, добавьте --enable-litespeed к обоснованным опциям, задайте отдельный prefix, соберите и проверьте бинарник до назначения сайту. Слепое копирование длинного списка --with-* из старой страницы может требовать удалённые расширения.
В модели LSAPI число разрешённых соединений и PHP_LSAPI_CHILDREN согласуют; PHP_LSAPI_MAX_REQUESTS задаёт срок жизни worker по числу запросов. При ручном lsphp -b адрес описывает backend, не HTTP-сайт. Предпочитайте ограниченный локальный сокет/интерфейс; пример прослушивания всех адресов из справочника не подходит для открытой сети.
Проверка: запрос health.php через выбранный виртуальный хост должен вернуть ожидаемый текст; диагностическая версия сайта должна совпасть с Command нужного handler. Упражнение: CLI показывает8.5, сайт —8.3. Решение: проверить сопоставление суффикса и путь LSPHP; PATH терминала не переключает handler панели. Подробные рецепты cPanel/Plesk и самостоятельного внешнего LSAPI остаются следующими платформенными подразделами.
Windows: проверить ZIP, архитектуру, TS/NTS и зависимые DLL
Первый путь через распаковку и hello.php уже описан в базовой установке Windows. Теперь разберём сбой «программа есть, но не запускается». Совместимость состоит из нескольких независимых условий. ZIPx64 не работает как x86 только после переименования, а TS означает поддержку многопоточного окружения, а не «ускоренную версию».
Для PHP8.5 выбирайте требования именно этой ветки и официальной Windows-сборки. Не переносите минимальную версию Windows из старой инструкции PHP7. Имеет значение и поддержка ОС поставщиком, и наличие подходящих обновлений CRT. Официальные готовые сборки представлены x86/x64; родной ARM-бинарник нельзя предполагать по факту ARM-процессора.
| Условие | Как решить |
|---|---|
| x86 или x64 | Согласовать PHP, серверный модуль, расширения и CRT |
| NTS | Обычный выбор для CLI и IIS/FastCGI |
| TS | Нужен для apache2handler на Windows |
| Компилятор и CRT | Установленная Microsoft runtime должна удовлетворять выбранной сборке |
| Ветка и API расширения | DLL расширения должна быть собрана для совместимого PHP |
| Дополнительные DLL | Зависимости расширения тоже должны разрешаться загрузчиком |
& 'C:\php85\php.exe' -n -v
& 'C:\php85\php.exe' -n -i | Select-String 'Architecture|Thread Safety|Compiler|PHP API'
PowerShell. Предусловие: выбранная Windows-сборка распакована в C:\php85, CRT совместима. & запускает путь в кавычках, -n отключает ini, -i выдаёт сведения, | передаёт текст Select-String для отбора строк. Пути и результат зависят от установки; эти команды здесь не меняют настройки.
Если -n -v запускается, а обычный -v сообщает Unable to load dynamic library, исследуйте подключённые ini и расширение. Если даже -n -v не запускается, сначала проверяют сам бинарник, архитектуру, CRT и системное сообщение, а не строку extension в ещё не прочитанном ini.
Перед новой веткой распакуйте её в отдельный каталог. Не заменяйте одну php.exe среди DLL старой поставки. Переносите настройки осмысленно: нужные директивы и расширения, затем проверка выбранного процесса; целиком старый ini способен содержать удалённые параметры.
Упражнение: добавили TS-DLL расширения в NTS PHP и получили ошибку. Решение: загрузить соответствующую NTS/архитектуре/API сборку или собрать совместимую; копирование её в System32 не меняет интерфейс. Полная практика установки сторонних расширений будет в ветке PECL/PIE.
Windows CLI: аргументы, консоль и необязательные ассоциации файлов
Отчёт должен получить месяц запуска. Для этого не требуется менять PATH, PATHEXT или реестр: надёжный первый шаг — явный полный путь к php.exe и отдельный путь к файлу. PHP получает аргументы в массиве $argv: элемент0 — имя файла, элемент1 — первый переданный аргумент.
Сначала самостоятельный запуск без аргументов. ?? задаёт значение по умолчанию, поэтому программа остаётся работоспособной при первом открытии терминала. Это только знакомство с передачей строки; проверка календарного формата добавляется на следующем уровне приложения.
<?php
$month = $argv[1] ?? '2026-10';
echo "Месяц отчёта: ", $month, "\n";
Ожидаемый результат
Месяц отчёта: 2026-10
$month хранит строку, $argv[1] читает первый аргумент, запятые echo разделяют выводимые части. Самостоятельный запуск без аргумента проверен. Реальный расчёт отчёта не выполняется: это минимальная проверка договора запуска.
& 'C:\php85\php.exe' -f 'C:\PHP Lessons\report.php' -- '2026-11'
PowerShell, оба пути существуют. -f выбирает файл, -- завершает список опций PHP, после него идёт аргумент программы. Ожидаемое тело: «Месяц отчёта: 2026-11» и перевод строки. Этот вызов с Windows-путями документирован, не исполнен автором.
| Механизм Windows | Что меняет | Почему не нужен для первого запуска |
|---|---|---|
| PATH | Поиск программы по короткому имени | Можно дать полный путь php.exe |
| PATHEXT | Какие расширения пробует командная оболочка | Порядок .PHP/.BAT влияет на совпадающие имена |
| assoc / ftype | Связь расширения и команды открытия в cmd | Ассоциация не нужна при явном запуске исполнителя |
| php-win.exe | Вариант без окна консоли | Для урока нужен видимый вывод/ошибки php.exe |
| Исторический InheritConsoleHandles | Поведение старых ассоциаций с конвейером | Не переносится как обязательная правка реестра на современную Windows |
В официальной странице сохранён рецепт assoc/ftype/PATHEXT. Это дополнительная настройка оболочки, а не условие работы языка. Команды assoc и ftype относятся к cmd, поэтому их нельзя считать встроенными командами PowerShell. Не перезаписывайте существующий PATH/PATHEXT значением из учебного примера.
Для фоновой задачи планировщика также указывают явные пути к исполнителю, файлу и рабочему каталогу. Двойной щелчок может закрыть консоль сразу после выполнения; для диагностики сначала запускайте из уже открытого терминала.
Упражнение: есть report.php и report.bat с одинаковой основой, а результат неожиданен. Решение: устранить неоднозначность явным вызовом php.exe с полным именем файла; затем исследовать ассоциации, не меняя их вслепую.
Apache на Windows: handler TS или отдельный FastCGI
Для собственного Windows-сайта с Apache существуют два разных пути: PHP-модуль внутри Apache и отдельный php-cgi.exe через FastCGI. Сначала выбирают один путь и совместимые сборки. Установленный Apache должен успешно отдать простой hello.txt из выделенного локального каталога до подключения PHP.
В режиме handler нужен TS PHP той же архитектуры, совместимый Apache2.4 и реально существующий php8apache2_4.dll. Apache-пути удобно писать с прямыми слешами и кавычками. Для PHP8 имя модуля php_module; php7_module относится к старой ветке.
LoadModule php_module "C:/php85-ts/php8apache2_4.dll"
PHPIniDir "C:/php85-ts"
<FilesMatch "\.php$">
SetHandler application/x-httpd-php
</FilesMatch>
Фрагмент конфигурации собственного Apache с подходящей TS-сборкой. Путь C:/php85-ts выбран для этой модели и должен существовать. После конфигурационной проверки владелец обновляет веб-процессы и запрашивает health.php; автор Apache не запускал.
PHPIniDir выбирает каталог ini для модуля; PATH терминала не заменяет эту настройку. Если Apache не стартует, читайте его журнал и проверяйте совместимость DLL/архитектуры; успешный CLI-NTS в другом каталоге здесь не является доказательством.
В варианте mod_fcgid отдельный модуль Apache управляет php-cgi.exe. В нём выбирают NTS-сборку, FcgidWrapper с её полным путём и FcgidInitialEnv PHPRC с её ini. FPM на Windows не требуется: это другой менеджер процессов.
FcgidInitialEnv PHPRC "C:/php85-nts"
FcgidWrapper "C:/php85-nts/php-cgi.exe" .php
<FilesMatch "\.php$">
SetHandler fcgid-script
</FilesMatch>
Контекстный фрагмент: mod_fcgid уже установлен/загружен, каталог сайта разрешён настройками Apache и ExecCGI в нужном контексте; конкурирующего handler PHP нет. Полная политика Directory и установка модуля определяются владельцем Apache. Не применять этот блок одновременно с предыдущим handler к одним файлам.
Классический CGI со ScriptAlias и отдельным процессом также сохранён в PHP.net. Он требует правил CGI-безопасности и согласованного пути к обработчику; это маршрут сопровождения конкретной конфигурации, а не следующий обязательный шаг после FastCGI. Не давайте клиенту выбирать произвольную программу или файл для исполнения.
Упражнение: изменили ini в C:/php85-nts, а сайт handler продолжает старые настройки. Решение: он использует C:/php85-ts из PHPIniDir. Сначала установите реальный SAPI и loaded ini сайта, затем меняйте правильный файл.
IIS: две связи — FastCGI-приложение и handler сайта
IIS принимает HTTP-запрос, но для выполнения PHP ему нужно знать и исполняемую программу, и какие файлы ей передавать. Создание записи FastCGI само по себе не добавляет сопоставление *.php. Эта разница объясняет частую ситуацию: PHP присутствует на диске, а страница всё ещё не исполняется.
Предусловия: собственная учебная Windows-среда с включёнными IIS и компонентом CGI, разрешённые административные действия, отдельный сайт с локальной привязкой, совместимая NTS-сборка в C:/php85-nts. Включение компонентов Windows и правка служб здесь не выполнялись; меню установки компонентов зависит от редакции Windows/Server.
- Handler сайта сопоставляет *.php с FastCgiModule
- FastCGI application указывает php-cgi.exe
- Процесс читает собственный ini и health.php
- IIS отдаёт результат браузеру
| Шаг в IIS Manager | Конкретный выбор | Проверка смысла |
|---|---|---|
| FastCGI Settings → Add Application | Full Path: C:\php85-nts\php-cgi.exe | Выбран CGI/FastCGI, не php.exe |
| Handler Mappings нужного сайта → Add Module Mapping | Request path: *.php; Module: FastCgiModule | Сопоставление относится к нужному сайту |
| Executable в этом mapping | Тот же php-cgi.exe | Путь совпадает с FastCGI application |
| Request Restrictions | Выполнение существующего файла | Произвольный отсутствующий путь не становится PHP-кодом |
| Права Application Pool identity | Чтение программы/кода, запись только необходимых данных | Не выдавать всему сайту полный доступ без причины |
Если PHP должен читать определённый ini, в окружении FastCGI application задают PHPRC с каталогом конфигурации. Не подменяйте это глобальным изменением системного PATH: другие программы сервера могут зависеть от прежнего окружения.
У FastCGI есть срок жизни процесса instanceMaxRequests; у PHP — PHP_FCGI_MAX_REQUESTS. Согласуйте их: предел IIS должен быть не больше PHP, чтобы управление повторным запуском не расходилось. Число запросов до переработки процесса отличается от activityTimeout, requestTimeout и максимального числа процессов; увеличение всех значений не является лечением медленного кода.
& 'C:\php85-nts\php-cgi.exe' -i | Select-String 'Loaded Configuration File|Thread Safety'
PowerShell. Предусловие: выбранный бинарник существует и запускается; вывод CGI может содержать HTML. Команда проверяет этот отдельный процесс, но не окружение identity/PHPRC, настроенное в IIS. Окончательное доказательство — запрос к учебному сайту через IIS.
Последовательность первого результата: hello.txt проверяет привязку и чтение; health.php возвращает «Каталог доступен»; missing.php не исполняется; журналы не содержат ошибок запуска CGI. После изменения ini обновляют соответствующие процессы приложения установленным способом, затем повторяют HTTP-проверку.
Не копируйте команды с clear/delete всех handler из старого рецепта: они затронут чужие приложения. Учебный путь — отдельный сайт и одно осмысленное сопоставление. Упражнение: FastCGI Settings заполнены, но *.php скачивается. Решение: проверить Handler Mappings именно этого сайта и наследование его конфигурации.
Windows: собрать собственный CLI и не заменить установленный PHP
Сборка из исходников нужна, например, для исследования изменения движка или разработки расширения. Для первой программы она обычно не нужна: готовый ZIP даёт более короткий путь. Прежде чем компилировать, зафиксируйте цель, версию исходников, архитектуру и TS/NTS.
Три отдельных набора: исходники PHP, компилятор с SDK и библиотеки-зависимости. Microsoft Redistributable позволяет запускать готовую программу, но не заменяет компилятор Visual C++. Официальный PHP SDK подготавливает окружение сборки; обычная пустая PowerShell-сессия не равнозначна его командной строке.
| Ветка PHP | Компилятор по официальной инструкции | Что не следует смешивать |
|---|---|---|
| 8.0–8.3 | Visual Studio2019 / VS16 | Зависимости другой целевой архитектуры |
| 8.4–8.5 | Visual Studio2022 / VS17 | Старый VC14 из примера для PHP7.1 |
| Любая выбранная ветка | Согласованный PHP SDK и зависимости | Случайный MinGW/Cygwin вместо поддерживаемого MSVC |
- Отдельный каталог SDK и исходников
- Командная строка SDK нужной архитектуры
- configure выбирает минимальный CLI
- nmake создаёт бинарник в release-каталоге
- Полным путём проверяем новый бинарник
До команд ниже установите согласованные инструменты по официальной инструкции в отдельной учебной среде. Запустите starter script SDK для VS17/x64; phpsdk_buildtree создаёт согласованную структуру. Разместите выбранные исходники внутри дерева, а зависимости — в его deps. Для этой ветки phpsdk_deps --update --branch 8.5 получает зависимости по сети: это действие выполняют только после выбора доверенного источника; здесь оно не запускалось.
buildconf
configure --help
configure --disable-all --enable-cli --disable-zts
nmake
nmake test
Это команды cmd/SDK, не PHP-код. Предусловия: MSVC2022, совместимый PHP SDK, исходники8.5 и зависимости, выбран targetx64. buildconf создаёт configure, configure формирует план, nmake компилирует, nmake test проверяет сборку. Команды автором не выполнялись; фиксированный итог тестов не обещается.
Выходной каталог зависит от архитектуры и типа: Release для NTS, Release_TS для TS; для64-битной сборки они находятся под x64. Debug и Debug_TS — другие сборки. Найдите фактический php.exe в результате и запустите его полным путём с -n -v, затем hello.php. Не копируйте его поверх штатного PHP.
nmake snap создаёт архив результата, но успешное создание ZIP не доказывает прохождение тестов и совместимость всех приложений. При изменении опций старые объектные файлы могут требовать очистки только собственного build-каталога по инструкции SDK.
Упражнение: DLL собрана под x86, PHP —x64. Решение: пересобрать согласованной архитектурой; изменение имени папки Release ничего не меняет. Самостоятельная сборка расширений через in-tree/phpize и PHPT остаётся последующим уроком ветки расширений.
Кеширование Windows: OPcache8.5 и контекст старого WinCache
Повторный HTTP-запрос снова исполняет код приложения. OPcache экономит подготовку кода, сохраняя скомпилированные операции. Он не становится кешем результата каждого SQL-запроса или HTML-страницы. Поэтому медленную базу нельзя автоматически исправить включением OPcache.
В PHP8.5 OPcache всегда встроен и загружен; отдельные opcache.so/php_opcache.dll больше не создаются. Старая строка zend_extension для OPcache вызовет предупреждение. Для8.2–8.4 загрузка отдельного модуля остаётся вопросом сборки/пакета. Отделяйте «расширение загружено» от «кеш включён для этого SAPI».
opcache.enable = 1
opcache.enable_cli = 0
opcache.validate_timestamps = 1
opcache.revalidate_freq = 0
Фрагмент ini для своей учебной среды PHP8.5; zend_extension для OPcache здесь не нужен. CLI-кеш выключен, проверка изменений файлов для веба включена на каждом запросе. Это удобно при обучении, но не универсальный performance-профиль; реальные веб-процессы должны перечитать настройки.
<?php
echo extension_loaded('Zend OPcache') ? "opcache:loaded\n" : "opcache:missing\n";
echo "enabled-cli:", ini_get('opcache.enable_cli') === '1' ? 'yes' : 'no', "\n";
Ожидаемый результат
opcache:loaded
enabled-cli:no
Точный результат проверен в чистом PHP8.5.11 CLI с -n, где CLI-кеш по умолчанию выключен. extension_loaded проверяет загрузку, ini_get читает настройку строкой. Этот вывод не измеряет ускорение и не проверяет OPcache сайта.
В development обновлённый файл должен обнаруживаться предсказуемо. При отключённой validate_timestamps production-развёртывание обязано предусматривать обновление кеша/процессов; иначе можно читать старые операции после изменения исходника. Не обещайте читателю, что обновление вкладки всегда обновляет PHP-код.
В официальном разделе Windows сохранена рекомендация WinCache. Это отдельное расширение с собственными версиями, файловым/user-кешем и историческими настройками; wincache.ocenabled удалена ещё в WinCache2.0. Не переносите старую DLL в PHP8.5 без опубликованной совместимости. Наличие имени в старой рекомендации не подтверждает доступность подходящей современной сборки.
Упражнение: extension_loaded сообщает OPcache, а CLI не ускоряется. Решение: загрузка и enable_cli различаются; одноразовый процесс, время I/O и способ измерения также влияют. Не включайте JIT или случайный кеш-пакет только ради изменения этой строки.
FPM: процессы, время, журналы и окружение на конкретной задаче
Учебный сервис принимает короткие заявки; иногда один запрос зависает. Нужно различить четыре независимые величины: число одновременных worker, очередь ожидания соединения, время выполнения запроса и время жизни процесса в запросах. Одинаковое число30 в разных полях не означает одинаковую единицу.
Сначала выбирают модель процессов. static держит ровно pm.max_children, dynamic поддерживает запас свободных процессов, ondemand создаёт их при работе и убирает после простоя. Значение max_children выбирают по памяти и измеренной нагрузке, оставляя запас ОС/серверу/другим pool; не умножают memory_limit на всю оперативную память без наблюдений.
pm = dynamic
pm.max_children = 4
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 2
pm.max_requests = 200
Фрагмент заменяет pm-поля учебного pool, а не добавляет второй pm рядом с ondemand. Это модель для разбора: стартуют2 worker, желаемый запас1–2 свободных, всего не более4. Не production-рекомендация; измерений нагрузки автор не проводил.
| Наблюдаем | Поля | Решение по смыслу |
|---|---|---|
| Мало свободных worker | pm.start_servers, pm.min_spare_servers, pm.max_spare_servers, pm.max_spawn_rate | Только dynamic: рост и резерв, не CPU-ускорение одного запроса |
| Простой у редких обращений | pm.process_idle_timeout | Только ondemand; секунды простоя |
| Рост памяти со временем | pm.max_requests | Переработка worker может ограничить накопление, но не лечит причину |
| Общий предел нескольких pool | process.max | Глобальная граница процессов, отличная от каждого max_children |
| Очередь соединений | listen.backlog | Очередь сокета, не число исполняемых PHP-запросов |
Для разбора медленного запроса используем slowlog. Он сохраняет стек после request_slowlog_timeout, но сам по себе запрос не прерывает. request_terminate_timeout, напротив, завершает worker: это аварийная граница, а не аккуратный return приложения.
request_slowlog_timeout = 3s
request_slowlog_trace_depth = 10
slowlog = /var/log/php-lessons/slow.log
request_terminate_timeout = 30s
request_terminate_timeout_track_finished = yes
access.log = /var/log/php-lessons/access.log
access.format = "%m %r %s %{milliseconds}d %{kilobytes}M"
Предусловия: каталог журналов существует, права и политика ptrace позволяют выбранную диагностику, pool загружает этот файл. Ожидается запись метода, пути без query, статуса, миллисекунд и пика памяти в KiB; конкретные числа зависят от запроса. Журналы/worker автором не создавались.
| Маркер access.format | Что записывает |
|---|---|
| %m / %r / %s | Метод, URI без query, HTTP-статус |
| %{milliseconds}d | Время обслуживания в миллисекундах |
| %{kilobytes}M | Пиковая память, выделенная PHP, в единицах1024байта |
| %q / %Q | Query и разделитель ?; могут раскрыть переданные в URL данные |
| %f / %n / %p / %P | Имя скрипта, pool, PID worker и его родителя |
| %R / %u | Адрес и имя Basic-auth, когда оно передано |
| %{NAME}e / %{Header}o | Переменная окружения / заголовок ответа |
| %C / %l / %t / %T / %% | Доля CPU, длина POST-тела, времена приёма/записи, знак% |
fastcgi_finish_request завершает ответ, но оставшаяся работа продолжает занимать worker. Без request_terminate_timeout_track_finished обычный terminate timeout не действует на часть после этого вызова и на завершение приложения; опция появилась в PHP7.3. Для длинной гарантированной фоновой задачи нужен отдельный worker/очередь, а не надежда, что пользователь уже получил ответ.
Status и ping нужны оператору: pm.status_path и ping.path задают специальные URI; pm.status_listen позволяет обслужить status отдельным скрытым pool даже при занятых основных worker. Эти endpoint ограничивают на уровне доступа сервера; иначе раскрываются внутренние сведения. access.suppress_path[] с PHP8.2 может убрать конкретный шумный request_uri из access-log, но не закрывает endpoint.
Окружение FPM по умолчанию очищается clear_env=yes. Нужные переменные добавляют поимённо через env[NAME], а не передают всю среду master без разбора. Секрет не должен попадать в access.format, phpinfo или учебный вывод.
clear_env = yes
env[LESSON_ENV] = training
php_flag[display_errors] = off
php_admin_flag[log_errors] = on
php_admin_value[error_log] = /var/log/php-lessons/application.log
Фрагмент pool; лог находится вне public и доступен для записи нужному процессу. env[...] передаёт строку приложению; php_flag и php_admin_* относятся уже к PHP-настройкам. Admin-настройку скрипт через ini_set не переопределит. Конфигурация требует FPM-проверки, здесь не выполненной.
| Оставшиеся группы настроек этой страницы | Роль и граница |
|---|---|
| pid, daemonize | PID-файл и фон/foreground; согласовать с менеджером службы |
| error_log, log_level, log_limit, log_buffering | Журнал самого FPM; это другой слой, чем error_log приложения |
| syslog.facility, syslog.ident | Маршрутизация и метка записей при error_log=syslog |
| emergency_restart_threshold / interval, process_control_timeout | Реакция на аварийные падения и ожидание управляющих сигналов |
| process.priority, rlimit_files, rlimit_core | Приоритет, дескрипторы, core-dump; есть master/pool-контексты и пределы ОС |
| events.mechanism, systemd_interval | Механизм событий платформы и частота health-уведомлений systemd |
| listen.owner/group/mode, listen.acl_users/groups | Linux Unix-socket права; ACL при задании заменяют owner/group |
| listen.setfib | Таблица маршрутизации FreeBSD с PHP8.2, не Linux-настройка |
| user, group, prefix, chroot, chdir | Права и пространство путей worker; внутри chroot абсолютные пути меняют смысл |
| process.dumpable, apparmor_hat | Отладка/доступ к процессу и политика AppArmor; не включать вслепую |
| catch_workers_output, decorate_workers_output | Перенаправление stdout/stderr worker и оформление, не HTTP-тело echo |
| security.limit_extensions | Разрешённые окончания главного скрипта; не песочница для недоверенного кода |
Изменение php_value/php_flag в pool задаёт обычные PHP-значения, php_admin_value/php_admin_flag закрепляет административные. У disable_functions особое поведение: список в FPM дополняет ранее заданный, не заменяет его. Передаваемые FastCGI-параметры PHP_VALUE/PHP_ADMIN_VALUE делают доступ к endpoint особенно чувствительным: недоверенный клиент не должен соединяться напрямую.
Упражнение: приложение молчит после8секунд, но slowlog задан3s. Решение: slowlog — наблюдение; для остановки есть другая директива. Упражнение: worker не видит окружение терминала. Решение: сначала проверить clear_env и явный env[NAME], а не выводить все секреты master.
Этот раздел даёт рабочую карту и несколько разборов. Все платформенные варианты ACL, chroot, аварийного восстановления, форматов status и сигналов менеджера ещё требуют собственных практик; таблица названий не засчитывает их как полностью изученные.
Что устанавливаем: исполнитель, расширение или библиотеку
Сервис должен уменьшать фотографии перед загрузкой. В PHP-файле уже есть вызов функции обработки изображения, но PHP отвечает «undefined function». Переустановка всего сайта наугад не нужна: сначала определим, какой детали не хватает. Исполнитель читает PHP-код; расширение добавляет ему возможности, часто написанные на C; библиотека состоит из файлов проекта и подключается из PHP. Это три разных объекта установки.
Предварительная ступень — первый файл и выбранный php.exe. Здесь нужны только файл, терминал и вывод. Функция — готовое действие с именем; круглые скобки передают ему данные. Пока мы вызываем готовые действия, собственные функции не пишем.
- Файл проекта вызывает функцию
- Выбранный PHP ищет функцию в загруженных расширениях
- Библиотека проекта может использовать эти функции
- Реальная операция проверяет совместную работу
| Потребность | Что приобретаем | Где проверяем |
|---|---|---|
| Запускать .php | PHP подходящей версии и SAPI | php -v и PHP_SAPI |
| Работать с изображениями | Расширение gd выбранного PHP | php --ri gd и маленькое изображение |
| Использовать готовый клиент API | Composer-библиотеку проекта | vendor/autoload.php и её минимальный вызов |
| Подключиться к базе | Драйвер PHP и отдельно доступную базу | Наличие драйвера ещё не доказывает успешное соединение |
<?php
var_dump(extension_loaded('json'));
echo json_encode(['item' => 'bolt', 'count' => 12]), "\n";
Ожидаемый результат
bool(true)
{"item":"bolt","count":12}
Сохраните как capability.php и выполните php capability.php. extension_loaded получает имя расширения и возвращает true/false; var_dump печатает тип и значение. JSON встроен во все PHP 8+, поэтому пример не требует отдельной установки. Квадратные скобки создают набор подписанных значений, => связывает подпись со значением; json_encode превращает его в текст JSON. Это пример возможностей, а не проверка GD.
На Windows расширение обычно имеет файл .dll, на Unix — .so; встроенному расширению отдельный файл не нужен. Переименование .dll в .so не меняет формат. Копия vendor с другого проекта также не устанавливает расширения PHP. Для изображения выбирают пакет своей ОС или поддерживаемый installer; для библиотеки — Composer. Если владелец управляемого хостинга не даёт устанавливать расширения, сначала уточняют доступный список или меняют выбранное решение.
Практика: для своего проекта составьте три строки «версия PHP / необходимые расширения / библиотеки». Не добавляйте все доступные модули про запас: каждое расширение обновляется и исполняется с правами процесса PHP.
Совместимость модуля: почему одинакового номера PHP мало
Для обработки фото нашли DLL, но PHP не загружает её. У модуля и исполнителя должен совпадать двоичный договор: ветка PHP, архитектура, режим thread safety, debug/release и совместимая сборочная среда. Это похоже на деталь с несколькими размерами крепления: одного названия детали недостаточно. Номер пакета расширения, например 3.x, не является номером PHP 8.x.
Начните с точного пути к исполнителю. Команда -i показывает сведения о сборке, --ini — загруженные настройки, -m — модули. Вывод содержит локальные пути и иногда переменные окружения: полный phpinfo не публикуют на общедоступной странице.
- Выбранный C:\php85\php.exe
- Паспорт: 8.5, x64, NTS, release
- Сравнение с паспортом DLL
- Загрузка в этом же PHP
& 'C:\php85\php.exe' -v
& 'C:\php85\php.exe' --ini
& 'C:\php85\php.exe' -i | Select-String 'Architecture|Thread Safety|Debug Build|PHP Extension Build|Zend Extension Build|extension_dir'
Предусловие: именно C:\php85\php.exe существует; замените путь своим. & запускает путь в кавычках, | передаёт текст следующей команде PowerShell, Select-String оставляет нужные строки. Версия, ABI и каталог зависят от архива. Это чтение сведений, не установка. Для Linux/macOS аналогичен /полный/путь/php -i, но Select-String — команда PowerShell.
| Признак | Что сверить в описании артефакта | Симптом несовпадения |
|---|---|---|
| 8.5 и Extension Build/API | Модуль собран для этой ветки и ABI | Module compiled with module API… |
| x64 / x86 / ARM64 | Архитектуру процесса, не только ОС | Не является допустимым приложением / wrong ELF class |
| TS / NTS; debug | Режим PHP и модуля одинаков | Не загружается или отказ проверки ABI |
| Windows toolset / CRT; Unix libc | Совместимые зависимости DLL/.so | Файл модуля есть, но его зависимость не найдена |
| CLI и веб-SAPI | Оба используют нужный бинарный PHP и ini | В терминале работает, в браузере функция отсутствует |
Alpine использует musl; Linux-сборку под glibc нельзя считать взаимозаменяемой. macOS arm64 и x86_64 — разные процессы, в том числе при Rosetta. PHP с ZTS не делает пользовательский код автоматически параллельным. PHP 8.5 включает OPcache в сборку всегда; прежнюю строку zend_extension=opcache для отдельного файла из 8.2–8.4 в новую установку не переносят.
Практика: запишите паспорт выбранного PHP и сравните с названием/описанием одного артефакта. При первом несовпадении остановитесь; загрузка случайных DLL из поисковой выдачи не является диагностикой.
Получить расширение из проверяемого источника
Нужно подключить расширение, которого нет в архиве PHP. Сначала проверяют пакетный репозиторий своей ОС, документацию самого расширения и поддерживаемые версии PHP. В каталоге PECL находятся описания, выпуски и ссылки на исходники; на Packagist Extensions — пакеты, совместимые с PIE. Одинаково звучащие имена в разных каталогах не доказывают одинакового автора.
У релиза есть номер и состояние: stable, beta, alpha, RC. Stable не означает вечную безопасность, а ограничение версии не заменяет чтение несовместимых изменений. Для повторяемой сборки фиксируют выбранный выпуск, источник, параметры сборки и проверенный хеш/подпись. Сумма с того же взломанного зеркала не доказывает доверенное происхождение.
- Проверяем владельца и требования
- Выбираем релиз и архив для своей платформы
- Проверяем опубликованную подпись/аттестацию или контрольную сумму
- Тестируем в отдельном окружении
- Сохраняем версию, конфигурацию и способ отката
pecl remote-info redis
pecl download redis
Предусловия: в отдельной учебной Unix-системе уже есть работающий PEAR/pecl и разрешён исходящий HTTPS. Команды обращаются к репозиторию; download записывает архив в текущую папку, но не компилирует и не подключает его. После выбора существующего номера в release list используйте redis-НОМЕР вместо redis. Слово НОМЕР необходимо заменить; автоматический latest не воспроизводит прошлую сборку.
Получение исходников из Git отличается от получения release-архива: могут понадобиться генераторы, подмодули и дополнительные шаги buildconf. Закреплённый commit надёжнее меняющейся ветки, но не гарантирует проверенность. PHP.net сохраняет исторический маршрут SVN; использовать его следует только если актуальная страница самого расширения действительно ссылается на этот репозиторий. Адреса из старого ответа на форуме не переносят автоматически.
Практика: найдите у выбранного расширения поддерживаемые PHP/ОС, текущий исходный репозиторий, список зависимостей и changelog. Сохраните эту карточку рядом с проектом; пароль репозитория или access token в неё не включают.
PIE: установить инструмент, затем выбрать PHP
PIE — PHP Installer for Extensions, современный путь установки внешних расширений. PHP.net помечает прежний PECL installer устаревшим. Это не означает, что все расширения PECL исчезли или что старую работающую систему надо немедленно переделать. Для нового окружения сначала проверяют доступность расширения через PIE; для уже управляемого пакетами PHP сохраняют согласованный способ сопровождения.
Файл pie.phar — упакованная PHP-программа. Для запуска PHAR-варианта нужен PHP 8.1+, а для целевого расширения может быть выбран другой установленный PHP. На Windows обычно получают подходящую DLL; Unix-сборке нужны PHP development headers, phpize/php-config, компилятор и зависимости расширения. Установка расширения затрагивает выбранную установку PHP, а не только текущую папку проекта.
- PHP 8.1+ запускает pie.phar
- PIE определяет целевой PHP
- Подбирает бинарный модуль или сборку
- Пытается включить расширение
- Проверяем именно целевой PHP
gh attestation verify --owner php .\pie.phar
& 'C:\php85\php.exe' .\pie.phar --version
& 'C:\php85\php.exe' .\pie.phar list
Предусловия: pie.phar скачан из releases репозитория php/pie в текущую учебную папку, gh установлен и имеет сетевой доступ для проверки аттестации; PHP по указанному пути работает. Первая команда проверяет происхождение, следующие показывают версию и команды. При неуспешной проверке файл не запускают. Изменение PATH не требуется. Это документальные команды, здесь PHAR не скачивался и не исполнялся.
& 'C:\tools\php85\php.exe' .\pie.phar info xdebug/xdebug
& 'C:\tools\php85\php.exe' .\pie.phar install --with-php-path='C:\labs\php85\php.exe' xdebug/xdebug
Предусловия: обе установки существуют; C:\labs\php85 — отдельная учебная установка, доступная для записи; выбран совместимый выпуск Xdebug. info читает сведения пакета, install скачивает и устанавливает его. Первый PHP обслуживает PIE, --with-php-path выбирает второй. Xdebug нужен для отладки; его функции и стоимость рассматривают отдельно, на production он по этому примеру не устанавливается.
На Unix выбор делают через --with-php-config=/путь/bin/php-config, а при необходимости ещё --with-phpize-path=/путь/bin/phpize: оба должны относиться к целевому PHP. В сообщениях PIE проверьте Target PHP installation до подтверждения установки. PIE может предложить установку недостающих системных инструментов/библиотек; такое предложение меняет систему, его не принимают вслепую. В CI автоматические изменения разрешают только явными опциями и заранее описанным образом сборки.
Практика: сначала добейтесь --version и list, затем изучите info одного пакета. Если цель и текущий CLI различаются, запишите оба полных пути. При ошибке zip/git/build-tools исправляйте указанную зависимость; отключение checks не создаёт отсутствующий инструмент.
PIE: включение, воспроизводимость, обновление и удаление
Файл расширения уже скопирован, но сайт не изменился. PIE пытается добавить extension или zend_extension в доступную конфигурацию. Это попытка: при отсутствии подходящего ini/прав он предупреждает, что включение надо выполнить отдельно. Кроме того, работающие FPM/IIS/Apache процессы ещё могут использовать прежнее состояние. Окончательная проверка относится к тому процессу, где работает приложение.
Сначала в отдельной установке проверьте командой php --ri xdebug, что модуль действительно загружен; для иного расширения подставьте его имя. Вывод содержит версию и параметры, которые зависят от окружения. Затем выполняют полезную операцию приложения. В production переводят уже проверенный комплект версии PHP, модулей и конфигурации.
- Версия в pie.lock
- Файл модуля в target PHP
- Строка загрузки в его ini
- Новый процесс: --ri и полезная операция
& 'C:\labs\php85\php.exe' .\pie.phar show -v
& 'C:\labs\php85\php.exe' --ri xdebug
& 'C:\labs\php85\php.exe' .\pie.phar help upgrade
Предусловия: PIE работает через этот учебный PHP. show -v показывает путь к состоянию PIE; это не composer.lock приложения. pie.json задаёт ограничения, pie.lock фиксирует разрешённые версии. upgrade обновляет установленные PIE-расширения в пределах ограничений; help только объясняет команду и не обновляет.
| Действие | Что меняет | Что проверить после |
|---|---|---|
| install vendor/package:ограничение | Модуль, состояние PIE и обычно ini | Версию, target PHP, загрузку, тест приложения |
| install --skip-enable-extension … | Установку без автоматического включения | Кто и где добавит directive до запуска приложения |
| install из сохранённого pie.lock | Воссоздаёт состав target installation | Совпадение ОС/архитектуры/PHP; lock не переносит ABI |
| upgrade | Выбирает новые подходящие выпуски | Changelog и проверку на копии до переключения |
| Удаление | Нужно согласовать ini, файл и учёт installer | Ни один новый процесс не пытается открыть удалённую DLL/.so |
В прочитанной документации PIE 1.6.x нет документированного эквивалента pecl uninstall. Поэтому команда pie uninstall здесь не выдумывается. В своей версии проверьте list/help; если поддерживаемого удаления нет, воспроизведите чистую отдельную установку с нужным составом и переключите приложение после теста. Для ручного сопровождения сначала отключают единственную строку загрузки, останавливают/перезапускают соответствующий процесс в согласованное окно и только затем удаляют больше не используемый артефакт. Не смешивайте ручное удаление с пакетным учётом ОС.
Практика: в копии конфигурации намеренно пропустите включение. Сопоставьте успешную загрузку архива, сообщение PIE и php --ri: это три разных результата. Для отката сохраняют целую проверенную установку, а не только старую строку ini.
Требование ext-redis в проекте и выбор поставщика
Проект заявляет ext-redis, но Composer не устанавливает native-модуль. Запись означает требование к среде. PIE умеет прочитать такие требования и подобрать поставщика, однако имя ext-redis и имя пакета phpredis/phpredis — разные уровни. Первое называет возможность PHP, второе — конкретную реализацию в каталоге.
Предварительно пройдите composer.json, install и autoload. JSON использует двойные кавычки, фигурные скобки для объекта и двоеточие между ключом и значением; комментарии и хвостовые запятые в этом файле не допускаются.
- composer.json требует ext-redis
- --select выбирает phpredis/phpredis
- PIE устанавливает модуль в PHP
- Отдельно проверяем соединение с Redis
{
"require": {
"php": "^8.2",
"ext-json": "*",
"ext-redis": "*"
}
}
Сохраните как composer.json в новой учебной папке. ^8.2 допускает совместимые версии 8.x не ниже 8.2; * у расширения не ограничивает его версию. Это заявка среды, она ещё не устанавливает модуль и не проверяет доступность Redis-сервера. Выбор реально поддерживаемой ветки PHP сверяют с upstream.
php pie.phar install --no-dev --select redis=phpredis/phpredis
Предусловия: текущая папка содержит показанный composer.json, pie.phar доступен здесь, target PHP и его build prerequisites уже выбраны. Команда устанавливает недостающую возможность и может менять PHP/ini. --no-dev исключает требования require-dev; --select связывает имя расширения с пакетом. Старый флаг --allow-non-interactive-project-install не заменяет --select в PIE 1.5+. Сеть и installation здесь не выполнялись.
Совпадение requirements не гарантирует нужную конфигурацию: Redis может отсутствовать или требовать пароль/TLS. Для реального сервиса отдельны установка клиента, настройка адреса/секретов и проверка соединения. Не выводите COMPOSER_AUTH, пароли базы или содержимое переменных среды в публичный диагностический ответ.
Практика: объясните, какие данные потребуются для повторения установки на другом компьютере. composer.lock приложения и pie.lock выбранного PHP решают разные задачи; один не заменяет другой.
Существующая система с PEAR/PECL: прочитать, собрать, включить
В проекте уже есть инструкция pecl install, а миграция инструментария сейчас не входит в изменение. PEAR — инфраструктура пакетов и команд PHP; PECL использует её инструменты для C-расширений. Это исторический поддерживаемый системой процесс, который надо понимать, даже если новая установка выбирает PIE. Пакет PEAR с PHP-кодом не тождественен PECL-модулю.
Предусловия следующего Unix-маршрута: отдельная учебная система, уже установленный и проверенный pecl, development package точно выбранного PHP, make/компилятор и библиотеки расширения. Сначала прочитайте pecl version и pecl config-show: команда из PATH может принадлежать другой ветке PHP. После выбора кандидата сверяйте changelog и требования релиза.
- pecl получает исходники redis
- Toolchain собирает redis.so
- install записывает файл
- extension=redis подключает при startup
pecl version
pecl remote-info redis
pecl install redis
Последняя команда скачивает, собирает и записывает модуль; её выполняют только на разрешённом учебном окружении. Без суффикса выбирается подходящий стабильный кандидат по правилам PECL. Существующий релиз можно закрепить как redis-НОМЕР; redis-beta намеренно допускает нестабильный канал. Если не хватает прав, сначала выясняют владельца prefix, а не добавляют sudo ко всей цепочке автоматически.
extension=redis
Этот текст помещают в ini целевого PHP по правилам его пакетной установки, не в PHP-файл. PECL install сам по себе не доказывает включения. Для Zend-расширения вроде Xdebug требуется zend_extension и инструкция производителя; это другая категория модулей.
После установки запустите полный путь php --ri redis, затем минимальную операцию, не требующую внешнего сервера, если расширение её предоставляет. Для веба проверьте то же через закрытый диагностический маршрут и после проверки удалите диагностику. Ошибка загрузки читается из startup stderr/error log, а не лечится подавлением display_errors. Если pecl не поддерживает нужную ветку PHP или установка требует несовместимый пакет, выбирайте новый путь PIE/пакет ОС, а не принудительный --force.
Практика: разделите журнал на четыре результата: «скачан», «собран», «записан», «загружен». Запишите, на каком шаге возникла ошибка. Эта классификация помогает и при новой установке PIE.
Windows: подключить DLL и вернуть рабочее состояние
Расширение уже скачано как совместимый Windows-архив. Сначала закройте эксперимент: работайте с копией учебной установки, сохраните её ini и перечень файлов. В архиве могут быть сама php_*.dll и дополнительные DLL библиотек. Размещайте зависимости по инструкции выпуска; копирование всего в C:\Windows\System32 не является универсальным решением и затрудняет откат.
Чтобы проверить загрузку без постоянной правки ini, можно запустить один дочерний PHP с -n и -d. -n отключает ini-файлы; -d задаёт параметр только этому процессу. Путь extension_dir — каталог модулей. Этот тест обнаруживает базовую загрузку, но не воспроизводит всю конфигурацию сайта.
- Совместимый php_gd.dll уже в ext
- -n убирает постоянную конфигурацию
- -d подключает GD одному процессу
- --ri показывает результат загрузки
& 'C:\labs\php85\php.exe' -n -d 'extension_dir=C:\labs\php85\ext' -d extension=gd --ri gd
Предусловия: этот официальный Windows-архив PHP содержит ext\php_gd.dll и необходимые зависимости; архитектура и версия согласованы. Вывод должен сообщить GD Support enabled, остальные поля зависят от сборки. Это проверочная команда для описанного окружения; наличие конкретной DLL у читателя не предполагается.
| Ошибка | Что проверить первым | Что не решает причину |
|---|---|---|
| Unable to load dynamic library | extension_dir, наличие файла, startup stderr | display_errors=Off |
| The specified module could not be found при существующей DLL | Зависимые DLL и VC runtime | Переименование архива |
| Module API / build ID mismatch | Точный PHP API, TS/NTS и архитектуру | Изменение имени функции |
| Module already loaded | Все ini из php --ini и повторную строку | Дублирование extension ещё раз |
| CLI работает, IIS нет | Handler php-cgi.exe, права identity, PHPRC и recycle | Обновление страницы браузера |
После успешного одноразового теста добавьте ровно одну extension=gd в конфигурацию нужного PHP и проверьте новый процесс. При startup failure верните сохранённый ini и прежний комплект файлов. Динамическая загрузка dl() внутри запроса не является общей альтернативой: она зависит от SAPI/настроек и не решает совместимость. Предпочтительнее воспроизводимый startup-состав.
Практика: сравните -n -m и обычный -m, не меняя конфигурацию. Назовите расширения, которые были частью самого PHP, и те, которые появились через ini. Не удаляйте файлы действующей установки ради опыта.
phpize: собрать один модуль для конкретного PHP
Расширение распространяется исходниками, а готового подходящего пакета нет. phpize подготавливает конфигурационную систему расширения с заголовками установленного PHP. Он не устанавливает PHP, не скачивает системные библиотеки и не компилирует сам модуль. Затем configure проверяет зависимости, make компилирует, make install записывает результат в extension_dir.
Предусловия: собственная Unix/macOS учебная установка с prefix /opt/php-lab, её development tools и headers, компилятор/make/autoconf, распакованный проверенный release расширения и выполненные требования его INSTALL. Путь /opt/php-lab здесь выбран для примера; владелец заранее даёт права на него. Не смешивайте /usr/bin/phpize с php-config другого prefix.
- Исходники расширения
- phpize выбранного PHP создаёт configure
- configure проверяет ABI и библиотеки
- make получает модуль
- make test, затем install и включение
/opt/php-lab/bin/phpize --version
/opt/php-lab/bin/phpize
./configure --with-php-config=/opt/php-lab/bin/php-config
make
make test
make install
Команды выполняют по одной и продолжают только после успеха. Дополнительные --enable/--with берут из ./configure --help именно этого расширения. Для выбранного расширения тесты могут требовать сервиса; его не запускают молча — условия тестового набора изучают заранее. make install меняет target prefix; здесь вся цепочка документальная, не выполнялась.
Ошибка Cannot find autoconf относится к инструменту генерации, php.h missing — к headers, Package … not found — часто к pkg-config и development library, Undefined symbol при загрузке — к ABI/зависимости. config.log содержит проверку, которая действительно не удалась; последняя строка make обычно лишь сообщает об остановке. После замены ветки PHP соберите расширение заново в чистой папке: старый .so может выглядеть нормально и всё же быть несовместим.
Практика: до запуска make назовите три полных пути: php, phpize, php-config. Их версии должны описывать одну установку. Для хостинга без компилятора обратитесь к владельцу/пакету ОС или используйте поддерживаемую библиотечную альтернативу; исходники сами по себе не дают права устанавливать системный модуль.
php-config: паспорт сборки для компилятора
На машине есть PHP 8.2 и 8.5. Интерактивная команда php выбрана одна, а расширение случайно собирается для другой. php-config — небольшой служебный скрипт из development-поставки PHP, который сообщает пути и параметры своей сборки. Он не читает «все настройки сайта» и не заменяет php --ini. Выбор полного пути устраняет неоднозначность.
Опция — слово после --; она просит одно значение. Каталог include содержит C-заголовки, extension-dir — итоговые модули, libs/ldflags — аргументы линковщика. Новичку не нужно вручную склеивать команды C: configure использует эти сведения через --with-php-config.
- /opt/php-lab/bin/php-config
- Версия + headers + extension-dir одной сборки
- configure расширения использует этот паспорт
/opt/php-lab/bin/php-config --version
/opt/php-lab/bin/php-config --php-binary
/opt/php-lab/bin/php-config --extension-dir
Предусловие: development tools действительно установлены в /opt/php-lab/bin. Результат — конкретная версия и два пути этой сборки; они не универсальны. Затем /opt/php-lab/bin/php -v должен описывать согласованный PHP. Если php-config отсутствует, нужен соответствующий development package или исходная сборка, а не случайный скрипт из интернета.
| Опция php-config | Для чего нужна |
|---|---|
| --prefix | Корень установки; помогает обнаружить чужой PHP |
| --includes / --include-dir | Аргументы поиска headers / сам каталог headers |
| --ldflags / --libs | Параметры линковки / библиотеки сборки |
| --extension-dir | Куда эта сборка ожидает устанавливаемые модули |
| --php-binary | Путь к CLI этой установки |
| --php-sapis | Какие SAPI собраны, а не какие службы сейчас запущены |
| --configure-options | Аргументы исходной конфигурации сборки |
| --version / --vernum | Текстовый номер / целочисленный номер версии |
| --help | Поддерживаемые опции установленного скрипта |
Сохранённый configure-options полезен для повторения намерений, но не гарантирует существование прежних библиотек или равные результаты тестов. На Windows обычный бинарный ZIP не следует считать Unix development-поставкой с этим shell-скриптом: используйте Windows SDK/PIE и их документированные способы выбора target.
Практика: объясните разницу между php-config --extension-dir и ini_get("extension_dir"). Первое отражает сборочную конфигурацию, второе — действующее значение текущего PHP-процесса, которое могло быть переопределено.
Статическое расширение: новый PHP вместо подключаемого файла
Для собственного автономного исполнителя нужно включить расширение прямо при сборке PHP. Такой модуль не загружается из .so на старте: его код входит в новый исполняемый комплект. Это уменьшает отдельные артефакты, но обновление расширения требует пересборки PHP. «Статическое расширение» не означает, что весь PHP статически связан со всеми системными библиотеками.
Этот путь предполагает пройденную сборку PHP из исходников, отдельное source tree, поддерживаемые инструменты и расширение, у которого upstream поддерживает in-tree/static build. Внешние модули различаются; универсальной команды --enable-extname для любого пакета нет.
- Поддерживаемое расширение в ext исходников
- buildconf и его configure-флаг
- Новый PHP включает код расширения
- -n -m проверяет состав без ini
./buildconf --force
./configure --help
Предусловие: выбранный release исходников расширения уже помещён в ext/его-имя внутри отдельного PHP source tree согласно upstream. buildconf заново собирает configure из config.m4; --help позволяет найти настоящий флаг расширения. Следующий configure должен задать отдельный --prefix, нужные SAPI/зависимости и именно поддерживаемый флаг. Это осознанная точка выбора, а не неполная команда, которую надо угадывать.
Дальше идут configure → make → make test → make install для всего PHP, как в исходной сборке. Сначала запустите новый prefix/bin/php -n -m: статический модуль должен быть виден без ini. Затем выполните малую операцию расширения и проектные тесты. Не оставляйте одновременно строку загрузки старого .so с тем же именем: duplicate module мешает диагностике.
В старом тексте PHP.net встречаются конкретные старые версии autoconf/automake. Они не являются требованиями PHP 8.5: для выбранного тега исходников читают его README/buildconf. Архив релиза и Git checkout имеют разный набор сгенерированных файлов. Практика: сравните стоимость обновления одного shared-модуля и статического комплекта; если собственной сборки не требуется, пакет ОС/PIE проще сопровождать.
Composer с нуля: сначала инструмент, затем библиотека проекта
Нужно использовать готовую библиотеку, например для работы с датами или API. Composer скачивает согласованные версии её PHP-файлов и зависимостей. Он сам тоже PHP-программа. Установка Composer на компьютер и установка библиотек в папку приложения — два разных действия. PHAR-вариант удобно держать в учебной папке и вызывать через явно выбранный PHP, не меняя PATH.
На Windows официальный Composer-Setup.exe помогает выбрать php.exe; установщик может менять PATH, поэтому в этом учебном маршруте используем composer.phar. Получите installer с getcomposer.org и сверяйте SHA-384 по актуальной официальной инструкции, не копируйте старую сумму из статьи. После проверки installer создаёт composer.phar. Проверку и установку здесь не выполняли; для своей системы используйте текущие шаги официальной страницы Download.
- Проверенный composer.phar запускается через выбранный PHP
- composer.json описывает проект
- install читает lock или разрешает зависимости
- vendor содержит установленные файлы
- PHP подключает vendor/autoload.php
& 'C:\labs\php85\php.exe' .\composer.phar --version
& 'C:\labs\php85\php.exe' .\composer.phar diagnose
Предусловия: этот PHP работает и проверенный composer.phar находится в текущей папке; diagnose может обращаться к сети. --version показывает версию инструмента, не версию проекта. На Unix: /путь/php ./composer.phar --version. Не нужно помещать Composer в публичную папку сайта.
Для первого запуска библиотеки продолжите урок с composer.json и автозагрузкой: там разобраны require, имена классов и запуск собственного файла. Устанавливать библиотеку глобально вместо локального проекта обычно не нужно: разные проекты вправе требовать разные версии. Глобальные инструменты вроде анализатора кода — отдельный осознанный случай.
Если Composer сообщает об отсутствии openssl/zip/другого расширения, проверьте php --ini и php -m именно того PHP, которым он запущен. Отсутствие сертификата доверия не исправляется disable-tls или secure-http=false: сверяют CA-настройки, системное время и доверенный прокси. Ошибка прав относится к папке проекта/кеша, а не требует запускать неизвестные пакеты от администратора.
Практика: объясните, где лежат сам Composer, composer.json и vendor. Если эти три пути слились в одну «установку PHP», вернитесь к модели в начале раздела.
Проверить готовность среды и не спрятать ошибку зависимостей
На компьютере разработчика библиотека установилась, а на сервере падает при первом запросе. В composer.json можно указать php и ext-* как требования среды. Composer сравнивает их с PHP, который запустил команду. Параметр config.platform может моделировать другую среду при разрешении версий; он не устанавливает PHP и не превращает текущий компьютер в сервер.
На машине сборки update разрешает новые версии и меняет lock; при доставке уже проверенного приложения install использует сохранённый lock. Не выполняйте update на production только потому, что install нашёл конфликт: это изменяет проверенный состав. Для проекта с известными зависимостями проверьте сначала validate, затем check-platform-reqs на реальном целевом исполнителе.
- composer.json задаёт требования
- lock фиксирует библиотеки
- check-platform-reqs читает реальный PHP
- Тест приложения проверяет совместную работу
php composer.phar validate --strict
php composer.phar check-platform-reqs --no-dev
php composer.phar audit
Предусловия: текущая папка содержит composer.json, composer.lock и установленный vendor; инструмент доступен как composer.phar. validate проверяет формат/согласованность, check-platform-reqs сверяет настоящие версии PHP/расширений, игнорируя имитацию config.platform, audit проверяет известные advisories и может использовать сеть. Ни одна из команд не доказывает отсутствие неизвестных дефектов и не проверяет другой веб-SAPI.
<?php
$requirements = ['php' => '8.2+', 'ext-json' => 'required'];
echo 'PHP: ', $requirements['php'], "\n";
echo 'JSON: ', $requirements['ext-json'], "\n";
Ожидаемый результат
PHP: 8.2+
JSON: required
Это маленький PHP-массив, объясняющий роль требования. $requirements — переменная с подписанными значениями; ключ в квадратных скобках читает одну запись. Строка 8.2+ здесь обычный текст, не parser версий Composer. Пример ничего не устанавливает; синтаксис настоящих ограничений имеет свои правила.
Пакеты могут запускать scripts и plugins. В незнакомом проекте сначала изучают composer.json; --no-plugins --no-scripts отключают эти механизмы для выбранной команды, но не делают произвольный код библиотеки безопасным при его последующем запуске. allow-plugins задают по именам доверенных пакетов, а не true для всего каталога. COMPOSER_AUTH и auth.json содержат секреты: не включайте их в репозиторий, веб-корень или публичный отчёт.
Практика: в копии простого composer.json намеренно добавьте требование отсутствующего модуля и прочитайте сообщение validate/install/check-platform-reqs. --ignore-platform-reqs скрывает проверку, но не создаёт функцию, которая понадобится приложению. Исправление — согласовать среду или выбрать действительно совместимую зависимость.
Облако: кто отвечает за PHP, файлы и обновления
Локальный отчёт заработал, теперь им должны пользоваться коллеги. Облако предоставляет вычислительные ресурсы, но слово «облако» не определяет способ запуска PHP. На виртуальной машине вы управляете ОС и службами; в управляемом приложении выбираете поддерживаемый runtime; в Functions передаёте обработчик событий. Сначала выбирают ответственность, затем продукт.
Здесь все облачные шаги описаны для отдельной учебной подписки с заранее установленным бюджетом. Никаких ресурсов, аккаунтов и платных действий при подготовке уроков не создавали. Потребуются необходимые права для выбранных ресурсов в учебной подписке, репозиторий без секретов и уже работающий локальный пример. На каждом сервисе цены/доступные версии проверяют перед созданием.
- Проверяем локальный результат
- Описываем PHP и ext-*
- Выбираем владение инфраструктурой
- Собираем отдельное тестовое окружение
- Проверяем HTTP и данные до подключения пользователей
| Модель | Кто обновляет PHP/ОС | Когда подходит | Что всё равно остаётся вам |
|---|---|---|---|
| VM: EC2/Droplet | Администратор вашей системы | Особые расширения/службы/полный контроль | Обновления, firewall, TLS, backup, секреты и данные |
| PaaS: App Service/App Platform | Платформа предоставляет стек; вы выбираете поддерживаемую версию | Обычный сайт/API из репозитория | Зависимости, настройка приложения, проверки и миграции данных |
| Контейнер | Вы собираете и обновляете образ | Точно определённый PHP и библиотеки | Неизменяемый образ не обновляется сам; нужны новый build и rollout |
| Functions | Платформа выполняет обработчик | Короткое действие по событию | Лимиты времени/памяти, повторы событий, внешнее хранение |
Локальный диск контейнера/функции может быть временным, несколько копий приложения не обязаны видеть один файл. Пользовательские загрузки и база данных требуют выбранного постоянного хранилища и резервирования. Адрес сервиса из переменной окружения — настройка; токен доступа — секрет. Их передают средствами платформы и не печатают в health endpoint.
Практика: для своего отчёта отметьте, нужны ли долгие фоновые задания, нестандартный модуль, постоянные загрузки и ограничения на регион данных. По этим требованиям обоснуйте выбор одной модели, а не только знакомого логотипа.
Маленькая проверка перед развёртыванием: тело ответа отдельно от HTTP
Первый облачный пример не должен зависеть от базы, авторизации и десятка библиотек. Пусть он возвращает постоянный ответ: так легче отделить ошибку доставки PHP от ошибки приложения. Начнём с одного вывода; затем добавим заголовок. Слово echo выводит текст, точка с запятой заканчивает команду. Обратный слеш n внутри двойных кавычек — перевод строки.
- ready.php формирует одну строку
- CLI проверяет тело без сети
- Web handler добавляет HTTP
- Клиент сверяет статус, заголовок и тело
<?php
echo "PHP application ready\n";
Ожидаемый результат
PHP application ready
Сохраните как ready.php и выполните php ready.php. Это проверенный CLI-результат. Он не подтверждает HTTP, маршрутизацию или готовность базы.
<?php
header('Content-Type: text/plain; charset=UTF-8');
echo "PHP application ready\n";
Ожидаемый результат
HTTP при успешной настройке: 200; Content-Type: text/plain; charset=UTF-8
Тело: PHP application ready
header задаёт метаданные HTTP до первого вывода. Файл должен находиться внутри отдельной папки public, которую сервер назначит document root. Этот вариант проверяется синтаксически, а не выдаётся за исполненный HTTP-запрос. В целевой среде смотрят и статус, и заголовок, и тело; вывод исходника вместо текста означает неправильную/опасную настройку PHP handler.
Второй шаг после такого smoke test — небольшая операция приложения с выбранной зависимостью. Не превращайте readiness endpoint в phpinfo с путями, env и секретами. Временный диагностический файл удаляют после проверки; рабочий health endpoint проектируют отдельно по требованиям маршрутизации и нагрузки.
Практика: объясните, почему строка из CLI не доказывает доступность сайта и почему HTTP 200 от статического index.html не доказывает выполнение PHP.
Azure App Service: Linux runtime и публичная папка приложения
Для небольшого PHP-сайта нужен управляемый runtime без самостоятельной установки Apache. App Service предлагает такой маршрут. В PHP.net сохранён старый Windows/WinCache контекст; Microsoft сообщает об окончании поддержки PHP в App Service on Windows в ноябре 2022. Новый учебный маршрут выбирает App Service on Linux. Это ограничение конкретного сервиса, а не запрет PHP на обычной Windows VM.
Подготовьте папку проекта с public/index.php из предыдущего урока. Если есть библиотеки, добавьте composer.json/lock и явный процесс сборки vendor. Настройки подключения задают в конфигурации приложения; секреты не помещают в Git. До создания ресурса выберите учебную resource group, регион, тариф и правила удаления учебных данных.
- public/index.php в учебном проекте
- Linux PHP runtime в App Service
- Build зависимостей и настройки
- Test URL и журнал отказа
az webapp list-runtimes --os linux
Предусловия: Azure CLI установлен и настроен для вашей учебной подписки. Команда читает каталог; она не создаёт приложение. Из списка выбирают поддерживаемый PHP, совместимый с проектом. Здесь нет зафиксированного «последнего» номера: каталог платформы меняется.
| Шаг в Azure | Что выбрать/проверить | Зачем |
|---|---|---|
| Создать Web App в отдельной группе | Linux, доступный PHP runtime, осознанный тариф | Не перенести старый Windows рецепт |
| Выбрать источник доставки | Учебный Git/ZIP с явным build шагом | Знать, где выполнен composer install и получен vendor |
| Настроить корень приложения | Маршрут к public/index.php в реальном runtime | composer.json, .env и исходники не должны раздаваться как файлы |
| Запустить test URL | Статус/заголовок/тело ready | Проверить HTTP, а не только успешный upload |
| Изучить startup/application log | Version/build/startup error без публикации секретов | Разделить ошибку сборки, PHP handler и приложения |
| Обновить runtime на копии/slot при доступности тарифа | Зависимости, smoke test и обратное переключение | Рабочая ветка не должна меняться без проверки |
Если используется собственный Nginx startup config, храните его воспроизводимо и проверяйте пути текущего контейнера; нельзя копировать Windows web.config в Linux и ожидать того же поведения. Доступность слотов, custom containers и расширений зависит от выбранного плана. Успешное чтение az list-runtimes также не разрешает создавать ресурсы в чужой подписке.
Практика: опишите pipeline из трёх мест — локальный код, сборка зависимостей, рабочий runtime. При неудаче найдите, на каком из этих этапов находится error. Завершение опыта включает удаление только точно выбранных учебных ресурсов после сохранения нужных данных; остановка приложения не равна отсутствию всех начислений.
Amazon EC2: PHP на своей виртуальной машине
Приложению нужен собственный набор расширений или системный сервис. EC2 даёт виртуальную машину, а не автоматически готовый PHP-сайт. У неё есть образ ОС, архитектура, диск, сетевые правила и identity для доступа к AWS. PHP устанавливается средствами выбранной ОС. AWS SDK for PHP — отдельная Composer-библиотека, нужна для вызовов AWS API, но не для самого запуска PHP на EC2.
В этом маршруте предпосылка — уже созданная отдельная учебная VM Amazon Linux 2023 и разрешённый административный SSH с вашего адреса. Порт FPM не открывают в internet. Не переносите amazon-linux-extras из AL2 в AL2023: это разные системы. Актуальная страница PHP in AL2023 перечисляет несколько веток, тогда как старый LAMP tutorial ещё показывает историческую ветку по умолчанию.
- Свой SSH → AL2023 VM
- PHP/FPM из выбранной ветки пакетов
- Web-server → закрытый FPM
- PHP → прикладные данные
cat /etc/os-release
dnf list --available 'php8.5*'
dnf info php8.5 php8.5-fpm
Предусловие: shell внутри вашей AL2023 VM; метаданные repository могут обращаться к сети. Проверяйте доступность именно выбранной ветки и patch version в данном release snapshot. Имена php8.5 приведены как конкретный маршрут при наличии этой ветки, а не обещание любого старого образа. Команды ничего не устанавливают.
После выбора ветки в отдельном окружении устанавливают её CLI/FPM и нужные модули через DNF, затем применяют маршрут Apache/FPM либо Nginx. Пакетный конфиг может уже связывать Apache и FPM; прежде чем добавлять вторую связь, прочитайте установленные файлы. Проверяют php -v, php --ini, FPM config test, web-server config test и только затем локальный HTTP. На публичный адрес переходят после настройки сети и HTTPS.
| Слой | Условие готовности | Типичный отказ |
|---|---|---|
| Security group/OS firewall | Открыты только необходимые порты и источники | Таймаут до веб-сервера |
| Веб-сервер | Правильный vhost/document root | Статическая страница или 404 вместо приложения |
| FPM | Listener совпадает с web config, права согласованы | 502/503 |
| PHP/модули | Та же ветка и требования приложения | Undefined function / missing driver |
| Данные/секреты | Минимальные права и внешнее хранение | Permission denied / отказ подключения |
IAM role для VM позволяет получать временные credentials вместо долговечного ключа в PHP-файле; настройку IAM и доступ к данным ограничивают конкретной задачей. Нельзя публиковать metadata/credentials через отладочный endpoint. Обновление ОС, PHP и приложения планируют вместе с резервированием данных. Stop VM прекращает часть расходов, но сохранённые диски и другие ресурсы могут оплачиваться; terminate — отдельное действие с последствиями для хранения.
Практика: нарисуйте путь browser → разрешённый web port → web-server → локальный FPM → PHP. Укажите, где будет обнаружен каждый отказ из таблицы. Реальный cloud runtime в этом уроке не запускался.
DigitalOcean: Droplet, App Platform, Cloudways или Functions
У DigitalOcean несколько разных путей PHP. Droplet — VM: выбирают ОС и проходят её установку PHP. App Platform собирает и запускает приложение из проекта/образа. Cloudways предоставляет управляемый hosting workflow для приложений. Functions исполняет отдельный обработчик. Эти режимы имеют разные ограничения и не должны смешиваться в одной инструкции.
Для обычного учебного сайта на App Platform положите public/index.php и composer.json в отдельный репозиторий без секретов. Текущий PHP buildpack использует требования composer.json; список поддерживаемых веток/patch versions смотрите в актуальном документе и release notes выбранного stack. Даже первичный документ может содержать устаревший пример версии — доступность проверяют перед build.
- Требования небольшого сайта
- Выбранная модель: VM, PaaS или функция
- Её runtime и способ доставки
- Проверка HTTP и хранения
{
"require": {
"php": "^8.2",
"ext-json": "*"
}
}
Это composer.json. После добавления реальных библиотек lock создаётся и проверяется в локальном процессе разработки. Buildpack может использовать требования ext-* для доступных в нём модулей; это поведение платформы, не общее свойство Composer. Наличие произвольного PECL-модуля на PaaS не обещается.
| Продукт | Минимальный путь | Граница ответственности |
|---|---|---|
| App Platform | Источник → PHP buildpack/образ → public document root → health URL | Доступные runtime/модули, build logs, runtime logs, секретные env |
| Droplet | SSH с ключом → distro package PHP → закрытый FPM → web-server | Вы обновляете ОС, сеть и services; включение VM не завершает LAMP |
| Cloudways | Выбор приложения/сервера в панели → runtime и staging → проверка | Проверяйте текущие версии и возможности панели; цена/масштабирование отдельны |
| Functions | index.php с main → project.yml runtime → локальный test → deploy | Ограничения времени/памяти, события и внешнее хранение |
App Platform различает build time и runtime. COMPOSER_AUTH при сборке — секрет доступа к private repository, его хранят в защищённой настройке платформы. Не печатайте его в build log. Для нестандартных системных зависимостей выбирают поддерживаемый Dockerfile/VM-маршрут и сопровождают образ. После deployment проверяют настоящий URL, логи и доступ к данным; успешное создание компонента не доказывает готовности сайта.
Практика: выберите между Droplet и App Platform для сайта с обычным JSON и для приложения с собственным C-модулем. Объясните решение через требования и ответственность. Отдельно перечислите, какие оплачиваемые ресурсы останутся после окончания опыта.
Windows: собственное расширение через SDK, а не Unix make
Для нужной ветки PHP нет готовой DLL, но upstream расширения поддерживает Windows. Это уже задача native-сборки: необходимы соответствующий compiler, PHP SDK и development package. Простого наличия php.exe недостаточно. Unix phpize/make и Windows phpize/nmake — похожие этапы, но разные инструменты.
Сначала пройдите базовую Windows SDK сборку. Для PHP 8.4–8.5 официальный recipe использует Visual Studio 2022 / VS17; разрядность compiler, PHP, headers и dependency libraries должна совпадать. Примерные пути ниже обозначают заранее подготовленную отдельную SDK-среду, не обычный PowerShell. Установка compiler/SDK здесь не выполнялась.
- PHP binary + соответствующий development ZIP
- SDK shell нужной архитектуры
- Исходники расширения и Windows config.w32
- phpize и configure выбирают target
- nmake + PHPT
- Проверка DLL в отдельном PHP
phpize
configure --help
configure --with-prefix=C:\labs\php85 --enable-apcu
nmake
nmake test
Предусловия: отдельный SDK command prompt, согласованный PHP 8.5 development ZIP, его tools и target PHP доступны в PATH только этого shell; текущая папка — проверенные исходники APCu с поддерживаемым Windows build. --enable-apcu должен присутствовать в help этой версии. Дополнительные C-библиотеки выбирают по upstream через --with-php-build либо --with-extra-includes/--with-extra-libs. Команды не универсальны для расширения с другим именем и не выполнялись автором.
Второй вариант — in-tree: исходники расширения включают в дерево PHP до buildconf и собирают весь PHP с его флагом. Для одного внешнего DLL при уже готовом PHP удобнее отдельный development package, если upstream это поддерживает. Результат SDK зависит от конфигурации: Release, Release_TS, Debug, Debug_TS; для x64 они находятся под каталогом x64. Не берите первый похожий php_*.dll из другой папки.
При unresolved external symbol сначала сверяют headers/library architecture и версию dependency, при C1047 — toolset промежуточных файлов, при load error — паспорт DLL из предыдущего урока. Если PHPT требует внешнего сервера, пометьте условия/пропуски; успешный nmake не заменяет test. Архив результата включает DLL, нужные зависимости, версию toolchain и инструкции загрузки, а не весь домашний SDK.
Практика: составьте список источников бинарника PHP, development ZIP, исходников расширения и dependency libraries. Если один элемент не имеет проверяемого происхождения или нужной ABI-версии, сборка пока не готова.
Apache на Windows: путь NTS через mod_fcgid
Есть отдельный NTS php-cgi.exe и Apache 2.4. Их связывает mod_fcgid, который запускает и обслуживает FastCGI-процессы. Это отличается от mod_proxy_fcgi, который обращается к уже работающему backend, и от TS Apache handler DLL. Выберите один маршрут для конкретного .php; две одновременно действующие привязки затрудняют диагностику.
Предпосылки: совместимый Apache 2.4 и установленный mod_fcgid, NTS PHP C:/labs/php85 с рабочим ini, отдельный учебный virtual host с document root C:/labs/site/public. Приведённый фрагмент вставляется в main config/vhost, а не в .htaccess. Пути реальные только после подготовки вашей копии.
- Apache получает /ready.php
- FilesMatch выбирает fcgid-script
- FcgidWrapper запускает php-cgi.exe
- PHP возвращает FastCGI-ответ Apache
FcgidInitialEnv PHPRC "C:/labs/php85"
FcgidInitialEnv PHP_FCGI_MAX_REQUESTS 500
FcgidMaxRequestsPerProcess 500
<Directory "C:/labs/site/public">
Options +ExecCGI -Indexes
AllowOverride None
Require all granted
<FilesMatch "\.php$">
SetHandler fcgid-script
</FilesMatch>
FcgidWrapper "C:/labs/php85/php-cgi.exe" .php
</Directory>
Предусловия перечислены выше; это часть отдельного учебного vhost, не полный Apache server config. Directory ограничивает область; ExecCGI разрешает выполнение; FilesMatch сопоставляет окончание .php; FcgidWrapper выбирает исполняемый файл, PHPRC — его ini. Числа ограничивают жизнь процесса по числу запросов; здесь одинаковы для понятного согласованного примера. Фрагмент не запускался на Apache.
Перед reload выполните проверку конфигурации установленного Apache; затем в учебной среде проверьте ready.php, отсутствующий missing.php, обычный .txt и попытку открыть файл вне public. При ошибке ожидается отказ/404, а не показ исходного PHP. Проверьте startup log и фактический SAPI: корректный NTS fastcgi-путь не требует php8apache2_4.dll. Рабочие ACL дают identity процесса чтение кода и запись только в нужные tmp/session/upload каталоги; права Everyone Full Control не являются настройкой PHP.
Классический CGI запускает процесс на запрос и требует отдельной безопасной CGI mapping; сохранённый официальный пункт не делает этот путь предпочтительным. Полный CGI стенд, IIS identity/impersonation и HTTP отрицательные пробы остаются самостоятельными платформенными практикумами. Практика: объясните, кто создаёт php-cgi процессы в этой схеме, и почему простое добавление proxy_fcgi не сделает то же самое.
FPM: статус пула, ожидание и доступные работники
Сайт отвечает медленно, а память ещё есть. Причина может быть в том, что все FPM workers заняты ожиданием внешнего API. Один worker обрабатывает один запрос одновременно; pm.max_children задаёт предел этой параллельной обработки, а очередь ждёт свободного worker. Увеличивать число без измерений опасно: вырастут память и число соединений к базе.
Предварительная ступень — пул FPM и его listener. Статус — служебная диагностика с чувствительными путями/URI, её закрывают от внешних клиентов на уровне web-server и сети. Строка pm.status_path сама не создаёт безопасный публичный HTTP endpoint.
- Запрос приходит в очередь
- Свободный worker начинает обработку
- Занятый worker удерживается до завершения PHP
- Статус показывает очередь и занятость
pm.status_path = /fpm-status
pm.status_listen = 127.0.0.1:9071
ping.path = /fpm-ping
ping.response = alive
Предусловия: уже работающий учебный FPM pool и отдельный закрытый web route, который умеет передать FastCGI параметры. 9071 — FastCGI, не HTTP: curl непосредственно на этот порт не является корректным тестом. status_listen даёт независимый обслуживающий механизм статуса, полезный при занятом основном пуле. Не публикуйте listener наружу.
| Наблюдение | Что можно заключить | Чего ещё не знаем |
|---|---|---|
| listen queue растёт | Запросы ожидают обработки | Причина: медленный код, зависимость, CPU или нехватка workers |
| active = total, idle = 0 | Все текущие workers заняты | Нужно ли увеличивать предел без исчерпания RAM/DB |
| max children reached увеличивается | Пул упирался в лимит | Как долго и насколько это влияло на задержку |
| slow requests увеличивается | Пройден настроенный slowlog threshold | Где именно ожидание: смотрим slowlog/trace |
| ping отвечает | FPM может вернуть служебный ответ | Готовность базы, авторизации и приложения не доказана |
Status имеет текстовый формат и варианты html/xml/json/openmetrics; full добавляет сведения о процессах. Выберите формат под мониторинг, затем ограничьте хранение персональных URI. Счётчики относятся к жизни пула и могут сброситься после перезапуска. Сравнение двух снимков полезнее одной цифры. fastcgi_finish_request() завершает ответ клиенту, но последующий PHP-код продолжает занимать worker: это не очередь фоновых задач.
Практика для отдельного стенда: сопоставьте запрос ready.php и заведомо медленное тестовое действие; запишите queue, active, slowlog и задержку. В этой партии FPM и нагрузочные запросы не выполнялись, поэтому значения не подставлены как выдуманный результат.
FPM: лог запроса с единицами измерения и без лишних секретов
Нужно отличить медленный PHP от неработающего web proxy. Access log FPM описывает обработанный запрос, error log — сбои FPM/PHP, slowlog — стек затянувшегося запроса. Один файл не заменяет все три. Сначала выберите минимальные поля: метод, путь, статус, длительность, память и имя пула; query string нередко содержит персональные данные и токены.
Процент с буквой в access.format — placeholder FPM, не PHP-оператор. Модификатор в фигурных скобках задаёт единицы или имя поля. Например %{milli}d — миллисекунды, %{kilo}M — килобайты по правилам FPM. После изменения format нужен валидный pool config и проверка реально записанной строки.
- Запрос к /ready.php
- Access log: статус, миллисекунды, память
- При задержке → отдельный slowlog
- При сбое → error log и воспроизведение
access.log = /var/log/php-lab/access.log
access.format = "%n %m %r %s %{milli}d %{kilo}M"
slowlog = /var/log/php-lab/slow.log
request_slowlog_timeout = 3s
request_slowlog_trace_depth = 10
request_terminate_timeout = 30s
request_terminate_timeout_track_finished = yes
Предусловия: учебный pool, каталог создан владельцем с нужными правами, политика хранения/ротации определена. slowlog через 3 секунды — диагностика, terminate через 30 секунд — прекращение worker; это разные действия. track_finished распространяет этот предел и на работу после finish_request/shutdown. Числа учебные и не являются подбором для production.
| Маркеры FPM 8.5.11 | Смысл |
|---|---|
| %%; %n; %p; %P | Процент; имя пула; PID worker; PID master |
| %m; %r; %s; %l | Метод; URI без query; статус; длина тела POST |
| %q; %Q | Query string; ? при её наличии — включайте только с осознанным учётом данных |
| %R; %u; %f | Удалённый IP; Basic Auth пользователь; путь script — сведения требуют контроля доступа |
| %d / %{seconds}d / %{milli}d / %{micro}d | Длительность; aliases milliseconds/microseconds также поддержаны |
| %M / %{bytes}M / %{kilo}M / %{mega}M | Пиковое выделение памяти PHP; aliases kilobytes/megabytes |
| %C / %{user}C / %{system}C / %{total}C | Доля CPU запроса по выбранной категории; не число активных workers |
| %t; %T; %{формат-strftime}t или T | Время приёма; завершения; формат времени |
| %{имя}e; %{имя}o | Переменная окружения/запроса; заголовок ответа — нельзя бездумно логировать секреты |
rlimit_files задаёт предел открытых дескрипторов процесса, rlimit_core — core dumps, а process.dumpable/права и политики ОС могут ограничивать диагностику дополнительно. Core dump способен содержать пароли и данные запросов; не включают unlimited ради обычного error log. emergency_restart_threshold/interval реагируют на серию аварий worker, а не исправляют сломанное расширение. Сначала воспроизводят его в отдельной debug-сборке.
Практика: расшифруйте учебную строку «catalog GET /ready.php 200 12.5 512»: pool, method, path, status, миллисекунды, килобайты. Это синтетическая иллюстрация формата, не измерение. Добавьте только поле, необходимое для своей гипотезы, и объясните, какие сведения оно раскрывает.
FPM: проверка конфигурации, перезапуск и границы изоляции
Новая строка ini сохранена, а workers продолжают работать по старой настройке. Долгоживущий master/worker не перечитывает произвольный файл после каждого сохранения. Нужны тест конфигурации и управляемое обновление процессов. Команды service manager зависят от пакета и ОС; сначала выясняют точное имя службы и её launcher.
Для собственной исходной сборки полный путь php-fpm и -y указывают нужный master config. -t проверяет конфигурацию; это не запуск HTTP и не проверка доступности базы. Файл включает pool configs, а pool выбирает listener/user/process model. Не подставляйте php.ini вместо php-fpm.conf.
- Изменён файл учебного pool
- -t проверяет конфигурацию
- Manager выполняет согласованный reload
- Новые запросы проверяют фактическое состояние
/opt/php-lab/sbin/php-fpm -t -y /opt/php-lab/etc/php-fpm.conf
Предусловия: FPM действительно собран в этом prefix, master/pool config и пользователи/каталоги существуют. Успех означает прохождение проверки данного файла данным бинарником. Команда не доказывает, что nginx/Apache использует этот listener или что права на каждый прикладной файл правильны.
| Сигнал master по manpage FPM | Назначение |
|---|---|
| SIGQUIT | Мягкая остановка с завершением обслуживаемой работы |
| SIGUSR2 | Мягкая перезагрузка workers и конфигурации/binary |
| SIGUSR1 | Повторно открыть log files после согласованной ротации |
| SIGINT / SIGTERM | Немедленное завершение; это не мягкий reload |
На машине под systemd/OpenRC/rc.d предпочтительнее соответствующая команда manager: он владеет PID и знает пакетные пути. Не посылайте сигнал процессу с угаданным PID. После reload проверяют статус, новый startup log, что запрос обслужен новой версией/конфигурацией, и отрицательный случай: отсутствующий .php должен отказать, а не раскрыть исходник. Сохранённый прежний config и binary дают путь возврата.
Пул с отдельным Unix user и socket permissions ограничивает доступ. На Linux listen.owner/group/mode задают доступ к Unix socket; при listen.acl_users/groups owner/group игнорируются. На BSD поведение socket permissions отличается. chroot меняет видимый корень путей, но требует внутри необходимых файлов, временных каталогов, DNS/CA и не является полной заменой изоляции ОС. AppArmor hat/SELinux policy требуют поддерживаемой сборки и согласованной политики, а не одной волшебной строки. Пулы одного FPM нельзя считать взаимно недоверенными виртуальными машинами.
Практика: составьте операционную запись из четырёх строк: config test, согласованное действие manager, проверка после, точный rollback. Для отдельного chroot стенда перечислите абсолютные пути к коду, log, session/temp и CA снаружи и внутри корня. В этой партии службы и chroot не запускались.
Functions: локально проверить тело обработчика, не изображая облако
Нужно вернуть результат короткого действия по событию, без постоянного веб-сервера. В Functions платформа вызывает функцию и превращает её возвращённое значение в ответ. Для DigitalOcean входной файл называется index.php, по умолчанию обработчик — main. Это уже следующая ступень после параметров и return и массивов; сначала разберём одну запись.
function main() объявляет действие; фигурные скобки ограничивают тело. return передаёт результат вызывающему коду. Массив с ключом body обозначает содержимое ответа по договору платформы. Следующий локальный wrapper лишь вызывает нашу функцию и печатает её данные; он не воспроизводит timeout, context, authentication или HTTP-инфраструктуру.
- Локальный вызов main()
- return возвращает массив с body
- Wrapper печатает JSON
- В облаке wrapper заменяет платформа
<?php
function main(): array
{
return ['body' => ['service' => 'stock-check', 'ready' => true]];
}
$response = main();
echo json_encode($response['body']), "\n";
Ожидаемый результат
{"service":"stock-check","ready":true}
: array обещает возвращаемый массив; => связывает ключ и значение. $response сохраняет результат, ['body'] читает тело. Для реального index.php оставляют объявление обработчика, а локальный вызов/echo убирают: облачная платформа вызывает main сама. Облачный deploy не выполнялся.
В реальном событии event содержит данные, context — контекст платформы. Их не следует возвращать целиком клиенту: там могут быть лишние сведения. Повторная доставка события требует осознанной идемпотентности, а временный файл процесса не заменяет базу. Для dependencies нужен composer.json и предусмотренный platform build шаг; конфигурация runtime в project.yml выбирается из текущего поддерживаемого списка.
Практика: измените service на имя своего маленького действия и получите точный JSON локально. Затем отдельно выпишите проверки, которые остаются только облачному стенду: HTTP status/headers, лимиты, secrets, повтор события. Локальный PASS закрывает лишь алгоритм формирования body.
Источники и обсуждения
- PHP: Общие требования
- PHP: Windows
- PHP: Ручная установка Windows
- PHP: Windows CLI
- PHP: Debian/Ubuntu
- PHP: macOS: пакеты
- PHP: macOS: поставляемый PHP
- PHP: Windows: расширения
- PHP: Параметры сборки
- PHP: Встроенный сервер
- PHP: CLI options
- PHP: extension_loaded
- PHP: JSON extension
- PHP: PHP 8.5: изменения OPcache
- PHP Windows downloads
- PowerShell: call operator
- PowerShell: command precedence
- Homebrew: php formula
- PHP: install.unix
- PHP: install.unix.dnf
- PHP: install.unix.alpine
- PHP: install.unix.pacman
- PHP: install.unix.openbsd
- PHP: install.unix.source
- PHP: install.macosx
- PHP: install.macosx.compile
- PHP: install.unix.solaris
- PHP: install.unix.commandline
- PHP: install.unix.apache2
- PHP: install.unix.nginx
- PHP: install.unix.lighttpd-14
- PHP: install.unix.litespeed
- PHP: install.windows.apache2
- PHP: install.windows.iis
- PHP: install.windows.building
- PHP: install.windows.recommended
- PHP: install.fpm
- PHP: install.fpm.install
- PHP: install.fpm.configuration
- PHP: configuration.file
- PHP: configuration.changes
- PHP: configuration.changes.modes
- PHP: configuration.file.per-user
- PHP: ini.sections
- Fedora Developer Portal: PHP
- ArchWiki: PHP
- OpenBSD FAQ: package management
- MacPorts Guide
- MacPorts php85 port
- PHP 8.5 source README
- Oracle: IPS basics
- CGI security
- CGI/1.1 specification
- Apache: mod_proxy_fcgi
- Nginx: FastCGI module
- Nginx: try_files
- Lighttpd: mod_fastcgi
- LiteSpeed: current LSPHP setup
- PHP Windows downloads
- Microsoft: latest supported Visual C++ redistributable
- Microsoft: IIS FastCGI configuration
- PHP Wiki: Windows build SDK
- PHP Windows SDK tools
- OPcache configuration
- WinCache package releases
- PHP8.5 FPM pool template
- PHP8.5 FPM master template
- PIE: current usage
- PIE: releases and requirements
- PHP extension packages
- PHP supported versions
- Composer: installation
- Composer: verified download
- Composer: programmatic installer verification
- Composer: basic usage and lock
- Composer: command line
- Composer: plugin permissions
- Composer: untrusted packages
- Azure: current PHP quickstart
- Azure: PHP runtime/configuration
- AWS: PHP branches in AL2023
- AWS: AL2023 LAMP tutorial
- AWS: EC2 instance lifecycle
- DigitalOcean: PHP buildpack
- DigitalOcean: Functions PHP runtime
- DigitalOcean: Droplet SSH
- Apache mod_fcgid
- FPM status page
- FPM finish request
- PHP 8.5.11 FPM sample pool
- PHP 8.5.11 FPM signals
- PHP: install
- PHP: install.pecl
- PHP: install.pecl.intro
- PHP: install.pecl.downloads
- PHP: install.pie
- PHP: install.pie.intro
- PHP: install.composer.intro
- PHP: install.pecl.pear
- PHP: install.pecl.phpize
- PHP: install.pecl.php-config
- PHP: install.pecl.static
- PHP: install.composer
- PHP: install.cloud
- PHP: install.cloud.azure
- PHP: install.cloud.ec2
- PHP: install.cloud.digitalocean
- Windows: DLL exists but a dependency is missing — обсуждение проблемы
- CLI and Apache see different extension state — обсуждение проблемы
- Composer reports missing iconv — обсуждение проблемы
- phpize API differs from PHP API — обсуждение проблемы
- Windows DLL loading failure on a recent setup — обсуждение проблемы
- Build an extension for multiple PHP versions — обсуждение проблемы
Код и руководство с собой
Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.
Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.
Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.


