Перейти к содержимому
Поиск
Php Разработка

PHP: полный мануал с примерами, функциями и ООП

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

Александр НекрасовИзменено:
Практический мануал PHP: от переменных и функций к объектной модели интернет-магазина
PHP 8.5.11468 глав6256 карточек справочника
Дерево руководства

Глава 136 · Перед первым подключением; сборка — отдельный расширенный маршрут

MySQL X DevAPI: установка, настройки PHP и проверка соединения

Проверить конкретный PHP и ini, прочитать все настройки X DevAPI, отличить отказ порта и собрать модуль с реальной загрузкой.

От сообщения об ошибке к работающему подключению

Новый проект должен обратиться к MySQL, но прежде чем писать запросы, нужно собрать четыре работающих звена: исполняющий PHP, его расширение mysql_xdevapi, X Protocol на сервере и подходящую учётную запись. Здесь результатом будут конкретные отчёты: какой PHP запущен, какие настройки действуют, почему соединение отклонено и загрузился ли действительно собранный модуль.

От файла PHP до результата базы
  1. example.php выполняет конкретный php.exe / php-fpm
  2. При запуске PHP читает ini и загружает DLL / SO
  3. mysql_xdevapi открывает Session через X Protocol
  4. MySQL проверяет соединение и выполняет SELECT
  5. Строка ready = 1 возвращается в PHP

Расширение — модуль, добавляющий функции и классы в PHP. DLL в Windows и SO в Linux — разные форматы такого модуля; переименование файла не делает их взаимозаменяемыми. SAPI — способ связи PHP с окружением: консоль, PHP-FPM или серверный модуль. ini — текстовая конфигурация, читаемая при запуске PHP. Протокол — правила общения клиента и сервера; X Protocol и классический MySQL используют разные точки входа.

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

Архив каждого урока содержит example.php, lab.php и README.txt. Запускайте файл в отдельном каталоге: он сохранит result.html для чтения человеком, result.json с фактическими наблюдениями и metrics.json со сводными проверками. Полные личные пути, URI и пароль в опубликованные отчёты не включаются. Для первого отчёта mysql_xdevapi может отсутствовать: это штатно объясняемый результат. Остальные уроки требуют загруженного расширения; только проверке соединения нужен PHPMAN_MYSQLX_URI.

Входные знания: переменные, условия, массивы, try/finally и исключения. Короткий пример перед полной программой объясняет новое действие; диагностические обёртки полного файла нужны для сохранения результата и гарантированного закрытия ресурсов. Первая коллекция объясняет исходный mysqlx URI, а отдельные учебные базы — их создание, владение и удаление.

Основные PHP-примеры имеют профиль Windows: PHP 8.3.35 NTS x64, mysql_xdevapi 8.0.30 и MySQL 8.4.13. Дополнительно ниже показана отдельная сборка расширения под Linux/PHP 8.3.6. Это два разных бинарных окружения. Успешная загрузка Linux-модуля не означает, что в Linux был проверен доступ к базе; соединение проверяется отдельно в Windows-примере.

Установка и настройка: полный маршрут

Нужно запустить импорт на новом компьютере и понять, на каком шаге он готов к работе. Официальный раздел Installing/Configuring объединяет требования, установку, настройки и сборку. Пройдём эти четыре шага в том порядке, в котором они помогают получить первый осмысленный результат.

ШагЧто требуетсяЧем подтверждается
ТребованияMySQL 8+ с X Plugin; для сборки — Boost 1.53+, OpenSSL и ProtobufВерсии процесса и серверный X-порт проверяются раздельно
УстановкаВнешнее расширение mysql_xdevapi, подходящее данному PHPextension_loaded и phpversion в нужном SAPI
КонфигурацияПравильный ini и все шесть директивПрочитанные local/global/access, изменение и восстановление INI_ALL
Сборка из исходниковСовместимый SDK или phpize, компилятор и библиотекиСобранный модуль действительно загружен отдельным PHP

Самая короткая проверка перед установкой

php -v
php --ini
php -m
php --ri mysql_xdevapi

Эти команды обращаются к php, найденному оболочкой. -v показывает версию и сборку, --ini — основной и сканируемые ini, -m — загруженные модули, --ri — сведения конкретного расширения. Если в PATH несколько PHP, укажите полный путь к нужному исполняемому файлу. Отсутствие расширения в --ri не доказывает отсутствие DLL на диске: оно доказывает, что этот процесс её не загрузил. Первый самостоятельный отчёт сохраняет те же различия в читаемой таблице.

Готовое расширение: установить файл и включить его — два шага

mysql_xdevapi не входит в базовую поставку PHP как обязательная встроенная возможность. Официальный архив расширения доступен в PECL. Установка библиотеки Composer с похожим названием не добавляет нативные классы mysql_xdevapi в PHP. Сначала нужен совместимый бинарный модуль либо сборка исходника; затем его должен загрузить конкретный PHP-процесс.

Для Windows сопоставьте версию PHP, разрядность x86/x64, TS/NTS, debug/release и компиляторную совместимость. Выбирайте файл с официальной страницы расширения, если для вашего профиля он доступен. DLL для другой ветки или архитектуры нельзя исправить переименованием. Отсутствующая зависимая DLL тоже может проявиться как ошибка загрузки основного файла; читайте startup-журнал, а не только проверяйте существование php_mysql_xdevapi.dll.

; Фрагмент php.ini своего PHP; путь замените своим.
extension_dir = "C:\PATH\TO\PHP\ext"
extension = mysql_xdevapi

Имена расширений без префикса php_ и суффикса .dll поддерживаются PHP начиная с 7.2. Полное имя файла и абсолютный путь также применяются в подходящей конфигурации. Не добавляйте модуль дважды в основной и дополнительный ini. После изменения настройку должен прочитать новый процесс: CLI запускается заново, а PHP-FPM или модуль веб-сервера надо перезапустить штатным способом.

В Debian/Ubuntu модуль часто включают отдельным файлом в mods-available и утилитой phpenmod, которая создаёт ссылки для выбранных SAPI. Это механизм дистрибутива, а не универсальная команда PHP для Windows и всех Linux. Официальная страница mysql_xdevapi.installation содержит исторический пример Ubuntu 18.04/PHP 7.2 и pecl install; он показывает этапы, но его пакеты и сторонний PPA не нужно копировать на Ubuntu 24.04. Общая документация PHP теперь рекомендует PIE вместо устаревающего установщика PECL; конкретную PIE-команду для этого пакета мы без подтверждённой поддержки не придумываем. Ниже используется точный архив 8.0.30 и ручной phpize-маршрут.

