エラーの内容
Fatal error: Uncaught Error: Call to undefined function some_function() in /var/www/html/app.php:42
Stack trace:
#0 {main}
thrown in /var/www/html/app.php on line 42
「Call to undefined function」の後に続く関数名がすべてを教えてくれます。curl_init → 拡張機能が未インストール。myhelper → includeが漏れている。他に何も触る前に、エラー全文を読んでください — その関数名こそが調査のすべてです。
原因
このエラーを引き起こすのは4つのケースだけです:
- 該当関数を提供するPHP拡張機能がサーバーで有効になっていない
- 関数を定義しているファイルがincludeされていない
- 名前空間の不一致 — 名前空間内のグローバル関数には
\プレフィックスが必要 - 関数名のタイポ、またはその関数がお使いのPHPバージョンに存在しない
修正1: 不足している拡張機能を有効にする
新しいサーバー、新しいデプロイ、新しいチームメンバーの環境 — これが最も多い原因です。古い環境から新しい環境への移行時に、どこかでPHP拡張機能が取り残されてしまいます。未定義の関数が既知の拡張機能に属するか確認してください:
curl_init()→ curlimagecreate()→ gdmb_strlen()→ mbstringsodium_crypto_secretbox()→ sodiumldap_connect()→ ldapzip_open()→ zip
現在ロードされている拡張機能を確認する:
php -m | grep curl
PHPコードから確認する場合:
<?php
var_dump(extension_loaded('curl'));
Ubuntu/Debianでのインストールと有効化:
sudo apt install php8.2-curl php8.2-gd php8.2-mbstring
sudo systemctl restart php8.2-fpm
# Apacheの場合
sudo systemctl restart apache2
CentOS/RHELの場合:
sudo dnf install php-curl php-gd php-mbstring
sudo systemctl restart php-fpm
php.iniを直接編集したい場合は、まず有効なファイルを見つけて、拡張機能の行のコメントを外してください:
# 有効なphp.iniを見つける
php --ini | grep "Loaded Configuration"
# 該当する行のコメントを外す
extension=curl
extension=gd
extension=mbstring
php.iniを変更したら必ずWebサーバーを再起動してください — そうしないと拡張機能はロードされません。
修正2: 不足しているincludeを追加する
自分で定義した関数もサードパーティのライブラリも、自動的にはロードされません。関数を定義しているファイルをPHPが読み込んでいなければ、実行時にその関数は存在しないのと同じです。エラーが発生しているファイルの先頭を確認してください:
<?php
// 関数を呼び出す前に記述する必要がある
require_once __DIR__ . '/helpers/user-functions.php';
// これで動作する
create_user($data);
Composerを使っている場合、たった1行の記述漏れがどんな原因よりも多くのデプロイを壊します — オートローダーです:
<?php
// 新しいデプロイ環境ではよく抜けている
require_once __DIR__ . '/vendor/autoload.php';
// これでComposerのパッケージが正しく解決される
$client = new GuzzleHttp\Client();
includeの順序も確認してください。PHPはファイルを上から下へ読み込みます — ファイルがロードされる前に関数を呼び出すことはできません。
修正3: 名前空間の問題を修正する
名前空間の内部では、PHPはまずその名前空間内で関数を探します。自動的にグローバルスコープにフォールバックすることはありません。組み込み関数や拡張機能の関数には、グローバル名前空間を明示的に参照するためにバックスラッシュのプレフィックスが必要です:
<?php
namespace App\Services;
// 失敗 — PHPはApp\Services\array_map()を探す
$result = array_map('strtolower', $items);
// 成功 — バックスラッシュでグローバル名前空間を強制参照
$result = \array_map('strtolower', $items);
拡張機能の関数も同様の問題が発生します:
<?php
namespace App\Http;
// 失敗
$ch = curl_init($url);
// 成功
$ch = \curl_init($url);
バックスラッシュを至る所に散りばめるとすぐに煩雑になります。よりすっきりした解決策として、ファイルの先頭でuse functionを一度宣言する方法があります:
<?php
namespace App\Http;
use function curl_init;
use function curl_setopt;
use function curl_exec;
$ch = curl_init($url); // これで動作する
修正4: PHPバージョンの違いまたはタイポ
一部の関数はバージョンによって使用できるかどうかが異なります。str_contains()はPHP 8.0で追加されました。array_is_list()はPHP 8.1で登場しました。7.4を使用していてこれらを呼び出すと、このエラーが発生します。まずバージョンを確認してください:
php --version
関数が存在するかどうかを確認する:
php -r "var_dump(function_exists('str_contains'));"
古いPHPバージョンを使い続けなければならない場合は、ポリフィルで1分以内に解決できます:
<?php
if (!function_exists('str_contains')) {
function str_contains(string $haystack, string $needle): bool {
return $needle === '' || strpos($haystack, $needle) !== false;
}
}
タイポの場合は、関数が定義されているはずの箇所をコードベース全体からgrepで検索してください:
grep -r "function the_function_name" /var/www/html/
修正を確認する
ブラウザで勘に頼らず、まずCLIから確認してください:
# 拡張機能がロードされているか確認
php -r "echo extension_loaded('curl') ? 'curl: OK' : 'curl: MISSING';"
# 関数にアクセスできるか確認
php -r "echo function_exists('curl_init') ? 'OK' : 'MISSING';"
# phpinfo出力から拡張機能を検索
php -r "phpinfo();" | grep -i curl
開発中は、問題のある呼び出しの前にガード処理を追加してください。無意味な500エラーページの代わりに、明確で具体的なエラーメッセージが得られます:
<?php
if (!function_exists('curl_init')) {
throw new \RuntimeException('curl extension not loaded — install php-curl and restart your server');
}
予防策
PHPの拡張機能の依存関係をcomposer.jsonに宣言してください。こうすることで、設定が不十分なサーバーではcomposer installが即座に失敗し、ユーザーがページにアクセスした実行時ではなく、明確なメッセージと共に問題を早期に検出できます:
{
"require": {
"php": "^8.1",
"ext-curl": "*",
"ext-mbstring": "*",
"ext-gd": "*"
}
}
重要な拡張機能については、アプリケーションの初期化ファイルに起動時チェックを追加してください:
<?php
$required = ['curl', 'mbstring', 'pdo_mysql', 'gd'];
foreach ($required as $ext) {
if (!extension_loaded($ext)) {
throw new \RuntimeException("Missing required PHP extension: {$ext}");
}
}
Dockerを使用している場合は、Dockerfileに必要な拡張機能をすべて明示的にインストールしてください。開発環境と本番環境が同じイメージを共有していれば、深夜2時に新しいサーバーでこのエラーが発生することはなくなります。

