Menu
Coddy logo textTech

例外クラス

CoddyのPHPジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 66/91。

PHPにおいて、例外は実行中に何らかの問題が発生したことを知らせるために使用されるオブジェクトです。すべての例外の基底クラスは Exception であり、その構造を理解することは、OOPアプリケーションでエラーを効果的に処理するのに役立ちます。

例外をスローするとき、何が問題だったかを説明するメッセージを添えて、Exceptionクラス(またはそのサブクラス)のインスタンスを作成します:

<?php
class BankAccount {
    public function __construct(private float $balance = 0) {}
    
    public function withdraw(float $amount): float {
        if ($amount > $this->balance) {
            throw new Exception("Insufficient funds");
        }
        $this->balance -= $amount;
        return $amount;
    }
}

$account = new BankAccount(100);
$account->withdraw(150);

これにより、"Insufficient funds" というメッセージとともに、キャッチされなかった例外エラーが発生します。

PHPは、さまざまな状況に対応するために、いくつかの組み込み例外クラスを提供しています。InvalidArgumentExceptionは不正な入力を示し、RuntimeExceptionは実行中のエラーを示し、LogicExceptionはプログラムの論理的なエラーを表します。

<?php
class Calculator {
    public function divide(int $a, int $b): float {
        if ($b === 0) {
            throw new InvalidArgumentException("Cannot divide by zero");
        }
        return $a / $b;
    }
}

すべての例外オブジェクトは有用な情報を保持しています。getMessage() はエラーメッセージを返し、getCode() はオプションのエラーコードを返し、getFile()getLine() は例外がスローされた場所を特定します。特定の例外タイプを使用することで、コードの意図がより明確になり、より正確なエラーハンドリングが可能になります。

challenge icon

チャレンジ

簡単

PHPの組み込み例外クラスを使用して、さまざまな種類の問題を通知する在庫管理システムを構築しましょう。操作が特定の意味のある方法で失敗する可能性がある製品在庫を作成します。

コードは3つのファイルに分けて構成します:

  • Product.php — 在庫内のアイテムを表す Product クラスを作成します。コンストラクタのプロパティ昇格(constructor promotion)を使用して、パブリックな $sku (string)、パブリックな $name (string)、およびプライベートな $quantity (int) を定義します。クラスには以下のものを含める必要があります:
    • 現在の数量を返す getQuantity(): int メソッド
    • 数量を増やす addStock(int $amount): void メソッド。金額が1未満の場合は、メッセージ "Amount must be positive" を持つ InvalidArgumentException をスローします。
    • 数量を減らす removeStock(int $amount): void メソッド。金額が1未満の場合は、メッセージ "Amount must be positive" を持つ InvalidArgumentException をスローします。金額が現在の数量を超える場合は、メッセージ "Insufficient stock" を持つ RuntimeException をスローします。
  • Inventory.php — 製品のコレクションを管理する Inventory クラスを作成します。Productファイルを含めてください。クラスには以下のものを含める必要があります:
    • SKUをキーとして製品を保存するプライベートな配列
    • 製品を追加する addProduct(Product $product): void メソッド。同じSKUの製品が既に存在する場合は、メッセージ "Product already exists: [sku]" を持つ LogicException をスローします。
    • SKUによって製品を返す getProduct(string $sku): Product メソッド。見つからない場合は、メッセージ "Product not found: [sku]" を持つ InvalidArgumentException をスローします。
  • main.php — Inventoryファイルを含めます。SKU、製品名、および操作("add""remove"、または "duplicate")の3つの入力を受け取ります。

    Inventory を作成し、指定されたSKU、名前、および初期数量 10 を持つ新しい Product を追加します。

    操作に基づいて以下を実行します:

    • "add": 製品に対して addStock(5) を呼び出し、次に "Stock updated: [quantity]" を出力します。
    • "remove": 製品に対して removeStock(15) を呼び出します(これは例外をスローするはずです)。
    • "duplicate": 同じSKUを持つ別の製品を追加しようとします(これは例外をスローするはずです)。

    例外がスローされた場合は、例外のクラス名に続けて ": " と例外のメッセージを出力します。クラス名を取得するにはPHPの get_class() 関数を使用してください。

このチャレンジでは、さまざまな例外タイプが、無効な入力、実行時の失敗、ロジックエラーなど、さまざまな種類の問題をどのように伝えるかを示し、コードのエラー処理をより正確で意味のあるものにする方法を学びます。

チートシート

PHPにおいて、例外は実行中のエラーを通知するオブジェクトです。基底クラスは Exception です。

例外をスローするには、説明的なメッセージを含むインスタンスを作成します:

<?php
class BankAccount {
    public function __construct(private float $balance = 0) {}
    
    public function withdraw(float $amount): float {
        if ($amount > $this->balance) {
            throw new Exception("Insufficient funds");
        }
        $this->balance -= $amount;
        return $amount;
    }
}

PHPは、さまざまな状況に対応する組み込みの例外クラスを提供しています:

  • InvalidArgumentException — 不適切な入力を通知します
  • RuntimeException — 実行中のエラーを示します
  • LogicException — プログラミング上のエラーを表します
<?php
class Calculator {
    public function divide(int $a, int $b): float {
        if ($b === 0) {
            throw new InvalidArgumentException("Cannot divide by zero");
        }
        return $a / $b;
    }
}

例外オブジェクトは便利なメソッドを提供します:

  • getMessage() — エラーメッセージを返します
  • getCode() — オプションのエラーコードを返します
  • getFile() — 例外がスローされたファイルを返します
  • getLine() — 例外がスローされた行番号を返します

例外オブジェクトのクラス名を取得するには、get_class() を使用します。

自分で試してみよう

<?php

require_once 'Inventory.php';

// 入力を読み込む
$sku = trim(fgets(STDIN));
$name = trim(fgets(STDIN));
$operation = trim(fgets(STDIN));

try {
    // TODO: Inventoryを作成する
    // TODO: 指定されたSKU、名前、初期数量10でProductを作成する
    // TODO: 商品を在庫(inventory)に追加する
    
    // TODO: 操作(operation)に基づいて以下を行う:
    // - "add": 商品のaddStock(5)を呼び出し、"Stock updated: [quantity]"を表示する
    // - "remove": 商品のremoveStock(15)を呼び出す
    // - "duplicate": 同じSKUを持つ別の商品を追加しようとする
    
} catch (Exception $e) {
    // TODO: 例外クラス名に続いて": "とメッセージを表示する
    // ヒント: クラス名を取得するにはget_class($e)を使用する
}

?>
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン