[PHP]phpinfo関数の使い方を徹底解説!サーバー環境確認の必須テクニック

PHP

PHPでWebアプリケーションを開発する際、サーバーの設定やインストールされているモジュールを確認する必要が頻繁に発生します。この記事では、PHPのphpinfo関数について、基本的な使い方から実践的な活用方法まで詳しく解説していきます。

phpinfo関数とは?

phpinfoは、PHP環境に関する詳細な情報を表示するための関数です。PHPのバージョン、設定値、インストールされているモジュール、サーバー情報など、あらゆる環境情報を一目で確認できる非常に便利な関数です。

基本的な構文

bool phpinfo(int $flags = INFO_ALL)

パラメータ:

  • $flags: 表示する情報の種類を指定する定数(オプション)

戻り値:

  • 常にtrueを返す

最もシンプルな使い方

<?php
phpinfo();
?>

たったこれだけで、PHPのすべての設定情報が見やすい形式で表示されます。

表示できる情報の種類

phpinfoでは、フラグを使って表示する情報を絞り込むことができます。

利用可能なフラグ定数

定数説明
INFO_GENERAL1PHP全般の情報(バージョン、ビルド日など)
INFO_CREDITS2PHPクレジット情報
INFO_CONFIGURATION4ローカルとマスターの設定値
INFO_MODULES8読み込まれているモジュール
INFO_ENVIRONMENT16環境変数情報
INFO_VARIABLES32EGPCS変数(Environment, GET, POST, Cookie, Server)
INFO_LICENSE64PHPライセンス情報
INFO_ALL-1すべての情報(デフォルト)

フラグの使い方

<?php
// 一般情報のみ表示
phpinfo(INFO_GENERAL);

// 設定情報のみ表示
phpinfo(INFO_CONFIGURATION);

// モジュール情報のみ表示
phpinfo(INFO_MODULES);

// 複数の情報を組み合わせて表示
phpinfo(INFO_GENERAL | INFO_CONFIGURATION);
?>

phpinfoが表示する主な情報

1. システム情報

  • PHPバージョン
  • ビルド日時
  • オペレーティングシステム
  • サーバーAPI(Apache、Nginx、CLI等)
  • Zendエンジンのバージョン

2. 設定情報

  • php.iniの場所
  • 各種ディレクティブの設定値
  • ローカル値とマスター値の比較

3. モジュール情報

  • インストールされている拡張モジュール
  • 各モジュールの設定

4. 環境変数

  • サーバー環境変数
  • PHP環境変数

実践的な使用例

1. 基本的なphpinfo表示ページ

<?php
// phpinfo.php - 環境確認用ファイル

// セキュリティ: 本番環境では必ずアクセス制限を!
$allowed_ips = ['127.0.0.1', '::1'];
$client_ip = $_SERVER['REMOTE_ADDR'] ?? '';

if (!in_array($client_ip, $allowed_ips)) {
    http_response_code(403);
    die('アクセスが拒否されました');
}

phpinfo();
?>

