Menu
CoddyTech

Kiểu liệt kê (PHP 8.1)

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 59 trên 91.

Trước PHP 8.1, để biểu diễn một tập hợp giá trị cố định như trạng thái hoặc loại, bạn phải dùng hằng số của lớp hoặc chuỗi ma thuật, cả hai cách đều dễ gây lỗi. Enum (kiểu liệt kê) cung cấp một cách phù hợp để định nghĩa kiểu dữ liệu chỉ có thể chứa các giá trị cụ thể đã xác định trước.

Định nghĩa một enum bằng từ khóa enum:

<?php
enum Status {
    case Pending;
    case Active;
    case Completed;
}

$status = Status::Active;
echo $status->name;

Đầu ra:

Active

Enum cũng có thể có giá trị nền, tức là giá trị chuỗi hoặc số nguyên gắn với từng trường hợp. Điều này hữu ích khi lưu enum trong cơ sở dữ liệu hoặc API:

<?php
enum Status: string {
    case Pending = 'pending';
    case Active = 'active';
    case Completed = 'completed';
}

$status = Status::Active;
echo $status->value;

Đầu ra:

active

Enum có giá trị nền hỗ trợ phương thức from() để tạo enum từ giá trị của nó, và tryFrom() trả về null thay vì ném lỗi khi gặp giá trị không hợp lệ:

<?php
$status = Status::from('active');      // Trả về Status::Active
$invalid = Status::tryFrom('unknown'); // Trả về null

Enum cũng có thể chứa phương thức, giúp chúng hữu ích trong việc đóng gói logic liên quan. Chúng hoạt động liền mạch với gợi ý kiểu dữ liệu, đảm bảo các hàm của bạn chỉ nhận giá trị hợp lệ, không cần kiểm tra xem một chuỗi có khớp với các lựa chọn mong đợi hay không.

challenge icon

Thử thách

Dễ

Hãy xây dựng một hệ thống quản lý đơn hàng sử dụng enum để biểu diễn trạng thái đơn hàng một cách an toàn về kiểu dữ liệu. Thay vì dựa vào các chuỗi có thể bị viết sai hoặc không hợp lệ, bạn sẽ tạo một enum có giá trị nền ánh xạ mỗi trạng thái sang một giá trị phù hợp với cơ sở dữ liệu.

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

  • OrderStatus.php: Tạo một enum có giá trị nền kiểu chuỗi tên là OrderStatus, gồm bốn trường hợp:
    • Pending có giá trị nền là 'pending'
    • Processing có giá trị nền là 'processing'
    • Shipped có giá trị nền là 'shipped'
    • Delivered có giá trị nền là 'delivered'
    Thêm phương thức label() trả về phần mô tả dễ hiểu cho từng trạng thái:
    • Pending trả về "Awaiting confirmation"
    • Processing trả về "Being prepared"
    • Shipped trả về "On the way"
    • Delivered trả về "Order complete"
  • Order.php: Tạo lớp Order sử dụng enum. Nạp tệp OrderStatus. Lớp này cần:
    • Nhận mã đơn hàng (chuỗi) và một OrderStatus trong hàm khởi tạo bằng cách dùng tính năng thăng cấp hàm khởi tạo
    • Có phương thức getInfo() trả về "Order [id]: [status label]"
    • Có phương thức getStatusValue() trả về giá trị nền của trạng thái, hữu ích khi lưu trữ trong cơ sở dữ liệu
  • main.php: Nạp tệp Order. Bạn sẽ nhận hai đầu vào: mã đơn hàng và một chuỗi trạng thái, chẳng hạn "shipped". Dùng tryFrom() để chuyển chuỗi đầu vào thành enum OrderStatus một cách an toàn. Nếu trạng thái hợp lệ, hãy tạo một Order và in ra hai dòng:
    • Kết quả của getInfo()
    • Kết quả của getStatusValue()
    Nếu chuỗi trạng thái không hợp lệ, hãy in "Invalid status".

Thử thách này minh họa cách enum giúp đảm bảo an toàn về kiểu dữ liệu. Lớp Order chỉ có thể nhận các trạng thái hợp lệ, còn phương thức tryFrom() giúp bạn xử lý đầu vào của người dùng an toàn mà không có nguy cơ nhận giá trị không hợp lệ.

Tự làm thử

<?php

require_once 'Order.php';

// Đọc đầu vào
$orderId = trim(fgets(STDIN));
$statusString = trim(fgets(STDIN));

// TODO: Dùng OrderStatus::tryFrom() để chuyển chuỗi trạng thái thành enum một cách an toàn
// tryFrom() trả về null nếu giá trị không hợp lệ

// TODO: Nếu trạng thái hợp lệ, tạo một Order và in ra:
// - Kết quả của getInfo()
// - Kết quả của getStatusValue()

// TODO: Nếu trạng thái không hợp lệ, in ra "Invalid status"

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