PHP 中的列舉
- 在 PHP 中使用抽象類模擬列舉
- 在 PHP 中使用具有驗證和更多常量值的抽象類來模擬列舉
-
使用 PHP
enum
進行列舉 - 支援的 PHP 列舉
- 使用 PHP 中的方法支援列舉
- 列出 PHP 中支援列舉的案例
本教程將教你如何在 PHP 8.1 之前和之後使用 PHP 中的列舉。
原因是在 PHP 8.1 之前,你只能使用抽象類來模擬列舉。但是,從 PHP 8.1 開始,PHP 提供了對列舉的原生支援。
在 PHP 中使用抽象類模擬列舉
在 PHP 8.1 之前,你可以使用抽象類來模擬列舉。由於列舉是將名稱分配給整數常量,因此你可以建立一個包含常量值的抽象類。
你可以通過範圍解析協議 ::
獲取類外的每個常量值。
我們的下一個示例程式碼有一個包含類常量的抽象類。之後,我們通過範圍解析協議呼叫其中一個常量。
這種方法有其侷限性;我們將在下一節討論它。
<?php
abstract class CalenderMonths {
const January = 1;
const February = 2;
const March = 3;
const April = 4;
const May = 5;
const June = 6;
const July = 7;
const August = 8;
const September = 9;
const October = 10;
const November = 11;
const December = 12;
}
$january = CalenderMonths::January;
echo $january;
?>
輸出:
1
在 PHP 中使用具有驗證和更多常量值的抽象類來模擬列舉
這個例子建立在我們之前的例子之上。但是在這裡,我們提出了一個改進的版本。
這個版本有驗證,可以儲存更多的常數值。此外,它還可以防止當你擴充套件類時,第一個擴充套件建立一個快取,而另一個擴充套件仍然使用相同的快取。
該程式碼塊使用抽象類模擬列舉,並且它具有防止無效引數的驗證。首先,我們定義抽象類。
<?php
abstract class EmulatePHPEnum {
private static $cache_array = NULL;
private static function get_constants() {
if (self::$cache_array == NULL) {
self::$cache_array = [];
}
$called_class = get_called_class();
if (!array_key_exists($called_class, self::$cache_array)) {
$reflection_object = new ReflectionClass($called_class);
self::$cache_array[$called_class] = $reflection_object->getConstants();
}
return self::$cache_array[$called_class];
}
public static function check_valid_name($name, $is_strict = false) {
$constants = self::get_constants();
if ($is_strict) {
return array_key_exists($name, $constants);
}
$keys = array_map('strtolower', array_keys($constants));
return in_array(strtolower($name), $keys);
}
public static function check_valid_value($value, $is_strict = true) {
$values = array_values(self::get_constants());
return in_array($value, $values, $is_strict);
}
}
?>
然後,我們擴充套件它並進行比較。
abstract class CalenderMonths extends EmulatePHPEnum {
const January = 1;
const February = 2;
const March = 3;
const April = 4;
const May = 5;
const June = 6;
const July = 7;
const August = 8;
const September = 9;
const October = 10;
const November = 11;
const December = 12;
}
echo "<b>First check: </b> ";
if (CalenderMonths::check_valid_name("Nothing")) {
echo "True";
} else {
echo "False";
}
echo "<br />";
echo "<b>Second check: </b>";
if (CalenderMonths::check_valid_name("September")) {
echo "True";
} else {
echo "False";
}
echo "<br />";
echo "<b>Third check: </b>";
if (CalenderMonths::check_valid_name("september")) {
echo "True";
} else {
echo "False";
}
echo "<br />";
echo "<b>Fourth check: </b>";
if (CalenderMonths::check_valid_name("september", $is_strict = true)) {
echo "True";
} else {
echo "False";
}
echo "<br />";
echo "<b>Fifth check: </b>";
if (CalenderMonths::check_valid_name(23)) {
echo "True";
} else {
echo "False";
}
echo "<br />";
輸出:
<b>First check</b>: False
<b>Second check</b>: True
<b>Third check</b>: True
<b>Fourth check</b>: False
<b>Fifth check</b>: False
使用 PHP enum
進行列舉
PHP 中列舉的定義是使用 enum
關鍵字後跟列舉名稱和一組花括號。在這些大括號中,你可以定義案例。
我們在下一個程式碼塊中提供一個示例。此外,我們在案例之間進行了一些比較檢查。
請注意,你不能將列舉與小於或大於運算子進行比較。
<?php
enum ProgrammingLanguages {
case JavaScript;
case PHP;
case Ruby;
case Erlang;
case Elixir;
}
$javascript = ProgrammingLanguages::JavaScript;
$js = ProgrammingLanguages::JavaScript;
$erlang = ProgrammingLanguages::Erlang;
echo $javascript === $js;
echo "<br/>";
if ($javascript === $erlang) {
echo "True";
} else {
echo "False";
}
echo "<br/>";
if ($javascript instanceof ProgrammingLanguages) {
echo "True";
} else {
echo "False";
}
echo "<br />";
if ($javascript > $js || $javascript < $js) {
echo "True";
} else {
echo "False";
}
?>
輸出:
1 <br />
False <br />
True <br />
False <br />
支援的 PHP 列舉
支援的列舉是列舉宣告,後跟列舉中每種情況的資料型別。
在我們檢視程式碼示例之前,請注意以下關於 PHP 中支援的列舉的以下內容。
- 為支援值定義值時,確保所有值都有支援值。
- 你應該在列舉名稱之後宣告支援值的型別。
- 列舉中的支援值是隻讀的。
- 如果你的列舉包含標量值,它們應該是唯一的。
- 支援的值應該是文字表示式或文字。
- 你可以使用語法
enum_name::backed_value
訪問支援的值。其中enum_name
是列舉名稱,backed_value
是你要訪問的值。 - 支援的列舉有一個稱為
BackedEnum
的內部介面。這個介面有兩個方法,from
和tryFrom
。 from
方法將丟擲不存在值的異常。而tryFrom
返回null
。
以下程式碼顯示瞭如何在 PHP 中使用支援的列舉。
<?php
enum Age : int {
case John = 23;
case Martinez = 30;
case Mary = 43;
case Velasquez = 25;
}
$first_age = Age::tryFrom(23);
if ($first_age) {
echo "True";
} else {
echo "False";
}
echo "<br />";
$second_age = Age::tryFrom(98);
if ($second_age) {
echo "True";
} else {
echo "False";
}
echo "<br />";
$third_age = Age::from(42);
?>
輸出:
True
False
<b>Fatal error</b>: Uncaught ValueError: 42 is not a valid backing value for enum "Age"
使用 PHP 中的方法支援列舉
支援的列舉可以有方法。結果,他們可以實現一個介面。
你將在下一個示例程式碼中找到一個示例。
<?php
interface isTravel {
public function calculate_travel_cost (int $distance_covered): int;
public function isRequireFuel(): bool;
}
enum CarTypes: int implements isTravel {
case Bughatti = 300;
case Lamborghini = 500;
case Ferrari = 450;
case Audi = 350;
public function calculate_travel_cost(int $distance_covered): int {
return $this->value * $distance_covered;
}
public function isRequireFuel(): bool {
return match($this) {
CarTypes::Bughatti, CarTypes::Lamborghini, CarTypes::Ferrari => true,
};
}
}
$car = CarTypes::Bughatti;
$does_it_require_fuel = $car->isRequireFuel();
if ($does_it_require_fuel) {
echo "True";
} else {
echo "False";
}
echo "<br />";
$car_travel_cost = $car ->calculate_travel_cost(250);
echo $car_travel_cost;
?>
輸出:
True
75000
列出 PHP 中支援列舉的案例
如果你希望列出支援列舉的情況,可以通過名為 UnitEnum
的內部介面來完成。這個介面有一個定義為 UnitEnum::cases
的靜態方法。
使用此介面,你可以檢索列舉中的案例。你將在下面找到示例程式碼。
<?php
interface isTravel {
public function calculate_travel_cost (int $distance_covered): int;
public function isRequireFuel(): bool;
}
enum CarTypes: int implements isTravel {
case Bughatti = 300;
case Lamborghini = 500;
case Ferrari = 450;
case Audi = 350;
public function calculate_travel_cost(int $distance_covered): int {
return $this->value * $distance_covered;
}
public function isRequireFuel(): bool {
return match($this) {
CarTypes::Bughatti, CarTypes::Lamborghini, CarTypes::Ferrari => true,
};
}
}
$car_names = CarTypes::cases();
echo "<pre>";
var_dump($car_names);
echo "</pre>";
?>
輸出:
<pre>
array(4) {
[0]=>
enum(CarTypes::Bughatti)
[1]=>
enum(CarTypes::Lamborghini)
[2]=>
enum(CarTypes::Ferrari)
[3]=>
enum(CarTypes::Audi)
}
</pre>
Habdul Hazeez is a technical writer with amazing research skills. He can connect the dots, and make sense of data that are scattered across different media.
LinkedIn