assert — 実行時前提を検証するアサート関数

PHP
  • カテゴリ: PHP
  • 掲載バージョン: PHP 8.4
  • 名前空間 / FQCN / コマンド: assert(mixed $expression, ?Throwable|string $description = null): bool
  • 関連: AssertionError / trigger_error / LogicException / InvalidArgumentException / php.ini: zend.assertions, assert.exception
  • 変更履歴: PHP 7 で“ゼロコスト”アサーション導入、Throwable指定可。PHP 7.2 で文字列式(eval)非推奨、PHP 8.0 で削除。PHP 8.x は zend.assertions / assert.exception を使用。

要点(TL;DR)

  • 用途: 開発時の不変条件や前提をチェックし、破れたら即座に失敗させる。
  • 最小: assert($x > 0, 'x must be positive');
  • :
    • 本番で zend.assertions=1 のままだと性能劣化
    • 文字列式 assert('2 > 1') は PHP 8 で不可
    • 例外が出ないときは zend.assertions / assert.exception の設定を確認

概要

assert() は「ここでは必ず〜であるべき」という開発時の前提を検証します。失敗時は例外(既定:AssertionError)を投げ、早期にバグを発見できます。入力検証や業務エラー処理とは目的が異なり、**本番では無効化(ゼロコスト)**する前提で使います。

構文 / シグネチャ

assert(bool|callable $expression, ?Throwable|string $description = null): bool
  • 引数(表) 引数 型 必須 既定値 説明 $expression bool | callable ✓ — true で合格。callable なら実行結果で判定。 $description Throwable | string | null null 失敗時のメッセージ、または投げる例外オブジェクト
  • 戻り値true(合格/無効化時)。失敗時は通常例外が投げられ制御は戻らない。
  • 例外/副作用:失敗時に AssertionError もしくは $description に渡した Throwable を送出。zend.assertions=-1 ではアサートコード自体が生成されず副作用なし(ゼロコスト)。

主要 ini 設定(PHP 8.x)

; 開発(デフォルト例)
zend.assertions=1
assert.exception=1   ; 失敗で AssertionError

; 本番
zend.assertions=-1   ; アサートを完全除去(ゼロコスト)
assert.exception=1

使用例

最小例

<?php
declare(strict_types=1);

$qty = 10;
assert($qty > 0, 'Quantity must be positive');

実務例(ドメイン不変条件 + カスタム例外)

<?php
declare(strict_types=1);

use LogicException;

final class Order
{
    public function __construct(
        public readonly int $id,
        public int $totalCents,
    ) {
        // 生成直後の整合性を保証(開発時のみ実行)
        assert($this->totalCents >= 0, new LogicException('Order total cannot be negative'));
    }

    public function applyDiscount(int $cents): void
    {
        $this->totalCents -= $cents;

        // 不変条件維持
        assert($this->totalCents >= 0, new LogicException('Discount made total negative'));
    }
}

よくある落とし穴・注意

  • 本番で有効のままzend.assertions=1 は常に評価されオーバーヘッド。必ず -1
  • 文字列式は不可assert('2 > 1') は PHP 8 で廃止。必ず ブール式または fn() => ... を渡す。
  • 例外が出ないassert.exception=0 だと例外ではなく警告扱い(運用非推奨)。
  • 用途の勘違い:ユーザー入力の検証や業務エラーは 例外/バリデーション を使う。assert() は開発時の契約・不変条件向け。

PHPカテゴリの補足

  • 必要拡張:なし(標準)
  • エラー形態:合格→継続、失敗→AssertionError$descriptionThrowable
  • エンコーディング:関与なし
  • 8.1/8.2/8.3/8.4 差分:挙動は安定。旧 ini(assert.active など)は PHP 8 で廃止済み。

代替・関連APIとの比較

  • 例外(LogicException / InvalidArgumentException:業務ルール/入力検証の失敗に使用。本番でも必ず実行
  • trigger_error():実行継続しつつ通知したいとき。契約破りの検出には不向き。
  • 静的解析・型:実行前に欠陥を減らす。assert() は実行時チェックで補完。

テスト例(Pest)

<?php

use AssertionError;

it('throws on failed assertion', function () {
    assert(1 === 2, 'should fail');
})->throws(AssertionError::class);

it('can throw custom exception', function () {
    assert(false, new LogicException('broken invariant'));
})->throws(LogicException::class);

トラブルシュート(エラー別)

症状/エラー原因対処
失敗しても何も起きないzend.assertions=-1 または =0開発時は =1 に。動作確認後は本番で =-1
例外が出ず警告だけassert.exception=0assert.exception=1 にする。
assert('A > B') が動かない文字列式廃止(PHP 8)ブール式または fn() => で書く。
本番で重いzend.assertions=1 のまま本番は zend.assertions=-1(ゼロコスト)。

参考リンク

長野県・北アルプス地方在住のフリーランスWebプログラマー。
「落ち着くためのWeb開発」をテーマに、訪れる人が安心して使えるサービスづくりを心がけています。

LaravelやWordPressなどのWebアプリケーション開発を得意とし、技術面の安定性はもちろん、運用後も長く活用できる設計を大切にしています。
静かな山間の暮らしから生まれる視点で、シンプルかつ本質的な解決策をご提案します。

野鳥観察も趣味のひとつで、特にミソサザイ(Wren)に魅力を感じています。
小さな体に反して力強く上向きの尾羽、そして澄んだ鳴き声が遠くまで響く姿に、静かな存在感と芯の強さを感じます。
このサイト名「Laravel Wren」には、そんなミソサザイのように、小さくても確かな価値を届けたいという想いを込めています。

信頼できるパートナーとして、そして気軽に相談できる存在として、あなたのWebプロジェクトをサポートします。

Yudai Tsuyuzakiをフォローする