はじめに
前回の記事では、コード中の現在行番号を取得するマジック定数 __LINE__ を解説しました。今回取り上げる __FILE__ は、それと並んでよく使われる、現在のファイルの絶対パスを取得するマジック定数です。
__FILE__ は、それが記述されているPHPファイル自身の、シンボリックリンクが解決された完全な絶対パスに、コンパイル時に置き換えられます。設定ファイルの読み込み、相対パスの解決、ログの出力元ファイルの特定、include/require でのパス指定など、ファイルシステム上の自分自身の位置を知る必要がある、非常に多くの場面で活用される基本的な仕組みです。本記事では基本的な使い方から、__DIR__ との使い分け、実践的な活用例まで詳しく解説します。
定数概要
| 項目 | 内容 |
|---|---|
| 定数名 | __FILE__ |
| 種別 | マジック定数 |
| 値の型 | 文字列(string) |
| 値の内容 | そのコードが記述されているファイルの絶対パス(シンボリックリンク解決済み) |
| 対応バージョン | PHP 4以降 |
| 関連するマジック定数 | __DIR__(PHP 5.3以降、dirname(__FILE__)の簡潔な代替) |
| includeされた場合の挙動 | 呼び出し元ではなく、__FILE__が実際に書かれているファイル自身のパスを返す |
パス解決の仕組み(イメージ図)
ディレクトリ構造
/var/www/app/
├── config/
│ └── database.php ← __FILE__がここに書かれている
└── index.php ← database.phpをincludeする側
database.php の中身:
<?php
echo __FILE__;
│
▼
出力: "/var/www/app/config/database.php"
(index.phpから呼び出されても、
database.php自身の絶対パスが返る)
ポイントは、__FILE__ がシンボリックリンクを解決した「実際の」絶対パスを返すという点です。もし database.php がシンボリックリンク経由でアクセスされていたとしても、__FILE__ はリンク先の実体のパスを返します。
実践サンプル7選
例1:基本的な使い方
<?php
echo '現在のファイル: ' . __FILE__ . PHP_EOL;
echo 'ファイル名のみ: ' . basename(__FILE__) . PHP_EOL;
echo 'ディレクトリ: ' . dirname(__FILE__) . PHP_EOL;
例2:相対パスでの設定ファイル読み込みを確実にするクラス
<?php
class ConfigLoader
{
/**
* __FILE__を基準にすることで、
* スクリプトがどこから実行されても正しいパスを解決できる
*/
public function load(): array
{
$configPath = dirname(__FILE__) . '/config/settings.php';
if (!file_exists($configPath)) {
throw new RuntimeException("設定ファイルが見つかりません: {$configPath}");
}
return include $configPath;
}
}
$loader = new ConfigLoader();
// $config = $loader->load();
例3:ログ出力元ファイルを記録するロガー
<?php
class FileAwareLogger
{
/**
* __FILE__を呼び出し元から渡してもらうことで、
* ログにどのファイルから出力されたかを記録する
*/
public static function log(string $message, string $sourceFile): void
{
$relativePath = str_replace(dirname(__DIR__ ?? '.'), '', $sourceFile);
echo "[{$relativePath}] {$message}" . PHP_EOL;
}
}
FileAwareLogger::log('処理を開始しました', __FILE__);
例4:autoloadファイルなしでの簡易クラス読み込み
<?php
// このファイル自身のディレクトリを基準にクラスファイルを読み込む
$classesDir = dirname(__FILE__) . '/classes';
/**
* Composerのautoloadを使わない簡易的な環境で、
* __FILE__基準の相対パスでファイルを読み込む典型的なパターン
*/
function loadClass(string $className): void
{
global $classesDir;
$path = $classesDir . '/' . $className . '.php';
if (file_exists($path)) {
require_once $path;
}
}
// loadClass('MyClass');
例5:ファイルの更新日時をチェックするキャッシュバスター
<?php
class AssetVersioner
{
/**
* __FILE__とfilemtime()を組み合わせて、
* ファイルの更新日時をバージョン文字列として付与する
* (ブラウザキャッシュ対策の典型的な手法)
*/
public static function getVersionedPath(string $relativePath): string
{
$fullPath = dirname(__FILE__) . '/public/' . $relativePath;
$version = file_exists($fullPath) ? filemtime($fullPath) : time();
return "/{$relativePath}?v={$version}";
}
}
echo AssetVersioner::getVersionedPath('css/style.css') . PHP_EOL;
例6:現在のファイルがコマンドラインから直接実行されたかを判定する
<?php
/**
* __FILE__と$_SERVER['SCRIPT_FILENAME'](またはargv[0])を比較することで、
* このファイルがinclude/requireされたのか、直接実行されたのかを判定できる
*/
function isExecutedDirectly(): bool
{
if (PHP_SAPI !== 'cli') {
return false;
}
return realpath($_SERVER['argv'][0] ?? '') === realpath(__FILE__);
}
if (isExecutedDirectly()) {
echo 'このファイルは直接実行されました' . PHP_EOL;
} else {
echo 'このファイルは他のファイルから読み込まれました' . PHP_EOL;
}
例7:デバッグ情報としてスタック的にファイルパスを記録するクラス
<?php
class FileLocationRecorder
{
private array $visitedFiles = [];
/**
* 複数のファイルをまたいで処理が行われる際、
* どのファイルを経由したかを記録する
*/
public function recordVisit(string $file): void
{
$this->visitedFiles[] = basename($file);
}
public function getTrail(): string
{
return implode(' → ', $this->visitedFiles);
}
}
function stepOne(FileLocationRecorder $recorder): void
{
$recorder->recordVisit(__FILE__);
}
$recorder = new FileLocationRecorder();
stepOne($recorder);
echo $recorder->getTrail() . PHP_EOL;
関連機能との比較
| 機能 | 役割 | __FILE__との違い |
|---|---|---|
__FILE__ | 現在のファイルの絶対パスを取得 | 本記事の対象。ファイル名まで含む完全なパスを返す |
__DIR__ | 現在のファイルが存在するディレクトリの絶対パスを取得 | dirname(__FILE__)の簡潔な代替(PHP 5.3以降) |
__LINE__ | 現在の行番号を取得 | ファイルパスではなく、行番号の情報を提供する(前回記事を参照) |
realpath() | 指定したパスの絶対パスを解決する | 任意のパス文字列を対象とし、__FILE__自体とは独立した汎用関数 |
$_SERVER['SCRIPT_FILENAME'] | 実行されたエントリーポイントのファイルパスを取得 | __FILE__とは異なり、スクリプト全体のエントリーポイントを指す |
よくある落とし穴(注意点)
__DIR__の方が簡潔な場合が多い ディレクトリパスだけが必要な場合、わざわざdirname(__FILE__)と書くよりも、PHP 5.3以降で使える__DIR__を直接使う方が簡潔です(例2・例4のような処理は__DIR__で書き換え可能です)。- includeされたファイルでは、そのファイル自身のパスになる
__FILE__は、include/requireの呼び出し元ファイルのパスではなく、__FILE__が実際に記述されているファイル自身のパスを返します。呼び出し階層をまたいだパス取得が必要な場合は、別の方法(debug_backtrace()など)を検討する必要があります。 - シンボリックリンク環境での挙動を理解しておく
__FILE__はシンボリックリンクを解決した実体のパスを返すため、シンボリックリンク自体のパスを期待していると、意図と異なる結果になることがあります。 - Windows環境でのパス区切り文字の違い
__FILE__が返すパスは、実行環境のOSに応じたディレクトリ区切り文字(Windowsでは\、Unix系では/)を使用します。クロスプラットフォームで動作するコードを書く場合、DIRECTORY_SEPARATOR定数やstr_replace()を使った正規化を検討しましょう。 - 本番環境でのパス情報の露出に注意する
__FILE__の値をエラーメッセージなどに含めてユーザーに表示してしまうと、サーバーのディレクトリ構造が露出し、セキュリティ上望ましくない情報開示につながる可能性があります。ログにのみ出力し、ユーザー向けの表示には含めないようにしましょう。
まとめ
| 観点 | まとめ |
|---|---|
| 何をする定数か | それが記述されているファイルの、絶対パスに置き換わる |
| 主な用途 | 相対パスでの設定ファイル読み込み、ログの出力元記録、キャッシュバスティング |
__DIR__との関係 | ディレクトリパスのみが必要な場合は__DIR__の方が簡潔 |
| includeされた場合の挙動 | 呼び出し元ではなく、__FILE__自身が書かれているファイルのパスを返す |
| 注意点 | シンボリックリンクの解決、OSごとのパス区切り文字の違い、本番環境でのパス情報露出への配慮 |
__FILE__ は、PHPスクリプトが自分自身の位置をファイルシステム上で正確に把握するための、基本的かつ重要なマジック定数です。相対パスに依存する処理を、実行時のカレントディレクトリに左右されずに安定して動作させるために、幅広い場面で活用されています。
