← Все статьи

SiteGuard12 мин чтения

Call to undefined function: как проверить расширения PHP на сайте

Ошибка Call to undefined function означает, что в момент вызова PHP не нашёл указанную функцию. Поиск «call to undefined function php» часто приводит к совету установить расширение, однако сообщение само по себе этого не доказывает. Причиной бывает другой обработчик PHP, запрещённая функция, устаревший код, неподключённый файл библиотеки или неверное пространство имён.

Рабочая последовательность начинается с точного имени функции и окружения, где произошёл сбой. Затем проверяют наличие функции и соответствующего модуля, выбирают исправление и повторяют исходный сценарий. Такой порядок помогает восстановить форму, интеграцию или обработку изображения без случайного включения расширений и ослабления ограничений хостинга.

1. Зафиксируйте полный вызов и условия ошибки

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

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

Проверьте, что это именно вызов функции, а не сообщение об отсутствующем классе или методе. Например, наличие расширения для базы данных ещё не объясняет ошибку в имени пользовательского метода. Если сообщение приходит из очереди или cron, сразу выделите этот исполнитель: браузер может обращаться к совершенно другому PHP. Задача первого шага — получить один воспроизводимый сбой, привязанный к конкретному процессу и версии кода.

2. Определите, откуда должна появиться функция

Найдите имя в документации PHP и в исходном коде проекта. У стандартной функции есть страница справочника с областью применения; у функции библиотеки — объявление и условие подключения. Например, curl_init относится к функциям cURL. Это даёт проверяемую связь с расширением curl, а похожее имя стороннего помощника такой связи не даёт.

ПроисхождениеЧто проверитьВероятное направление исправления
Функция расширенияДокументацию, имя модуля, его загрузку в нужном PHPПодключить совместимый модуль или исправить его загрузку
Функция приложения или библиотекиФайл объявления, зависимости, порядок подключенияВосстановить комплект кода и правильный вызов
Функция, удалённая из PHPВерсию удаления и рекомендации по переходуОбновить компонент, который использует старый API
Имя с пространством имёнПолное имя и правила его разрешенияИсправить импорт или обращение к нужной функции
Опечатка или переименованиеОбъявление и места использования в текущем выпускеСогласовать вызов с фактическим интерфейсом

Не подбирайте пакет по одному фрагменту названия. Отдельно посмотрите требования конкретной версии CMS или плагина: модуль мог заменить прежний механизм, а на сервер попала смесь старых и новых файлов. В такой ситуации установка дополнительного расширения оставит настоящую причину нетронутой.

3. Разделяйте function_exists и extension_loaded

function_exists проверяет наличие определённой функции, включая встроенные и пользовательские. Проверка ничего не выполняет и не подтверждает корректность будущего бизнес-результата. Даже существующая функция может оказаться непригодной для конкретной операции из-за параметров сборки или конфигурации. Поэтому положительный ответ — промежуточное доказательство, а не завершение ремонта.

extension_loaded проверяет загрузку расширения по его имени. Это другой вопрос: загруженный модуль и доступная функция не являются взаимозаменяемыми признаками. Сначала установите ожидаемую связь по документации, затем сравните результаты в одном и том же процессе.

  • Модуль и функция отсутствуют: проверьте правильность выбранного модуля, его включение и сообщения запуска.
  • Модуль загружен, функции нет: проверьте имя, поддержку в используемой версии и ограничения встроенных функций.
  • Модуль и функция доступны: воспроизведите исходный маршрут; возможно, ошибку выдаёт другой экземпляр или другой выпуск приложения.
  • Функция есть, предполагаемого модуля нет: уточните её происхождение, включая пользовательскую реализацию или ошибочную гипотезу о модуле.

Если нужна инвентаризация, get_loaded_extensions возвращает имена загруженных модулей. По умолчанию перечисляются обычные расширения; аргумент true запрашивает только Zend-расширения. Не принимайте один такой список за полный ответ о возможностях всех обработчиков на сервере.

4. Получите ограниченную диагностику из HTTP-обработчика