Как не перепутать ini сайта и консоли

PHP читает настройки в порядке своей конфигурации запуска. Специальный php-SAPI.ini может иметь приоритет над обычным php.ini; дополнительные ini берутся из каталога сканирования, на который может влиять PHP_INI_SCAN_DIR. --ini показывает именно CLI. Для сайта проверяйте значения внутри обслуживающего его процесса, например защищённым временным диагностическим файлом. CLI-ключ -c явно выбирает файл или каталог, -n отключает чтение ini, -d задаёт настройку только этому запуску. Подробнее — выбор конфигурационного файла.

& 'C:\PATH\TO\PHP\php.exe' -c 'C:\PATH\TO\PHP\php.ini' .\example.php
# Изолированная загрузка конкретной DLL без чтения ini:
& 'C:\PATH\TO\PHP\php.exe' -n -d 'extension=C:\PATH\TO\PHP\ext\php_mysql_xdevapi.dll' .\example.php

Первый вариант проверяет вашу обычную конфигурацию. Второй нужен для локализации проблемы и должен учитывать зависимости конкретной сборки; это не команда установки на веб-сервер. В наших Windows-запусках DLL загружается абсолютным путём. Поэтому проверка существования extension_dir и проверка extension_loaded намеренно показаны разными строками.

Два реальных применения

При переносе CLI-импорта сравните сохранённые отчёты старого и нового PHP, затем выполните контрольный SELECT. При отказе только сайта начните с SAPI и его ini: рабочая консоль не доказывает загрузку модуля PHP-FPM. Если модуль загрузился, но getSession не сработал, переходите к адресу X Protocol, TLS и учётной записи — переустановка DLL уже не является первым объяснением.

Официальная структура Installing/Configuring: PHP Manual. Отчёт окружения даёт начальную точку, контрольное соединение завершает маршрут.

Понять, какой PHP выполняет файл и загружен ли нужный модуль

В консоли запрос работает, а сайт пишет «Class mysql_xdevapi\Session not found». Сначала надо узнать, одним ли PHP они выполняются и загружен ли модуль именно в проблемном процессе. Отчёт работает и без mysql_xdevapi: он показывает причину остановки, а не пытается подключиться несуществующим классом.

Путь проверки
  1. Запущенный PHP → версия, SAPI, TS/NTS и разрядность
  2. Его startup-настройки → основной и дополнительные ini
  3. extension_loaded → модуль действительно есть или отсутствует
  4. Отчёт → настройка модуля либо проверка соединения

Начните с одного действия

<?php
$loaded = extension_loaded('mysql_xdevapi');
echo $loaded ? 'Модуль загружен' : 'Модуль не загружен';

Строка mysql_xdevapi — имя расширения. extension_loaded возвращает логическое true или false. Знак ? выбирает первый текст при true, а часть после : — второй. Это только проверка текущего процесса. PHP_SAPI показывает способ запуска: cli для консоли, например fpm-fcgi для PHP-FPM. PHP_ZTS различает сборки TS и NTS, PHP_INT_SIZE * 8 — разрядность целого числа. Полный файл отдельно спрашивает PHP о прочитанных ini и наличии класса, не вызывая ни одного метода Session.

Результат в указанном Windows-профиле

НаблюдениеРезультат
PHP8.3.35
Режим запускаcli
Разрядность64
СборкаNTS
Имя PHPphp.exe
mysql_xdevapi загруженда
Версия расширения8.0.30
Класс Session доступенда
Основной ini прочитаннет
Дополнительные ini прочитанынет
Каталог extension_dir существуетнет
Следующий шагМожно проверять соединение

В другом PHP значения версии, SAPI, ini и инструментов могут отличаться: это и есть полезная часть диагностики. Сравнивайте наблюдения и причину, а не подгоняйте свой компьютер под текст таблицы.

Самостоятельная программа и архив
Понять, какой PHP выполняет файл и загружен ли нужный модульСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/lab.php';
$session = null;
$config = null;
$owned = $tokens = $removed = $rows = $checks = [];
$observations = ['schema_absence_before'=>null, 'schema_absence_after'=>null];
$runtime = x146Runtime();
try {

    $loaded=extension_loaded('mysql_xdevapi');
    $version=$loaded ? phpversion('mysql_xdevapi') : false;
    $sessionClass=class_exists('mysql_xdevapi\Session',false);
    $ini=php_ini_loaded_file();
    $scanned=php_ini_scanned_files();
    $extensionDirectory=ini_get('extension_dir');
    $directoryExists=is_string($extensionDirectory) && is_dir($extensionDirectory);
    $binaryName=basename(str_replace('\\','/',PHP_BINARY));
    $iniName=$ini===false ? null : basename(str_replace('\\','/',$ini));
    $scannedNames=[];
    if (is_string($scanned)) {
        foreach (preg_split('/,\s*/',trim($scanned)) as $path) {
            if ($path!=='') {$scannedNames[]=basename(str_replace('\\','/',$path));}
        }
    }
    $decision=$loaded ? 'Можно проверять соединение' : 'Сначала установите и включите совместимый модуль';
    $rows=[['PHP',PHP_VERSION],['Режим запуска',PHP_SAPI],['Разрядность',PHP_INT_SIZE*8],
        ['Сборка',PHP_ZTS ? 'TS' : 'NTS'],['Имя PHP',$binaryName],
        ['mysql_xdevapi загружен',$loaded],['Версия расширения',$version ?: 'не загружено'],
        ['Класс Session доступен',$sessionClass],['Основной ini прочитан',$ini!==false],
        ['Дополнительные ini прочитаны',is_string($scanned) && trim($scanned)!==''],
        ['Каталог extension_dir существует',$directoryExists],['Следующий шаг',$decision]];
    $checks=['report_matches_loaded_state'=>$loaded ? is_string($version) && $sessionClass : $version===false && !$sessionClass,
        'binary_identity_available'=>$binaryName!=='','no_database_contact'=>$session===null,
        'ini_discovery_recorded'=>is_array($scannedNames)];
    $observations+=['extension_loaded'=>$loaded,'extension_version'=>$version ?: null,
        'binary_name'=>$binaryName,'binary_absolute_path_available_locally'=>PHP_BINARY!=='',
        'sapi'=>PHP_SAPI,'bits'=>PHP_INT_SIZE*8,'zts'=>(bool)PHP_ZTS,'debug'=>(bool)PHP_DEBUG,
        'loaded_ini_name'=>$iniName,'scanned_ini_names'=>$scannedNames,
        'extension_dir_exists'=>$directoryExists,'private_paths_omitted'=>true,
        'database_connection_attempted'=>false];

} finally {
    if ($session instanceof mysql_xdevapi\Session) {
        try {
            $removed=x146Cleanup($session,$owned,$tokens,$removed);
            $observations['schema_absence_after']=x146Absence($session);
        } finally {$session->close();}
    }
}