2. カスタムスタイルでphpinfoを表示

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>PHP環境情報</title>
    <style>
        body {
            font-family: 'Segoe UI', Arial, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            margin: 0;
            padding: 20px;
        }
        .container {
            max-width: 1400px;
            margin: 0 auto;
            background: white;
            border-radius: 12px;
            box-shadow: 0 10px 40px rgba(0,0,0,0.2);
            overflow: hidden;
        }
        .header {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 30px;
            text-align: center;
        }
        .header h1 {
            margin: 0;
            font-size: 2.5em;
        }
        .content {
            padding: 30px;
        }
        .info-box {
            background: #f8f9fa;
            border-left: 4px solid #667eea;
            padding: 20px;
            margin: 20px 0;
            border-radius: 4px;
        }
        .info-box h2 {
            margin-top: 0;
            color: #667eea;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🔧 PHP環境情報</h1>
            <p>サーバー環境の詳細情報</p>
        </div>
        
        <div class="content">
            <div class="info-box">
                <h2>クイック情報</h2>
                <p><strong>PHPバージョン:</strong> <?php echo PHP_VERSION; ?></p>
                <p><strong>Zendバージョン:</strong> <?php echo zend_version(); ?></p>
                <p><strong>サーバーAPI:</strong> <?php echo php_sapi_name(); ?></p>
                <p><strong>OS:</strong> <?php echo PHP_OS; ?></p>
            </div>
            
            <?php phpinfo(); ?>
        </div>
    </div>
</body>
</html>

3. phpinfo情報の取得と解析

<?php
/**
 * phpinfoの出力を配列として取得
 */
function getPhpInfoArray() {
    // 出力バッファリング開始
    ob_start();
    phpinfo(INFO_ALL);
    $phpinfo = ob_get_clean();
    
    // HTMLをパース
    $phpinfo = strip_tags($phpinfo, '<h2><th><td>');
    $phpinfo = preg_replace('/<th[^>]*>([^<]+)<\/th>/', '<info>\1</info>', $phpinfo);
    $phpinfo = preg_replace('/<td[^>]*>([^<]+)<\/td>/', '<info>\1</info>', $phpinfo);
    
    $array = [];
    $category = 'general';
    
    if (preg_match_all('/<h2[^>]*>([^<]+)<\/h2>/', $phpinfo, $titles)) {
        foreach ($titles[1] as $title) {
            $category = trim($title);
            $array[$category] = [];
        }
    }
    
    if (preg_match_all('/<info>([^<]+)<\/info>/', $phpinfo, $matches, PREG_SET_ORDER)) {
        $category = 'general';
        
        for ($i = 0; $i < count($matches); $i += 2) {
            if (isset($matches[$i + 1])) {
                $key = trim($matches[$i][1]);
                $value = trim($matches[$i + 1][1]);
                $array[$category][$key] = $value;
            }
        }
    }
    
    return $array;
}

/**
 * 特定の設定値を取得
 */
function getPhpConfig($directive) {
    return ini_get($directive);
}

// 使用例
$phpinfo = getPhpInfoArray();

echo "PHPバージョン: " . PHP_VERSION . "\n";
echo "メモリ制限: " . getPhpConfig('memory_limit') . "\n";
echo "最大実行時間: " . getPhpConfig('max_execution_time') . "秒\n";
echo "アップロード最大サイズ: " . getPhpConfig('upload_max_filesize') . "\n";
?>

4. 管理画面での環境情報表示

<?php
// 認証チェック(簡易版)
session_start();
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
    http_response_code(403);
    die('管理者権限が必要です');
}

class PhpInfoDashboard {
    
    /**
     * 重要な設定情報を取得
     */
    public static function getKeySettings() {
        return [
            'PHP設定' => [
                'PHPバージョン' => PHP_VERSION,
                'Zendエンジン' => zend_version(),
                'メモリ制限' => ini_get('memory_limit'),
                '最大実行時間' => ini_get('max_execution_time') . '秒',
                'エラー表示' => ini_get('display_errors') ? 'ON' : 'OFF',
                'エラーログ' => ini_get('error_log') ?: '未設定',
            ],
            'アップロード設定' => [
                'ファイルアップロード' => ini_get('file_uploads') ? '有効' : '無効',
                '最大アップロードサイズ' => ini_get('upload_max_filesize'),
                'POST最大サイズ' => ini_get('post_max_size'),
                '最大同時アップロード' => ini_get('max_file_uploads'),
            ],
            'セッション設定' => [
                'セッション保存パス' => ini_get('session.save_path'),
                'セッションハンドラ' => ini_get('session.save_handler'),
                'セッション名' => ini_get('session.name'),
                'Cookie有効期限' => ini_get('session.cookie_lifetime') . '秒',
            ],
            'データベース' => [
                'MySQL拡張' => extension_loaded('mysqli') ? '有効' : '無効',
                'PDO' => extension_loaded('pdo') ? '有効' : '無効',
                'PDO MySQL' => extension_loaded('pdo_mysql') ? '有効' : '無効',
                'PDO PostgreSQL' => extension_loaded('pdo_pgsql') ? '有効' : '無効',
            ],
            'その他の拡張' => [
                'cURL' => extension_loaded('curl') ? '有効' : '無効',
                'GD' => extension_loaded('gd') ? '有効' : '無効',
                'mbstring' => extension_loaded('mbstring') ? '有効' : '無効',
                'OpenSSL' => extension_loaded('openssl') ? '有効' : '無効',
                'JSON' => extension_loaded('json') ? '有効' : '無効',
                'XML' => extension_loaded('xml') ? '有効' : '無効',
                'ZIP' => extension_loaded('zip') ? '有効' : '無効',
            ]
        ];
    }
    