Когда падает страница сайта, сведения нужны из того PHP, который обслуживает запрос этого домена. Разработчик может временно добавить небольшой отчёт в уже защищённый служебный маршрут. Доступ ограничивают существующей административной авторизацией или сетевыми правилами, исключают публичное кеширование и назначают срок удаления. Случайное имя файла не заменяет контроль доступа.

Ниже учебный фрагмент формирования данных для такого закрытого отчёта. Он не реализует авторизацию и не должен становиться самостоятельной общедоступной страницей. Значения получают после действующей проверки доступа; сам фрагмент не отправляет сетевых запросов и не меняет данные сайта.

<?php
$diagnostic = [
    'php_version' => PHP_VERSION,
    'sapi' => PHP_SAPI,
    'curl_extension' => extension_loaded('curl'),
    'curl_init_exists' => function_exists('curl_init'),
];

Для другой ошибки заменяют проверяемую пару на подтверждённые имя модуля и функции. Результат передают в закрытый журнал или административный интерфейс без вывода окружения целиком. Полный phpinfo() здесь не нужен: он раскрывает значительно больше сведений, чем требуется для ответа на четыре конкретных вопроса.

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

5. Сравните CLI, HTTP и фоновые исполнители

Команды php -v и php -m полезны, но описывают выбранный консольный интерпретатор. В системе могут одновременно работать несколько веток PHP, а команда из терминала может указывать на другую ветку, чем обработчик домена. Её успешный результат не опровергает ошибку, которую посетитель получает через PHP-FPM.

Сопоставьте версию, SAPI и наличие нужного расширения у каждого затронутого исполнителя. Если cron запускает PHP напрямую, проверьте интерпретатор из задания, а не произвольную команду в своей оболочке. Если задание обращается к URL, исследуйте обработчик этого URL. Долгоживущий воркер тоже имеет собственный момент запуска и может продолжать работу со старым окружением.

По правилам загрузки конфигурации PHP основной файл читается при запуске; дополнительно могут подключаться другие INI-файлы. Поэтому запись об установленном пакете на машине не доказывает его загрузку в нужном процессе. Разбор всех слоёв настроек — отдельная задача; для этой ошибки достаточно сначала связать функцию с фактическим обработчиком.

На распределённом сайте сравните также узлы. Признак «иногда работает» может означать разный набор модулей у экземпляров. Сопоставляйте запросы с внутренним идентификатором узла в закрытых журналах. Несколько успешных обновлений страницы без такой привязки не подтверждают исправление всей группы серверов.

6. Если модуль включён, найдите ошибку его загрузки

Строка включения расширения означает намерение загрузить его, но не результат. Сравните время запуска соответствующего PHP с журналом службы или хостинга. Сообщения о невозможности загрузить динамическую библиотеку, отсутствующей зависимости или несовместимом API объясняют, почему строка присутствует, а extension_loaded возвращает отрицательный ответ.

Нативное расширение должно подходить к используемой сборке. В официальной инструкции для Windows отдельно указаны совместимость версии, архитектуры и параметров сборки, включая потокобезопасность. Там же рекомендуют проверять журнал, расположение библиотеки и её зависимости. Скопированная со старого сервера DLL не становится подходящей только потому, что файл существует.

Для Linux действует практическое правило: устанавливайте поддерживаемый пакет или сборку именно для целевого PHP по документации вашей платформы. Не смешивайте вручную библиотеки от разных репозиториев и веток. Если журнал указывает несовпадение module API, исправляют совместимость сборок, а не переименовывают файл в надежде обойти проверку. ABI здесь означает совместимость двоичного интерфейса модуля и интерпретатора.

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

7. Учтите disable_functions в PHP 8

Отдельная ветка проверки нужна, когда расширение загружено, но конкретной встроенной функции нет. В документации disable_functions указано: начиная с PHP 8.0 отключение удаляет определение встроенной функции. Поэтому ограничение может проявиться как Call to undefined function, а проверка существования даст отрицательный результат. Директива относится к внутренним функциям PHP, а не к произвольным функциям приложения.

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

Результатом может стать обновление компонента, изменение архитектуры операции или согласованное адресное изменение политики. Если хостинг не разрешает требуемую возможность, разработчик должен сообщить об этом как об ограничении эксплуатации. Повторная установка уже загруженного расширения ничего не исправит. Не создавайте фиктивную функцию с тем же именем, возвращающую «успех»: так сбой превращается в незаметную потерю ожидаемого действия.

