[PHP]php_ini_scanned_files関数の使い方を完全解説!追加の設定ファイルを確認する方法

PHP

はじめに

PHPの設定を調べる時、「メインのphp.ini以外にどんな設定ファイルが読み込まれているの?」と疑問に思ったことはありませんか?

実は、PHPはメインのphp.iniファイル以外にも、複数の追加設定ファイル(.iniファイル)を読み込むことができます。特にLinux環境では、拡張機能ごとに個別の.iniファイルが用意されていることが一般的です。

そんな追加設定ファイルを確認するのが**php_ini_scanned_files関数**です。この関数を使えば、どの設定ファイルが読み込まれているかを正確に把握できます。

この記事では、php_ini_scanned_filesの基本から実践的な活用方法まで、詳しく解説します。

php_ini_scanned_filesとは?

php_ini_scanned_filesは、追加で読み込まれた.iniファイルのリストをカンマ区切りの文字列として返す関数です。

基本構文

php_ini_scanned_files(): string|false

パラメータ

この関数はパラメータを取りません。

戻り値

  • 成功時: カンマ区切りの.iniファイルパスの文字列
  • 失敗時: 追加の.iniファイルが読み込まれていない場合はfalse

対応バージョン

  • PHP 4.3.0 以降で使用可能

基本的な使い方

シンプルな確認方法

<?php
$scanned_files = php_ini_scanned_files();

if ($scanned_files) {
    echo "追加で読み込まれた.iniファイル:\n";
    echo $scanned_files;
} else {
    echo "追加の.iniファイルはありません";
}

// 出力例(Linux):
// /etc/php/8.2/cli/conf.d/10-opcache.ini,
// /etc/php/8.2/cli/conf.d/10-pdo.ini,
// /etc/php/8.2/cli/conf.d/20-mysqli.ini
?>

配列に変換して扱いやすく

<?php
$scanned = php_ini_scanned_files();

if ($scanned) {
    // カンマ区切りを配列に変換
    $files = explode(',', $scanned);
    
    // 前後の空白を削除
    $files = array_map('trim', $files);
    
    echo "読み込まれている.iniファイル数: " . count($files) . "\n\n";
    
    foreach ($files as $index => $file) {
        echo ($index + 1) . ". {$file}\n";
    }
} else {
    echo "追加の.iniファイルはありません\n";
}
?>

実践的な使用例

例1: すべての設定ファイルを一覧表示

<?php
function getAllConfigFiles() {
    $config_files = [
        'main' => php_ini_loaded_file(),
        'additional' => []
    ];
    
    $scanned = php_ini_scanned_files();
    if ($scanned) {
        $files = explode(',', $scanned);
        $config_files['additional'] = array_map('trim', $files);
    }
    
    return $config_files;
}

$configs = getAllConfigFiles();

echo "=== PHP設定ファイル一覧 ===\n\n";

echo "【メイン設定ファイル】\n";
echo $configs['main'] ?: '(なし)';
echo "\n\n";

echo "【追加設定ファイル】\n";
if (!empty($configs['additional'])) {
    foreach ($configs['additional'] as $i => $file) {
        echo sprintf("%2d. %s\n", $i + 1, $file);
    }
} else {
    echo "(なし)\n";
}
?>

例2: 特定の拡張機能の設定ファイルを検索

<?php
function findExtensionIni($extension_name) {
    $scanned = php_ini_scanned_files();
    
    if (!$scanned) {
        return null;
    }
    
    $files = array_map('trim', explode(',', $scanned));
    
    foreach ($files as $file) {
        $basename = basename($file);
        
        // ファイル名に拡張機能名が含まれているか確認
        if (stripos($basename, $extension_name) !== false) {
            return $file;
        }
    }
    
    return null;
}

// 使用例
$extensions = ['opcache', 'mysqli', 'pdo', 'redis'];

echo "=== 拡張機能の設定ファイル検索 ===\n\n";

foreach ($extensions as $ext) {
    $ini_file = findExtensionIni($ext);
    
    if ($ini_file) {
        echo "✓ {$ext}: {$ini_file}\n";
    } else {
        echo "✗ {$ext}: 設定ファイルが見つかりません\n";
    }
}
?>

例3: 設定ファイルの詳細情報を取得

