如果您熟悉任何主要編程語(yǔ)言(.NET、Java、Python 等),您可能熟悉“枚舉”或“枚舉”的概念。這些用于通過(guò)將可讀名稱(chēng)分配給靜態(tài)值集合來(lái)幫助提高可讀性。閱讀“Color.Red”比查看“#FF0000”或“1”要容易得多。為了擴(kuò)展這個(gè)想法,想象寫(xiě)一個(gè) if 語(yǔ)句,你將一個(gè)十六進(jìn)制值與紅色進(jìn)行比較?if ("#FF0000" == Color.Red) { // Do stuff }
?似乎更有意義并且直截了當(dāng)?;蛘?,您可能正在將一個(gè)值與 switch 語(yǔ)句中的多個(gè)情況進(jìn)行比較。比較 "#FF0000" 與 Color.Red、Color.Blue 和 Color.Green 比 "#FF0000"、"#00FF00" 更容易
如果您熟悉枚舉和 PHP,您可能會(huì)說(shuō)“在PHP中沒(méi)有枚舉!”那么如果這么,那你是對(duì)的。但這并不意味著我們不能使用類(lèi)輕松創(chuàng)建它們。在本文中,我將快速向您展示如何使用類(lèi)和常量創(chuàng)建枚舉。此外,我將展示使用反射查找給定值的枚舉鍵(這通常與使用枚舉的原因相反,但仍然可以保證)。
PHP 中的枚舉
首先,我們將創(chuàng)建一個(gè)簡(jiǎn)單的顏色枚舉,它將列出三種顏色:紅色、藍(lán)色和綠色。與其他語(yǔ)言一樣,您可能知道我們會(huì)在我們的代碼中引用這些顏色值,如 Color.Red、Color.Blue 和 Color.Green。我們不必創(chuàng)建某種類(lèi)實(shí)例或任何東西。通常,語(yǔ)言將自己的枚舉定義為語(yǔ)言語(yǔ)法的一部分和/或讓您添加自己的枚舉。另一方面,PHP 沒(méi)有這個(gè)概念。所以我們必須做的是使用一個(gè)類(lèi),準(zhǔn)確地說(shuō)是一個(gè)抽象類(lèi),來(lái)做我們想做的事。對(duì)于我們的各種值,我們將定義一些常量。這是它的樣子......
abstract class Color {
const RED = 1;
const BLUE = 2;
const GREEN = 3;
}
使用抽象類(lèi),我們不需要?jiǎng)?chuàng)建類(lèi)的實(shí)例來(lái)訪問(wèn)它包含的變量。有了這個(gè)定義,我們可以開(kāi)始使用我們的枚舉類(lèi)來(lái)比較值 1、2 和 3,分別是紅色、藍(lán)色和綠色。除了可讀性之外,我們?yōu)槭裁匆褂妹杜e?好吧,也許我們只能將顏色作為整數(shù)存儲(chǔ)在數(shù)據(jù)庫(kù)中。我們可以在數(shù)據(jù)庫(kù)中存儲(chǔ) 1,然后比較數(shù)據(jù)庫(kù)中的值,看看它是否等于 Color.RED。如果沒(méi)有這個(gè)枚舉,我們可能不知道 1 是數(shù)據(jù)庫(kù)中“紅色”的表示。不只是在數(shù)據(jù)庫(kù)中使用字符串聽(tīng)起來(lái)很愚蠢,但是您會(huì)驚訝為什么事情從來(lái)沒(méi)有那么簡(jiǎn)單……尤其是在擁有數(shù)十名開(kāi)發(fā)人員的大型組織中工作時(shí)。
如何使用
大多數(shù)熟悉枚舉的人通常都知道使用句點(diǎn)來(lái)訪問(wèn)值。例如 Color.Blue 或 Color.Green。由于這是一個(gè)抽象類(lèi),并且 PHP 用于訪問(wèn)類(lèi)成員的解析運(yùn)算符是?::
?那么您將不得不使用?Color::BLUE
?和?Color::GREEN
?。還不錯(cuò)吧?
將枚舉值轉(zhuǎn)換為其鍵
正如一開(kāi)始提到的,大多數(shù)時(shí)候你會(huì)使用一個(gè)枚舉來(lái)比較你從其他地方得到的一些值和枚舉的值。從數(shù)據(jù)庫(kù)中獲取值,將其與 Color.BLUE 進(jìn)行比較,然后將頁(yè)面顏色更改為藍(lán)色作為響應(yīng)。但是,如果我們有一個(gè)像 3 這樣的值并且我們想知道枚舉中的顏色呢?當(dāng)然,我們可以針對(duì)我們定義的三個(gè)常量中的每一個(gè)嘗試該值并得到我們的答案。但是如果我們不知道所有的常數(shù)值是多少呢?如果有 20 個(gè)常量呢?做 20 個(gè) if/else 語(yǔ)句或設(shè)置一個(gè)包含 20 個(gè) case 的 switch 會(huì)有點(diǎn)多。下面的代碼采用了不同的方法。我們使用反射來(lái)獲取常量,遍歷它們并將每個(gè)常量的值與我們提供的值進(jìn)行比較。如果沒(méi)有找到,我們返回 null。
function getConstantName($enum, $constantValue) {
try {
$reflection = new ReflectionClass($enum);
} catch (ReflectionException $ex) {
return null;
}
$constants = $reflection->getConstants();
foreach ($constants as $key => $val) {
if ($val === $constantValue) {
return $key;
}
}
return null;
}
使用此代碼,我們可以輸入 Color 枚舉名稱(chēng)和我們正在尋找的值,它將返回鍵。確保你給它一個(gè)枚舉名稱(chēng)或我們類(lèi)的實(shí)例,函數(shù)可以看到定義!例如,如果我們調(diào)用?getConstantName('Color', 3);
?將返回“綠色”。您可能會(huì)也可能不會(huì)決定使用此功能,但是如果您想知道 3 是否甚至等于我們的枚舉“Color”中定義的顏色,那么您肯定可以使用它。如果你使用?getConstantName('Color',
? 6); 你得到一個(gè)空值,并且知道它甚至不是受支持的顏色,并且可以將頁(yè)面的顏色默認(rèn)為?Color::Red
?。
未來(lái)的考慮
現(xiàn)在當(dāng)然我知道你可能想用枚舉做很多其他的事情。而且你甚至可以做一些事情,比如混合?Color::BLUE
?和?Color::YELLOW
?如果你希望它返回?Color::GREEN
?。由于我們創(chuàng)建了一個(gè)抽象類(lèi),因此將您的函數(shù)移動(dòng)到類(lèi)中并使其成為靜態(tài)方法沒(méi)有問(wèn)題。如果您在網(wǎng)絡(luò)上進(jìn)行一些搜索,您會(huì)發(fā)現(xiàn)其他人提到了與此類(lèi)似的想法,并將其轉(zhuǎn)向其他方向,包括定義基類(lèi)并從中繼承。