0Pricing
PHP Academy · レッスン

カスタム例外の作成

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フィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. PHPのエラーの種類と報告
  2. Try、Catch、Finally
  3. カスタム例外の作成
  4. エラーのログ記録とベストプラクティス
← PHP Academyに戻る