x146Report('mysql146-x-environment-report', 'Понять, какой PHP выполняет файл и загружен ли нужный модуль', $rows, $checks, $observations, $runtime, $owned, $removed);
Ожидаемый результат
PHP — 8.3.35
Режим запуска — cli
Разрядность — 64
Сборка — NTS
Имя PHP — php.exe
mysql_xdevapi загружен — да
Версия расширения — 8.0.30
Класс Session доступен — да
Основной ini прочитан — нет
Дополнительные ini прочитаны — нет
Каталог extension_dir существует — нет
Следующий шаг — Можно проверять соединение

CLI-файл сохраняет result.html/result.json. Ничего не устанавливает и не создаёт объектов базы. Не открывает соединение с MySQL.

Таблица фактического запуска · Наблюдения и проверки JSON.

Что этот результат подтверждает

Установленный файл DLL/SO ещё не означает, что этот процесс его загрузил. Даже одинаковый путь ini не доказывает одинаковые бинарные файлы, рабочий каталог и найденные зависимости. В проверенном Windows-профиле ini не читается из-за -n, а DLL передана абсолютным путём через -d extension=...; поэтому модуль доступен при несуществующем extension_dir. Это наблюдение конкретного запуска, а не совет оставить неверную настройку веб-сервера. В опубликованном JSON пути скрыты; для локального расследования можно отдельно вывести PHP_BINARY, php_ini_loaded_file() и php_ini_scanned_files(). Не оставляйте такой диагностический обработчик открытым в интернете.

Вопрос показывает, почему одного совпадения ini недостаточно: разработчик видел разные результаты запуска. Мы сопоставляем исполняющий PHP, SAPI, загрузку модуля и пути поиска; старые ограничения путей Windows 7 не выдаём за универсальное правило современных PHP. Расширение работает в CLI, но отсутствует в Apache при том же ini.

Попробуйте другое условие

Запустите файл другим php.exe или в PHP-FPM. Какие поля могут измениться, даже если example.php остался тем же?

Разбор

Сравните версию и имя PHP, SAPI, TS/NTS, разрядность, загруженный модуль и имена ini. После изменения конфигурации перезапустите обслуживающий сайт процесс; новый CLI-процесс перечитает настройки при своём запуске. При отсутствии расширения отчёт должен завершиться с полезным следующим шагом; это не успешное соединение с базой.

Прочитать все настройки X DevAPI и восстановить временное изменение

Длинный CLI-импорт должен временно изменить разрешённую настройку и затем вернуть прежний режим. Перед изменением посмотрим, какие параметры принадлежат расширению и какие из них вообще доступны из PHP-кода. Отказ ini_set тоже будет видимым результатом.

Путь проверки
  1. ini_get_all → 6 зарегистрированных директив
  2. INI_ALL collect_statistics: 1 → 0
  3. finally → восстановлено прежнее 1
  4. INI_SYSTEM: ini_set вернул false → значение осталось 0

Начните с одного действия

<?php
$before = ini_get('xmysqlnd.collect_statistics');
$previous = ini_set('xmysqlnd.collect_statistics', '0');
var_dump($previous); // В нашем профиле string(1) "1".
if ($previous !== false) {
    ini_set('xmysqlnd.collect_statistics', $before);
}

ini_get читает текущее значение в виде строки либо false для неизвестного имени. ini_set возвращает предыдущее значение либо false при отказе; сравниваем строго через !== false, иначе строка "0" вводит в заблуждение. Массив ini_get_all содержит global_value, local_value и числовой access. В полной программе try/finally гарантирует восстановление прежнего локального значения после блока. Мы проверяем изменения настройки, а не объявляем ускорение импорта.

Результат в указанном Windows-профиле

НаблюдениеРезультат
Зарегистрировано настроек6
collect_statistics до изменения1
collect_statistics внутри блока0
collect_statistics восстановленада
INI_SYSTEM изменена через ini_setнет
collect_memory_statistics осталось прежнимда

В другом PHP значения версии, SAPI, ini и инструментов могут отличаться: это и есть полезная часть диагностики. Сравнивайте наблюдения и причину, а не подгоняйте свой компьютер под текст таблицы.

Самостоятельная программа и архив
Прочитать все настройки X DevAPI и восстановить временное изменениеСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/lab.php';
$session = null;
$config = null;
$owned = $tokens = $removed = $rows = $checks = [];
$observations = ['schema_absence_before'=>null, 'schema_absence_after'=>null];
$runtime = x146Runtime();
try {

    if (!extension_loaded('mysql_xdevapi')) {throw new RuntimeException('Для этого урока включите mysql_xdevapi. Сначала запустите environment-report.');}
    $beforeAll=ini_get_all('mysql_xdevapi',true);
    if (!is_array($beforeAll)) {throw new RuntimeException('Не удалось получить настройки расширения.');}
    $option='xmysqlnd.collect_statistics';
    $before=ini_get($option);
    if ($before===false) {throw new RuntimeException('Настройка не зарегистрирована.');}
    $previous=false; $during=null;
    try {
        $previous=ini_set($option,'0');
        if ($previous===false) {throw new RuntimeException('Текущее окружение запретило изменение INI_ALL.');}
        $during=ini_get($option);
    } finally {if ($previous!==false) {ini_set($option,$before);}}
    $after=ini_get($option);
    $systemOption='xmysqlnd.collect_memory_statistics';
    $systemBefore=ini_get($systemOption);
    $systemAttempt=ini_set($systemOption,'1');
    $systemAfter=ini_get($systemOption);
    $rows=[['Зарегистрировано настроек',count($beforeAll)],
        ['collect_statistics до изменения',$before],['collect_statistics внутри блока',$during],
        ['collect_statistics восстановлена',$after===$before],
        ['INI_SYSTEM изменена через ini_set',$systemAttempt!==false],
        ['collect_memory_statistics осталось прежним',$systemAfter===$systemBefore]];
    $checks=['all_six_directives'=>count($beforeAll)===6,
        'temporary_override_and_restore'=>$previous===$before && $during==='0' && $after===$before,
        'system_change_rejected'=>$systemAttempt===false && $systemAfter===$systemBefore,
        'no_database_contact'=>$session===null];
    $observations+=['directives'=>$beforeAll,'collect_statistics'=>['before'=>$before,'returned_previous'=>$previous,'during'=>$during,'after'=>$after],
        'system_change'=>['name'=>$systemOption,'before'=>$systemBefore,'returned'=>$systemAttempt,'after'=>$systemAfter],
        'database_connection_attempted'=>false];

} finally {
    if ($session instanceof mysql_xdevapi\Session) {
        try {
            $removed=x146Cleanup($session,$owned,$tokens,$removed);
            $observations['schema_absence_after']=x146Absence($session);
        } finally {$session->close();}
    }
}