    /**
     * ダッシュボードHTML生成
     */
    public static function render() {
        $settings = self::getKeySettings();
        ?>
        <!DOCTYPE html>
        <html lang="ja">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>PHP環境ダッシュボード</title>
            <style>
                * { box-sizing: border-box; margin: 0; padding: 0; }
                body {
                    font-family: 'Segoe UI', sans-serif;
                    background: #f0f2f5;
                    padding: 20px;
                }
                .dashboard {
                    max-width: 1400px;
                    margin: 0 auto;
                }
                .header {
                    background: white;
                    padding: 30px;
                    border-radius: 12px;
                    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
                    margin-bottom: 20px;
                }
                .header h1 {
                    color: #1a73e8;
                    margin-bottom: 10px;
                }
                .tabs {
                    display: flex;
                    gap: 10px;
                    margin-bottom: 20px;
                    flex-wrap: wrap;
                }
                .tab-button {
                    padding: 12px 24px;
                    background: white;
                    border: 2px solid #e0e0e0;
                    border-radius: 8px;
                    cursor: pointer;
                    font-size: 14px;
                    font-weight: 500;
                    transition: all 0.3s;
                }
                .tab-button:hover {
                    border-color: #1a73e8;
                    color: #1a73e8;
                }
                .tab-button.active {
                    background: #1a73e8;
                    color: white;
                    border-color: #1a73e8;
                }
                .grid {
                    display: grid;
                    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
                    gap: 20px;
                    margin-bottom: 20px;
                }
                .card {
                    background: white;
                    padding: 24px;
                    border-radius: 12px;
                    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
                }
                .card h2 {
                    color: #333;
                    font-size: 18px;
                    margin-bottom: 20px;
                    padding-bottom: 12px;
                    border-bottom: 2px solid #f0f2f5;
                }
                .setting-row {
                    display: flex;
                    justify-content: space-between;
                    padding: 12px 0;
                    border-bottom: 1px solid #f0f2f5;
                }
                .setting-row:last-child {
                    border-bottom: none;
                }
                .setting-label {
                    color: #666;
                    font-size: 14px;
                }
                .setting-value {
                    color: #333;
                    font-weight: 500;
                    font-size: 14px;
                }
                .full-info {
                    background: white;
                    padding: 30px;
                    border-radius: 12px;
                    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
                    display: none;
                }
                .full-info.active {
                    display: block;
                }
                .extensions-list {
                    display: flex;
                    flex-wrap: wrap;
                    gap: 10px;
                    margin-top: 20px;
                }
                .extension-badge {
                    background: #e8f5e9;
                    color: #2e7d32;
                    padding: 6px 12px;
                    border-radius: 16px;
                    font-size: 13px;
                    font-weight: 500;
                }
            </style>
        </head>
        <body>
            <div class="dashboard">
                <div class="header">
                    <h1>🔧 PHP環境ダッシュボード</h1>
                    <p>サーバー環境の詳細情報と設定</p>
                </div>
                
                <div class="tabs">
                    <button class="tab-button active" onclick="showTab('summary')">サマリー</button>
                    <button class="tab-button" onclick="showTab('full')">完全な情報</button>
                    <button class="tab-button" onclick="showTab('extensions')">拡張モジュール</button>
                </div>
                
                <div id="summary" class="tab-content">
                    <div class="grid">
                        <?php foreach ($settings as $category => $items): ?>
                        <div class="card">
                            <h2><?php echo htmlspecialchars($category); ?></h2>
                            <?php foreach ($items as $label => $value): ?>
                            <div class="setting-row">
                                <span class="setting-label"><?php echo htmlspecialchars($label); ?></span>
                                <span class="setting-value"><?php echo htmlspecialchars($value); ?></span>
                            </div>
                            <?php endforeach; ?>
                        </div>
                        <?php endforeach; ?>
                    </div>
                </div>
                
                <div id="full" class="full-info">
                    <?php phpinfo(); ?>
                </div>
                
                <div id="extensions" class="full-info">
                    <div class="card">
                        <h2>読み込まれている拡張モジュール</h2>
                        <div class="extensions-list">
                            <?php
                            $extensions = get_loaded_extensions();
                            sort($extensions);
                            foreach ($extensions as $ext):
                            ?>
                            <span class="extension-badge"><?php echo htmlspecialchars($ext); ?></span>
                            <?php endforeach; ?>
                        </div>
                    </div>
                </div>
            </div>
            
            <script>
                function showTab(tabName) {
                    // すべてのタブコンテンツを非表示
                    document.querySelectorAll('.tab-content, .full-info').forEach(el => {
                        el.style.display = 'none';
                        el.classList.remove('active');
                    });
                    
                    // すべてのタブボタンを非アクティブ化
                    document.querySelectorAll('.tab-button').forEach(btn => {
                        btn.classList.remove('active');
                    });
                    
                    // 選択されたタブを表示
                    const selectedTab = document.getElementById(tabName);
                    if (selectedTab) {
                        selectedTab.style.display = 'block';
                        selectedTab.classList.add('active');
                    }
                    
                    // ボタンをアクティブ化
                    event.target.classList.add('active');
                }
            </script>
        </body>
        </html>
        <?php
    }
}

