PHP assertで想定条件を明記

コメントじゃなくassert()で想定条件を明記する

作成日:2019-10-31, 更新日:2019-10-31

基本

・目的は「想定条件を明記するため」。
→コメントでもいいのに・・・と思うけどそのコメントがデタラメって可能性を考えるとassertのほうが無難かな。

・本番環境では使わない。テスト環境、デバッグなどで使う
→本番環境では機能を無効にして処理をスキップさせる

・assertで条件が「false」のときにエラーを出力させたりする
→ユニットテストとかでも使える

サンプル

PHP5と7で微妙に異なるそうだ。
※「AssertionError」が7.2以上

PHP7.2未満

PHP7.2以上でも使えるが非推奨とかも含まれる内容

assert_options(ASSERT_ACTIVE,     1);                 // assert() による評価を有効にする(初期値:1)
assert_options(ASSERT_WARNING,    1);                 // assersion に失敗した場合に PHP 警告を発生する(初期値:1)
assert_options(ASSERT_BAIL,       1);                 // assersion に失敗した場合に実行を終了する(初期値:0)
assert_options(ASSERT_QUIET_EVAL, 1);                 // assersion 式については error_reporting を無効にする(初期値:0)
assert_options(ASSERT_CALLBACK, 'my_assert_handler'); // assertion に失敗した場合にコールされるコールバック(初期値:null)

// 「assert_options()」の「ASSERT_CALLBACK」で設定したコールバック関数
function my_assert_handler($file, $line, $code) {
  $err = 'Assertion Failed - '
       . 'File:' . $file . ', '
       . 'Line:' . $line . ', '
       . 'Code:' . $code . ', '
       . '';
  
  echo $err;
}

$a = 5;

// 条件が「false」のときにエラーを出力する
assert($a!=='');
assert($a<=0);

var_dump($a);

PHP7.2以上

PHP7.2未満でも途中まで使える。設定次第では使えるかも?(未調査)

// ▼PHP7.2以上:php.ini ディレクティブに記載 or 直接記述
ini_set('zend.assertions',  1);
// 1:アサーションのコードを生成して実行(開発モード)。
// 0:アサーションのコードは生成しますが実行時にはスキップ(実行しません)。
// -1:アサーションのコードを生成せず、アサーションのコストがゼロになる(実運用モード)。

ini_set('assert.exception', 1);
// 1: アサーションに失敗→exception で指定したオブジェクトをスロー or exception を指定していない場合は AssertionError オブジェクトをスロー。
// 0: 先述の Throwable を使ったり生成したりしますが、 そのオブジェクト上で警告を生成するだけであり、スローしません (PHP 5 と互換性のある挙動です)。
// ▲PHP7.2以上:php.ini ディレクティブに記載 or 直接記述

function my_assert_handler($e) {
  $objErr = array(
    'Message'       => $e->getMessage(),
    'Previous'      => $e->getPrevious(),
    'Code'          => $e->getCode(),
    'File'          => $e->getFile(),
    'Line'          => $e->getLine(),
    'Trace'         => $e->getTrace(),
    'TraceAsString' => $e->getTraceAsString(),
  );
  
  var_export($objErr);
}

$a = 5;

// 条件が「false」のときにエラーになる
try {
  assert($a!=='');
  assert($a<=0);
}
catch (AssertionError $e) {
  // 「assert.exception=1」で「AssertionError」が無ければ「Fatal error: Uncaught AssertionError」になる
  // 「assert.exception=0」ならPHP5とかで使ってた「ASSERT_WARNING」と同じ挙動になる
  my_assert_handler($e);
}
catch (Exception $e) {
  // ココには入ってこない。設定次第では入ってくるかも?(未調査)
  echo 'Exception:' . $e->getMessage();
}

var_dump($a);