何が起きたのか
この警告が表示された場合 — おそらく白紙ページやアプリの破損も伴っているでしょう — PHPが指定されたファイルを見つけられなかったことが原因です:
Warning: include(config.php): Failed to open stream: No such file or directory in /var/www/html/index.php on line 3
PHPはconfig.phpをディスク上の実際のファイルとして解決できませんでした。十中八九、次の3つのいずれかが問題です:指定したパスにファイルが存在しない、カレントワーキングディレクトリが想定と異なる、またはパス自体にタイポや誤りがある。
デバッグの手順
ステップ1:PHPが実際に探しているパスを確認する
警告には渡した引数しか表示されず、PHPが実際に開こうとした完全な解決済みパスは表示されません。includeの上にデバッグ用のコードを追加して、実際に何が起きているかを確認しましょう:
<?php
echo __DIR__ . '/' . 'config.php' . PHP_EOL;
include('config.php');
またはrealpath()を使ってファイルが存在するかどうかを確認します:
<?php
$path = __DIR__ . '/config.php';
var_dump(file_exists($path), $path);
これを実行し、出力結果をディスク上の実際のファイルと比較してください。
ステップ2:カレントワーキングディレクトリを確認する
include('config.php')のような相対パスは、includeを含むファイルからではなく、**カレントワーキングディレクトリ(CWD)**を基準に解決されます。この2つはしばしば異なります。別のディレクトリからスクリプトを呼び出す場合、フレームワークのフロントコントローラーを使う場合、またはCLIから実行する場合にこの罠にはまりがちです。
<?php
echo getcwd(); // カレントワーキングディレクトリを出力
/var/www/htmlを期待していたのに/var/wwwが返ってきた場合、それが原因です。
ステップ3:ファイルが実際に存在するかを確認する
# Linux/macOSの場合
ls -la /var/www/html/config.php
# タイポを探す — Linuxは大文字小文字を区別する
find /var/www/html -name "config*"
LinuxではConfig.phpとconfig.phpは別々のファイルです。WindowsはNot case-sensitiveなので、XAMPP上では問題なく動くタイポが、Linuxサーバーにプッシュした途端に破綻します。
解決策
修正1:信頼性の高い相対パスに__DIR__を使う(推奨)
ほとんどのケースはこれで解決します。__DIR__は、PHPが呼び出された場所ではなく、現在のファイルのディレクトリに解決されるマジック定数です。
<?php
// BEFORE(脆弱 — CWDが変わると壊れる)
include('config.php');
include('../lib/helpers.php');
// AFTER(信頼性が高い — 常にこのファイルからの相対パス)
include(__DIR__ . '/config.php');
include(__DIR__ . '/../lib/helpers.php');
プロジェクト内のすべての裸の相対include/requireを__DIR__を使うように変更してください。この一つの変更で、includeパスに関するバグの大半をなくすことができます。
修正2:重要なファイルにはincludeではなくrequireを使う
config.phpが不可欠な場合 — データベース認証情報、アプリ設定、アプリが欠かすことのできないもの — includeの代わりにrequireまたはrequire_onceを使いましょう。
重要な違い:includeはWarningを出力して処理を続行します。requireはFatal Errorをスローして即座に停止します。設定ファイルが欠けたまま静かに処理を続けると、ほぼ必ず20行後に追跡困難な2つ目のエラーが発生します。
<?php
// config.phpが存在しない場合、即座に実行を停止する
require __DIR__ . '/config.php';
修正3:実際のファイルパスを確認して修正する
CWDは正しいが、ファイルが別の場所にある場合はパスを修正します:
<?php
// ファイルの場所: /var/www/html/includes/config.php
// スクリプトの場所: /var/www/html/index.php
// 間違い
include('config.php');
// 正しい
include __DIR__ . '/includes/config.php';
修正4:ファイルが本当に存在しない場合 — 作成する
最もシンプルな説明が正しいこともあります。新規チェックアウト時には.gitignoreによってconfig.phpが除外されていることがよくあります。テンプレートを探してみましょう:
# サンプル設定ファイルを確認
ls /var/www/html/config.php.example
ls /var/www/html/config.example.php
# コピーして値を入力する
cp config.php.example config.php
nano config.php
修正5:ファイルのパーミッション(あまり多くないが実際にある)
ファイルは存在するがPHPが開けない場合:
# 所有者とパーミッションを確認する
ls -la /var/www/html/config.php
# PHPは通常www-dataとして実行される — 読み取りアクセスを付与する
chown www-data:www-data /var/www/html/config.php
chmod 644 /var/www/html/config.php
ここに落とし穴があります:PHPはファイルが存在しない場合とパーミッションが拒否された場合の両方で「No such file or directory」と報告します。ファイルが確実に存在するのに警告が続く場合は、次にパーミッションを確認してください。
修正6:include_pathの問題
古いコードベースの中には、PHPのinclude_path設定(php.iniまたはset_include_path()で設定)に依存しているものがあります。現在の設定を確認するには:
<?php
// 現在のinclude_pathを確認する
echo get_include_path();
// ディレクトリを追加する
set_include_path(get_include_path() . PATH_SEPARATOR . '/var/www/html/includes');
include 'config.php'; // PHPはincludes/も検索するようになる
ただし、自分のアプリケーションファイルにinclude_pathを頼るのはやめましょう — 脆弱です。明示的な__DIR__パスを使い、include_pathはライブラリやオートロードの設定に限定してください。
確認
修正を適用した後、デバッグコードを削除する前に実際に動作することを確認しましょう:
<?php
$file = __DIR__ . '/config.php';
if (!file_exists($file)) {
die('File not found: ' . $file);
}
if (!is_readable($file)) {
die('File not readable: ' . $file);
}
require $file;
echo 'Config loaded OK';
「Config loaded OK」と表示されたら、デバッグ用のコードを削除します。そしてPHPエラーログを確認して警告が消えていることを確認しましょう:
# Apache
tail -f /var/log/apache2/error.log
# Nginx + PHP-FPM
tail -f /var/log/php8.x-fpm.log
# またはphp.iniのerror_logが指している場所
クイックリファレンス:includeとrequireの違い
include— 失敗時にWarningを出力し、実行を継続するrequire— 失敗時にFatal Errorをスローし、実行を停止するinclude_once/require_once— 同じ動作だが、すでにインクルード済みの場合はスキップする
設定ファイル、データベース接続、または重要な処理には常にrequireを使いましょう。includeはオプションのテンプレート断片に限定してください。
教訓
根本的な混乱はほぼ常に同じです:PHPが呼び出された場所とincludeを含むファイルが存在する場所は同じではありません。__DIR__を使いましょう。毎回。例外なく。
require 'something.php'の代わりにrequire __DIR__ . '/something.php'と書けば、この警告を二度と見ることはなくなります。
裸の相対includeだらけのコードベースを引き継いだ場合は、このgrepコマンドでクリーンアップの全体像を把握できます:
grep -rn "include\|require" /var/www/html --include="*.php" | grep -v "__DIR__" | grep -v "vendor/"
その出力の各行は、いつ発生してもおかしくないパスバグの候補です。