8. Отделите удалённый API от отсутствующего расширения

Старые инструкции особенно опасны после смены версии PHP. Исходное расширение MySQL удалено в PHP 7.0; официальный справочник предлагает использовать MySQLi или PDO_MySQL. Поэтому ошибка на mysql_connect() в современном PHP не исправляется включением обычного современного модуля для MySQL. У него другой интерфейс, и прежние функции автоматически не появятся.

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

Аналогично проверяйте любое другое старое имя по документации конкретной функции и руководству миграции. Не откатывайте весь сайт на давно неподдерживаемую ветку только ради одного вызова. Для временного возврата к прежнему рабочему окружению всё равно нужны согласованные условия, совместимость данных и срок устранения причины; это не замена обновлению устаревшего компонента.

9. Проверьте функции приложения и пространства имён

Если функция принадлежит проекту, найдите её объявление в том выпуске, который реально развёрнут. Проверьте наличие файла, штатное подключение библиотеки и условия, при которых объявление выполняется. Частичный выпуск способен оставить новый вызов рядом со старой библиотекой. В этом случае следует восстановить согласованный комплект приложения, а не добавлять случайные файлы прямо на работающем сайте.

Учитывайте правила поиска функций внутри namespace: для неполного имени без префикса PHP может перейти к глобальной функции, если одноимённая функция текущего пространства отсутствует. Это не означает, что любой явно указанный путь будет автоматически исправлен. Сравните имя в ошибке с объявлением и импортами в исходном файле.

При проверке строкового имени также указывайте нужное пространство. Например, для объявленной функции Shop\format_price проверяют function_exists('Shop\format_price'), а не только function_exists('format_price'). Особенности строковых имён описаны в разделе PHP о динамическом обращении к элементам namespace. Неправильная диагностическая строка способна создать ложное впечатление, что функция отсутствует.

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

10. Исправляйте нужную ветку и нужный обработчик

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

В карточке укажите домен, затронутый сценарий, версию и SAPI из HTTP, название расширения, имя функции и результат двух проверок. Приложите время ошибки и попросите подтвердить загрузку модуля в обслуживающем этот домен обработчике. Это конкретнее просьбы «установить PHP», особенно если консоль и сайт используют разные ветки.

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

До изменения оцените соседние сайты, использующие ту же службу. Общий обработчик означает, что установка или перезапуск могут затронуть несколько проектов. Назначьте окно работ, сохраните исходное состояние и определите проверку после применения. Если пакет требует неожиданной замены ветки PHP или большого набора зависимостей, остановитесь и пересмотрите план на тестовом окружении: исправление одной недоступной функции не должно незаметно превратиться в обновление всей платформы.

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

11. Учебный разбор: cURL есть в терминале, но форма падает

Предположим, после переноса сайта форма обращения перестала получать данные из внешнего справочника. В закрытом журнале записано отсутствие curl_init. Команда в терминале показывает загруженный curl, но защищённая HTTP-проверка возвращает отсутствие и расширения, и функции. Это условный пример диагностики, а не история конкретного клиента.

Сравнение показывает, что домен обслуживает отдельная ветка PHP-FPM. В её наборе модуль не включён. Исполнитель согласует изменение именно для этой ветки, проверяет журнал запуска и повторяет HTTP-диагностику: оба результата становятся положительными. Пока доказана только доступность функции в нужном обработчике.

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

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

12. Подтвердите исправление и сохраните требования

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

  1. Повторите точную проверку функции и расширения через затронутый обработчик.
  2. Выполните безопасный сценарий приложения и проверьте сохранённый результат, а не только HTTP 200.
  3. Проверьте свежие записи журналов и запуск затронутых фоновых исполнителей.
  4. Удалите временные диагностические материалы из доступных через сайт мест.
  5. Добавьте проверенную зависимость в документацию переноса и выпуска проекта.

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

Для внешнего наблюдения за HTTP-доступностью сайта подключите SiteGuard. Наличие расширений и результат работы функций проверяйте в своём PHP-окружении и сценариях приложения.