[PHP]var_exportとは?変数をPHPコードとして出力・再利用する方法を徹底解説

PHP

はじめに

前回の記事では、変数の中身を型情報付きで詳細表示する var_dump() を解説しました。今回紹介する var_export() は、似たような目的で使われることもありますが、決定的に異なる特徴を持っています。それは、出力結果がそのままPHPのコードとして評価(実行)可能な形式になるという点です。

つまり var_export() は、単なるデバッグ表示のための関数ではなく、「変数の状態をPHPのソースコードとして書き出し、後で eval()include によって再びPHPの値として読み込む」という用途にも使える、実用性の高い関数です。設定ファイルのキャッシュ生成やコードジェネレーターなど、実務で意外と活躍する場面が多くあります。本記事では基本的な使い方から、実践的な活用パターンまで詳しく解説します。


関数概要

項目内容
関数名var_export()
所属拡張コア関数(標準で常に利用可能)
シグネチャvar_export(mixed $value, bool $return = false): ?string
引数1$value — 出力対象の変数
引数2$returntrueにすると出力せず文字列として返す
戻り値$return=trueの場合は文字列、false(デフォルト)の場合はnull(直接出力する)
対応バージョンPHP 4以降
出力形式PHPのソースコードとして評価可能な形式
類似関数var_dump()(型情報の詳細表示)、serialize()(独自形式でのシリアライズ)

出力の流れ(イメージ図)

  変数
  $config = ['debug' => true, 'timeout' => 30, 'name' => "app"];
              │
              ▼
      var_export($config, true)
              │
   ┌──────────┴──────────────────┐
   │ PHPコードとしてそのまま       │
   │ evalやファイル出力に使える形式に  │
   └──────────┬──────────────────┘
              ▼
  array (
    'debug' => true,
    'timeout' => 30,
    'name' => 'app',
  )

ポイントは、この出力結果の先頭に return を付けて .php ファイルとして保存すれば、include するだけで元の配列がそのまま復元できるという点です。これは var_dump() の人間可読な表示専用フォーマットとは根本的に異なる、実用上非常に重要な特徴です。


実践サンプル7選

例1:基本的な使い方(直接出力とreturnモードの違い)

<?php

class BasicExporter
{
    public function displayDirectly(mixed $value): void
    {
        // 第2引数を省略/falseにすると、その場で直接出力される
        var_export($value);
    }

    public function getAsString(mixed $value): string
    {
        // 第2引数をtrueにすると、出力せず文字列として受け取れる
        return var_export($value, true);
    }
}

$exporter = new BasicExporter();
$exporter->displayDirectly(['a' => 1, 'b' => 2]);
echo PHP_EOL;
echo $exporter->getAsString('hello') . PHP_EOL; // 'hello'

例2:設定データをPHPファイルとしてキャッシュするクラス

<?php

class ConfigCacheWriter
{
    /**
     * データベースなどから取得した設定値を、
     * 高速に読み込めるPHPファイル形式でキャッシュする
     */
    public function writeCache(array $config, string $filePath): void
    {
        $exported = var_export($config, true);
        $phpCode = "<?php\n\nreturn {$exported};\n";

        file_put_contents($filePath, $phpCode);
    }

    public function readCache(string $filePath): array
    {
        // include するだけで元の配列がそのまま復元される
        return include $filePath;
    }
}

$writer = new ConfigCacheWriter();
$writer->writeCache(['db_host' => 'localhost', 'db_port' => 3306], '/tmp/config_cache.php');
print_r($writer->readCache('/tmp/config_cache.php'));

例3:オブジェクトのコピー用コードを生成するデバッグツール

<?php

class ObjectCodeExporter
{
    /**
     * オブジェクトをvar_export()すると
     * "\stdClass::__set_state(...)" 形式で出力される点を確認する
     */
    public function exportStdClass(object $obj): string
    {
        return var_export($obj, true);
    }
}

$exporter = new ObjectCodeExporter();
$obj = new stdClass();
$obj->name = '太郎';
$obj->age = 30;

echo $exporter->exportStdClass($obj) . PHP_EOL;
// \stdClass::__set_state(array(
//    'name' => '太郎',
//    'age' => 30,
// ))

例4:単体テストのフィクスチャデータを自動生成するツール

<?php

class TestFixtureGenerator
{
    /**
     * APIレスポンスなどの実データを、
     * そのままPHPのテストコードに貼り付けられる形式で出力する
     */
    public function generateFixtureCode(array $data, string $variableName): string
    {
        $exported = var_export($data, true);
        return "\${$variableName} = {$exported};";
    }
}

$generator = new TestFixtureGenerator();
$apiResponse = ['id' => 1, 'status' => 'success', 'items' => ['a', 'b', 'c']];
echo $generator->generateFixtureCode($apiResponse, 'expectedResponse') . PHP_EOL;
// $expectedResponse = array (
//   'id' => 1,
//   'status' => 'success',
//   'items' => array (0 => 'a', 1 => 'b', 2 => 'c'),
// );

例5:var_exportとvar_dumpとserializeの出力形式比較

<?php

