【PHP】「ファイルが見つかりません」エラーの原因と対処法

phpアイキャッチ PHP

こんにちは、かつコーチです。

前回はNotice・Warning・Fatal Errorといった、エラーの「レベル」の違いを解説しました。

今回はその中でも初心者が本当によく遭遇する、次のようなエラーを深掘りします。

Warning: require(../config/database.php): Failed to open stream: No such file or directory in /var/www/html/index.php on line 3

いわゆる「ファイルが見つかりません」エラーです。

私自身、PHPを学び始めた頃に一番多く検索したエラーがこれでした。

原因のパターンさえ押さえておけば、慌てず対処できるようになります。

「ファイルが見つかりません」エラーの正体

どんな場面で発生するか

このエラーは、requireincluderequire_onceinclude_onceなど、他のPHPファイルを読み込む処理で発生します。

<?php
// config/database.php を読み込もうとしている
require "../config/database.php";

指定したパスにファイルが存在しない場合、PHPは次のようなメッセージを表示します。

Warning: require(../config/database.php): Failed to open stream: No such file or directory in /var/www/html/pages/user.php on line 3

Fatal error: Uncaught Error: Failed opening required '../config/database.php' in /var/www/html/pages/user.php:3

requireとincludeでエラーの重さが違う

同じ「ファイルが見つからない」状況でも、使う関数によって深刻度が変わります。

関数ファイルが見つからないとき
include / include_onceWarningを出して処理は続行する
require / require_onceWarningの後、Fatal Errorで処理が止まる

データベース接続設定や共通関数など、なくては困るファイルrequireを使うのが基本です。

処理が止まらずに進んでしまうと、後続の処理でさらに分かりにくいエラーが連鎖してしまうためです。

<?php
// ✅ 必須のファイルは require、任意のファイルは include
require_once "../config/database.php";  // これがないと動かない
include "../parts/announcement.php";     // なくても致命的ではない

原因1:相対パスの基準を勘違いしている

かつコーチが実際につまずいた経験

私が一番時間を溶かした原因が、この「相対パスの基準」でした。

あるとき、以下のようなディレクトリ構成のプロジェクトで、pages/user.phpからconfig/database.phpを読み込もうとしました。

project/
├── config/
│   └── database.php
├── pages/
│   └── user.php
└── index.php
<?php
// pages/user.php の中
// ❌ Before:index.phpから見たパスで書いてしまった
require "config/database.php";

index.phpをブラウザで開くと動くのに、pages/user.phpを直接開くとFailed to open streamエラーが出る、という現象に丸1日悩まされました。

原因は、相対パスの基準が「読み込んだ側のファイルの場所」ではなく「実行された起点のファイルの場所」によって変わることがあるためです。

厳密には、requireの相対パスは「そのrequireが書かれているファイルがあるディレクトリ」を基準にするのが本来の仕様ですが、include_pathの設定やサーバーの動作次第で挙動が変わることがあり、初心者のうちは混乱しやすいポイントです。

解決策:__DIR__で絶対パスに変換する

この問題を根本的に解決するのが、__DIR__というマジック定数です。

__DIR__は「今書いているファイルが置かれているディレクトリの絶対パス」を返してくれます。

<?php
// pages/user.php の中
// ✅ After:__DIR__ を使って絶対パスに変換する
require __DIR__ . "/../config/database.php";

__DIR__を使えば、どこから実行されても・どのファイルから読み込まれても、パスの基準がぶれることがありません。

このエラーで悩んで以来、私はrequireincludeを書くときは必ず__DIR__をセットで使うようにしています。

<?php
// よく使う組み合わせ例
require_once __DIR__ . "/../config/database.php";
require_once __DIR__ . "/../functions/common.php";

原因2:ファイル名・拡張子の単純なミス

大文字小文字・拡張子の間違い

意外と多いのが、単純なタイプミスによるものです。

<?php
// ❌ Before:拡張子や大文字小文字を間違えている
require __DIR__ . "/../Config/Database.php"; // 実際は config/database.php

Windows環境ではファイル名の大文字小文字を区別しないことが多いため、ローカルでは動くのに、Linuxサーバーにアップロードした途端エラーになる、というトラブルも起きがちです。

<?php
// ✅ After:実際のファイル名・大文字小文字を正確に一致させる
require __DIR__ . "/../config/database.php";

デプロイ前にファイル名の大文字小文字を再確認しておくと、本番環境だけで起きるエラーを防げます。

ファイル自体を作り忘れている

もう一つのよくあるケースが、そもそも読み込み先のファイルをまだ作成していないパターンです。

コーディング中に「後で作ろう」と思ってrequireだけ先に書いてしまい、そのまま忘れてしまうことがあります。

エラーメッセージに書かれているファイルパスを実際にエディタで開いてみて、ファイルが存在するかをまず確認しましょう。

原因3:サーバー環境ごとのパスの違い

ローカルと本番でディレクトリ構成が違う

ローカル環境(XAMPPやMAMPなど)と本番のレンタルサーバーでは、プロジェクトが配置されるディレクトリの階層が異なることがあります。

【ローカル】
/Applications/XAMPP/htdocs/myproject/config/database.php

【本番サーバー】
/home/username/public_html/myproject/config/database.php

絶対パスを直接ベタ書きしてしまうと、ローカルでは動いても本番では確実にエラーになります。

<?php
// ❌ Before:環境固有の絶対パスを直接書いてしまう
require "/Applications/XAMPP/htdocs/myproject/config/database.php";
<?php
// ✅ After:__DIR__ を使い、環境が変わっても崩れないパスにする
require __DIR__ . "/../config/database.php";

ここでも__DIR__が活躍します。

環境に依存する絶対パスは書かず、常にファイル自身の場所を起点にした相対パスで組み立てる、これが鉄則です。

デバッグ時に役立つチェック方法

エラー前に一度パスを出力してみる

パスが正しいかどうか自信がないときは、requireの直前で一度パスを出力してみると確実です。

<?php
$path = __DIR__ . "/../config/database.php";

// デバッグ用:実際に計算されたパスを確認する
echo $path;

// ファイルが存在するかどうかもチェックできる
var_dump(file_exists($path));

require $path;

file_exists()trueが返ってくれば、少なくともパスの指定自体は正しいことが分かります。

falseが返ってきた場合は、パスの組み立て方かファイル名そのものを見直しましょう。

まとめ

この記事のポイント

  • 「ファイルが見つかりません」エラーはrequireincludeでのファイル読み込みが原因で起こる
  • requireはエラー時に処理が止まり、includeは止まらずに続く
  • 相対パスの基準を勘違いしやすいので、__DIR__を使って絶対パスに変換するのが確実
  • ファイル名の大文字小文字や、環境固有の絶対パスの直書きにも注意する
  • file_exists()でパスが正しいか事前に確認できる

次に読むべき記事

ファイルの読み込みエラーが解決できるようになったら、次は文字化けというもう一つの定番エラーに向き合っていきましょう。

→ 次の記事:PHPの文字化け対処法:mb_convert_encodingの使い方

タイトルとURLをコピーしました