Hướng dẫn dùng enumeration trong PHP

PHP 8.1 cuối cùng sẽ bổ sung hỗ trợ ngôn ngữ cho các phép liệt kê. Enumerations, viết tắt của enumerations, là những kiểu chỉ có thể được khởi tạo với các giá trị cụ thể. Chúng thường được tìm thấy trong các ngôn ngữ hướng đối tượng khác, nhưng trước đây chúng yêu cầu người dùng thực hiện các giải pháp thay thế trong PHP.

  • Cú pháp cơ bản
  • Phép liệt kê thuần túy hoặc duy trì
  • Thêm phương thức vào bảng liệt kê
  • Hằng số
  • Khi nào sử dụng phép liệt kê?
  • Kết luận

Cú pháp cơ bản

Đây là kiểu liệt kê đơn giản:

enum PostStatus {
    trường hợp Được phát hành;
    trường hợp InReview;
    trường hợp Bản nháp;
}

Les case từ khóa, trước đây là một phần của switch hướng dẫn, được sử dụng để phân định các giá trị cụ thể mà kiểu liệt kê chấp nhận. Giá trị được tham chiếu theo cách giống như hằng số lớp:

$ đã xuất bản = Trạng thái bài đăng::Được phát hành;

Các phép liệt kê hoạt động giống như các lớp và giao diện. Chúng hoàn toàn tương thích với hệ thống kiểu, vì vậy bạn có thể chỉ ra rằng một hàm chỉ chấp nhận một giá trị được xác định trong một kiểu liệt kê:

tốt nghiệp lớp XNUMX Bài viết trên blog {
 
    công khai chức năng __xây dựng(
        công khai chuỗi $ Headline,
        công khai chuỗi $ Nội dung,
        công khai Trạng thái bài đăng Trạng thái $=Trạng thái bài đăng::Bản nháp) {}
 
}

Đây là một ví dụ về việc sử dụng BlogPost để phân loại:

// VÂNG
$ bài = mới Bài viết trên blog(
    "Bài đăng mẫu",
    "Một ví dụ",
    Trạng thái bài đăng::Bản nháp
);
 
// TypeError: Đối số # 3 ($ Status) phải thuộc loại PostStatus
$ bài = mới Bài viết trên blog(
    "Ví dụ bị hỏng",
    "Một ví dụ hỏng",
    "Đã gửi"
);

Phiên bản đầu tiên hoạt động vì $Status là một giá trị hợp lệ của PostStatus enum. Trong trường hợp thứ hai, một chuỗi đơn giản được chuyển dưới dạng $Status, điều này bị cấm vì giá trị phải được xác định trong PostStatus.

Các trường hợp liệt kê được biểu diễn dưới dạng hằng số trên đối tượng enum. Điều này có nghĩa là bạn có thể sử dụng chúng dưới dạng giá trị tĩnh và như một phần của biểu thức hằng số. Các BlogPost hàm tạo hiển thị một trường hợp liệt kê được sử dụng làm giá trị tham số mặc định, trong đó $Status được tự động đặt thành Nháp khi không có giá trị nào được cung cấp bởi người gọi.

Bạn có thể truy cập tất cả các giá trị có sẵn trong một bảng liệt kê bằng cách sử dụng cases phương pháp:

Trạng thái bài đăng::trường hợp();
// [PostStatus :: Published, PostStatus :: InReview, PostStatus :: Draft]

Phép liệt kê thuần túy hoặc duy trì

Les PostStatus enum ở trên là một pur enum. Nó chỉ chứa case khai báo, không có dữ liệu bổ sung. PHP cũng cho phép bạn đính kèm một giá trị vào các trường hợp enum, tạo ra một được hỗ trợ enum.

enum PostStatus : chuỗi {
    trường hợp Được phát hành = "S1";
    trường hợp InReview = "S2";
    trường hợp Bản nháp = "S3";
}

Đây PostStatus enum đã được sửa đổi để tạo một enum đã lưu. Kiểu chữ trong định nghĩa liệt kê nói rằng mỗi trường hợp có một giá trị chuỗi được gán cho nó. Trong ví dụ này, chúng tôi giả định rằng mỗi trạng thái bài đăng được đặt tên có một số nhận dạng ngắn được liên kết. Mã định danh này có thể được lưu trong cơ sở dữ liệu khi các bài đăng liên tục.

Bạn có thể truy cập các giá trị đã lưu thông qua value tài sản trên các trường hợp trường hợp:

tốt nghiệp lớp XNUMX BlogPostRepository {
 
    công khai chức năng tiết kiệm(Bài viết trên blog $ Đăng) : làm mất hiệu lực {
        $ cái này -> chèn(
            "bài đăng trên blog",
            [
                "tiêu đề" => $ Đăng -> Headline,
                "sung sướng" => $ Đăng -> Nội dung,
                "trạng thái" => $ Đăng -> Trạng thái -> giá trị
            ]
        );
    }
 
}
 