<?php
function getIniFilesDetails() {
    $details = [];
    
    // メインファイル
    $main_ini = php_ini_loaded_file();
    if ($main_ini && file_exists($main_ini)) {
        $details['main'] = [
            'path' => $main_ini,
            'size' => filesize($main_ini),
            'modified' => date('Y-m-d H:i:s', filemtime($main_ini)),
            'readable' => is_readable($main_ini),
            'writable' => is_writable($main_ini)
        ];
    }
    
    // 追加ファイル
    $scanned = php_ini_scanned_files();
    if ($scanned) {
        $files = array_map('trim', explode(',', $scanned));
        
        foreach ($files as $file) {
            if (file_exists($file)) {
                $details['additional'][] = [
                    'path' => $file,
                    'name' => basename($file),
                    'size' => filesize($file),
                    'modified' => date('Y-m-d H:i:s', filemtime($file)),
                    'readable' => is_readable($file)
                ];
            }
        }
    }
    
    return $details;
}

$details = getIniFilesDetails();

echo "=== 設定ファイル詳細 ===\n\n";

if (isset($details['main'])) {
    echo "【メインファイル】\n";
    echo "パス: {$details['main']['path']}\n";
    echo "サイズ: " . number_format($details['main']['size']) . " bytes\n";
    echo "更新日時: {$details['main']['modified']}\n";
    echo "\n";
}

if (isset($details['additional'])) {
    echo "【追加ファイル】\n";
    foreach ($details['additional'] as $i => $info) {
        echo ($i + 1) . ". {$info['name']}\n";
        echo "   パス: {$info['path']}\n";
        echo "   サイズ: " . number_format($info['size']) . " bytes\n";
        echo "   更新: {$info['modified']}\n\n";
    }
}
?>

例4: 設定ファイルの内容を検索

<?php
function searchInIniFiles($search_term) {
    $results = [];
    
    // メインファイルを検索
    $main_ini = php_ini_loaded_file();
    if ($main_ini && file_exists($main_ini)) {
        $content = file_get_contents($main_ini);
        if (stripos($content, $search_term) !== false) {
            $results[] = [
                'file' => $main_ini,
                'type' => 'main'
            ];
        }
    }
    
    // 追加ファイルを検索
    $scanned = php_ini_scanned_files();
    if ($scanned) {
        $files = array_map('trim', explode(',', $scanned));
        
        foreach ($files as $file) {
            if (file_exists($file)) {
                $content = file_get_contents($file);
                if (stripos($content, $search_term) !== false) {
                    $results[] = [
                        'file' => $file,
                        'type' => 'additional',
                        'name' => basename($file)
                    ];
                }
            }
        }
    }
    
    return $results;
}

// 使用例
$term = 'memory_limit';
$found = searchInIniFiles($term);

echo "「{$term}」を含む設定ファイル:\n\n";

if (empty($found)) {
    echo "見つかりませんでした\n";
} else {
    foreach ($found as $result) {
        echo "[{$result['type']}] {$result['file']}\n";
    }
}
?>

例5: 拡張機能のロード順序を確認

<?php
function getExtensionLoadOrder() {
    $order = [];
    
    $scanned = php_ini_scanned_files();
    if (!$scanned) {
        return $order;
    }
    
    $files = array_map('trim', explode(',', $scanned));
    
    foreach ($files as $index => $file) {
        $basename = basename($file);
        
        // 数字のプレフィックスを抽出(例: 10-opcache.ini → 10)
        if (preg_match('/^(\d+)-/', $basename, $matches)) {
            $priority = (int)$matches[1];
            $name = preg_replace('/^\d+-/', '', $basename);
        } else {
            $priority = 999;
            $name = $basename;
        }
        
        $order[] = [
            'priority' => $priority,
            'name' => $name,
            'path' => $file,
            'load_order' => $index + 1
        ];
    }
    
    return $order;
}

$extensions = getExtensionLoadOrder();

echo "=== 拡張機能のロード順序 ===\n\n";
echo sprintf("%-5s %-10s %-30s\n", "順序", "優先度", "ファイル名");
echo str_repeat("-", 60) . "\n";

foreach ($extensions as $ext) {
    echo sprintf(
        "%-5d %-10d %-30s\n",
        $ext['load_order'],
        $ext['priority'],
        $ext['name']
    );
}
?>

conf.dディレクトリの仕組み

多くのLinuxディストリビューションでは、追加の.iniファイルはconf.dディレクトリに配置されます。

典型的なディレクトリ構造

/etc/php/8.2/
├── cli/
│   ├── php.ini              ← メイン設定
│   └── conf.d/              ← 追加設定
│       ├── 10-opcache.ini
│       ├── 10-pdo.ini
│       ├── 20-mysqli.ini
│       ├── 20-pdo_mysql.ini
│       └── 30-xdebug.ini
├── apache2/
│   ├── php.ini
│   └── conf.d/
└── fpm/
    ├── php.ini
    └── conf.d/

