| type | idea |
|---|---|
| title | PHPコアにdd()関数を追加する — var_dump() + exit()のショートカット |
| slug | idea-add-dd-function |
| php_src_ref | c4105b6243e8c0ae6882e847414df5930ac45ac7 |
| status | in-progress |
status: done
PHPには複数のデバッグ出力関数(var_dump()、print_r()、var_export())があるが、「変数を出力して即座に実行を停止する」というデバッグ時の最頻出パターンに対応する組み込み関数がない。dd()(dump and die)をPHPコアの組み込み関数として提供することで、フレームワーク非依存のデバッグ体験を改善し、すべてのPHP開発者が追加の依存なしに利用できるようにする。
- フレームワーク非使用の開発者: Laravel・Symfonyの
dd()にアクセスできないPHP開発者。素のPHPスクリプトやレガシーアプリケーションの保守者 - PHP初学者: デバッグ手法の学習曲線を下げる。
var_dump($x); exit;の2行パターンを1行で書ける - CLI/スクリプト開発者: ワンショットスクリプトやバッチ処理のデバッグ時に即座に値を確認して停止したい場面が多い
- すべてのPHP開発者: IDEやエディタのスニペットに頼らず、言語レベルで統一されたデバッグプリミティブを持てる
- internals保守的派: 「ユーザーランドで簡単に実装できるものをコアに追加する意味がない」という立場。PHPコアの肥大化を懸念する層
- フレームワーク開発者: LaravelやSymfonyは独自の高機能な
dd()を提供しており、コアの簡素なdd()との名前衝突・動作差異が混乱を招く可能性を指摘する層(特にLaravelのdd()はsymfony/var-dumperベースで色付き出力やHTML出力を行う) - 言語設計純粋主義者: デバッグ専用関数はxdebugやphpdbgなど専用ツールの仕事であり、言語コアの責務ではないという立場
- 名前空間を重視する層: グローバル名前空間に短い名前の関数を追加することへの反対。既存のユーザーランド
dd()関数との衝突リスクを指摘
フレームワークやライブラリが独自にdd()を提供しており、事実上のデファクトスタンダードとなっている:
Laravel(Illuminate\Support\helpers.php):
function dd(...$vars): never
{
if (!in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) {
header('HTTP/1.1 500 Internal Server Error');
}
foreach ($vars as $v) {
VarDumper::dump($v);
}
exit(1);
}ソース: https://github.com/laravel/framework/blob/master/src/Illuminate/Support/helpers.php
Symfony(symfony/var-dumper):
function dd(mixed ...$vars): never
{
// ...
foreach ($vars as $v) {
VarDumper::dump($v);
}
exit(1);
}ソース: https://github.com/symfony/var-dumper — dd()はcomposerのautoload.filesで自動ロードされる
WordPress(デバッグプラグイン各種): Kintプラグインなどがdd()相当の機能を提供
素のPHPでの一般的パターン(ユーザーランドワークアラウンド):
var_dump($variable); exit;
var_dump($variable); die;
echo "<pre>"; var_dump($variable); echo "</pre>"; exit;| 言語 | 機能 | 説明 |
|---|---|---|
| Ruby | Kernel#p + abort |
pはオブジェクトの.inspectを出力。dd相当は標準ライブラリにないが、pの手軽さが同様のDX改善を実現。Railsではbinding.pryがデバッグの主流 |
| Rust | dbg!() マクロ |
Rust 1.32で標準ライブラリに追加。式の値をstderrに出力し、値をそのまま返す。プロセスは停止しない。ソース: https://doc.rust-lang.org/std/macro.dbg.html |
| Elixir | IO.inspect/2 + dbg/2 |
Elixir 1.14でdbg/2マクロが追加。パイプライン中に挟んでデバッグ出力できる。プロセスは停止しない。ソース: https://hexdocs.pm/elixir/Kernel.html#dbg/2 |
注目すべき点: 主要言語の多くは「ダンプして停止」ではなく「ダンプして続行」のデバッグプリミティブを採用している。dd()(die付き)をコアに入れる言語は他にない。これはRFCのフレーミングに影響する。
| 賛成(Pro) | 反対(Con) |
|---|---|
| PHPで最も一般的なデバッグパターンを1関数にまとめる。フレームワーク非依存 | ユーザーランドで2行(var_dump(); exit;)で実現可能。コアに追加する必要性が低い |
LaravelやSymfonyでdd()は既にデファクトスタンダード。PHP開発者の期待に合致 |
Laravel/Symfonyのdd()はリッチな出力(色、折りたたみ、HTML)を提供。コアの素朴なdd()は「劣化版」と見なされる可能性 |
PHP初学者の学習曲線を下げる。「デバッグどうやるの?」→ dd($x) |
グローバル名前空間に短い名前を追加すると、既存のdd()定義と衝突する(function_existsガードなしの場合fatal error) |
Rustのdbg!()、Elixirのdbg/2のように、モダン言語はコアにデバッグプリミティブを持つ流れがある |
exit()を含むデバッグ関数は本番コードに残りやすく、危険。xdebgやphpdbgの使用を阻害する |
実装コストが非常に低い(var_dump() + exit()のラッパー) |
実装コストが低いということは、コアに追加する理由も弱いということ |
ext/standard/var.c:var_dump()、var_export()、debug_zval_dump()の実装場所。dd()も同ファイルに追加するのが自然ext/standard/basic_functions.stub.php: PHP関数のスタブ定義。dd()のシグネチャをここに追加ext/standard/basic_functions_arginfo.h:build/gen_stub.phpから自動生成されるarginfo。スタブファイルから再生成Zend/zend_builtin_functions.c:exit()/die()の実装場所。dd()からexitを呼ぶ際にこの機構(zend_throw_unwind_exit())を利用
- INIディレクティブによる出力のカスタマイズ(深さ制限、文字列切り詰め、色付けなど)
- HTTP SAPI用のレスポンスヘッダ設定(500ステータスコードなど)
- HTMLの
<pre>タグ自動付与 dump()(exit無し版)の同時追加- RFC本文のドラフト
- フレームワークの
dd()との互換性レイヤー - 出力先のカスタマイズ(stderr vs stdout)
status: done
PHPコアにdd()関数を追加した場合、以下のすべてを満たすことで成功とする(反証可能な判定基準):
-
動作の正確性:
dd($x)がvar_dump($x); exit(0);とバイト単位で同一の標準出力を生成し、同じ終了コード(0)でプロセスを終了する。これを3つの.phptテストケースで検証する:- スカラー値(int、string、bool、null)
- 複合型(配列、ネストされた配列)
- 複数引数(
dd($a, $b, $c))
-
既存の
dd()定義との共存: ユーザーランドでfunction dd() {}が定義済みの場合、PHPが明確なfatal errorを出すこと(暗黙の上書きやサイレントな無視ではない)。これは既存のPHP動作(組み込み関数と同名のユーザー関数定義はfatal error)に準拠するが、明示的に確認する。 -
ビルドの健全性:
make -j$(nproc)がゼロ新規コンパイラ警告で完了する。
反証条件: 上記3項目のうちいずれか1つでも失敗した場合、メトリクスは未達成とする。
以下の3つのPHPスクリプトをプロトタイプビルドのsapi/cli/phpで実行する:
テスト1: 基本的なスカラー値のダンプ
<?php
dd(42, "hello", true, null);期待出力: var_dump(42, "hello", true, null)と同一の出力後、終了コード0で停止。
テスト2: 複合型のダンプ
<?php
dd(["a" => 1, "b" => [2, 3]]);期待出力: var_dump(["a" => 1, "b" => [2, 3]])と同一の出力後、終了コード0で停止。
テスト3: dd()後のコードが実行されないことの確認
<?php
dd("stop here");
echo "THIS SHOULD NOT APPEAR";期待出力: var_dump("stop here")の出力のみ。"THIS SHOULD NOT APPEAR"は出力されない。終了コード0。
PHPバージョン: 現在のmasterブランチ(c4105b6243e)をベースにビルド。
status: done
- pre: Hypothesis & Metricフェーズ完了済み
- post: 4つのソースのうち3つが実行完了(gh-prsは0件)
-
keywords —
dd,dump die,var_dump exit,dd function,dump and die,Pre-RFC dd dump -
algolia-internals — 3件の関連ヒット(複数クエリの合計)
- 「Pre-RFC: dd() and dump() functions for PHP core」 — Larry Garfield, 2025-06-17 — https://externals.io/message/127699 — 直接関連: 2025年6月にBraunson Yagerが提案した、まさに今回と同じ
dd()+dump()をPHPコアに追加する提案。強い反対を受けてRFCに至らず - 「Pre-RFC: dd() and dump() functions for PHP core」(Grekas返信) — Nicolas Grekas, 2025-06-19 — https://externals.io/message/127719 — 直接関連: Symfony VarDumperの作者による詳細な反対意見。名前衝突、イノベーション凍結、パフォーマンス主張の棄却、ユーザーランドの十分性を指摘
- 「Pre-RFC: dd() and dump() functions for PHP core」(Vollebregt返信) — Jonathan Vollebregt, 2025-06-17 — https://externals.io/message/127701 — 直接関連: 名前衝突の意図的発生を批判。PHPコアには既に
print_r、var_dump、debug_zval_dump、var_exportの4つのダンプ関数があると指摘 - 「New function proposal」 — Korvin Szanto, 2015-10-10 — https://externals.io/message/88733 — 直接関連: 2015年にMattias Gonzalezが
var_die($var)を提案。Johannes Schlüterが「ユーザーランドで簡単に実装でき、パフォーマンスの利点もない。コアに追加する理由がない」と却下
- 「Pre-RFC: dd() and dump() functions for PHP core」 — Larry Garfield, 2025-06-17 — https://externals.io/message/127699 — 直接関連: 2025年6月にBraunson Yagerが提案した、まさに今回と同じ
-
gh-issues — 0件の直接関連ヒット
GitHub issueの検索では
dd()関数の追加に直接関連するissueは見つからなかった。議論はすべてinternals MLで行われている。 -
gh-prs — 0件
dd()やdump()の追加に関するPRは提出されていない。Pre-RFCの段階で議論が終了しているため、実装に至っていない。 -
git-log — 0件の直接関連コミット
dd()関数の追加に関するコミットは存在しない。var_dumpやdebug_zval_dumpに関する多数のコミットが存在するが、dd()の実装を試みたものはない。
この提案は過去に2回(2015年、2025年)internals@で議論され、いずれも強い反対を受けてRFCに至っていない。 主な反対論点は一貫している: (1) ユーザーランドで2行で実装可能でコアに追加する理由がない(Schlüter 2015, Tekiela 2025)、(2) dd/dumpという名前はLaravel/Symfonyで広く使われており意図的な名前衝突になる(Vollebregt, Grekas 2025)、(3) ユーザーランド実装の方がイノベーションの自由度が高い(Grekas 2025)、(4) var_dumpに加えて5つ目のダンプ関数は冗長(Vollebregt 2025)。特にNicolas Grekas(Symfony VarDumperの作者)の反対は技術的に詳細で、拡張性(casters API)の喪失やパフォーマンス主張の無意味さを指摘している。プロトタイプのVerdictでは、これらの反対論点に対して技術的証拠で応答できるものとできないものを明確に区別する必要がある。
status: done
最小限のプロトタイプに必要な変更ファイル一覧:
ext/standard/basic_functions.stub.php—dd()のPHPスタブ定義を追加(シグネチャ:function dd(mixed $value, mixed ...$values): never {})。var_dump()定義の直後(3794行付近)に配置ext/standard/basic_functions_arginfo.h—build/gen_stub.phpで再生成。dd用のarginfo定義とZEND_FE(dd, ...)エントリが自動追加されるext/standard/var.c—PHP_FUNCTION(dd)の実装を追加。PHP_FUNCTION(var_dump)(242行)の直後に配置。内容はvar_dumpのコードをコピーし、末尾にzend_throw_unwind_exit()を追加するだけ
Per Researchの発見: 2025年のPre-RFCで議論されたのはリッチな出力を持つdd()だったが、本プロトタイプはvar_dumpとバイト同一の出力に限定する。Grekas(externals.io/message/127719)が指摘した「パフォーマンスの利点はない」という点については、プロトタイプはパフォーマンスを主張しないため直接の反論は不要。
| 次元 | プロトタイプの選択 | RFCで議論すべき選択肢 |
|---|---|---|
| 関数名 | dd |
debug_dump, dump_die, var_dump_exit, 名前空間付き\Debug\dd |
| 終了コード | 0(exit()デフォルトに合致) |
1(Laravel/Symfony互換)、設定可能 |
| 出力フォーマット | var_dump()とバイト同一 |
色付き出力、構造化出力、深さ制限、文字列切り詰め |
| INI設定 | なし | dd.depth_limit, dd.string_truncation, dd.colorize |
| SAPI動作 | 全SAPI統一(CLIと同じ出力) | HTTP 500レスポンスヘッダ、<pre>タグ自動付与 |
| 戻り値型 | never(プロセス停止するため) |
never一択(設計上変更の余地なし) |
dump()(exit無し版)同時追加 |
しない | RFCでdump()を同時提案するか議論 |
| 反対論点 | 発言者 | プロトタイプ証拠で対応可能か | 対応する証拠 |
|---|---|---|---|
| ユーザーランドで2行で実装可能、コア追加不要 | Schlüter (2015), Tekiela (2025) | no | これは「必要性」の哲学的議論であり、技術的証拠では覆せない。RFC本文で「利便性の正当化」を別途論じる必要がある |
dd名はLaravel/Symfonyと衝突する |
Vollebregt, Grekas (2025) | partially | プロトタイプで既存のfunction dd()定義時のfatal errorを確認できる(PHPの標準動作)。ただし衝突が「望ましくない」かは政治的判断 |
| ユーザーランドの方がイノベーション自由度が高い | Grekas (2025) | no | コアのdd()が素朴であることは設計判断。リッチなDumperを阻害しないことは論じられるが、プロトタイプでは証明不可 |
| 5つ目のダンプ関数は冗長 | Vollebregt (2025) | partially | dd()は既存ダンプ関数と異なりnever戻り値型でプロセスを停止する。機能的に新しい組み合わせであることをシグネチャで示せる |
コアの素朴なdd()は「劣化版」と見なされる |
(Context Con #2) | yes | プロトタイプがvar_dumpと同一出力であることを明示し、「最小限のコアプリミティブ」という位置づけを証拠で示す。フレームワークのリッチ版と競合する意図がないことを実装で裏付ける |
exit()含むデバッグ関数は本番に残りやすい |
(Context Con #4) | no | 静的解析ツールやCI linterの領域。プロトタイプで対応不可 |
ファイル: ext/standard/basic_functions.stub.php(3794行のvar_dump定義の後)
追加内容:
/** @return never */
function dd(mixed $value, mixed ...$values): never {}コマンド: php build/gen_stub.php ext/standard/basic_functions.stub.php
これによりext/standard/basic_functions_arginfo.hに以下が自動追加される:
arginfo_dd定義(IS_NEVER戻り値型付き)ZEND_FUNCTION(dd);宣言ZEND_FE(dd, arginfo_dd)エントリ
ファイル: ext/standard/var.c(255行、PHP_FUNCTION(var_dump)の}の直後)
実装内容:
PHP_FUNCTION(dd)
{
zval *args;
int argc;
int i;
ZEND_PARSE_PARAMETERS_START(1, -1)
Z_PARAM_VARIADIC('+', args, argc)
ZEND_PARSE_PARAMETERS_END();
for (i = 0; i < argc; i++) {
php_var_dump(&args[i], 1);
}
zend_throw_unwind_exit();
RETURN_THROWS();
}コマンド: make -j$(nproc) — 成功で完了
status: todo
(Survey & Plan完了後に記入)
status: todo
(Prototype完了後に記入)
- 2026-05-26 — idea-prototype — Contextフェーズ完了。仮説を再定義し、8つの必須セクションすべてを記入。
- 2026-05-26 — idea-prototype — Hypothesis & Metricフェーズ完了。DX型メトリクスを定義:動作の正確性(3つの.phptケース)、既存定義との共存、ビルド健全性。
- 2026-05-26 — research — Researchフェーズ完了。4ソース中3ソース実行。重要発見: 2015年と2025年に同じ提案がinternals@で議論され、いずれも強い反対で却下。Grekas(VarDumper作者)の詳細な技術的反対が最大の障壁。
- 2026-05-26 — idea-prototype — Survey & Planフェーズ完了。最小プロトタイプ: 3ファイル変更(stub, arginfo, var.c)。design-space 7次元、counter-position-binding 6反対論点をマッピング。