$ bài = mới Bài viết trên blog("Thí dụ", "Bản giới thiệu", Trạng thái bài đăng::Được phát hành);
(mới BlogPostRepository()) -> tiết kiệm($ bài);

Ví dụ này sẽ đặt giá trị bền vững status lĩnh vực để S1, dựa trên phiên bản đã lưu của PostStatus enum hiển thị ở trên.

Bảng kê được hỗ trợ seul chấp nhận chuỗi và số nguyên làm giá trị. Không thể sử dụng loại liên hợp string|int Đó là. Ngoài ra, mỗi trường hợp cần một giá trị duy nhất - ví dụ sau không được phép:

enum PostStatus : chuỗi {
 
    trường hợp Được phát hành = "S1";
    trường hợp Bản nháp = "S1";
 
}

PHP cung cấp một phương thức tiện ích về kiểu liệt kê để tạo một thể hiện từ một giá trị đã lưu:

// tìm nạp bài đăng trên blog trước đó từ cơ sở dữ liệu
// trường "trạng thái" = S1
$ trạng thái = Trạng thái bài đăng::từ($ kỷ lục["trạng thái"]);

Les from() Phương thức này sẽ hydrat hóa các thể hiện từ các trường hợp giá trị. Trong ví dụ này, S1 được ánh xạ tới Published trường hợp và mã của bạn nhận được một phiên bản của PostStatus::Published.

from() ném một ValueError nếu giá trị đầu vào không hợp lệ; trong các tình huống mà bạn biết giá trị có thể không sử dụng được, lựa chọn thay thế tryFrom() phương pháp có thể được sử dụng thay thế. Điều này trở lại null khi không có trận đấu, thay vì ném lỗi.

Thêm phương thức vào bảng liệt kê

Vì các phép liệt kê dựa trên các lớp, bạn cũng có thể thêm các phương thức cho chúng!

enum PostStatus {
 
    trường hợp Được phát hành;
    trường hợp Bản nháp;
 
    công khai chức năng isPubliclyAccessible() : bool {
        trở lại ($ cái này ví dụ tự::Được phát hành);
    }
 
}

Điều này cho phép bạn duy trì hành vi theo từng trường hợp cụ thể trong bảng liệt kê của mình, thay vì sao chép nó trong cơ sở mã của bạn.

Các phép liệt kê cũng có thể triển khai các giao diện:

enum PostStatus thực hiện PublicAccessGatable {
 
    trường hợp Được phát hành;
    trường hợp Bản nháp;
 
    công khai chức năng isPubliclyAccessible() : bool {
        trở lại ($ cái này ví dụ tự::Được phát hành);
    }
 
}

Bây giờ bạn có thể chi tiêu PostStatus ví dụ cho tất cả những người chấp nhận một PublicAccessGatable:

tốt nghiệp lớp XNUMX UserAuthenticator {
 
    chức năng shouldAllowAccess(PublicAccessGatable $ Tài nguyên) : bool {
        trở lại ($ cái này -> người sử dang -> isAdmin() || $ Tài nguyên -> isPubliclyAccessible());
    }
 
}
 
$ auth = mới UserAuthenticator();
 
// lấy một bài blog từ cơ sở dữ liệu
if (!$ auth -> shouldAllowAccess($ bài -> Trạng thái)) {
    http_response_code(403);
}

Không có giới hạn nào về những gì bạn có thể làm với các phương thức enum - xét cho cùng thì chúng cũng là các phương thức PHP bình thường - nhưng nói chung, bạn sẽ mong đợi chúng thực hiện một số loại so sánh với trường hợp của ví dụ l., Sau đó trả về một giá trị tĩnh. Các phép liệt kê có thể sử dụng các nét vẽ, vì vậy bạn có thể trích xuất các phương thức hiện có mà bạn cũng đã tóm tắt theo cách này.

Bạn có thể sử dụng public, protected et private các phương pháp trong phép liệt kê, mặc dù protected et private có tác dụng tương tự. Các bảng kê không thể mở rộng như vậy private là dư thừa một cách hiệu quả. Bạn cũng không thể thêm một hàm tạo hoặc hàm hủy. Các phương thức tĩnh được hỗ trợ và có thể được gọi trên lớp enum hoặc các thể hiện trường hợp của nó.

Các phép liệt kê cũng có thể có các hằng số của riêng chúng, dưới dạng các giá trị chữ thông thường hoặc là một tham chiếu đến một trường hợp liệt kê:

enum PostStatus {
 
