Ошибка 'Unable to load dynamic library' в PHP: способы исправления
Основные причины ошибки и их устранение
Ошибка "PHP Warning: PHP Startup: Unable to load dynamic library" возникает при запуске PHP, когда интерпретатор не может найти или загрузить указанное расширение. Типичные причины: отсутствие файла библиотеки (dll/so), неправильный путь в директиве extension_dir, несоответствие версий PHP и расширения, конфликты с другими расширениями или отсутствие системных зависимостей. Рассмотрим последовательность действий для диагностики и исправления.
Как проверить и настроить путь к библиотеке в php.ini?
Первый шаг – убедиться, что директива extension_dir указывает на правильный каталог, где находятся расширения. Найдите файл php.ini (обычно в /etc/php/версия/cli/php.ini или в папке с PHP). Выполните команду:
php -i | grep "extension_dir"Unexpected variable php (неожиданная переменная в php)
Вывод покажет текущий путь. Если он отсутствует или неверен, задайте его явно:
extension_dir = "/usr/lib/php/20200930"Php warning include failed opening (предупреждение: не удалось открыть include в php)
После этого убедитесь, что файл расширения (например, myextension.so) существует в указанной директории. Проверка:
ls /usr/lib/php/20200930/myextension.soPhp unable to load dynamic library (ошибка загрузки динамической библиотеки в php)
Если файла нет, требуется его установка или компиляция. Также проверьте права доступа – PHP должен иметь право на чтение.
Возможные проблемы:
- Версия расширения не совпадает с версией PHP (например, built для PHP 7.4, а используется 8.2). В этом случае файл загружается, но вызывает ошибку. Рекомендуется переустановить расширение под текущую версию.
- Путь extension_dir может быть пустым – тогда PHP ищет библиотеки в текущем каталоге. Лучше указать абсолютный путь.
- Наличие пробелов или специальных символов в пути.
Как установить расширение PHP через системный менеджер пакетов?
Для распространенных расширений (mysqli, pdo, gd) проще всего использовать менеджер пакетов ОС. Например, для Ubuntu/Debian:
sudo apt update && sudo apt install php-mysqli php-gdUndefined variable php (неопределенная переменная в php)
Для CentOS/RHEL:
sudo yum install php-mysqli php-gd
Для macOS (Homebrew):
brew install php@8.2-mysqli
После установки расширения обычно автоматически добавляются в php.ini. Если нет, добавьте строку вручную:
extension=mysqli.so
Проверьте подключение через php -m | grep mysqli.
Возможные проблемы:
- Пакет может быть несовместим с версией PHP – возникает ошибка загрузки. Используйте точное указание версии, например php8.2-mysqli.
- После установки не обновился php.ini – проверьте наличие директивы extension в файлах конфигурации (обычно /etc/php/версия/cli/conf.d/ или /etc/php/версия/apache2/conf.d/).
Как собрать расширение из исходного кода с помощью phpize?
Если расширение недоступно в репозиториях, его можно скомпилировать. Для этого потребуются исходный код PHP и инструменты сборки. Установите php-dev и php-pear:
sudo apt install php-dev php-pear
Скачайте исходники расширения (например, xdebug), распакуйте, перейдите в каталог и выполните:
phpize
./configure
make -j4
sudo make install
После установки файл .so появится в extension_dir. Добавьте в php.ini:
zend_extension=xdebug.so
Проверьте загрузку: php -v.
Возможные проблемы:
- Отсутствие зависимостей (libssl, libcurl и т.д.) – компиляция завершится с ошибкой. Установите соответствующие dev-пакеты.
- Несовместимость API – расширение собрано для другой серии PHP. Проверьте номер API с помощью php -i | grep "PHP API". Расширение должно быть скомпилировано с тем же номером.
- Права на запись в extension_dir – сборка может поместить файл в недоступное место, исправьте права или используйте sudo.
Как выбрать версию расширения, соответствующую сборке PHP?
PHP распространяется в нескольких конфигурациях: Thread Safety (ts) и Non-Thread Safety (nts), 32-битная или 64-битная, отладка (debug) и релиз. Расширение должно быть собрано под ту же конфигурацию. Определите параметры вашего PHP:
php -i | grep -E "Thread Safety|Architecture|Debug Build"
Результат:
Thread Safety => enabled (или disabled) Architecture => x64 PHP API => 20200930
Скачивайте и устанавливайте расширение, соответствующее этой строке. Например, для Windows DLL обычно имеют маркировку: php_xdebug-3.3.1-8.2-ts-vs16-x64.dll.
Возможные проблемы:
- Использование NTS-расширения в TS-сборке PHP приводит к ошибке загрузки. Всегда внимательно читайте документацию.
- Разрядность: 32-битное расширение не загрузится в 64-битном PHP.
Какие расширения могут конфликтовать и как их временно отключить?
Иногда два расширения требуют одну и ту же библиотеку разных версий. Для диагностики отключите все необязательные расширения, оставив только проблемное. Переименуйте файлы конфигурации в /etc/php/version/conf.d/ (например, mv 20-mysqli.ini 20-mysqli.ini.bak). Проверьте загрузку:
php -v
Если ошибка исчезла, включайте расширения по одному, чтобы найти конфликт.
Возможные проблемы:
- После отключения расширения может перестать работать часть функционала сайта. Для тестирования используйте изолированное окружение.
- Конфликт может быть между системной библиотекой и расширением – тогда поможет только перекомпиляция с другими флагами.
Где искать более подробную информацию об ошибке загрузки?
PHP выводит только краткое предупреждение. Чтобы получить больше деталей, включите отображение ошибок в php.ini:
display_errors = On
error_reporting = E_ALL
Также смотрите системные логи. Для Linux:
tail -f /var/log/apache2/error.log
или
journalctl -u php-fpm -n 50
Windows: Event Viewer и логи PHP (если настроены).
Возможные проблемы:
- Логи могут быть не настроены. В php.ini укажите error_log=/var/log/php_errors.log.
- Иногда ошибка скрыта в логах веб-сервера, а не PHP.
Как помочь PHP найти системные зависимости расширения?
Многие расширения зависят от внешних библиотек (.so в Linux, .dll в Windows). Если библиотека находится в нестандартном месте, укажите путь к ней через переменные окружения. В Linux добавьте путь в LD_LIBRARY_PATH:
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
php -v
Или задайте в конфигурации PHP через dl() (но не рекомендуется). Лучше слинковать библиотеку в стандартный каталог /usr/lib. Для Windows можно добавить каталог в PATH.
Возможные проблемы:
- Переменная LD_LIBRARY_PATH может быть переопределена в безопасном режиме. Используйте ldconfig для обновления кэша.
- Наличие нескольких версий одной библиотеки – может загрузиться не та.
Подробные примеры и их результаты
Ниже приведены расширенные сценарии, иллюстрирующие диагностику и исправление ошибки загрузки динамических библиотек PHP.
Пример 1: Проверка и настройка extension_dir
Выполнить команду для определения текущего каталога расширений:
php -i | grep extension_dir
Возможный вывод:
extension_dir => /usr/lib/php/20200930 => /usr/lib/php/20200930
Проверить наличие файла расширения, например, mysqli.so:
ls -la /usr/lib/php/20200930/mysqli.so
Если файл отсутствует, вывод будет:
ls: cannot access '/usr/lib/php/20200930/mysqli.so': No such file or directory
Тогда установите пакет или скопируйте правильную версию в этот каталог.
Пример 2: Установка расширения через apt с указанием версии PHP
Предположим, используется PHP 8.2. Установить модуль pdo_mysql:
sudo apt install php8.2-mysql
После установки проверить, появился ли файл конфигурации:
ls /etc/php/8.2/cli/conf.d/ | grep mysql
Результат:
20-mysqli.ini 20-pdo_mysql.ini
Убедиться, что расширения загружаются:
php -m | grep -i mysql
Вывод:
mysqli pdo_mysql
Пример 3: Компиляция простого расширения "hello"
Создадим минимальное расширение на C. Исходный код (файл hello.c):
#include <php.h>
#include <ext/standard/info.h>
PHP_FUNCTION(hello_world) {
php_printf("Hello, World!\n");
}
const zend_function_entry hello_functions[] = {
PHP_FE(hello_world, NULL)
PHP_FE_END
};
zend_module_entry hello_module_entry = {
STANDARD_MODULE_HEADER,
"hello",
hello_functions,
NULL,
NULL,
NULL,
NULL,
PHP_MINFO(hello),
PHP_HELLO_VERSION,
STANDARD_MODULE_PROPERTIES
};
#ifdef COMPILE_DL_HELLO
ZEND_GET_MODULE(hello)
#endif
Создайте файл config.m4:
PHP_ARG_ENABLE(hello, whether to enable hello, [ --enable-hello Enable hello support])
if test "$PHP_HELLO" != "no"; then
PHP_NEW_EXTENSION(hello, hello.c, $ext_shared)
fi
Выполните:
phpize
./configure --enable-hello
make -j4
sudo make install
Результат make install поместит hello.so в extension_dir. Добавьте в php.ini:
extension=hello.so
Проверка:
php -r 'hello_world();'
Ожидаемый вывод:
Hello, World!
Пример 4: Проверка и выбор Thread Safety для Windows
На Windows PHP имеет две версии. Определите текущую:
php -i | findstr "Thread Safety"
Вывод:
Thread Safety => enabled
Скачайте расширение xdebug для PHP 8.2 TS x64. Пусть файл называется php_xdebug-3.3.1-8.2-ts-vs16-x64.dll. Скопируйте его в ext (обычно C:\php\ext). Добавьте в php.ini:
zend_extension=C:\php\ext\php_xdebug-3.3.1-8.2-ts-vs16-x64.dll
Проверьте загрузку:
php -v
Если версия несовместима, появится предупреждение об ошибке загрузки. В таком случае загрузите NTS-версию, если PHP без Thread Safety.
Пример 5: Отключение расширений для поиска конфликта
Предположим, после установки imagick возникает ошибка. Временно отключите все расширения, кроме core:
cd /etc/php/8.2/cli/conf.d/
sudo mkdir backup && sudo mv *.ini backup/
Затем включите только imagick:
sudo cp backup/20-imagick.ini .
Проверьте загрузку:
php -v
Если ошибка исчезла, конфликт с другим расширением. Включайте по одному.
Пример 6: Использование ldd для проверки зависимостей расширения
В Linux, если расширение загружается с ошибкой "undefined symbol", проверьте его зависимости:
ldd /usr/lib/php/20200930/imagick.so
Возможный вывод:
linux-vdso.so.1 (0x00007fffc4d5c000) libMagickWand-7.Q16HDRI.so.7 => not found libMagickCore-7.Q16HDRI.so.7 => /usr/lib/x86_64-linux-gnu/libMagickCore-7.Q16HDRI.so.7 (0x00007f...)
Если какая-то библиотека не найдена (not found), установите соответствующую версию (например, libmagickwand-dev).