亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > PHP > 正文

如何使用PHP來實現枚舉?

2020-03-22 17:57:18
字體:
來源:轉載
供稿:網友

本篇文章給大家帶來的內容是關于如何使用PHP來實現枚舉?有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。

枚舉

在數學和計算機科學理論中,一個集的枚舉是列出某些有窮序列集的所有成員的程序,或者是一種特定類型對象的計數。這兩種類型經常(但不總是)重疊。

枚舉是一個被命名的整型常數的集合,枚舉在日常生活中很常見,例如表示星期的SUNDAY、MONDAY、TUESDAY、WEDNESDAY、THURSDAY、FRIDAY、SATURDAY就是一個枚舉。—— 維基百科

業務場景

在實際開發過程中我們非常容易接觸到枚舉類型,但是又因為 PHP 原生對枚舉的支持不是太好,所以很多時候 開發人員并沒有重視枚舉的使用,而是使用全局常量或者類常量代替,而這兩個數據原則上還是 字符串 并不能用來做類型判斷。

業務訂單狀態 待支付/待發貨/待收貨/待評價會員狀態 激活/未激活....

等等 ,很多時候我們都會用簡單的 1/2/3/4 或者0/1 這樣的方式去代表,然后在文檔或者注釋中規定這些東西。

更高級一點兒的就是定義成常量,然后方便統一存取,但是常量的值還是是字符串,無法進行類型判斷。

這里就要看一下 PHP 對枚舉的支持,雖然 PHP 對枚舉沒有完美的支持,但是在 SPL 中還是有一個基礎的枚舉類

