ob_start、register_shutdown_function あたり挙動がPHP4、PHP5で異なる。

rhacoのSnapshotのバグを調査してて、PHP4とPHP5での動きの違いがあったので、純粋なPHPのみで検証してみた。

結論その1

ob_startした後、Fatal error を意図的に発生させています。Fatal error が発生すると、shutdown関数がCallされて、その中でob_get_contents&ob_get_cleanしています。

  • PHP4
    • 'Fatal error: ...' は自動で表示される。
    • ob_get_contentsで''が返ってくる。
  • PHP5
    • 'Fatal error: ...' は表示されない。
    • ob_get_contentsで'Fatal error: ...'が返ってくる。

検証に使ったスクリプト

<?php

echo phpversion() . "<br/>\n";

function shutdown(){
	$buf = ob_get_contents();
	ob_get_clean();
	echo "<table border='1'><tr><td>\n";
	print_r($buf);
	echo "</td></tr></table>\n";
	echo "shutdown.<br/>\n";
	exit;
}
register_shutdown_function("shutdown");

ob_start();
echo "contents<br/>";
xxx();	// Fatal error
$buf = ob_get_contents();
ob_get_clean();
echo $buf;
echo "finish.<br/>";

?>

PHP4.4.7での実行結果


PHP5.2.2での実行結果


結論その2

さらに、PHP5の場合、shutdownの中で ob_get_cleanしたり、しなかったりで挙動が変わった。なんか不思議な動きなんだけど。

  • PHP4
    • Fatal発生→バッファを吐き出し→shutdown関数Call
  • PHP5
    • shutdown関数の中でob_get_cleanしている場合、Fatal発生→shutdown関数Call
    • shutdown関数の中でob_get_cleanしていない場合、Fatal発生→バッファ吐き出し→shutdown関数Call

ようは、PHP5でshutdown関数の中でog_get_cleanしてしまうと、Fatal error が表示されなくなってしまう。
こんな感じに見える。