    trường hợp Được phát hành;
    trường hợp Bản nháp;
 
    công khai const Trực tiếp = tự::Được phát hành;
    công khai const PlainConstant = "foobar";
 
}

Điều này có thể tạo ra sự nhầm lẫn vì cùng một cú pháp được sử dụng để truy cập các trường hợp (trường hợp liệt kê) và các hằng số:

$ đã xuất bản = Trạng thái bài đăng::Được phát hành;
$ đồng bằng = Trạng thái bài đăng::PlainConstant;

Seoul $published sẽ đáp ứng một PostStatus đánh máy, như $plain đề cập đến một giá trị vô hướng đơn giản.

Khi nào sử dụng phép liệt kê?

Phép liệt kê dành cho những trường hợp bạn cần sự linh hoạt trong giá trị mà một biến có thể nhận, nhưng chỉ trong một tập hợp các trường hợp có thể được xác định trước.

Lớp bài đăng trên blog được giới thiệu trong bài viết này là một ví dụ điển hình. Thông báo chỉ có thể ở một trong các bộ trạng thái đã biết, nhưng PHP trước đây không có cách nào dễ dàng để đạt được điều này.

Trong các phiên bản cũ hơn, bạn có thể đã sử dụng phương pháp này:

tốt nghiệp lớp XNUMX Trạng thái bài đăng {
    const Được phát hành = 0;
    const Bản nháp = 1;
}
 
tốt nghiệp lớp XNUMX Bài viết trên blog {
    công khai chức năng __xây dựng(
        công khai chuỗi $ Headline,
        công khai int Trạng thái $
    ) {}
}
 
$ bài = mới Bài viết trên blog("Tiêu đề của tôi", Trạng thái bài đăng::Được phát hành);

Vấn đề ở đây là $Status thực sự chấp nhận bất kỳ số nguyên nào, vì vậy lệnh gọi sau sẽ hoàn toàn hợp lệ:

$ bài = mới Bài viết trên blog("Tiêu đề của tôi", 9000);

Hơn nữa, BlogPost et PostStatus hoàn toàn tách biệt - không có chuyện ai đó đang đọc BlogPost có thể tìm hiểu phạm vi giá trị $Status thực sự Đã được chấp nhận. Mặc dù những vấn đề này có thể được giảm thiểu bằng cách sử dụng các thủ thuật tương tự như docblock thích hợp hoặc các gói "không có thật" của bên thứ ba, tất cả chúng đều thêm các lớp bổ sung xung quanh một khái niệm mà các ngôn ngữ lập trình khác đơn giản hóa.

Thêm các kiểu liệt kê bản địa vào PHP là một bước để hoàn thiện hệ thống kiểu của ngôn ngữ. Cuối cùng, bạn có thể nhập các giá trị được phép để mọi người có cùng bước sóng. Nếu bạn chuyển một giá trị không hợp lệ, bạn sẽ gặp lỗi thời gian chạy. IDE của bạn có thể giúp bạn cung cấp các giá trị chính xác tốt hơn vì IDE sẽ biết rằng $Status chỉ chấp nhận ba tùy chọn, thay vì "bất kỳ số nguyên nào".

Kết luận

Các phép liệt kê giải quyết một số vấn đề phổ biến cho các nhà phát triển khi làm việc trong PHP. Chúng được sử dụng để chỉ ra rằng các tham số, giá trị trả về và thuộc tính phải là một phần của tập hợp các tùy chọn được xác định trước.

Các bảng liệt kê là các thực thể cơ sở mã linh hoạt mà bạn có thể giữ đơn giản ở dạng thuần túy hoặc mở rộng với các giá trị đã lưu, triển khai giao diện và phương pháp tùy chỉnh. Các phép liệt kê hoạt động giống như các đối tượng bình thường trong hầu hết các trường hợp và hỗ trợ các tính năng của lớp như __call(), __invoke, Và ::class.

Bạn có thể xem xét nội dung bảng liệt kê với enum_exists() chức năng và ReflectionEnum Lớp phản ánh. Ngoài ra, enums triển khai hai giao diện mới, UnitEnum (trong trường hợp liệt kê thuần túy), và BackedEnum (đối với các kiểu liệt kê với các giá trị đã lưu). Chúng có thể được sử dụng trong một mã khuôn khổ chung hoạt động với tất cả enum. Không thể thực hiện thủ công các giao diện bằng mã người dùng.

Các bảng kê sẽ có trong PHP như một phần của phiên bản 8.1 vào tháng 2021 năm 8.1. Chúng đã có sẵn trong các phiên bản beta mới nhất. PHP XNUMX cũng sẽ đi kèm với một số tính năng tiện dụng khác, bao gồm các thuộc tính chỉ đọc và các kiểu giao nhau.