conf.dディレクトリの確認

<?php
function getConfDDirectory() {
    $main_ini = php_ini_loaded_file();
    
    if (!$main_ini) {
        return null;
    }
    
    // php.iniのディレクトリからconf.dディレクトリを推測
    $ini_dir = dirname($main_ini);
    $conf_d = $ini_dir . '/conf.d';
    
    if (is_dir($conf_d)) {
        return $conf_d;
    }
    
    return null;
}

$conf_d = getConfDDirectory();

if ($conf_d) {
    echo "conf.dディレクトリ: {$conf_d}\n\n";
    
    // ディレクトリ内のファイル一覧
    $files = glob($conf_d . '/*.ini');
    
    echo "利用可能な.iniファイル:\n";
    foreach ($files as $file) {
        $basename = basename($file);
        $scanned = php_ini_scanned_files();
        $is_loaded = $scanned && strpos($scanned, $file) !== false;
        
        $status = $is_loaded ? '✓ 読込済' : '✗ 未読込';
        echo "  {$status} {$basename}\n";
    }
} else {
    echo "conf.dディレクトリが見つかりません\n";
}
?>

環境別の設定確認

CLI、Apache、FPMの比較

<?php
function compareEnvironments() {
    $current_sapi = PHP_SAPI;
    $current_ini = php_ini_loaded_file();
    $current_scanned = php_ini_scanned_files();
    
    echo "=== 現在の環境 ===\n";
    echo "SAPI: {$current_sapi}\n";
    echo "メインini: {$current_ini}\n\n";
    
    if ($current_scanned) {
        $count = count(explode(',', $current_scanned));
        echo "追加iniファイル数: {$count}\n";
    } else {
        echo "追加iniファイル: なし\n";
    }
    
    // よくある環境のパス
    $environments = [
        'CLI' => '/etc/php/8.2/cli/conf.d',
        'Apache' => '/etc/php/8.2/apache2/conf.d',
        'FPM' => '/etc/php/8.2/fpm/conf.d'
    ];
    
    echo "\n=== 各環境のconf.dディレクトリ ===\n";
    foreach ($environments as $env => $path) {
        if (is_dir($path)) {
            $count = count(glob($path . '/*.ini'));
            echo "{$env}: {$path} ({$count}ファイル)\n";
        } else {
            echo "{$env}: {$path} (存在しません)\n";
        }
    }
}

compareEnvironments();
?>

Docker環境での確認

<?php
function checkDockerIniFiles() {
    $is_docker = file_exists('/.dockerenv');
    
    echo "Docker環境: " . ($is_docker ? 'はい' : 'いいえ') . "\n\n";
    
    $main_ini = php_ini_loaded_file();
    $scanned = php_ini_scanned_files();
    
    echo "メイン設定: " . ($main_ini ?: 'なし') . "\n";
    
    if ($scanned) {
        $files = array_map('trim', explode(',', $scanned));
        echo "\n追加設定ファイル (" . count($files) . "個):\n";
        
        foreach ($files as $file) {
            // Dockerボリュームマウントの確認
            $is_mounted = strpos($file, '/usr/local/etc/php/conf.d') !== false;
            $marker = $is_mounted ? ' [ボリューム]' : '';
            echo "  - " . basename($file) . $marker . "\n";
        }
    } else {
        echo "追加設定: なし\n";
    }
}

checkDockerIniFiles();
?>

トラブルシューティング

ケース1: 拡張機能が有効にならない

