- カテゴリ: 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か$descriptionのThrowable - エンコーディング:関与なし
- 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=0 | assert.exception=1 にする。 |
assert('A > B') が動かない | 文字列式廃止(PHP 8) | ブール式または fn() => で書く。 |
| 本番で重い | zend.assertions=1 のまま | 本番は zend.assertions=-1(ゼロコスト)。 |