x146Report('mysql146-x-runtime-configuration', 'Прочитать все настройки X DevAPI и восстановить временное изменение', $rows, $checks, $observations, $runtime, $owned, $removed);
Ожидаемый результат
Зарегистрировано настроек — 6
collect_statistics до изменения — 1
collect_statistics внутри блока — 0
collect_statistics восстановлена — да
INI_SYSTEM изменена через ini_set — нет
collect_memory_statistics осталось прежним — да

CLI-файл сохраняет result.html/result.json. Ничего не устанавливает и не создаёт объектов базы. Не открывает соединение с MySQL.

Таблица фактического запуска · Наблюдения и проверки JSON.

Что этот результат подтверждает

Пример рассчитан на шесть директив PECL 8.0.30; иная версия может зарегистрировать другой набор. Для INI_SYSTEM правка php.ini и перезапуск PHP-процесса отличаются от ini_set. Не путайте глобальное значение конфигурации этого процесса с общей переменной всех серверов. В release-сборке debug/trace не превращаются в обещание полноценной отладки. Не меняйте net_read_timeout в надежде исправить неслушающий TCP-порт: время подключения и чтение — разные этапы. Полный перечень и ограничения исходника разобраны ниже.

Попробуйте другое условие

Внешний код уже установил collect_statistics в "0". Какое значение надо вернуть после вашей функции?

Разбор

Сохраните значение перед входом и верните именно его. Не устанавливайте безусловно "1" и не заменяйте это ini_restore: тот восстанавливает исходную настройку конфигурации, а не обязательно локальное значение вызывающего кода.

Отличить рабочий X Protocol от отказа порта и проверить TLS

Расширение уже загружено, но приложение не соединяется с базой. Теперь отделим PHP-конфигурацию от доступности X-порта, а доступность порта — от работающего запроса и шифрования. В одном файле получим настоящий SELECT, TLS-параметры и контролируемый отказ другого локального порта.

Путь проверки
  1. mysqlx URI → X Protocol, а не классический MySQL-порт
  2. Session → SELECT ready = 1
  3. Mysqlx_ssl_* → TLSv1.3 и согласованный шифр
  4. Зарезервированный порт без listen → ошибка 2002
  5. Прежняя Session → снова ready = 1

Начните с одного действия

$session = mysql_xdevapi\getSession(getenv('PHPMAN_MYSQLX_URI'));
$row = $session->sql('SELECT 1 AS ready')->execute()->fetchOne();
echo $row['ready']; // 1
$session->close();

URI — строка с протоколом, учётной записью, адресом и параметрами; getenv берёт её из окружения, а не из опубликованного исходника. getSession создаёт соединение. sql подготавливает команду, execute выполняет её, fetchOne читает строку; AS ready даёт столбцу понятное имя. Полный файл также использует fetchAll для таблицы TLS и защищает закрытие через finally. bind тестового TCP-сокета резервирует адрес, но без STREAM_SERVER_LISTEN не принимает соединения: так отказ воспроизводится без обращения к чужому серверу.

Результат в указанном Windows-профиле

НаблюдениеРезультат
Первый контрольный SELECT1
X Protocol использует TLSда
Версия TLSTLSv1.3
Шифр X ProtocolTLS_AES_256_GCM_SHA384
Код отказа неслушающего порта2002
Рабочее соединение после отказа1

В другом PHP значения версии, SAPI, ini и инструментов могут отличаться: это и есть полезная часть диагностики. Сравнивайте наблюдения и причину, а не подгоняйте свой компьютер под текст таблицы.

Самостоятельная программа и архив
Отличить рабочий X Protocol от отказа порта и проверить TLSСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/lab.php';
$session = null;
$config = null;
$owned = $tokens = $removed = $rows = $checks = [];
$observations = ['schema_absence_before'=>null, 'schema_absence_after'=>null];
$runtime = x146Runtime();
try {

    $config=x146Config();
    $session=mysql_xdevapi\getSession($config['uri']);
    $runtime=x146Runtime($session,$config);
    $observations['schema_absence_before']=x146Absence($session);
    if (in_array(false,$observations['schema_absence_before'],true)) {
        throw new RuntimeException('Одно из учебных имён занято; запуск прекращён без удаления.');
    }

    $first=$session->sql('SELECT 1 AS ready')->execute()->fetchAll();
    $statusRows=$session->sql("SHOW SESSION STATUS LIKE 'Mysqlx_ssl%'")->execute()->fetchAll();
    $tls=[];
    foreach ($statusRows as $row) {$tls[$row['Variable_name']]=$row['Value'];}
    $bound=null; $failure=null; $badPort=null;
    try {
        $bound=stream_socket_server('tcp://127.0.0.1:0',$socketError,$socketMessage,STREAM_SERVER_BIND);
        if ($bound===false) {throw new RuntimeException('Не удалось зарезервировать локальный тестовый порт.');}
        $address=stream_socket_get_name($bound,false);
        $badPort=(int)substr($address,strrpos($address,':')+1);
        if ($badPort<1 || $badPort>65535) {throw new RuntimeException('Не удалось определить тестовый порт.');}
        $parts=parse_url($config['uri']);
        $badUri='mysqlx://'.($parts['user']??'').':'.($parts['pass']??'').'@127.0.0.1:'.$badPort.
            '?ssl-mode=required&connect-timeout=1000';
        $failure=x146Failure(static function() use($badUri): void {
            $unexpectedSession=mysql_xdevapi\getSession($badUri);
            $unexpectedSession->close();
        });
    } finally {
        if (is_resource($bound)) {fclose($bound);}
    }
    $last=$session->sql('SELECT 1 AS ready')->execute()->fetchAll();
    $errorCode=$failure[0]['code']??null;
    $rows=[['Первый контрольный SELECT',$first[0]['ready']],
        ['X Protocol использует TLS',($tls['Mysqlx_ssl_active']??'')==='ON'],
        ['Версия TLS',$tls['Mysqlx_ssl_version']??''],
        ['Шифр X Protocol',$tls['Mysqlx_ssl_cipher']??''],
        ['Код отказа неслушающего порта',$errorCode],
        ['Рабочее соединение после отказа',$last[0]['ready']]];
    $checks=['real_query_succeeded'=>$first===[['ready'=>1]],
        'x_protocol_tls_observed'=>($tls['Mysqlx_ssl_active']??'')==='ON' && ($tls['Mysqlx_ssl_cipher']??'')!=='',
        'bounded_expected_failure'=>$failure!==null && $errorCode===2002,
        'original_session_still_usable'=>$last===[['ready'=>1]],
        'no_schema_objects_created'=>$owned===[]];
    $observations+=['first_query'=>$first,'x_protocol_tls'=>[
        'active'=>$tls['Mysqlx_ssl_active']??null,'cipher'=>$tls['Mysqlx_ssl_cipher']??null,'version'=>$tls['Mysqlx_ssl_version']??null],
        'failed_endpoint'=>['host'=>'127.0.0.1','port'=>$badPort,'bound_without_listen'=>true,'connect_timeout_ms'=>1000,'failure'=>$failure],
        'last_query'=>$last,'uri_omitted'=>true];

} finally {
    if ($session instanceof mysql_xdevapi\Session) {
        try {
            $removed=x146Cleanup($session,$owned,$tokens,$removed);
            $observations['schema_absence_after']=x146Absence($session);
        } finally {$session->close();}
    }
}