class ExportFormatComparator
{
    /**
     * 同じデータに対する3種類の出力形式の違いを比較する
     */
    public function compare(mixed $value): array
    {
        return [
            'var_export (PHPコードとして評価可能)' => var_export($value, true),
            'serialize (独自シリアライズ形式)'      => serialize($value),
            'json_encode (JSON形式)'               => json_encode($value),
        ];
    }
}

$comparator = new ExportFormatComparator();
print_r($comparator->compare(['x' => 1, 'y' => true, 'z' => null]));

例6:ルーティング定義など静的データをコンパイル済みファイルに出力する

<?php

class RouteCompiler
{
    /**
     * 実行時に動的に組み立てたルーティング定義を、
     * デプロイ時に静的なPHPファイルとして書き出し高速化する
     */
    public function compile(array $routes, string $outputPath): void
    {
        $header = "<?php\n\n// このファイルは自動生成されています。直接編集しないでください。\n\nreturn ";
        $body = var_export($routes, true);

        file_put_contents($outputPath, $header . $body . ";\n");
    }
}

$compiler = new RouteCompiler();
$routes = [
    'GET /users'      => 'UserController@index',
    'POST /users'     => 'UserController@store',
    'GET /users/{id}' => 'UserController@show',
];
$compiler->compile($routes, '/tmp/compiled_routes.php');

例7:整形済みコードとして保存する際のインデント調整ユーティリティ

<?php

class PrettyConfigExporter
{
    /**
     * var_export()のデフォルトのインデントは4スペースだが、
     * プロジェクトのコーディング規約(例: 2スペース)に合わせて調整する
     */
    public function exportWithCustomIndent(array $data, int $spaces = 2): string
    {
        $exported = var_export($data, true);

        // デフォルトの4スペースインデントを指定のスペース数に置換する簡易実装
        $lines = explode("\n", $exported);
        $adjusted = array_map(function (string $line) use ($spaces) {
            return preg_replace_callback('/^(\s+)/', function ($matches) use ($spaces) {
                $level = strlen($matches[1]) / 2; // var_exportは2スペース単位でネストする
                return str_repeat(' ', $level * $spaces);
            }, $line);
        }, $lines);

        return implode("\n", $adjusted);
    }
}

$exporter = new PrettyConfigExporter();
echo $exporter->exportWithCustomIndent(['level1' => ['level2' => 'value']], 4) . PHP_EOL;

関連関数との比較

関数役割var_exportとの違い
var_export()変数をPHPコードとして評価可能な形式で出力本記事の対象。出力結果をそのままPHPコードとして使える
var_dump()変数を型情報付きで詳細に出力出力形式が独自のデバッグ表示用であり、PHPコードとしては使えない
serialize()変数を独自形式の文字列に変換よりコンパクトだが人間には読みにくく、unserialize()でのみ復元可能
json_encode()変数をJSON形式の文字列に変換言語間の互換性が高いが、PHP固有の型(オブジェクトの一部など)は表現に制約がある
print_r()変数を人間が読みやすい形式で出力型情報がなく、PHPコードとしても評価できない、あくまで表示専用

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

  1. var_dump() と混同して使ってしまう デバッグ表示が目的なら var_dump() の方が型情報も含めて詳細に確認できます。「PHPコードとして再利用したいかどうか」を基準に使い分けましょう。
  2. すべてのオブジェクトが正しくエクスポートできるわけではない var_export() はプライベート・プロテクテッドプロパティを持つオブジェクトや、リソース型の変数を正しくエクスポートできない場合があります。特に複雑なオブジェクトグラフには注意が必要です。
  3. __set_state() マジックメソッドの実装が必要な場合がある var_export() で出力されたオブジェクトのコードを実際に eval() などで復元する際、独自クラスであれば静的メソッド __set_state() を実装しておく必要があります。実装していないとエラーになります。
  4. 生成したPHPファイルを信頼できない入力から作らない ユーザー入力を元にデータを組み立てて var_export() した結果をそのままファイルに書き込み、後で include するような設計は、データの内容によっては意図しないコード実行につながるリスクがあるため、入力元の信頼性を十分に検証する必要があります。
  5. 大量データのエクスポートによるパフォーマンスへの影響 巨大な配列をエクスポートすると生成される文字列も非常に長くなり、ファイルサイズや処理時間に影響します。設定キャッシュなどの用途では、必要なデータのみを対象にする設計が望ましいです。

まとめ

観点まとめ
何をする関数か変数をPHPのソースコードとして評価可能な形式の文字列に変換する
主な用途設定ファイルのキャッシュ生成、テストフィクスチャの自動生成、ルーティング定義のコンパイルなど
最大の特徴出力結果がそのままPHPコードとしてincludeevalで再利用できる
類似関数との違いvar_dump()はデバッグ表示専用、serialize()/json_encode()はPHPコードとしては評価できない
注意点オブジェクトのエクスポート制約、__set_state()の実装、信頼できない入力からの生成を避けること

var_export() は、単なるデバッグ用の表示関数にとどまらず、「PHPの値をコードとして永続化する」という実用的な用途に活用できる、意外と奥の深い関数です。設定キャッシュやコード生成といった場面で、その特性をぜひ活かしてみてください。

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