例外

Nette Database は例外の階層を使います。基底クラスは Nette\Database\DriverException で、PDOException を継承し、データベースのエラーを扱うための機能を強化します。

  • getDriverCode() メソッドはデータベースドライバのエラーコードを返します。
  • getSqlState() メソッドは SQLSTATE のコードを返します。
  • getQueryString()getParameters() メソッドで、もとのクエリとそのパラメータを取り出せます。

DriverException クラスは、次の特化した例外に継承されます。

  • ConnectionException – データベースサーバーへの接続に失敗したことを示します。
    • ConnectionLostException .{data-version:3.2.9} – 処理の途中で接続が切れました(サーバーの再起動、ネットワークの障害、idle timeout)。続けて使う前に接続し直す必要があります。
  • ConstraintViolationException – データベースの制約違反の基底クラスで、次の例外がこれを継承します。
    • ForeignKeyConstraintViolationException – 外部キー制約の違反。
    • NotNullConstraintViolationException – NOT NULL 制約の違反。
    • UniqueConstraintViolationException – 一意性の制約の違反。
    • CheckConstraintViolationException .{data-version:3.2.9} – CHECK 制約の違反。
  • DeadlockException .{data-version:3.2.9} – サーバーが検出した deadlock または直列化の衝突。トランザクションはロールバックされ、やり直せます。
  • LockTimeoutException .{data-version:3.2.9} – ロック待ちの制限時間を超えました。その文は中止されましたが、それを囲むトランザクションはふつう開いたままです。

次の例は UniqueConstraintViolationException の捕まえ方を示します。これはデータベースにすでにあるメールアドレスでユーザーを挿入しようとしたときに起きます(email 列に一意インデックスがあるものとします)。

try {
	$database->query('INSERT INTO users', [
		'email' => 'john@example.com',
		'name' => 'John Doe',
		'password' => $hashedPassword,
	]);
} catch (Nette\Database\UniqueConstraintViolationException $e) {
	echo 'このメールアドレスのユーザーはすでに存在します。';

} catch (Nette\Database\DriverException $e) {
	echo '登録の途中でエラーが起きました: ' . $e->getMessage();
}