x146Report('mysql146-x-connection-checklist', 'Отличить рабочий X Protocol от отказа порта и проверить TLS', $rows, $checks, $observations, $runtime, $owned, $removed);
Ожидаемый результат
Первый контрольный SELECT — 1
X Protocol использует TLS — да
Версия TLS — TLSv1.3
Шифр X Protocol — TLS_AES_256_GCM_SHA384
Код отказа неслушающего порта — 2002
Рабочее соединение после отказа — 1

CLI-файл сохраняет result.html/result.json. Ничего не устанавливает и не создаёт объектов базы. Открывает собственную Session, проверяет чтение и закрывает её.

Таблица фактического запуска · Наблюдения и проверки JSON.

Что этот результат подтверждает

Нужны MySQL 8+ с включённым X Plugin, доступный X-порт, разрешённая учётная запись и совместимый TLS. Обычный порт 3306 предназначен для классического протокола; стандартный X-порт — 33060, в нашей отдельной лаборатории — 33140. ssl-mode=required требует шифрование, но не является проверкой личности сервера уровня verify_identity с доверенным CA и именем узла. Для X-соединения смотрим Mysqlx_ssl_cipher, а не классический Ssl_cipher. Таймаут подключения 1000 мс не ограничивает любой SQL-запрос; runner дополнительно ограничивает весь процесс. Код 2002 относится здесь к заведомо неслушающему порту; такой же код в другом окружении требует изучить адрес, маршрутизацию и сообщение. URI и пароли в отчёт не попадают.

Попробуйте другое условие

После переноса приложения SELECT не работает. В каком порядке проверять модуль, порт, TLS и права?

Разбор

Сначала отчёт текущего PHP. Затем проверьте, что адрес/порт относятся к X Protocol и сервер слушает его. При успешном соединении выполните простой SELECT и прочитайте X-specific TLS. Отказы аутентификации/прав разберите отдельно; не переключайте вслепую TLS в disabled и не выдавайте глобальные административные права.

Выбрать совместимый модуль и увидеть, готова ли среда сборки

Для существующего PHP нужен совместимый DLL/SO. Если подходящего готового файла нет, нужна сборочная среда. Программа показывает признаки текущего PHP и наличие строго перечисленных инструментов в PATH; ничего не устанавливает и не выдаёт наличие компилятора за готовое расширение.

Путь проверки
  1. PHP 8.3, x64, NTS → критерии совместимости DLL
  2. PATH → наличие восьми известных инструментов
  3. Диагностический отчёт → выбрать DLL или подготовить SDK
  4. Отдельная настоящая сборка ниже → SO → загрузка новым PHP-процессом

Начните с одного действия

<?php
echo PHP_OS_FAMILY, "\n";
echo PHP_MAJOR_VERSION, '.', PHP_MINOR_VERSION, "\n";
echo PHP_INT_SIZE * 8, " bit ", PHP_ZTS ? 'TS' : 'NTS';

Константы PHP описывают исполняющий программу интерпретатор. Ветка 8.3, архитектура x64 и NTS — три разных условия совместимости расширения. PATH — список каталогов поиска программ, а не доказательство, что они совместимы. В полной программе foreach перебирает фиксированные имена и пути, is_file проверяет файл, is_executable — возможность запуска в Unix. В Windows добавляются расширения PATHEXT. Команды из найденных файлов не выполняются, значения PATH и личные пути не публикуются.

Результат в указанном Windows-профиле

НаблюдениеРезультат
Операционная системаWindows
Ветка PHP8.3
Разрядность64
СборкаNTS
mysql_xdevapi загруженда
Инструментов из списка найдено0
Подходящий маршрутСовместимый DLL или Windows PHP SDK
Компиляция этим PHP-файлом запускаласьнет

В другом PHP значения версии, SAPI, ini и инструментов могут отличаться: это и есть полезная часть диагностики. Сравнивайте наблюдения и причину, а не подгоняйте свой компьютер под текст таблицы.

