カスタム例外の作成
Exceptionクラスを拡張して、ドメイン固有のエラー型を作成します
「カスタム例外の作成」はCoddyKit上の無料PHP Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはPHP Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 PHP Academyコースには全4レッスンが含まれています。
カスタム例外を使う理由
カスタム例外を使うと、次のことができます。
- アプリケーションのエラーと一般的な PHP エラーを区別できます
- ドメイン固有のデータ(注文 ID、ユーザー ID など)を保持できます
- 異なる層で特定のエラータイプを捕捉できます
- 意味が明確で自己説明的なエラー階層を作成できます
Exception を拡張する
Exception 基底クラスを拡張して、カスタム例外を作成します。
<?php
class ValidationException extends \Exception
{
private array $errors;
public function __construct(array $errors, string $message = '', int $code = 0)
{
$this->errors = $errors;
parent::__construct($message ?: implode(', ', $errors), $code);
}
public function getErrors(): array
{
return $this->errors;
}
}カスタム例外を使用する
カスタム例外をスローして捕捉します。
<?php
function createUser(array $data): void {
$errors = [];
if (empty($data['email'])) $errors[] = 'Email required';
if (empty($data['name'])) $errors[] = 'Name required';
if ($errors) {
throw new ValidationException($errors);
}
// save user...
}
try {
createUser([]);
} catch (ValidationException $e) {
foreach ($e->getErrors() as $err) {
echo '- ' . $err . PHP_EOL;
}
}例外階層の設計
ドメインに合わせて階層を設計します。
<?php
// Base exception for your app
class AppException extends \RuntimeException {}
// Domain-specific exceptions
class NotFoundException extends AppException {}
class AuthException extends AppException {}
class PaymentException extends AppException {}
// Specific payment errors
class InsufficientFundsException extends PaymentException {
public function __construct(public readonly float $balance, public readonly float $required) {
parent::__construct("Insufficient funds: have $balance, need $required");
}
}階層による捕捉
基底クラスを捕捉して、派生したすべての例外を処理します。
<?php
try {
processPayment($order);
} catch (InsufficientFundsException $e) {
echo 'Low balance: need ' . $e->required;
} catch (PaymentException $e) {
echo 'Payment failed: ' . $e->getMessage();
} catch (AppException $e) {
echo 'App error: ' . $e->getMessage();
} catch (\Throwable $e) {
// Last resort
error_log($e);
}例外にコンテキストを追加する
デバッグ用の追加データを使って、例外の情報を充実させます。
<?php
class HttpException extends \RuntimeException
{
public function __construct(
private int $statusCode,
string $message = '',
?\Throwable $previous = null
) {
parent::__construct($message, $statusCode, $previous);
}
public function getStatusCode(): int
{
return $this->statusCode;
}
}HTTP 例外の例
Web アプリケーションで HTTP 例外を使用します。
<?php
try {
$user = findUserById($id);
if (!$user) throw new HttpException(404, 'User not found');
if (!$user->canAccess($resource)) {
throw new HttpException(403, 'Access denied');
}
} catch (HttpException $e) {
http_response_code($e->getStatusCode());
echo json_encode(['error' => $e->getMessage()]);
}インターフェースベースの例外
インターフェースを使って、関連のない例外クラスをグループ化します。
<?php
interface UserFacingException
{
public function getUserMessage(): string;
}
class ValidationException extends \Exception implements UserFacingException
{
public function getUserMessage(): string
{
return 'Please check your input: ' . $this->getMessage();
}
}
// In controller:
catch (UserFacingException $e) {
echo $e->getUserMessage();
}名前付きコンストラクタパターン
よくある例外の発生状況には、静的ファクトリメソッドを使用します。
<?php
class OrderException extends \RuntimeException
{
public static function notFound(int $id): self
{
return new self("Order #$id not found", 404);
}
public static function alreadyShipped(int $id): self
{
return new self("Order #$id already shipped", 409);
}
}
throw OrderException::notFound($orderId);例外をシリアライズする
ログ記録や API レスポンスのために、例外データを配列へ変換します。
<?php
function exceptionToArray(\Throwable $e): array {
return [
'type' => get_class($e),
'message' => $e->getMessage(),
'code' => $e->getCode(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'trace' => $e->getTraceAsString(),
'previous' => $e->getPrevious()
? exceptionToArray($e->getPrevious())
: null,
];
}カスタム例外のベストプラクティス
カスタム例外を設計する際のガイドライン:
- 予期しない状態には
RuntimeExceptionを拡張します - プログラマーのエラー(無効な引数など)には
LogicExceptionを拡張します - 考えられるメッセージごとに例外クラスを作成せず、代わりにコードを使用します
- 例外クラス名は PascalCase にし、末尾を Exception にします
- 各メソッドがスローする可能性のある例外を文書化します
理解度チェック
コード内の論理エラーを表すカスタム例外を作成するには、どの PHP 基底クラスを拡張すべきですか。
まとめ:カスタム例外
カスタム例外のまとめ:
Exceptionまたはそのサブクラスを拡張します- ドメイン固有のプロパティとメソッドを追加します
- 階層を設計し、親を捕捉してすべての子を捕捉します
- インターフェースを使って、関連のない例外をグループ化します
- 明確さを高めるため、静的な名前付きコンストラクタを使用します
- 必ず
parent::__construct()を呼び出します
よくある質問
「カスタム例外の作成」レッスンは無料ですか?
はい。「カスタム例外の作成」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、PHP Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 PHP Academyコースには全4レッスンが含まれています。
「カスタム例外の作成」で何を学びますか?
Exceptionクラスを拡張して、ドメイン固有のエラー型を作成します ブラウザで直接実行するハンズオンコードでPHP Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
PHP Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのPHP Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「カスタム例外の作成」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このPHP Academyレッスンでコードを書いて実行できますか?
はい。すべてのPHP Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。