[PHP]yaml_parse_fileとは?YAMLファイルを直接読み込んでPHPの値に変換する方法を徹底解説

PHP

はじめに

これまでの記事で、PHPの値をYAML形式に変換する yaml_emit()yaml_emit_file() を解説してきました。今回はその逆方向、つまりYAML形式のデータを読み込んでPHPの値に変換する関数の中から、ファイルを直接指定できる yaml_parse_file() を取り上げます。

設定ファイルとしてYAMLを採用しているプロジェクトでは、アプリケーション起動時に config.yaml のような設定ファイルを読み込み、PHPの配列として扱いたい場面が頻繁にあります。yaml_parse_file() は、ファイルパスを渡すだけでその内容を解析し、対応するPHPの値(多くの場合は連想配列)を返してくれる、シンプルで実用的な関数です。本記事では基本的な使い方から実践的な活用例まで詳しく解説します。


関数概要

項目内容
関数名yaml_parse_file()
所属拡張yaml拡張(PECL、標準では無効)
シグネチャyaml_parse_file(string $filename, int $pos = 0, int &$ndocs = null, array $callbacks = []): mixed
引数1$filename — 読み込むYAMLファイルのパス
引数2$pos — 複数ドキュメントが含まれる場合の開始位置
引数3$ndocs — 参照渡し。ファイル内のドキュメント総数が格納される
引数4$callbacks — カスタムのデシリアライズ処理を指定するコールバック配列
戻り値解析結果のPHPの値。失敗時は false
対応バージョンyaml拡張2.0.0以降(PECL)
対になる関数yaml_emit_file()(PHPの値をYAMLファイルとして書き出す)

処理の流れ(イメージ図)

  YAMLファイル (config.yaml)
  app:
    name: MyApp
    debug: false
  database:
    host: localhost
    port: 5432
              │
              ▼
   yaml_parse_file('/path/to/config.yaml')
              │
   ┌──────────┴──────────────┐
   │ ファイルを読み込み、               │
   │ YAML構文を解析してPHPの値に変換     │
   └──────────┬──────────────┘
              ▼
  PHPの連想配列
  [
    'app' => ['name' => 'MyApp', 'debug' => false],
    'database' => ['host' => 'localhost', 'port' => 5432],
  ]

ポイントは、yaml_parse_file()ファイルの読み込みと構文解析を1回の呼び出しでまとめて行ってくれるという点です。file_get_contents() で文字列として読み込んでから yaml_parse() に渡すという2ステップの処理を、この関数1つで完結できます。


実践サンプル7選

例1:基本的な使い方

<?php

class BasicYamlFileParser
{
    public function parse(string $filePath): mixed
    {
        if (!extension_loaded('yaml')) {
            throw new RuntimeException('yaml拡張がインストールされていません。');
        }

        return yaml_parse_file($filePath);
    }
}

$parser = new BasicYamlFileParser();
$config = $parser->parse('/tmp/config.yaml');
print_r($config);

例2:ファイルの存在確認とエラーハンドリングを含む堅牢な読み込みクラス

<?php

class SafeConfigLoader
{
    /**
     * ファイルの存在確認と解析失敗の両方を
     * 適切にハンドリングする
     */
    public function load(string $filePath): array
    {
        if (!file_exists($filePath)) {
            throw new RuntimeException("設定ファイルが見つかりません: {$filePath}");
        }

        $result = yaml_parse_file($filePath);

        if ($result === false) {
            throw new RuntimeException("YAMLファイルの解析に失敗しました: {$filePath}");
        }

        return (array) $result;
    }
}

$loader = new SafeConfigLoader();
try {
    $config = $loader->load('/tmp/app_config.yaml');
    print_r($config);
} catch (RuntimeException $e) {
    echo 'エラー: ' . $e->getMessage() . PHP_EOL;
}

例3:アプリケーション設定をシングルトン的にキャッシュするクラス

<?php

class ConfigRepository
{
    private static ?array $cache = null;

    /**
     * 一度読み込んだ設定をメモリ上にキャッシュし、
     * 同じリクエスト内での重複読み込みを避ける
     */
    public static function get(string $filePath): array
    {
        if (self::$cache === null) {
            self::$cache = (array) yaml_parse_file($filePath);
        }

        return self::$cache;
    }
}

$config = ConfigRepository::get('/tmp/singleton_config.yaml');
print_r($config);

例4:環境ごとに異なる設定ファイルを読み込む切り替えクラス

<?php

class EnvironmentAwareConfigLoader
{
    /**
     * APP_ENVなどの環境変数に応じて、
     * 対応するYAML設定ファイルを読み込む
     */
    public function loadForEnvironment(string $configDir, string $environment): array
    {
        $filePath = "{$configDir}/{$environment}.yaml";

        if (!file_exists($filePath)) {
            $filePath = "{$configDir}/default.yaml";
        }

        return (array) yaml_parse_file($filePath);
    }
}

$loader = new EnvironmentAwareConfigLoader();
$env = getenv('APP_ENV') ?: 'development';
print_r($loader->loadForEnvironment('/tmp/configs', $env));

例5:複数ドキュメントを含むYAMLファイルを扱うクラス

<?php