Самостоятельная программа и архив
Выбрать совместимый модуль и увидеть, готова ли среда сборкиСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/lab.php';
$session = null;
$config = null;
$owned = $tokens = $removed = $rows = $checks = [];
$observations = ['schema_absence_before'=>null, 'schema_absence_after'=>null];
$runtime = x146Runtime();
try {

    $tools=['phpize','php-config','g++','make','protoc','bison','cl','cmake'];
    $paths=explode(PATH_SEPARATOR,getenv('PATH') ?: '');
    $windows=PHP_OS_FAMILY==='Windows';
    $extensions=$windows ? array_values(array_unique(array_merge([''],explode(';',getenv('PATHEXT') ?: '.EXE;.CMD;.BAT')))) : [''];
    $found=[];
    foreach ($tools as $tool) {
        $found[$tool]=false;
        foreach ($paths as $directory) {
            $directory=trim($directory,'"');
            if ($directory==='') {continue;}
            foreach ($extensions as $suffix) {
                $candidate=rtrim($directory,"\\/").DIRECTORY_SEPARATOR.$tool.$suffix;
                if (is_file($candidate) && ($windows || is_executable($candidate))) {$found[$tool]=true; break 2;}
            }
        }
    }
    $linuxTools=['phpize','php-config','g++','make','protoc','bison'];
    $missing=[];
    foreach ($linuxTools as $tool) {if (!$found[$tool]) {$missing[]=$tool;}}
    $route=$windows ? 'Совместимый DLL или Windows PHP SDK' : 'Совместимый SO или phpize и зависимости';
    $rows=[['Операционная система',PHP_OS_FAMILY],['Ветка PHP',PHP_MAJOR_VERSION.'.'.PHP_MINOR_VERSION],
        ['Разрядность',PHP_INT_SIZE*8],['Сборка',PHP_ZTS ? 'TS' : 'NTS'],
        ['mysql_xdevapi загружен',extension_loaded('mysql_xdevapi')],
        ['Инструментов из списка найдено',count(array_filter($found))],
        ['Подходящий маршрут',$route],['Компиляция этим PHP-файлом запускалась',false]];
    $checks=['fixed_tool_allowlist'=>count($found)===8 && count(array_diff(array_keys($found),$tools))===0,
        'no_compilation_or_installation'=>true,'no_database_contact'=>$session===null,
        'abi_fields_observed'=>PHP_INT_SIZE>0 && PHP_MAJOR_VERSION>0];
    $observations+=['platform'=>PHP_OS_FAMILY,'php_branch'=>PHP_MAJOR_VERSION.'.'.PHP_MINOR_VERSION,
        'bits'=>PHP_INT_SIZE*8,'zts'=>(bool)PHP_ZTS,'debug'=>(bool)PHP_DEBUG,
        'fixed_tool_presence'=>$found,'missing_unix_tool_names'=>$missing,
        'searched_path_values_omitted'=>true,'compiler_executed'=>false,'database_connection_attempted'=>false];

} finally {
    if ($session instanceof mysql_xdevapi\Session) {
        try {
            $removed=x146Cleanup($session,$owned,$tokens,$removed);
            $observations['schema_absence_after']=x146Absence($session);
        } finally {$session->close();}
    }
}

x146Report('mysql146-x-build-prerequisites', 'Выбрать совместимый модуль и увидеть, готова ли среда сборки', $rows, $checks, $observations, $runtime, $owned, $removed);
Ожидаемый результат
Операционная система — Windows
Ветка PHP — 8.3
Разрядность — 64
Сборка — NTS
mysql_xdevapi загружен — да
Инструментов из списка найдено — 0
Подходящий маршрут — Совместимый DLL или Windows PHP SDK
Компиляция этим PHP-файлом запускалась — нет

CLI-файл сохраняет result.html/result.json. Ничего не устанавливает и не создаёт объектов базы. Не открывает соединение с MySQL.

Таблица фактического запуска · Наблюдения и проверки JSON.

Что этот результат подтверждает

В нашем Windows-процессе не найдено ни одного из восьми инструментов, однако готовая DLL уже загружена: пользователю готового модуля компилятор не требуется. Отсутствие phpize в Windows нормально для SDK-маршрута. Найденный protoc сам по себе не доказывает наличие заголовков Protobuf и библиотеки, которые нужны configure. Отчёт не проверяет ABI произвольного найденного DLL и не подтверждает компиляцию. Ниже отдельно показан реально выполненный Linux-маршрут с конкретными версиями, флагом совместимости и проверкой загрузки.

Разработчик считал вывод protoc --version подтверждением всей зависимости. Наш разбор отдельно требует генератор, заголовки и библиотеку. Это задача из macOS; используемые здесь команды Ubuntu и Windows SDK описаны для своих платформ, а не перенесены из чужого окружения. protoc установлен, но configure не находит Protobuf.

Исторический сбой касался proto_gen и файлов сборки. Он мотивирует сохранять configure/make-журнал и явно проверять генерацию протоколов. Старые рецепты с PHP 7.2, сторонним PPA и сменой версии PHP здесь не копируются; маршрут сверяется с matching исходником и отдельным запуском. Сборка mysql_xdevapi прекращается на сгенерированных протоколах.

Попробуйте другое условие

protoc найден, а configure пишет «protobuf not found». Какое предположение надо проверить?

Разбор

Проверьте все три составляющие: компилятор protoc в PATH, заголовок google/protobuf/any.h в выбранном корне и библиотеку Protobuf. Укажите корень через --with-protobuf или MYSQL_XDEVAPI_PROTOBUF_ROOT. Не заменяйте это установкой случайной другой версии PHP и не считайте вывод protoc --version доказательством готовности всей зависимости.

Все настройки расширения и границы их действия

Для поддержки импорта нужно знать не только название опции, но и место, где её разрешено менять. Здесь сохранён весь перечень официальной страницы Runtime Configuration: шесть директив, типы, исходные значения и уровни изменения. Подробности, которых эта краткая страница не объясняет, отделены как наблюдения matching исходника 8.0.30.

ДирективаТипЗначение по умолчаниюГде меняется
xmysqlnd.collect_memory_statisticsint0INI_SYSTEM (4)
xmysqlnd.collect_statisticsint1INI_ALL (7)
xmysqlnd.debugstringпустоINI_SYSTEM (4)
xmysqlnd.mempool_default_sizeint16000INI_ALL (7)
xmysqlnd.net_read_timeoutint31536000INI_SYSTEM (4)
xmysqlnd.trace_allocstringпустоINI_SYSTEM (4)

INI_SYSTEM означает конфигурацию запуска/сервера, а не изменение произвольным ini_set в прикладном коде. INI_ALL допускает также локальную настройку из PHP. Числовые access 4 и 7 — битовая маска разрешённых уровней. В ini_get_all global_value — начальное значение конфигурации, local_value — действующее в текущем контексте. В PHP 8.3 не запрашиваем builtin_default_value: такое поле добавлено только в PHP 8.6; исходные значения здесь отдельно взяты из регистрации расширения и официальной таблицы.

xmysqlnd.collect_memory_statistics

Управляет сбором статистики памяти внутри расширения; это не memory_limit и не лимит размера выборки.

Тип: int; исходное значение: 0; уровень: INI_SYSTEM (4). В matching коде флаг участвует в статистических макросах. Изменение через ini_set запрещено; включение может добавить накладные расходы.

xmysqlnd.collect_statistics

Флаг сбора статистики внутренних операций; значение 0 отключает соответствующие накопления.

Тип: int; исходное значение: 1; уровень: INI_ALL (7). В примере временно меняется и восстанавливается. Сам факт изменения не доказывает ускорение конкретного запроса.

xmysqlnd.debug

Строка для внутреннего отладочного механизма; это не display_errors приложения.

Тип: string; исходное значение: пусто; уровень: INI_SYSTEM (4). Инициализация tracing в исходнике 8.0.30 зависит от PHP_DEBUG. У release-профиля PHP_DEBUG=0; не обещаем получение трассы одним ini-значением.

