Menu
CoddyTech

Các lớp ngoại lệ

Thuộc phần Lập trình hướng đối tượng trong hành trình PHP của Coddy. Bài học 66 trên 91.

Trong PHP, ngoại lệ là các đối tượng dùng để báo hiệu có lỗi xảy ra trong quá trình thực thi. Lớp cơ sở của mọi ngoại lệ là Exception, và hiểu cấu trúc của lớp này giúp bạn xử lý lỗi hiệu quả trong các ứng dụng lập trình hướng đối tượng.

Khi ném một ngoại lệ, bạn tạo một đối tượng của lớp Exception (hoặc lớp con) kèm theo thông báo mô tả sự cố:

<?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);

Đoạn code này sẽ tạo ra lỗi ngoại lệ chưa được bắt, kèm thông báo "Insufficient funds".

PHP cung cấp một số lớp ngoại lệ có sẵn cho các tình huống khác nhau. InvalidArgumentException báo hiệu đầu vào không hợp lệ, RuntimeException cho biết có lỗi trong quá trình thực thi, còn LogicException biểu thị lỗi lập trình:

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

Mỗi đối tượng ngoại lệ đều chứa thông tin hữu ích: getMessage() trả về thông báo lỗi, getCode() trả về mã lỗi không bắt buộc, getFile() và getLine() cho bạn biết ngoại lệ được ném ra ở đâu. Dùng các kiểu ngoại lệ cụ thể giúp ý định của đoạn code rõ ràng hơn và cho phép xử lý lỗi chính xác hơn.

challenge icon

Thử thách

Dễ

Hãy xây dựng một hệ thống quản lý hàng tồn kho sử dụng các lớp ngoại lệ có sẵn của PHP để báo hiệu những loại sự cố khác nhau. Bạn sẽ tạo một kho hàng, trong đó các thao tác có thể thất bại theo những cách cụ thể và có ý nghĩa.

Bạn sẽ sắp xếp code trong ba tệp:

  • Product.php: Tạo lớp Product đại diện cho một mặt hàng trong kho. Dùng cú pháp khai báo thuộc tính trong hàm khởi tạo để tạo $sku công khai kiểu chuỗi (string), $name công khai kiểu chuỗi (string) và $quantity riêng tư kiểu số nguyên (int). Lớp của bạn cần có:
    • Một phương thức getQuantity(): int trả về số lượng hiện tại
    • Một phương thức addStock(int $amount): void tăng số lượng. Nếu số lượng thêm vào nhỏ hơn 1, hãy ném ngoại lệ InvalidArgumentException với thông báo "Amount must be positive"
    • Một phương thức removeStock(int $amount): void giảm số lượng. Nếu số lượng cần giảm nhỏ hơn 1, hãy ném ngoại lệ InvalidArgumentException với thông báo "Amount must be positive". Nếu số lượng cần giảm vượt quá số lượng hiện tại, hãy ném ngoại lệ RuntimeException với thông báo "Insufficient stock"
  • Inventory.php: Tạo lớp Inventory để quản lý danh sách sản phẩm. Thêm tệp Product vào. Lớp của bạn cần có:
    • Một mảng riêng tư để lưu sản phẩm, được đánh chỉ số bằng SKU
    • Một phương thức addProduct(Product $product): void thêm sản phẩm. Nếu đã có sản phẩm cùng SKU, hãy ném ngoại lệ LogicException với thông báo "Product already exists: [sku]"
    • Một phương thức getProduct(string $sku): Product trả về sản phẩm theo SKU. Nếu không tìm thấy, hãy ném ngoại lệ InvalidArgumentException với thông báo "Product not found: [sku]"
  • main.php: Thêm tệp Inventory vào. Bạn sẽ nhận ba đầu vào: một SKU, tên sản phẩm và một thao tác ("add", "remove" hoặc "duplicate").

    Tạo một Inventory và thêm một Product mới với SKU, tên đã cho và số lượng ban đầu là 10.

    Dựa trên thao tác:

    • "add": Gọi addStock(5) trên sản phẩm, sau đó in ra "Stock updated: [quantity]"
    • "remove": Gọi removeStock(15) trên sản phẩm, thao tác này sẽ ném ngoại lệ
    • "duplicate": Thử thêm một sản phẩm khác có cùng SKU, thao tác này sẽ ném ngoại lệ

    Khi có ngoại lệ, hãy in tên lớp của ngoại lệ, theo sau là ": " và thông báo của ngoại lệ. Dùng hàm get_class() của PHP để lấy tên lớp.

Thử thách này cho thấy các loại ngoại lệ khác nhau truyền đạt những loại sự cố khác nhau như thế nào: đầu vào không hợp lệ, lỗi khi chạy và lỗi logic. Nhờ đó, code của bạn có thể xử lý lỗi chính xác và rõ ràng hơn.

Tự làm thử

<?php

require_once 'Inventory.php';

// Đọc dữ liệu đầu vào
$sku = trim(fgets(STDIN));
$name = trim(fgets(STDIN));
$operation = trim(fgets(STDIN));

try {
    // TODO: Tạo một Inventory
    // TODO: Tạo một Product với SKU, tên đã cho và số lượng ban đầu là 10
    // TODO: Thêm sản phẩm vào kho
    
    // TODO: Dựa vào thao tác:
    // - "add": Gọi addStock(5) trên sản phẩm, rồi in ra "Stock updated: [quantity]"
    // - "remove": Gọi removeStock(15) trên sản phẩm
    // - "duplicate": Thử thêm một sản phẩm khác có cùng SKU
    
} catch (Exception $e) {
    // TODO: In ra tên lớp ngoại lệ, tiếp theo là ": " và thông báo
    // Gợi ý: Dùng get_class($e) để lấy tên lớp
}

?>
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch PHP online