SPL 枚舉
SplEnum extends SplType {/ Constants /const NULL __default = NULL ;/ 方法 /html' target='_blank'>public getConstList ([ bool $include_default = FALSE ] ) : array/ 繼承的方法 /SplType::__construct ( [mixed $initial_value [, bool $strict ]] )}

但是!這個需要額外的安裝 PECL 用 PECL 安裝 Spl_Types,無意間增加了使用成本,那有沒有其他解決方案?答案是肯定的。

直接手寫一個。

開始準備

首先定一個枚舉

class Enum // 默認值 const __default = self::WAIT_PAYMENT; // 待付款 const WAIT_PAYMENT = 0; // 待發貨 const WAIT_SHIP = 1; // 待收貨 const WAIT_RECEIPT = 2; // 待評價 const WAIT_COMMENT = 3;}

這樣似乎就完成了,我們直接使用 Enum::WAIT_PAYMENT 就可以拿到里面的值了,但是傳參的地方我們并沒法校驗他。

function setStatus(Enum $status){ // TODOsetStatus(Enum::WAIT_PAYMENT);// Error 顯然這是不行的 因為上面常量的值時一個 int 并不是 Enum 類型。

這里我們就需要用到 PHP 面向對象中的一個魔術方法 __toString()

public __toString ( void ) : string__toString() 方法用于一個類被當成字符串時應怎樣回應。例如 echo $obj; 應該顯示些什么。此方法必須返回一個字符串,否則將發出一條 E_RECOVERABLE_ERROR 級別的致命錯誤。

現在我們來完善一下這個方法。

class OrderStatus extends Enum // 默認值 const __default = self::WAIT_PAYMENT; // 待付款 const WAIT_PAYMENT = 0; // 待發貨 const WAIT_SHIP = 1; // 待收貨 const WAIT_RECEIPT = 2; // 待評價 const WAIT_COMMENT = 3; public function __toString() return 233 // objectecho gettype($orderStatus) . PHP_EOL;// boolean truevar_dump($orderStatus instanceof Enum);// 233echo $orderStatus;

初具模型

這里似乎實現了一部分,那我們應該怎么樣讓他做的更好?再來改造一下。

class OrderStatus extends Enum // 默認值 const __default = self::WAIT_PAYMENT; // 待付款 const WAIT_PAYMENT = 0; // 待發貨 const WAIT_SHIP = 1; // 待收貨 const WAIT_RECEIPT = 2; // 待評價 const WAIT_COMMENT = 3; * @var string protected $value; public function __construct($value = null) $this- value = is_null($value) ? self::__default : $value; public function __toString() return (string)$this- value;// 1??$orderStatus = new OrderStatus(OrderStatus::WAIT_SHIP);// objectecho gettype($orderStatus) . PHP_EOL;// boolean truevar_dump($orderStatus instanceof Enum);echo $orderStatus . PHP_EOL;// 2??$orderStatus = new OrderStatus();// objectecho gettype($orderStatus) . PHP_EOL;// boolean truevar_dump($orderStatus instanceof Enum);echo $orderStatus;// 3??$orderStatus = new OrderStatus( 意外的參數 // objectecho gettype($orderStatus) . PHP_EOL;// boolean truevar_dump($orderStatus instanceof Enum);// 意外的參數echo $orderStatus;

在這一次,我們加入了 構造函數 并且允許他傳入一個可選的值,然后來作為 __toString 方法的輸出值,這次看起來不錯,功能都已經實現了,如果傳入的參數否和我們的預期的話。但是 萬一不符合呢?看看,第 3?? 個那里,就已經成了意外了,哪還有沒有辦法補救?答案當然是 有的 ,在這里我們會用到 PHP 另一個好東西 反射類 ,當然這個不是 PHP 特有的,其他語言也有。
當然,除了反射,我們還會用到另外一個東西 方法重載 里面的 __callStatic 方法。

更進一步

public static __callStatic ( string $name , array $arguments ) : mixed在靜態上下文中調用一個不可訪問方法時,__callStatic() 會被調用。

$name 參數是要調用的方法名稱。$arguments 參數是一個枚舉數組,包含著要傳遞給方法 $name 的參數。

繼續改造。

class Enum const __default = null; * @var string protected static $value; // 注意這里 將構造函數的 修飾符改成了 受保護的 即 外部無法直接 new protected function __construct($value = null) // 很常規 self::$value = is_null($value) ? static::__default : $value; * @param $name * @param $arguments * @return mixed * @throws ReflectionException public static function __callStatic($name, $arguments) // 實例化一個反射類 static::class 表示調用者 $reflectionClass = new ReflectionClass(static::class); // 這里我們要有一個約定, 就是類常量成員的名字必須的大寫。 // 這里就是取出來調用的靜態方法名對應的常量值 雖然這里有個 getValue 方法 // 但是因為其返回值不可靠 我們就依賴于他原本的隱式的 __toString 方法來幫我們輸出字符串即可。 $constant = $reflectionClass- getConstant(strtoupper($name)); // 獲取調用者的 構造方法 $construct = $reflectionClass- getConstructor(); // 設置成可訪問 因為我們把修飾符設置成了受保護的 這里需要訪問到,所以就需要設置成可訪問的。 $construct- setAccessible(true); // 因為現在類已經是可以訪問的了所以我們直接實例化即可,實例化之后 PHP 會自動調用 __toString 方法 使得返回預期的值。 $static = new static($constant); return $static; public function __toString() return (string)self::$value;class OrderStatus extends Enum // 默認值 const __default = self::WAIT_PAYMENT; // 待付款 const WAIT_PAYMENT = 0; // 待發貨 const WAIT_SHIP = 1; // 待收貨 const WAIT_RECEIPT = 2; // 待評價 const WAIT_COMMENT = 3;$WAIT_SHIP = OrderStatus::WAIT_SHIP();var_dump($WAIT_SHIP . var_dump($WAIT_SHIP instanceof Enum);

到這里 一個簡單的枚舉類就完成了。

完結

那如果我們還有其他需求、比如 判斷一個值是不是在枚舉范圍內?獲取所有的枚舉值?獲取所有的枚舉鍵,判斷枚舉鍵是否有效?自動格式化「因為 __toString 方法只允許返回字符串 ,但是有的時候我們強制需要整形、bool 等類型」

class Enum const __default = null; * @var string protected static $value; * @var ReflectionClass protected static $reflectionClass; // 注意這里 將構造函數的 修飾符改成了 受保護的 即 外部無法直接 new protected function __construct($value = null) // 很常規 self::$value = is_null($value) ? static::__default : $value; * @param $name * @param $arguments * @return mixed public static function __callStatic($name, $arguments) // 實例化一個反射類 static::class 表示調用者 $reflectionClass = self::getReflectionClass(); // 這里我們要有一個約定, 就是類常量成員的名字必須的大寫。 // 這里就是取出來調用的靜態方法名對應的常量值 雖然這里有個 getValue 方法 // 但是因為其返回值不可靠 我們就依賴于他原本的隱式的 __toString 方法來幫我們輸出字符串即可。 $constant = $reflectionClass- getConstant(strtoupper($name)); // 獲取調用者的 構造方法 $construct = $reflectionClass- getConstructor(); // 設置成可訪問 因為我們把修飾符設置成了受保護的 這里需要訪問到,所以就需要設置成可訪問的。 $construct- setAccessible(true); // 因為現在類已經是可以訪問的了所以我們直接實例化即可,實例化之后 PHP 會自動調用 __toString 方法 使得返回預期的值。 $static = new static($constant); return $static; * 實例化一個反射類 * @return ReflectionClass * @throws ReflectionException protected static function getReflectionClass() if (!self::$reflectionClass instanceof ReflectionClass) { self::$reflectionClass = new ReflectionClass(static::class); return self::$reflectionClass; * @return string public function __toString() return (string)self::$value; * 判斷一個值是否有效 即是否為枚舉成員的值 * @param $val * @return bool * @throws ReflectionException public static function isValid($val) return in_array($val, self::toArray()); * 轉換枚舉成員為鍵值對輸出 * @return array * @throws ReflectionException public static function toArray() return self::getEnumMembers(); * 獲取枚舉的常量成員數組 * @return array * @throws ReflectionException public static function getEnumMembers() return self::getReflectionClass() - getConstants(); * 獲取枚舉成員值數組 * @return array * @throws ReflectionException public static function values() return array_values(self::toArray()); * 獲取枚舉成員鍵數組 * @return array * @throws ReflectionException public static function keys() return array_keys(self::getEnumMembers()); * 判斷 Key 是否有效 即存在 * @param $key * @return bool * @throws ReflectionException public static function isKey($key) return in_array($key, array_keys(self::getEnumMembers())); * 根據 Key 去獲取枚舉成員值 * @param $key * @return static public static function getKey($key) return self::$key(); * 格式枚舉結果類型 * @param null|bool|int $type 當此處的值時什么類時 格式化輸出的即為此類型 * @return bool|int|string|null public function format($type = null) switch (true) { // 當為純數字 或者類型處傳入的為 int 值時 轉為 int case ctype_digit(self::$value) || is_int($type): return (int)self::$value; break; // 當 type 傳入 true 時 返回 bool 類型 case $type === true: return (bool)filter_var(self::$value, FILTER_VALIDATE_BOOLEAN); break; default: return self::$value; break;class OrderStatus extends Enum // 默認值 const __default = self::WAIT_PAYMENT; // 待付款 const WAIT_PAYMENT = 0; // 待發貨 const WAIT_SHIP = 1; // 待收貨 const WAIT_RECEIPT = 2; // 待評價 const WAIT_COMMENT = 3;$WAIT_SHIP = OrderStatus::WAIT_SHIP();// 直接輸出是字符串echo $WAIT_SHIP;// 判斷類型是否存在var_dump($WAIT_SHIP instanceof OrderStatus);// 格式化輸出一下 是要 字符串 、還是 bool 還是整形// 自動var_dump($WAIT_SHIP- format());// 整形var_dump($WAIT_SHIP- format(1));// boolvar_dump($WAIT_SHIP- format(true));// 判斷這個值是否有效的枚舉值var_dump(OrderStatus::isValid(2));// 判斷這個值是否有效的枚舉值var_dump(OrderStatus::isValid(8));// 獲取所有枚舉成員的 Keyvar_dump(OrderStatus::keys());// 獲取所有枚舉成員的值var_dump(OrderStatus::values());// 獲取枚舉成員的鍵值對var_dump(OrderStatus::toArray());// 判斷枚舉 Key 是否有效var_dump(OrderStatus::isKey( WAIT_PAYMENT // 判斷枚舉 Key 是否有效var_dump(OrderStatus::isKey( WAIT_PAYMENT_TMP // 根據 Key 取去 值 注意 這里取出來的已經不帶有類型了// 更加建議直接使用 取類常量的方式去取 或者在高版本的 直接使用類常量修飾符 // 將類常量不可見最佳,但是需要額外處理了var_dump(OrderStatus::getKey( WAIT_PAYMENT ) - format(1));

截至目前 一個完整的枚舉就完成了~

以上就是如何使用PHP來實現枚舉?的詳細內容,PHP教程

鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
最近中文字幕日韩精品| 欧美福利在线观看| 欧美最顶级的aⅴ艳星| 中文字幕少妇一区二区三区| 欧美有码在线观看视频| 91成人在线播放| 午夜精品一区二区三区在线视| 精品亚洲国产视频| 日韩精品在线看| 欧美日韩午夜视频在线观看| 日韩精品极品视频| 欧美成人一区在线| 亚洲国产精品电影在线观看| 亚洲一二三在线| 国产亚洲激情视频在线| xxxxx成人.com| 亚洲视频在线观看视频| 久久亚洲精品一区二区| 国产日韩中文字幕| 一区二区三区天堂av| 亚洲国产精品国自产拍av秋霞| 欧美大片在线看| 欧美精品免费看| 国产一区视频在线播放| 久久久精品久久久久| 欧美国产视频一区二区| 亚洲精品久久久久国产| 国产精品视频男人的天堂| 搡老女人一区二区三区视频tv| 欧美一区二区视频97| 成人福利在线视频| 91精品国产高清久久久久久91| 日韩欧美第一页| 91视频国产一区| 亚洲精品美女在线观看播放| 日韩av电影在线免费播放| 久久久久久久久久久av| 精品久久久精品| 亚洲美女精品成人在线视频| 国产视频欧美视频| 亚洲欧美国产日韩天堂区| 日本精品视频在线观看| 国产欧美在线播放| 精品久久久久久久久久国产| 伊人久久精品视频| 福利微拍一区二区| 国产成人在线视频| 26uuu另类亚洲欧美日本一| 最新91在线视频| 91成人天堂久久成人| 亚洲精品久久久久国产| 亚洲第一福利网| 欧美色videos| 美女啪啪无遮挡免费久久网站| 人妖精品videosex性欧美| 欧美日韩国产限制| 91成人国产在线观看| 亚洲美女动态图120秒| 91精品91久久久久久| 中文字幕亚洲一区二区三区五十路| 亚洲一区www| 成人网中文字幕| 亚洲国产天堂久久综合| 最近2019中文字幕一页二页| 国产一区二区精品丝袜| 日韩精品免费综合视频在线播放| 国产成人av网| 亚洲国产日韩欧美综合久久| 亚洲国产中文字幕在线观看| 欧美视频免费在线观看| 欧美激情视频在线观看| 国产精品99久久久久久久久| 亚洲最新在线视频| 中文字幕亚洲情99在线| 欧美日韩午夜剧场| 午夜免费日韩视频| 日本精品久久电影| 久久91亚洲人成电影网站| 国产精品一二三视频| 亚洲人成电影在线观看天堂色| 日韩成人小视频| 亚洲va欧美va在线观看| 国产成人在线一区二区| 国产精品电影网| 九九热精品在线| 成人免费高清完整版在线观看| 成人精品视频99在线观看免费| 91久久精品国产91性色| 97热在线精品视频在线观看| 欧美激情精品在线| 91中文在线观看| 国产一级揄自揄精品视频| 欧美做受高潮电影o| 亚洲毛茸茸少妇高潮呻吟| 欧美精品激情视频| 91精品国产91久久久久久最新| 青青久久aⅴ北条麻妃| 国产亚洲福利一区| 日韩在线欧美在线| 精品久久香蕉国产线看观看亚洲| 久久久亚洲国产天美传媒修理工| 麻豆乱码国产一区二区三区| 欧美日韩国产中字| 亚洲中国色老太| 国模精品视频一区二区三区| 欧美一二三视频| 精品久久久91| 国产视频精品在线| 国产精品高潮呻吟久久av无限| 不卡av日日日| 久久福利网址导航| 亚洲a级在线播放观看| 日韩在线视频导航| 亚洲图中文字幕| 欧美中文字幕视频在线观看| 久久亚洲国产精品成人av秋霞| 国内精品久久久久久中文字幕| 成人福利视频在线观看| 欧美亚洲国产视频小说| 亚洲国产精品成人一区二区| 亚洲欧美在线一区| 久久精品国产亚洲精品| 亚洲福利在线观看| 国产精品免费一区豆花| 黑人精品xxx一区一二区| 国产精品久久中文| 欧美富婆性猛交| 国产噜噜噜噜噜久久久久久久久| 亚洲午夜激情免费视频| 国产99久久久欧美黑人| 精品成人国产在线观看男人呻吟| 91精品久久久久久久久久久久久| 日韩欧美一区二区三区久久| 久久国内精品一国内精品| 97精品久久久中文字幕免费| 国产精品一区二区在线| 日韩欧美精品网址| 另类图片亚洲另类| 青草青草久热精品视频在线观看| 日韩成人免费视频| 日韩精品免费在线视频| 中文字幕精品一区二区精品| 国产精品免费视频xxxx| 国产精品99久久99久久久二8| 日韩美女免费视频| 最近2019好看的中文字幕免费| 久久久之久亚州精品露出| 久久视频在线观看免费| 欧美综合一区第一页| 69视频在线播放| 97在线视频免费| 久久久亚洲影院| 日韩精品视频在线播放| 久久成人国产精品| 亚洲美腿欧美激情另类| 久久精品国产亚洲一区二区| 青草热久免费精品视频| 中文字幕免费国产精品| 国产成人精品在线播放| 中文字幕日韩高清| 亚洲aⅴ日韩av电影在线观看| 国产精品免费小视频| 国产精品视频xxx| 韩国福利视频一区|