PHP

PHP7調査(25)assert関数が実用的になった

More than 3 years have passed since last update.

PHP7から、assert関数が他の言語と同程度に実用的になりました。つまり、開発時だけアサーションのチェックを行い、商用環境ではコンパイル時に関数ごと除去するような運用ができるようになりました。

PHP5でもassert関数は存在していましたが、商用環境でも関数呼び出しのコストが発生したり、アサーションを文字列として定義する前提だったりと非常にイケていない仕組みだったせいか、誰も使わないような関数でした。

assert関数の利用例

assert関数には、絶対に正しいはずの評価式を書くような使い方をします。つまり、アサーションが失敗するとしたらバグがあるという状況です。別のサーバとの通信に失敗したような場合など、商用環境でも起こりうる実行時エラーに対してアサーションを使ってはいけません。

assert関数の利用例としては次のようなコードが考えられます。

<?php
class AcmeHttp
{
    const DATA = [
        "key" => "X-HTTP ",
        "value" => "testing"
    ];

    public function getData() {
        assert(preg_match('/^([a-zA-Z0-9-]+)$/', self::DATA["key"]));
        /* ... */
    }
}
(new AcmeHttp())->getData();

ここではクラス定数に対する制約をアサーションで確認しています。これは開発環境で一度確認できれば商用環境で毎回チェックする必要はありませんから、アサーションを使うのに適していると言えるでしょう。

assert関数についての設定

php.iniで設定できる値として、zend.assertionsassert.exceptionの2つが新設されています。

設定zend.assertionsはそれぞれ次のような意味になります。

  • 1 - assert()に対応するopcodeを生成し、assert()を評価 (開発モード)
  • 0 - assert()に対応するopcodeを生成するが、実行時にassert()部分をスキップする
  • -1 - assert()に対応するopcodeを生成しない (assertのコストゼロ, 商用環境モード)

また、assert.exceptionが非ゼロのとき、アサーション失敗時に例外AssertionErrorをスローするようになります。

感想など

RFCには、ライブラリ作者はアサーションをバリバリ使うといいよ!などと書いてあります。読みやすくてバグの少ないコードが書けるようになればいいですね。

参照