<?php
function diagnoseExtension($extension_name) {
    echo "=== {$extension_name} 拡張機能の診断 ===\n\n";
    
    // 拡張機能がロードされているか確認
    $is_loaded = extension_loaded($extension_name);
    echo "1. 拡張機能の状態: " . ($is_loaded ? '✓ ロード済み' : '✗ 未ロード') . "\n";
    
    if (!$is_loaded) {
        echo "   → 拡張機能がロードされていません\n\n";
        
        // 設定ファイルを確認
        echo "2. 設定ファイルの確認:\n";
        
        $scanned = php_ini_scanned_files();
        if ($scanned) {
            $files = array_map('trim', explode(',', $scanned));
            $found = false;
            
            foreach ($files as $file) {
                if (stripos(basename($file), $extension_name) !== false) {
                    echo "   ✓ 設定ファイルが見つかりました: {$file}\n";
                    
                    // ファイルの内容を確認
                    if (file_exists($file)) {
                        $content = file_get_contents($file);
                        if (preg_match('/^extension\s*=\s*' . $extension_name . '/m', $content)) {
                            echo "   ✓ extension={$extension_name} の記述あり\n";
                        } else {
                            echo "   ✗ extension={$extension_name} の記述なし\n";
                        }
                        
                        // コメントアウトされていないか確認
                        if (preg_match('/^;\s*extension\s*=\s*' . $extension_name . '/m', $content)) {
                            echo "   ⚠ 設定がコメントアウトされています\n";
                        }
                    }
                    $found = true;
                    break;
                }
            }
            
            if (!$found) {
                echo "   ✗ {$extension_name} 用の設定ファイルが見つかりません\n";
                echo "\n対処法:\n";
                echo "   - パッケージマネージャーで拡張機能をインストール\n";
                echo "   - conf.dディレクトリに .ini ファイルを作成\n";
            }
        } else {
            echo "   追加の設定ファイルがありません\n";
        }
    } else {
        echo "   → 拡張機能は正常にロードされています\n";
        
        // 設定値を表示
        if (function_exists($extension_name . '_get_config')) {
            echo "\n設定値:\n";
            $config = call_user_func($extension_name . '_get_config');
            print_r($config);
        }
    }
}

// 使用例
diagnoseExtension('mysqli');
?>

ケース2: 設定が重複している

<?php
function findDuplicateSettings($setting_name) {
    $occurrences = [];
    
    // メインファイルを確認
    $main_ini = php_ini_loaded_file();
    if ($main_ini && file_exists($main_ini)) {
        $content = file($main_ini, FILE_IGNORE_NEW_LINES);
        foreach ($content as $line_num => $line) {
            if (preg_match('/^\s*' . preg_quote($setting_name) . '\s*=/', $line)) {
                $occurrences[] = [
                    'file' => $main_ini,
                    'line' => $line_num + 1,
                    'content' => trim($line),
                    'type' => 'main'
                ];
            }
        }
    }
    
    // 追加ファイルを確認
    $scanned = php_ini_scanned_files();
    if ($scanned) {
        $files = array_map('trim', explode(',', $scanned));
        
        foreach ($files as $file) {
            if (file_exists($file)) {
                $content = file($file, FILE_IGNORE_NEW_LINES);
                foreach ($content as $line_num => $line) {
                    if (preg_match('/^\s*' . preg_quote($setting_name) . '\s*=/', $line)) {
                        $occurrences[] = [
                            'file' => $file,
                            'line' => $line_num + 1,
                            'content' => trim($line),
                            'type' => 'additional'
                        ];
                    }
                }
            }
        }
    }
    
    return $occurrences;
}

// 使用例
$setting = 'memory_limit';
$dupes = findDuplicateSettings($setting);

echo "=== {$setting} の設定箇所 ===\n\n";

if (empty($dupes)) {
    echo "設定が見つかりません\n";
} else {
    echo "現在の値: " . ini_get($setting) . "\n\n";
    echo "設定箇所 (" . count($dupes) . "個):\n";
    
    foreach ($dupes as $i => $item) {
        echo ($i + 1) . ". [{$item['type']}] " . basename($item['file']) . ":{$item['line']}\n";
        echo "   {$item['content']}\n\n";
    }
    
    if (count($dupes) > 1) {
        echo "⚠ 警告: 複数の箇所で設定されています\n";
        echo "   → 最後に読み込まれた設定が有効になります\n";
    }
}
?>

ケース3: ファイルの読み込み順序の問題

<?php
function analyzeLoadOrder() {
    $scanned = php_ini_scanned_files();
    
    if (!$scanned) {
        echo "追加の設定ファイルはありません\n";
        return;
    }
    
    $files = array_map('trim', explode(',', $scanned));
    
    echo "=== .iniファイルの読み込み順序 ===\n\n";
    echo "重要: 後から読み込まれた設定が優先されます\n\n";
    
    foreach ($files as $index => $file) {
        $basename = basename($file);
        $order = $index + 1;
        
        // プレフィックス番号を抽出
        if (preg_match('/^(\d+)-/', $basename, $matches)) {
            $prefix = $matches[1];
            echo "{$order}. [{$prefix}] {$basename}\n";
        } else {
            echo "{$order}. [--] {$basename}\n";
        }
    }
    
    echo "\nヒント:\n";
    echo "- 番号の小さいファイルから順に読み込まれます\n";
    echo "- 依存関係のある拡張機能は番号で順序を制御できます\n";
    echo "  例: 10-pdo.ini → 20-pdo_mysql.ini\n";
}