xmysqlnd.mempool_default_size

Документированная настройка исходного размера внутреннего пула памяти.

Тип: int; исходное значение: 16000; уровень: INI_ALL (7). В просмотренном matching исходнике найдено объявление/регистрация, но не рабочее чтение параметра аллокатором. Не предлагаем подбирать его как доказанный ускоритель.

xmysqlnd.net_read_timeout

Документированный параметр таймаута сетевого чтения; он не равен URI connect-timeout.

Тип: int; исходное значение: 31536000; уровень: INI_SYSTEM (4). В matching 8.0.30 найдены регистрация и отображение, но не использование поля в пути чтения. Поэтому этот урок не обещает, что настройка прервёт зависший запрос.

xmysqlnd.trace_alloc

Строка настройки внутренней трассировки выделений памяти.

Тип: string; исходное значение: пусто; уровень: INI_SYSTEM (4). Отладочная инициализация зависит от сборки; это не инструмент профилирования бизнес-кода и не путь лога, который можно обещать для любой DLL.

$settings = ini_get_all('mysql_xdevapi', true);
$memory = $settings['xmysqlnd.mempool_default_size'];
// Наш PHP 8.3: global_value='16000', local_value='16000', access=7.

Второй аргумент true включает подробности. Функция возвращает массив; отсутствующее имя расширения нельзя опрашивать как установленное, поэтому полная программа сначала проверяет extension_loaded. Пустые строковые настройки debug и trace_alloc в наших данных представлены null, а не выдуманной пустой строкой; отчёт сохраняет фактические типы.

Два применения с контролем последствий

Для одного длительного CLI-задания можно временно отключить разрешённый сбор статистики, сохранить возвращённое прежнее значение и восстановить его в finally. Для расследования различий двух серверов полезнее сначала сохранить все шесть global/local/access, чем менять параметры наугад. Отчёт показывает, что collect_statistics прошёл 1 → 0 → 1, а попытка изменить collect_memory_statistics из PHP вернула false.

У этих параметров нет описанного changelog на официальной странице. Отсутствие подробного описания не даёт основания обещать несуществующий эффект. Название mempool_default_size не является ограничением памяти скрипта; net_read_timeout не заменяет ограничение времени всего процесса. Для надёжной проверки используем ограниченный тест подключения с отдельным connect-timeout и внешний лимит выполнения.

Полный пример чтения, отказа и восстановления · Все директивы в PHP Manual · Семантика ini_get_all.

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

Сборка нужна, когда готового совместимого модуля нет или необходимо воспроизвести точный профиль. Полезный результат здесь — файл mysql_xdevapi.so, который выбранный PHP действительно загрузил. Наличие каталога исходников или удачный configure этого ещё не доказывают.

Сборка и три разные границы
  1. Исходник 8.0.30 с проверенным SHA256
  2. phpize + configure → Makefile для конкретного PHP
  3. protoc + make → настоящий modules/mysql_xdevapi.so
  4. php -n -d extension=... → класс Session доступен
  5. Отдельный getSession + SELECT → проверка базы

Полный набор требований к сборке

ЧастьЗачем нужнаКак выбрать
PHP development files, phpize, php-configЗаголовки и параметры ABI целевого PHP--with-php-config выбирает конкретную установку; не смешивать dev-файлы другой ветки
C/C++ toolchain и makeКомпиляция и линковка расширенияMatching config.m4 8.0.30 включает C++17
BoostЗаголовочные алгоритмы и структурыНужны headers, не бинарные библиотеки Boost; minimum 1.53 в config.m4
OpenSSLКриптографическая зависимостьНужен соответствующий development-пакет и рабочие зависимости PHP/mysqlnd
ProtobufЗаголовки и библиотека протокольных сообщений--with-protobuf=DIR или MYSQL_XDEVAPI_PROTOBUF_ROOT
protocГенерация .pb.cc/.h из .protoИменно выбранный protoc должен находиться в PATH
BisonГенерация парсеров в сборочной цепочкеДоступен в PATH; Windows — версия из выбранного PHP SDK
mysqlndНативный драйвер, от которого зависит расширениеПри изолированной загрузке динамического mysqlnd загрузить его раньше mysql_xdevapi

Имя расширения — mysql_xdevapi, флаг configure — --enable-mysql-xdevapi. Корень Boost можно передать через --with-boost=DIR или MYSQL_XDEVAPI_BOOST_ROOT; для Protobuf есть аналогичные --with-protobuf и MYSQL_XDEVAPI_PROTOBUF_ROOT. Установка одного protoc не устанавливает автоматически все нужные заголовки и библиотеки. Проверяйте найденные configure пути, а не только список пакетов.

make protobufs создаёт C++-файлы сообщений; make clean-protobufs удаляет именно сгенерированные протокольные файлы в рабочем исходнике. Это не очистка базы. В нашем профиле они регенерированы protoc 3.21.12 под установленную библиотеку Protobuf. Исходный архив сохранён неизменным; рабочие .pb-файлы являются результатом сборки.

Реально выполненный профиль Linux

КомпонентФактический профиль
СистемаUbuntu 24.04 в WSL, x64
PHP для сборки и загрузки8.3.6 NTS, PHP_DEBUG=0
КомпиляторG++ 13.3.0; C++17 из config.m4
Boost1.83.0
Protobuf / protoc3.21.12
РасширениеPECL mysql_xdevapi 8.0.30
Генерация протоколовmake clean-protobufs, затем make protobufs
Дополнительный CXXFLAGS-include boost/assert/source_location.hpp
Загрузкаphp8.3 -n, сначала mysqlnd, затем абсолютный путь SO
Контакт с базой из этого Linux-процессаНе выполнялся

Первый make действительно завершился ошибкой: заголовок PHP определяет snprintf как макрос, а Boost 1.83 использует std::snprintf. После подстановки получалось несуществующее std::ap_php_snprintf. Единственная целевая поправка команды — предварительное подключение boost/assert/source_location.hpp до PHP-заголовков. Это адаптация порядка include для зафиксированного профиля, а не заявление, что исходник собирается с настройками по умолчанию в любой современной системе.

Основание можно проверить в Boost source_location.hpp и PHP snprintf.h. Не отключаем все предупреждения, не редактируем функции расширения и не заменяем исходник сторонним форком. Первый неуспешный журнал сохранён отдельно; последующая сборка использует тот же рабочий каталог и этот явный флаг.

Команды для такого же отдельного Linux-профиля