PhpInfoDashboard::render();
?>

5. phpinfo情報のエクスポート

<?php
/**
 * phpinfo情報を様々な形式でエクスポート
 */
class PhpInfoExporter {
    
    /**
     * HTML形式で取得
     */
    public static function toHtml() {
        ob_start();
        phpinfo();
        return ob_get_clean();
    }
    
    /**
     * プレーンテキスト形式で取得
     */
    public static function toText() {
        ob_start();
        phpinfo(INFO_ALL);
        $html = ob_get_clean();
        return strip_tags($html);
    }
    
    /**
     * JSON形式で取得
     */
    public static function toJson() {
        $info = [
            'php_version' => PHP_VERSION,
            'php_version_id' => PHP_VERSION_ID,
            'zend_version' => zend_version(),
            'sapi' => php_sapi_name(),
            'os' => PHP_OS,
            'os_family' => PHP_OS_FAMILY,
            'architecture' => PHP_INT_SIZE * 8 . '-bit',
            'extensions' => get_loaded_extensions(),
            'ini_files' => [
                'loaded' => php_ini_loaded_file(),
                'scanned' => php_ini_scanned_files()
            ],
            'configuration' => [
                'memory_limit' => ini_get('memory_limit'),
                'max_execution_time' => ini_get('max_execution_time'),
                'upload_max_filesize' => ini_get('upload_max_filesize'),
                'post_max_size' => ini_get('post_max_size'),
                'display_errors' => ini_get('display_errors'),
                'error_reporting' => ini_get('error_reporting'),
                'date.timezone' => ini_get('date.timezone'),
            ]
        ];
        
        return json_encode($info, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
    }
    
    /**
     * ファイルに保存
     */
    public static function saveToFile($format = 'html', $filename = null) {
        if ($filename === null) {
            $filename = 'phpinfo_' . date('Y-m-d_His') . '.' . $format;
        }
        
        switch ($format) {
            case 'html':
                $content = self::toHtml();
                break;
            case 'txt':
                $content = self::toText();
                break;
            case 'json':
                $content = self::toJson();
                break;
            default:
                throw new Exception('未対応のフォーマット');
        }
        
        file_put_contents($filename, $content);
        return $filename;
    }
}

// 使用例
if (isset($_GET['export'])) {
    $format = $_GET['format'] ?? 'html';
    
    header('Content-Type: ' . ($format === 'json' ? 'application/json' : 'text/plain'));
    header('Content-Disposition: attachment; filename="phpinfo_' . date('Y-m-d') . '.' . $format . '"');
    
    switch ($format) {
        case 'html':
            echo PhpInfoExporter::toHtml();
            break;
        case 'txt':
            echo PhpInfoExporter::toText();
            break;
        case 'json':
            echo PhpInfoExporter::toJson();
            break;
    }
    exit;
}
?>

<!DOCTYPE html>
<html>
<head>
    <title>phpinfo エクスポート</title>
</head>
<body>
    <h1>phpinfo エクスポート</h1>
    <p>以下の形式でエクスポートできます:</p>
    <ul>
        <li><a href="?export=1&format=html">HTML形式</a></li>
        <li><a href="?export=1&format=txt">テキスト形式</a></li>
        <li><a href="?export=1&format=json">JSON形式</a></li>
    </ul>
</body>
</html>

セキュリティ上の重要な注意点

本番環境での使用は絶対に避ける

phpinfo()は機密情報を大量に表示するため、本番環境で誰でもアクセスできる状態にするのは非常に危険です。

<?php
// ❌ 絶対にやってはいけない例
// 本番環境のルートディレクトリに phpinfo.php を置く
phpinfo();
?>

安全な使用方法

<?php
// ✅ 開発環境でのみ実行
if (getenv('APP_ENV') !== 'production') {
    phpinfo();
} else {
    http_response_code(404);
    die();
}
?>
<?php
// ✅ IPアドレスで制限
$allowedIPs = ['127.0.0.1', '::1', '192.168.1.100'];
if (!in_array($_SERVER['REMOTE_ADDR'], $allowedIPs)) {
    http_response_code(403);
    die('アクセスが拒否されました');
}
phpinfo();
?>
<?php
// ✅ 認証で保護
session_start();
if (!isset($_SESSION['authenticated']) || !$_SESSION['authenticated']) {
    header('Location: login.php');
    exit;
}
phpinfo();
?>
<?php
// ✅ ランダムなURLで保護
$secret_key = 'your-secret-key-here';
$provided_key = $_GET['key'] ?? '';

if (!hash_equals($secret_key, $provided_key)) {
    http_response_code(404);
    die();
}
phpinfo();
?>

よくあるトラブルシューティング

問題1: phpinfoが表示されない

<?php
// 出力バッファリングの問題かチェック
if (ob_get_level()) {
    ob_end_clean();
}
phpinfo();
?>

問題2: 一部の情報が表示されない

<?php
// すべての情報を表示
phpinfo(INFO_ALL);

// または特定の情報を指定
phpinfo(INFO_GENERAL | INFO_CONFIGURATION | INFO_MODULES);
?>

問題3: メモリ不足エラー

<?php
// メモリ制限を一時的に増やす
ini_set('memory_limit', '256M');
phpinfo();
?>

まとめ

phpinfo関数は、PHP環境の診断・確認に欠かせない強力なツールです。以下のポイントを押さえておきましょう。

  • 開発・デバッグ時の必須ツールとして非常に便利
  • PHP設定、モジュール、環境変数など包括的な情報を表示
  • フラグで表示する情報を絞り込み可能
  • 本番環境では絶対に公開しない
  • 使用する場合は必ず認証・IP制限・環境分離で保護
  • 情報をエクスポートして記録・共有も可能
  • 管理画面の一部として安全に組み込むことも可能

phpinfo()は開発者にとって非常に便利な関数ですが、セキュリティリスクも高いため、適切に管理して使用しましょう。開発環境でのみ使用するか、本番環境では厳重なアクセス制限を設けることが重要です!

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