PHP中實現多值枚舉

PHP 枚舉

前面的文章中咱們介紹了PHP枚舉的使用,最近對項目總體進行重構,增長了枚舉類的封閉性和安全性,尤爲對多值枚舉進行了優化。php

枚舉類

PHPEnum包含三個核心枚舉類,分別爲:前端

  • 基礎枚舉 - 測試用例 這是一個單值枚舉類,也是一個基礎類,枚舉類都會繼承此類
  • 列表枚舉 - 測試用例 這是一個基於單值枚舉類實現的多值枚舉類,能夠定義任意數量的屬性
  • 數組枚舉 - 測試用例 這是一個多值枚舉的實現類,基於最經常使用的兩個屬性值的枚舉場景預約義了key和value兩個屬性

這裏所說的單值和多值的值是指屬性值,其實枚舉自己沒有單值和多值之分,但因爲語言特性,沒有很好的辦法將其在一個類中實現。git

快速開始

讓咱們經過一個表示用戶性別的枚舉爲例,來了解各個枚舉的用法和區別github

數組枚舉

定義數組枚舉時須要注意全部的常量值都須要定義爲有兩個元素的數組,不然系統將會拋出一個異常數組

首先咱們基於數組枚舉來定義用戶性別枚舉,它的定義方式與普通的常量定義同樣:緩存

class UserGenderEnum extends \PhpEnum\ArrayEnum { 
    const MALE   = [1, 'male'];
    const FEMALE = [2, 'female']; 
 }

當咱們定義好用戶性別枚舉後,讓咱們看看數組枚舉爲咱們提供了哪些功能:安全

  1. 當咱們想獲取一個男性的枚舉實例時,咱們能夠經過下面任意一個方法,獲取到的枚舉實例始終爲同一個測試

    UserGenderEnum::MALE() // 只會緩存當前實例
       UserGenderEnum::ofEnumName('MALE') // 會緩存全部實例       
       UserGenderEnum::ofKey(1) // 會緩存全部實例
       UserGenderEnum::ofValue('male') // 會緩存全部實例
  2. 當咱們想獲取枚舉名稱或屬性值時,咱們能夠這樣作優化

    UserGenderEnum::MALE()->name() // string(4) "MALE" 
        UserGenderEnum::MALE()->getKey() // int(1) 
        UserGenderEnum::MALE()->getValue() // string(4) "male"
  3. 當咱們想比較一個屬性時,咱們能夠這樣作this

    UserGenderEnum::MALE()->enumNameEquals('MALE') // bool(true)
        UserGenderEnum::MALE()->keyEquals(1) // bool(true)
        UserGenderEnum::MALE()->valueEquals('male') // bool(true)
  4. 當咱們想要驗證前端傳遞的數據是否正確時,枚舉能夠很快速的實現它

    UserGenderEnum::containsEnumName('MALE') // int(1) 返回查找到的枚舉數量
       UserGenderEnum::containsKey(1) // int(1) 返回查找到的枚舉數量 
       UserGenderEnum::containsValue('male') // int(1) 返回查找到的枚舉數量
  5. 可能有的時候咱們沒法獲得一個具體的值去驗證,好比在Laravel驗證器中,咱們須要獲得一個字符串進行驗證,只須要這麼作

    implode(',', UserGenderEnum::names()) // string(11) "MALE,FEMALE"
        implode(',', UserGenderEnum::getProperties('key')) // string(3) "1,2"
        implode(',', UserGenderEnum::getProperties('value')) // string(11) "male,female"

經過上面的示例咱們瞭解到了數組枚舉部分功能的用法,但你可能以爲預約義的屬性名稱key和value
在不一樣的場景下對理解它們表明什麼含義並不友好,那麼接下來你須要瞭解下列表枚舉的使用。

列表枚舉

定義列表枚舉時須要注意必需要定義protected修飾的構造方法listEnumConstruct,枚舉常量值必須爲非空數組且長度要與構造方法參數的個數徹底一致,不然系統將會拋出一個異常

此次讓咱們基於列表枚舉來定義用戶性別枚舉, 此次除了定義常量外,咱們使用了自定義的屬性名稱id和name,並經過構造方法爲其賦值

class UserGenderEnum extends \PhpEnum\ListEnum {
 
     const MALE   = [1, 'male'];
     const FEMALE = [2, 'female'];
     
     private $id;
     private $name;
     
     protected function listEnumConstruct($id, $name)
     { 
         $this->id = $id;
         $this->name = $name; 
     } 
 }