analyzeLoadOrder();
?>

実用的なツール作成

設定ファイル管理ツール

<?php
class IniFileManager {
    private $mainIni;
    private $scannedFiles;
    
    public function __construct() {
        $this->mainIni = php_ini_loaded_file();
        $this->scannedFiles = $this->parseScannedFiles();
    }
    
    private function parseScannedFiles() {
        $scanned = php_ini_scanned_files();
        
        if (!$scanned) {
            return [];
        }
        
        return array_map('trim', explode(',', $scanned));
    }
    
    public function getAllFiles() {
        $files = [];
        
        if ($this->mainIni) {
            $files[] = [
                'type' => 'main',
                'path' => $this->mainIni,
                'name' => basename($this->mainIni)
            ];
        }
        
        foreach ($this->scannedFiles as $file) {
            $files[] = [
                'type' => 'additional',
                'path' => $file,
                'name' => basename($file)
            ];
        }
        
        return $files;
    }
    
    public function searchSetting($setting_name) {
        $results = [];
        
        foreach ($this->getAllFiles() as $file) {
            if (!file_exists($file['path'])) {
                continue;
            }
            
            $content = file_get_contents($file['path']);
            $lines = explode("\n", $content);
            
            foreach ($lines as $num => $line) {
                if (preg_match('/^\s*' . preg_quote($setting_name) . '\s*=\s*(.+)/', $line, $matches)) {
                    $results[] = [
                        'file' => $file['name'],
                        'path' => $file['path'],
                        'line' => $num + 1,
                        'value' => trim($matches[1])
                    ];
                }
            }
        }
        
        return $results;
    }
    
    public function getStatistics() {
        $stats = [
            'total_files' => count($this->getAllFiles()),
            'main_file' => $this->mainIni ? 1 : 0,
            'additional_files' => count($this->scannedFiles),
            'total_size' => 0
        ];
        
        foreach ($this->getAllFiles() as $file) {
            if (file_exists($file['path'])) {
                $stats['total_size'] += filesize($file['path']);
            }
        }
        
        return $stats;
    }
    
    public function generateReport() {
        $report = "=== PHP設定ファイルレポート ===\n\n";
        $report .= "生成日時: " . date('Y-m-d H:i:s') . "\n";
        $report .= "PHPバージョン: " . PHP_VERSION . "\n";
        $report .= "SAPI: " . PHP_SAPI . "\n\n";
        
        $stats = $this->getStatistics();
        $report .= "統計情報:\n";
        $report .= "  設定ファイル総数: {$stats['total_files']}\n";
        $report .= "  追加ファイル数: {$stats['additional_files']}\n";
        $report .= "  合計サイズ: " . number_format($stats['total_size']) . " bytes\n\n";
        
        $report .= "設定ファイル一覧:\n";
        foreach ($this->getAllFiles() as $i => $file) {
            $report .= sprintf(
                "%2d. [%s] %s\n    %s\n",
                $i + 1,
                $file['type'],
                $file['name'],
                $file['path']
            );
        }
        
        return $report;
    }
}

// 使用例
$manager = new IniFileManager();

// レポートを生成
echo $manager->generateReport();

// 特定の設定を検索
echo "\n=== memory_limit の設定箇所 ===\n";
$results = $manager->searchSetting('memory_limit');
foreach ($results as $result) {
    echo "{$result['file']}:{$result['line']} = {$result['value']}\n";
}
?>

まとめ

php_ini_scanned_filesは、追加で読み込まれた.iniファイルを確認するための重要な関数です。

主な特徴:

  • ✅ 追加の.iniファイル一覧を取得
  • ✅ カンマ区切りの文字列として返される
  • php_ini_loaded_file()と併用で全設定ファイルを把握
  • ✅ 拡張機能の設定管理に便利

重要なポイント:

  • Linuxではconf.dディレクトリが一般的
  • ファイル名のプレフィックス番号で読み込み順序を制御
  • CLI/Apache/FPMで異なる設定ファイルが使われる
  • 後から読み込まれた設定が優先される

活用シーン:

  • 拡張機能のトラブルシューティング
  • 設定の重複チェック
  • 環境構築の確認
  • 設定管理ツールの作成

関連する関数:

  • php_ini_loaded_file(): メインのphp.iniのパスを取得
  • ini_get(): 現在の設定値を取得
  • get_loaded_extensions(): ロード済み拡張機能一覧

この関数を活用して、PHPの設定管理をより効率的に行いましょう!

参考リンク

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