Сначала подготовьте зависимости и скачайте точный архив 8.0.30. Работайте в новой отдельной папке: mkdir source должен завершиться отказом, если она уже существует. Ниже показан маршрут, соответствующий выполненным этапам. Команды apt рассчитаны на Ubuntu 24.04; они устанавливают инструменты и могут обновить пакеты дистрибутива. Они не нужны для запуска уже установленной Windows DLL.

# Ubuntu 24.04; отдельная рабочая папка, не каталог работающего сайта.
# Администратор устанавливает инструменты для выбранного PHP:
sudo apt-get update
sudo apt-get install --no-install-recommends \
  php8.3-dev php8.3-mysql build-essential autoconf pkg-config \
  libboost-dev libprotobuf-dev protobuf-compiler libssl-dev bison

# Получите mysql_xdevapi-8.0.30.tgz с официального PECL.
# В каталоге архива проверяется конкретный исходник:
printf '%s  %s\n' \
  '4a1f7ac8fc59579194548365d3fcc380372749e9cc50895d8e065ea7f4717cfd' \
  mysql_xdevapi-8.0.30.tgz | sha256sum --check
mkdir source
tar -xzf mysql_xdevapi-8.0.30.tgz -C source
cd source/mysql_xdevapi-8.0.30

phpize8.3
./configure --enable-mysql-xdevapi \
  --with-php-config=/usr/bin/php-config8.3 \
  --with-boost=/usr --with-protobuf=/usr
make clean-protobufs
make protobufs

# Адаптация для проверенного сочетания PHP 8.3.6 и Boost 1.83:
make -j2 CXXFLAGS='-g -O2 -include boost/assert/source_location.hpp'

test -f modules/mysql_xdevapi.so
sha256sum modules/mysql_xdevapi.so
ldd modules/mysql_xdevapi.so
php8.3 -n -d extension=mysqlnd \
  -d "extension=$(pwd)/modules/mysql_xdevapi.so" \
  -r 'echo PHP_VERSION, "\n", phpversion("mysql_xdevapi"), "\n"; var_dump(class_exists("mysql_xdevapi\\Session"));'

В нашей WSL-среде сетевой apt завершился отказом до установки. Зависимости были получены по официальным Ubuntu HTTPS-ссылкам через Windows, сверены по размеру и SHA256 из apt-метаданных и установлены apt-get --no-download. Для устаревших URL использован официальный snapshot по дате уже имеющихся метаданных. Это восстановление доставки пакетов, а не обход подписи или инструкция отключить проверку. Повторять такой путь при обычном работающем apt не требуется. Версия PHP осталась 8.3.6.

phpize готовит сборочную структуру под выбранный PHP. configure проверяет зависимости и создаёт Makefile. make компилирует модуль; -j2 ограничивает параллельность двумя заданиями. Предварительное -include касается C++-заголовка в этом окружении. ldd показывает динамические зависимости полученного SO. Команда загрузки использует -n, поэтому не меняет системный ini, а -d действует только на этот процесс. make install и глобальное включение mysql_xdevapi в этом опыте не выполнялись.

Какой результат реально получен

8.3.6
8.0.30
bool(true)

Это значения PHP_VERSION, phpversion("mysql_xdevapi") и class_exists("mysql_xdevapi\\Session") из реально загруженного Linux-модуля. Полный проверочный файл также подтвердил mysqlnd, отсутствие прочитанных ini, наличие Session::createSchema и все шесть настроек. stderr при загрузке пуст. Сборка не объявлена свободной от предупреждений компилятора: сохранённый первый журнал содержит и предупреждение формата, и описанный фатальный конфликт include.

ФайлSHA256
Исходный mysql_xdevapi-8.0.30.tgz4a1f7ac8fc59579194548365d3fcc380372749e9cc50895d8e065ea7f4717cfd
Полученный модуль в проверенном окружении6dd33e35257426b7246b67e7834f688475c2e3d59556ca00b5075d1007395865

Хеш SO связывает именно наш результат, а не обещает побайтовую воспроизводимость в другом каталоге, с другой датой и набором пакетов. Исходный tarball проверяется по стабильному указанному хешу. Успешная загрузка подтверждает совместимость этого модуля с этим PHP; следующий шаг — отдельная проверка подключения и SELECT.

Windows SDK: что отличается от Linux

Windows собирает DLL в выбранном официальном PHP SDK, с компилятором и зависимостями соответствующей ветки PHP. Для PHP 8.3 официальный маршрут использует VS16 / Visual Studio 2019; для новых веток SDK и toolset надо сверять отдельно. Наличие g++ или Linux phpize в WSL не создаёт DLL для Windows. Сначала сопоставьте TS/NTS, x64/x86, debug/release и ветку PHP; затем запускайте консоль нужного SDK.

Protobuf на Windows может требовать статическую библиотеку с многопоточным DLL runtime. Официальные параметры CMake для такого варианта приведены ниже; исходный каталог, выбранную систему сборки CMake и архитектуру выбирают для своего SDK. В нашем выпуске Windows DLL использовалась готовая; её компиляция Visual Studio здесь не запускалась.

cmake -S C:\PATH\TO\protobuf\cmake -B C:\PATH\TO\protobuf\build -Dprotobuf_MSVC_STATIC_RUNTIME=OFF -Dprotobuf_BUILD_SHARED_LIBS=OFF

Это запись параметров CMake, а не строка Bash для вставки в cmd.exe: в Windows объедините её в одну команду либо используйте правила переноса своей оболочки. Используйте обратные слеши в путях, как рекомендует страница сборки. Скрипты старта PHP SDK могут изменить PATH; уже после запуска SDK ещё раз проверьте, какие protoc и bison найдены. Bison из несогласованного окружения может дать C2375 для zendparse; официальный Manual рекомендует Bison, поставляемый с выбранным SDK.

Два применения и следующий шаг

Для сопровождения локального сервиса сохраните исходный архив, версии зависимостей, команды и проверку загрузки: это позволяет отличить новый сбой сборки от изменения среды. Для расследования «protobuf not found» изучайте именно заголовки/библиотеку/генератор и configure-журнал, не меняя вслепую версию PHP. Короткий отчёт инструментов помогает выбрать путь до установки, но не заменяет перечисленные реальные этапы.

Полный официальный baseline сборки · phpize и выбор php-config.

Подготовить среду своего приложения

Сохраните отчёт целевого PHP, добейтесь загрузки совместимого модуля, затем подтвердите SELECT и TLS нужного X-соединения. Для нового учебного проекта переходите к созданию отдельной базы с проверкой владения, а для прикладных данных — к первой коллекции и таблицам с параметризованными запросами.

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

Источники и обсуждения

Код и руководство с собой

Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.

Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.

Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.