當咱們定義好用戶性別枚舉後,上面咱們在數組枚舉中演示過的功能在這裏也全都生效,只是須要將key換成id,將value換成name,如:

  1. 當咱們想獲取一個男性的枚舉實例時,咱們能夠經過下面任意一個方法,獲取到的枚舉實例始終爲同一個。

    UserGenderEnum::MALE() // 只會緩存當前實例
        UserGenderEnum::ofEnumName('MALE') // 會緩存全部實例
        UserGenderEnum::ofId(1) // 會緩存全部實例
        UserGenderEnum::ofName('male') // 會緩存全部實例
  2. 當咱們想獲取枚舉名稱或屬性值時,咱們能夠這樣作

    UserGenderEnum::MALE()->name() // string(4) "MALE"
        UserGenderEnum::MALE()->getId() // int(1)
        UserGenderEnum::MALE()->getName() // string(4) "male"
  3. 當咱們想比較一個屬性時,咱們能夠這樣作

    UserGenderEnum::MALE()->enumNameEquals('MALE') // bool(true)
        UserGenderEnum::MALE()->idEquals(1) // bool(true)
        UserGenderEnum::MALE()->nameEquals('male') // bool(true)
  4. 當咱們想要驗證前端傳遞的數據是否正確時,枚舉能夠很快速的實現它

    UserGenderEnum::containsEnumName('MALE') // int(1) 返回查找到的枚舉數量
        UserGenderEnum::containsId(1) // int(1) 返回查找到的枚舉數量
        UserGenderEnum::containsName('male') // int(1) 返回查找到的枚舉數量
  5. 可能有的時候咱們沒法獲得一個具體的值去驗證,好比在Laravel驗證器中,咱們須要獲得一個字符串進行驗證,只須要這麼作

    implode(',', UserGenderEnum::names()) // string(11) "MALE,FEMALE" 
        implode(',', UserGenderEnum::getProperties('id')) // string(3) "1,2"
        implode(',', UserGenderEnum::getProperties('name')) // string(11) "male,female"

列表枚舉的實現可能是參考JAVA枚舉,但因爲JAVA自己是在語言層面對枚舉功能作的支持,定義JAVA枚舉元素就是在定義構造方法,這些在PHP中沒法支持,因此只能用數組來代替。

基礎枚舉

基礎枚舉是單值枚舉,只有屬性名稱name和屬性值value,基礎枚舉不限制屬性值的類型,但同時屬性值始終做爲一個總體,沒法再細分

此次讓咱們再基於基礎枚舉來定義用戶性別枚舉,基礎枚舉的定義同數組枚舉的定義相同

class UserGenderEnum extends \PhpEnum\Enum { 
    const MALE   = [1, 'male'];
    const FEMALE = [2, 'female']; 
 }

當咱們定義好用戶性別枚舉後,讓咱們看看基礎枚舉爲咱們提供了哪些功能(注意基礎枚舉中的屬性值[1, 'male']只能做爲一個總體使用):

  1. 當咱們想獲取一個男性的枚舉實例時,咱們能夠經過下面任意一個方法,獲取到的枚舉實例始終爲同一個

    UserGenderEnum::MALE() // 只會緩存當前實例
        UserGenderEnum::ofEnumName('MALE') // 會緩存全部實例
        UserGenderEnum::ofEnumValue([1, 'male']) // 會緩存全部實例
  2. 當咱們想獲取枚舉名稱或屬性值時,咱們能夠這樣作

    UserGenderEnum::MALE()->name() // string(4) "MALE"
        UserGenderEnum::MALE()->value() // array(2) {[0]=>int(1)[1]=>string(4) "male"}
  3. 當咱們想比較一個屬性時,咱們能夠這樣作

    UserGenderEnum::MALE()->enumNameEquals('MALE') // bool(true) 
        UserGenderEnum::MALE()->enumValueEquals([1, 'male']) // bool(true)
  4. 當咱們想要驗證前端傳遞的數據是否正確時,枚舉能夠很快速的實現它

    UserGenderEnum::containsEnumName('MALE') // int(1) 返回查找到的枚舉數量 
        UserGenderEnum::containsValue([1, 'male']') // int(1) 返回查找到的枚舉數量
  5. 當咱們須要獲得一個字符串時,能夠這樣作

    implode(',', UserGenderEnum::names()) // string(11) "MALE,FEMALE"

到這裏枚舉經常使用的功能就介紹完了,三種不一樣類型的枚舉提供不一樣的功能,要根據實際的使用場景進行選擇使用

相關文章
相關標籤/搜索