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.
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ớpProductđạ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$skucông khai kiểu chuỗi (string),$namecông khai kiểu chuỗi (string) và$quantityriêng tư kiểu số nguyên (int). Lớp của bạn cần có:- Một phương thức
getQuantity(): inttrả về số lượng hiện tại - Một phương thức
addStock(int $amount): voidtăng số lượng. Nếu số lượng thêm vào nhỏ hơn 1, hãy ném ngoại lệInvalidArgumentExceptionvới thông báo"Amount must be positive" - Một phương thức
removeStock(int $amount): voidgiảm số lượng. Nếu số lượng cần giảm nhỏ hơn 1, hãy ném ngoại lệInvalidArgumentExceptionvớ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ệRuntimeExceptionvới thông báo"Insufficient stock"
- Một phương thức
Inventory.php: Tạo lớpInventoryđể 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): voidthêm sản phẩm. Nếu đã có sản phẩm cùng SKU, hãy ném ngoại lệLogicExceptionvới thông báo"Product already exists: [sku]" - Một phương thức
getProduct(string $sku): Producttrả về sản phẩm theo SKU. Nếu không tìm thấy, hãy ném ngoại lệInvalidArgumentExceptionvớ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
Inventoryvà thêm mộtProductmới với SKU, tên đã cho và số lượng ban đầu là10.Dựa trên thao tác:
"add": GọiaddStock(5)trên sản phẩm, sau đó in ra"Stock updated: [quantity]""remove": GọiremoveStock(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àmget_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
}
?>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
1Nền tảng về OOP
Tệp bên ngoàiGiới thiệu về OOPLớp và đối tượngTừ khóa $thisPhương thứcThuộc tínhHàm khởi tạo (__construct)Hàm hủy (__destruct)Ôn tập: máy tính đơn giản4Kế thừa
Kế thừa cơ bảnTừ khóa parent::Ghi đè phương thứcTừ khóa finalLớp trừu tượngÔn tập: hệ thống phân cấp nhân viên7Đóng gói
Công khai, được bảo vệ, riêng tưTìm hiểu sâu về bộ điều chỉnh quyền truy cậpGetter và setterẨn thông tinRút gọn hàm khởi tạo (8.0)Ôn tập: hệ thống hồ sơ học sinh2Không gian tên và tự động nạp
Giới thiệu về không gian tênTừ khóa useChuẩn tự động nạp PSR-4Trình tự động nạp của ComposerÔn tập: dự án có tổ chức5Giao diện và hợp đồng
Giới thiệu về giao diệnTriển khai giao diệnTriển khai nhiều giao diệnGiao diện và lớp trừu tượngGợi ý kiểu với giao diệnÔn tập: Máy tính hình học8Phương thức ma thuật
Giới thiệu về phương thức ma thuật__toString và __debugInfo__get, __set, __isset, __unset__call và __callStatic__clone và sao chép đối tượng__serialize và __unserializeÔn tập: Bộ sưu tập tùy chỉnh11Hệ thống kiểu dữ liệu và xử lý lỗi
Khai báo kiểu dữ liệuKiểu dữ liệu có thể nhận giá trị nullKiểu hợp và kiểu giaoCác lớp ngoại lệHệ thống phân cấp ngoại lệ tùy chỉnhTry, Catch, FinallyÔn tập: Trình xác thực biểu mẫu3Thuộc tính của lớp
Thuộc tính instance và staticHằng số trong lớpPhương thức và thuộc tính staticThuộc tính private và protectedThuộc tính chỉ đọc (PHP 8.1)Ôn tập: Trình quản lý tài khoản ngân hàng6Đa hình
Xem lại việc ghi đè phương thứcĐa hình qua giao diệnGợi ý kiểu và kiểu hợpLiên kết tĩnh muộnÔn tập: bộ xử lý thanh toánTự luyện tập: Trình biên dịch PHP online