thecodingmachine/safe: All PHP functions, rewritten to throw exceptions instead of returning false
thecodingmachine/safe8: All PHP functions, rewritten to throw exceptions instead of returning false, now for php8
PHP の関数には処理に失敗した場合、後の処理が致命的に破綻しそうな関数であっても単に false や PHP 内部にエラーをため込むのみの関数がしばしばあります。例えば substr 関数は正常に動作すると文字列を返しますが文字列長より長いオフセットを指定した場合、返り値が false になります。
PHP: substr – Manual
<?php var_dump(substr('a', 2)); // bool(false)
PHP のプログラム内で不意に false が動き回っても、文字列として扱う際は空文字列になるので問題になることは少ないです(結果的に想定通りに動くだけなので問題になることももちろんあります)。
まずいの想定通りに動きもせず、どこで壊れたのかわかりにくいパターンです。例えば次です。
<?php $sub = array_replace([2, 1], ''); // null $ret = sort($sub); // false var_dump($ret);// bool(false)
array_replace の返り値は処理に成功した場合は配列が、失敗した場合は null が返ってきます。また null を配列に変換する処理は PHP に組み込まれていないため array_replace の後に配列の処理を加えていくといずれも処理に失敗していきます。表示する PHP のエラーレベルを WARNING 以上としていたならば WARNING エラーを追うことで処理失敗箇所を追えますが、プログラム外のデータを書き換えたりする処理の存在の可能性や読みやすいエラーメッセージのためには、処理失敗時にエラーを通知して例外を投げ、例外がキャッチされなければ PHP プロセスを異常終了させることが望ましいです。
次リンクの Safe PHP は安全に PHP を動かすための定型的な処理、特にエラーの例外化をまとめたライブラリです。
thecodingmachine/safe: All PHP functions, rewritten to throw exceptions instead of returning false
thecodingmachine/safe8: All PHP functions, rewritten to throw exceptions instead of returning false, now for php8
Safe PHP 例えば次のコードが含まれています。
function json_encode($value, int $flags = 0, int $depth = 512): string { error_clear_last(); $result = \json_encode($value, $flags, $depth); if ($result === false) { throw JsonException::createFromPhpError(); } return $result; }
json_encode は JSON に変換できないものを渡された場合、デフォルトでは false を返します(PHP 7.3以降では JSON_THROW_ON_ERROR フラグを立てることで JsonException を投げるようになります)。
PHP: json_encode – Manual
Safe PHP はこのようなエラー制御をまとめています。Safe PHP中で定義された関数を PHP 組み込みの同名関数の代わりに用いることでエラーに気づきやすくなり、また例外の種類によって何が原因かわかりやすくなります。Safe PHPが特に役に立つのは何らかの事情で set_error_handler 関数が使えない時です。
PHP: set_error_handler – Manual
set_error_handler 関数は PHP 内でエラーが発生した時の処理を記述する関数で PHP のフレームワークのエラーハンドリングではしばしばこれが使われています。もし set_error_handler 関数を使えるならば次のスニペットを PHP プログラムの入り口に置くことでより手軽にエラーに気づけます。
set_error_handler(static function(...$error){ var_dump($error);// error 時の中身をすべて $error 変数に格納して表示 exit(1);// エラー発生コード(0以外)で終了 });