はじめに
これまでの記事で、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形式である点が異なる |
よくある落とし穴(注意点)
- yaml拡張がインストールされていないと即座にエラーになる これまでの
yaml_emit()系関数と同様、事前にextension_loaded('yaml')で拡張の有無を確認する習慣をつけましょう(例1を参照)。 - 戻り値
falseと、値としてのfalseを区別できない YAML内に明示的にfalseという値が記述されていた場合の戻り値と、解析失敗時の戻り値がどちらもfalseになるため、単純な=== falseの判定だけでは失敗を正確に検知できないことがあります。ファイルの存在確認や、必要に応じたエラーハンドリング機構の併用が重要です(例2を参照)。 - ファイルが存在しない場合の挙動を確認せずに使う 存在しないファイルパスを渡すと、警告が発生した上で
falseが返ります。事前にfile_exists()で確認するのが安全です(例2を参照)。 - 複数ドキュメントを含むファイルの扱いを誤解する YAMLファイルには
---区切りで複数のドキュメントを含めることができますが、yaml_parse_file()はデフォルトでは最初のドキュメントのみを返します。すべてのドキュメントを取得したい場合は、第2引数(位置)と第3引数(総数の参照渡し)を活用したループ処理が必要です(例5を参照)。 - 読み込んだ結果の型を過信しない YAMLファイルのトップレベルが必ずしも連想配列であるとは限りません(単純な文字列やリストの場合もあります)。想定する型と異なる可能性を考慮し、必要に応じてキャストやバリデーションを行いましょう(例6を参照)。
まとめ
| 観点 | まとめ |
|---|---|
| 何をする関数か | 指定したパスのYAMLファイルを読み込み、解析してPHPの値に変換する |
| 主な用途 | アプリケーション設定ファイルの読み込み、環境別設定の切り替え |
yaml_parse()との違い | ファイルパスを直接指定でき、読み込みと解析を1回の呼び出しで完結できる |
| 前提条件 | yaml PECL拡張が有効になっていること |
| 注意点 | ファイル不存在時の挙動、falseの二重の意味、複数ドキュメントファイルの扱い |
yaml_parse_file() は、YAML形式の設定ファイルをPHPアプリケーションに読み込むための基本的かつ実用的な関数です。yaml_emit_file() と組み合わせることで、YAML形式でのデータの書き出しと読み込みを一貫して扱うことができ、設定管理やデータ永続化の実装をシンプルにできます。