class MultiDocumentYamlReader
{
    /**
     * "---"で区切られた複数のYAMLドキュメントを含むファイルから、
     * すべてのドキュメントを配列として取得する
     */
    public function readAllDocuments(string $filePath): array
    {
        $documents = [];
        $position = 0;
        $totalDocs = 0;

        // 最初の呼び出しで$ndocsにドキュメント総数が格納される
        $firstDoc = yaml_parse_file($filePath, $position, $totalDocs);
        $documents[] = $firstDoc;

        for ($position = 1; $position < $totalDocs; $position++) {
            $documents[] = yaml_parse_file($filePath, $position);
        }

        return $documents;
    }
}

$reader = new MultiDocumentYamlReader();
print_r($reader->readAllDocuments('/tmp/multi_doc.yaml'));

例6:設定値のバリデーションを組み合わせたローダー

<?php

class ValidatedConfigLoader
{
    /**
     * 読み込んだ設定に必須キーが揃っているかを検証する
     */
    public function loadAndValidate(string $filePath, array $requiredKeys): array
    {
        $config = yaml_parse_file($filePath);

        if ($config === false) {
            throw new RuntimeException('YAML解析に失敗しました');
        }

        $missing = array_diff($requiredKeys, array_keys($config));
        if (!empty($missing)) {
            throw new RuntimeException('必須の設定キーが不足しています: ' . implode(', ', $missing));
        }

        return $config;
    }
}

$loader = new ValidatedConfigLoader();
try {
    $config = $loader->loadAndValidate('/tmp/validated_config.yaml', ['app', 'database']);
    print_r($config);
} catch (RuntimeException $e) {
    echo 'エラー: ' . $e->getMessage() . PHP_EOL;
}

例7:yaml_parse_fileとyaml_parseの使い分けを示す比較デモ

<?php

class ParseVsParseFileComparison
{
    /**
     * 既に文字列としてデータを持っている場合はyaml_parse()、
     * ファイルパスから直接読み込みたい場合はyaml_parse_file()を使う
     */
    public function parseFromString(string $yamlContent): mixed
    {
        return yaml_parse($yamlContent);
    }

    public function parseFromFile(string $filePath): mixed
    {
        return yaml_parse_file($filePath);
    }

    /**
     * 外部APIレスポンスなど、既に文字列としてYAMLを受け取っている場合の例
     */
    public function parseApiResponse(string $rawYamlResponse): mixed
    {
        // ファイルではなく文字列として受け取っているため、yaml_parse()を使う
        return yaml_parse($rawYamlResponse);
    }
}

$comparison = new ParseVsParseFileComparison();
print_r($comparison->parseFromFile('/tmp/comparison_config.yaml'));
print_r($comparison->parseFromString("key: value\nnested:\n  item: 1"));

関連関数との比較

関数役割yaml_parse_fileとの違い
yaml_parse_file()YAMLファイルを読み込んでPHPの値に変換本記事の対象。ファイルパスを直接指定できる
yaml_parse()YAML形式の文字列をPHPの値に変換既に文字列として持っているデータを解析する場合に使う
yaml_emit_file()PHPの値をYAML形式に変換し、ファイルに書き込むyaml_parse_file()の対になるエンコード関数
json_decode() + file_get_contents()JSONファイルの読み込み・デコードフォーマットがJSONである点が異なる
parse_ini_file()INIファイルを読み込んでPHPの値に変換対象のフォーマットがINI形式である点が異なる

よくある落とし穴(注意点)

  1. yaml拡張がインストールされていないと即座にエラーになる これまでのyaml_emit()系関数と同様、事前に extension_loaded('yaml') で拡張の有無を確認する習慣をつけましょう(例1を参照)。
  2. 戻り値falseと、値としてのfalseを区別できない YAML内に明示的に false という値が記述されていた場合の戻り値と、解析失敗時の戻り値がどちらも false になるため、単純な === false の判定だけでは失敗を正確に検知できないことがあります。ファイルの存在確認や、必要に応じたエラーハンドリング機構の併用が重要です(例2を参照)。
  3. ファイルが存在しない場合の挙動を確認せずに使う 存在しないファイルパスを渡すと、警告が発生した上で false が返ります。事前に file_exists() で確認するのが安全です(例2を参照)。
  4. 複数ドキュメントを含むファイルの扱いを誤解する YAMLファイルには --- 区切りで複数のドキュメントを含めることができますが、yaml_parse_file() はデフォルトでは最初のドキュメントのみを返します。すべてのドキュメントを取得したい場合は、第2引数(位置)と第3引数(総数の参照渡し)を活用したループ処理が必要です(例5を参照)。
  5. 読み込んだ結果の型を過信しない YAMLファイルのトップレベルが必ずしも連想配列であるとは限りません(単純な文字列やリストの場合もあります)。想定する型と異なる可能性を考慮し、必要に応じてキャストやバリデーションを行いましょう(例6を参照)。

まとめ

観点まとめ
何をする関数か指定したパスのYAMLファイルを読み込み、解析してPHPの値に変換する
主な用途アプリケーション設定ファイルの読み込み、環境別設定の切り替え
yaml_parse()との違いファイルパスを直接指定でき、読み込みと解析を1回の呼び出しで完結できる
前提条件yaml PECL拡張が有効になっていること
注意点ファイル不存在時の挙動、falseの二重の意味、複数ドキュメントファイルの扱い

yaml_parse_file() は、YAML形式の設定ファイルをPHPアプリケーションに読み込むための基本的かつ実用的な関数です。yaml_emit_file() と組み合わせることで、YAML形式でのデータの書き出しと読み込みを一貫して扱うことができ、設定管理やデータ永続化の実装をシンプルにできます。

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