PHP dan Pencacahan

1149

Saya tahu bahwa PHP tidak memiliki Enumerasi asli. Tapi saya sudah terbiasa dengan mereka dari dunia Jawa. Saya akan senang menggunakan enum sebagai cara untuk memberikan nilai yang telah ditentukan yang dapat dimengerti oleh fitur pelengkapan otomatis IDE.

Konstanta melakukan trik, tetapi ada masalah tabrakan namespace dan (atau sebenarnya karena ) mereka bersifat global. Array tidak memiliki masalah namespace, tetapi mereka terlalu kabur, mereka dapat ditimpa saat runtime dan IDE jarang (tidak pernah?) Tahu cara mengisi kunci otomatis.

Apakah ada solusi / solusi yang biasa Anda gunakan? Apakah ada yang ingat apakah orang-orang PHP memiliki pemikiran atau keputusan di sekitar enum?

Henrik Paul
sumber
1
Saya membuat pekerjaan di sekitar fungsi yang menyebutkan konstanta sebagai bitwise atau tidak. Tidak melihat Anda menanyakan ini sebelumnya, tapi saya punya solusi yang lebih baik daripada variabel kelas di sini: stackoverflow.com/questions/3836385/…
NoodleOfDeath
github.com/myclabs/php-enum
Matthieu Napoli
Apakah Anda keberatan berbagi sedikit tentang masalah Konstanta? "Konstanta melakukan trik, tetapi ada masalah tabrakan namespace dan (atau sebenarnya karena) mereka bersifat global."
XuDing
github.com/githubjeka/enum
Evgeniy Tkachenko

Jawaban:

1492

Bergantung pada use case, saya biasanya menggunakan sesuatu yang sederhana seperti berikut:

abstract class DaysOfWeek
{
    const Sunday = 0;
    const Monday = 1;
    // etc.
}

$today = DaysOfWeek::Sunday;

Namun, kasus penggunaan lainnya mungkin memerlukan lebih banyak validasi konstanta dan nilai. Berdasarkan komentar di bawah ini tentang refleksi, dan beberapa catatan lainnya , inilah contoh yang diperluas yang mungkin lebih baik melayani berbagai kasus yang jauh lebih luas:

abstract class BasicEnum {
    private static $constCacheArray = NULL;

    private static function getConstants() {
        if (self::$constCacheArray == NULL) {
            self::$constCacheArray = [];
        }
        $calledClass = get_called_class();
        if (!array_key_exists($calledClass, self::$constCacheArray)) {
            $reflect = new ReflectionClass($calledClass);
            self::$constCacheArray[$calledClass] = $reflect->getConstants();
        }
        return self::$constCacheArray[$calledClass];
    }

    public static function isValidName($name, $strict = false) {
        $constants = self::getConstants();

        if ($strict) {
            return array_key_exists($name, $constants);
        }

        $keys = array_map('strtolower', array_keys($constants));
        return in_array(strtolower($name), $keys);
    }

    public static function isValidValue($value, $strict = true) {
        $values = array_values(self::getConstants());
        return in_array($value, $values, $strict);
    }
}

Dengan membuat kelas enum sederhana yang memperluas BasicEnum, Anda sekarang memiliki kemampuan untuk menggunakan metode demikian untuk validasi input sederhana:

abstract class DaysOfWeek extends BasicEnum {
    const Sunday = 0;
    const Monday = 1;
    const Tuesday = 2;
    const Wednesday = 3;
    const Thursday = 4;
    const Friday = 5;
    const Saturday = 6;
}

DaysOfWeek::isValidName('Humpday');                  // false
DaysOfWeek::isValidName('Monday');                   // true
DaysOfWeek::isValidName('monday');                   // true
DaysOfWeek::isValidName('monday', $strict = true);   // false
DaysOfWeek::isValidName(0);                          // false

DaysOfWeek::isValidValue(0);                         // true
DaysOfWeek::isValidValue(5);                         // true
DaysOfWeek::isValidValue(7);                         // false
DaysOfWeek::isValidValue('Friday');                  // false

Sebagai catatan, setiap kali saya menggunakan refleksi setidaknya sekali pada kelas statis / const di mana data tidak akan berubah (seperti dalam enum), saya cache hasil panggilan refleksi tersebut, karena menggunakan objek refleksi baru setiap kali pada akhirnya akan memiliki dampak kinerja yang nyata (Disimpan dalam array assocciative untuk beberapa enum).

Sekarang sebagian besar orang akhirnya ditingkatkan menjadi setidaknya 5,3, dan SplEnumtersedia, yang tentu saja merupakan pilihan yang layak - selama Anda tidak keberatan dengan gagasan tradisional yang tidak intuitif tentang memiliki instance enum aktual di seluruh basis kode Anda. Dalam contoh di atas, BasicEnumdan DaysOfWeektidak dapat dipakai sama sekali, mereka juga tidak boleh.

Brian Cline
sumber
70
Saya menggunakan ini juga. Anda mungkin juga mempertimbangkan membuat kelas abstractdan final, jadi itu tidak bisa dipakai atau diperluas.
ryeguy
21
Anda bisa membuat kelas keduanya abstractdan final? Saya tahu di Jawa ini tidak diizinkan. Anda bisa melakukannya di php?
corsiKa
20
@ryeguy Tampaknya Anda tidak dapat membuat itu baik abstract dan final. Dalam hal ini, saya akan mengambil abstrak.
Nicole
45
Tentang abstrak atau final; Saya membuat mereka final dan memberi mereka konstruktor pribadi yang kosong
rael_kid
21
Berhati-hatilah dengan penggunaan 0, sehingga Anda tidak mengalami masalah perbandingan kepalsuan yang tidak terduga, misalnya kesetaraan dengan nulldan teman dalam switchpernyataan. Pernah ke sana.
yitznewton
185

Ada ekstensi asli juga. The SplEnum

SplEnum memberikan kemampuan untuk meniru dan membuat objek enumerasi secara native di PHP.

http://www.php.net/manual/en/class.splenum.php

Perhatian:

https://www.php.net/manual/en/spl-types.installation.php

Ekstensi PECL tidak dibundel dengan PHP.

DLL untuk ekstensi PECL ini saat ini tidak tersedia.

jasie
sumber
4
Berikut ini contoh dengan splenum: dreamincode.net/forums/topic/201638-enum-in-php
Nordes
4
Saya memutar kembali, saya lebih suka kalau saya bisa melihat tautannya. Ini memberi saya informasi konteks.
markus
5
Saya berguling kembali. Saya tidak ingin kalian mengedit tautannya.
markus
6
Hati-hati menggunakan ini. Jenis SPL bersifat eksperimental: "Ekstensi ini adalah EKSPERIMENTAL. Perilaku ekstensi ini termasuk nama fungsinya dan dokumentasi lain di sekitar ekstensi ini dapat berubah tanpa pemberitahuan di rilis PHP mendatang. Ekstensi ini harus digunakan dengan risiko Anda sendiri. "
bzeaman
6
SplEnum tidak dibundel dengan PHP, ia membutuhkan ekstensi
SPL_Types
46

Bagaimana dengan konstanta kelas?

<?php

class YourClass
{
    const SOME_CONSTANT = 1;

    public function echoConstant()
    {
        echo self::SOME_CONSTANT;
    }
}

echo YourClass::SOME_CONSTANT;

$c = new YourClass;
$c->echoConstant();
Peter Bailey
sumber
Saya lebih suka pendekatan sederhana ini
David Lemon
echoConstantdapat diganti dengan __toString. Dan kemudian secara sederhanaecho $c
Justinas
35

Jawaban teratas di atas sangat fantastis. Namun, jika Anda extendmelakukannya dengan dua cara berbeda, maka ekstensi mana yang dilakukan terlebih dahulu menghasilkan panggilan ke fungsi akan membuat cache. Tembolok ini kemudian akan digunakan oleh semua panggilan berikutnya, tidak peduli ekstensi mana pun yang dimulai oleh ...

Untuk mengatasi ini, ganti variabel dan fungsi pertama dengan:

private static $constCacheArray = null;

private static function getConstants() {
    if (self::$constCacheArray === null) self::$constCacheArray = array();

    $calledClass = get_called_class();
    if (!array_key_exists($calledClass, self::$constCacheArray)) {
        $reflect = new \ReflectionClass($calledClass);
        self::$constCacheArray[$calledClass] = $reflect->getConstants();
    }

    return self::$constCacheArray[$calledClass];
}
Neil Townsend
sumber
2
Punya masalah ini. Brian atau seseorang dengan hak istimewa edit harus menyentuhnya di jawaban yang diterima. Saya memecahkannya dalam kode saya menggunakan metode 'static ::' alih-alih 'self ::' dalam fungsi getConstants () dan mendeklarasikan ulang $ constCache di enum anak.
Sp3igel
Ini mungkin tidak seksi, tetapi menggunakan konstanta antarmuka mungkin cara terbaik untuk masuk dalam PHP.
Anthony Rutledge
27

Saya menggunakan kelas dengan konstanta:

class Enum {
    const NAME       = 'aaaa';
    const SOME_VALUE = 'bbbb';
}

print Enum::NAME;
andy.gurin
sumber
27

Saya menggunakan interfacebukannya class:

interface DaysOfWeek
{
    const Sunday = 0;
    const Monday = 1;
    // etc.
}

var $today = DaysOfWeek::Sunday;
Dan itu
sumber
6
class Foo implements DaysOfWeek { }lalu Foo::Sunday... apa?
Dan Lugg
3
Penulis pertanyaan meminta solusi untuk dua hal: namespace dan penyelesaian otomatis oleh IDE. Seperti yang disarankan jawaban berperingkat teratas, cara termudah adalah dengan menggunakan class(atau interface, yang hanya masalah preferensi).
Andi T
4
antarmuka digunakan untuk menegakkan integritas implementasi kelas, ini berada di luar cakupan antarmuka
user3886650
2
@ user3886650 Antarmuka dapat dan pernah / digunakan di Jawa untuk menjaga nilai konstan. Jadi Anda tidak dipaksa untuk instantiate kelas hanya untuk mendapatkan nilai konstan dan setiap IDE menawarkan penyelesaian kode. Juga jika Anda membuat kelas yang mengimplementasikan antarmuka itu akan mewarisi semua konstanta - kadang-kadang cukup berguna.
Alex
@ user3886650 Benar, tetapi dalam PHP, antarmuka dapat memiliki konstanta. Selain itu, konstanta antarmuka ini tidak dapat ditimpa dengan menerapkan kelas, atau anak-anak mereka. Akibatnya, ini adalah jawaban terbaik dalam hal PHP, karena apa pun yang dapat ditimpa tidak benar-benar berfungsi seperti seharusnya. Konstan harus berarti konstan, tidak kadang-kadang (meskipun polimorfisme dapat bermanfaat pada waktu tertentu).
Anthony Rutledge
25

Saya sudah mengomentari beberapa jawaban lain di sini, jadi saya pikir saya akan menimbang juga. Pada akhirnya, karena PHP tidak mendukung pencacahan yang diketik, Anda dapat melakukan salah satu dari dua cara: meretas pencacahan yang diketik, atau hidup dengan kenyataan bahwa mereka sangat sulit untuk dibajak secara efektif.

Saya lebih suka hidup dengan fakta, dan alih-alih menggunakan constmetode yang digunakan oleh jawaban lain di sini:

abstract class Enum
{

    const NONE = null;

    final private function __construct()
    {
        throw new NotSupportedException(); // 
    }

    final private function __clone()
    {
        throw new NotSupportedException();
    }

    final public static function toArray()
    {
        return (new ReflectionClass(static::class))->getConstants();
    }

    final public static function isValid($value)
    {
        return in_array($value, static::toArray());
    }

}

Contoh penghitungan:

final class ResponseStatusCode extends Enum
{

    const OK                         = 200;
    const CREATED                    = 201;
    const ACCEPTED                   = 202;
    // ...
    const SERVICE_UNAVAILABLE        = 503;
    const GATEWAY_TIME_OUT           = 504;
    const HTTP_VERSION_NOT_SUPPORTED = 505;

}

Menggunakan Enumsebagai kelas dasar dari mana semua mantri lainnya memperpanjang memungkinkan untuk metode pembantu, seperti toArray, isValid, dan sebagainya. Bagi saya, mengetik enumerasi ( dan mengelola instans mereka ) akhirnya menjadi terlalu berantakan.


Hipotetis

Jika , ada __getStaticmetode sihir ( dan lebih disukai __equalsmetode sihir juga ) banyak dari ini dapat dikurangi dengan semacam pola multiton.

( Berikut ini adalah hipotesis; itu tidak akan berhasil, meskipun mungkin suatu hari nanti akan )

final class TestEnum
{

    private static $_values = [
        'FOO' => 1,
        'BAR' => 2,
        'QUX' => 3,
    ];
    private static $_instances = [];

    public static function __getStatic($name)
    {
        if (isset(static::$_values[$name]))
        {
            if (empty(static::$_instances[$name]))
            {
                static::$_instances[$name] = new static($name);
            }
            return static::$_instances[$name];
        }
        throw new Exception(sprintf('Invalid enumeration value, "%s"', $name));
    }

    private $_value;

    public function __construct($name)
    {
        $this->_value = static::$_values[$name];
    }

    public function __equals($object)
    {
        if ($object instanceof static)
        {
            return $object->_value === $this->_value;
        }
        return $object === $this->_value;
    }

}

$foo = TestEnum::$FOO; // object(TestEnum)#1 (1) {
                       //   ["_value":"TestEnum":private]=>
                       //   int(1)
                       // }

$zap = TestEnum::$ZAP; // Uncaught exception 'Exception' with message
                       // 'Invalid enumeration member, "ZAP"'

$qux = TestEnum::$QUX;
TestEnum::$QUX == $qux; // true
'hello world!' == $qux; // false
Dan Lugg
sumber
Saya sangat suka kesederhanaan jawaban ini. Ini adalah jenis hal yang dapat Anda ingat kembali nanti dan dengan cepat memahami cara kerjanya tanpa membuatnya tampak seperti Anda melakukan semacam pendekatan yang diretas. Sayang itu tidak memiliki lebih banyak suara.
Reactgular
23

Nah, untuk java sederhana seperti enum di php, saya menggunakan:

class SomeTypeName {
    private static $enum = array(1 => "Read", 2 => "Write");

    public function toOrdinal($name) {
        return array_search($name, self::$enum);
    }

    public function toString($ordinal) {
        return self::$enum[$ordinal];
    }
}

Dan untuk menyebutnya:

SomeTypeName::toOrdinal("Read");
SomeTypeName::toString(1);

Tapi aku pemula PHP, berjuang dengan sintaks jadi ini mungkin bukan cara terbaik. Saya bereksperimen dengan Konstanta Kelas, menggunakan Refleksi untuk mendapatkan nama konstan dari nilainya, mungkin lebih rapi.

aelg
sumber
Jawaban bagus, sebagian besar jawaban lain menggunakan kelas. Anda tidak dapat memiliki kelas bersarang.
Keyo
Ini memiliki manfaat untuk dapat beralih melalui nilai-nilai dengan foreach. Dan kerugian yang nilai ilegal tidak ditangkap.
Bob Stein
2
Tidak ada penyelesaian otomatis dalam IDE, jadi akan merangsang kerja menebak. Konstanta akan memungkinkan penyelesaian otomatis, terdengar lebih baik.
KrekkieD
19

Empat tahun kemudian saya menemukan ini lagi. Pendekatan saya saat ini adalah ini karena memungkinkan untuk penyelesaian kode di IDE serta keamanan jenis:

Kelas dasar:

abstract class TypedEnum
{
    private static $_instancedValues;

    private $_value;
    private $_name;

    private function __construct($value, $name)
    {
        $this->_value = $value;
        $this->_name = $name;
    }

    private static function _fromGetter($getter, $value)
    {
        $reflectionClass = new ReflectionClass(get_called_class());
        $methods = $reflectionClass->getMethods(ReflectionMethod::IS_STATIC | ReflectionMethod::IS_PUBLIC);    
        $className = get_called_class();

        foreach($methods as $method)
        {
            if ($method->class === $className)
            {
                $enumItem = $method->invoke(null);

                if ($enumItem instanceof $className && $enumItem->$getter() === $value)
                {
                    return $enumItem;
                }
            }
        }

        throw new OutOfRangeException();
    }

    protected static function _create($value)
    {
        if (self::$_instancedValues === null)
        {
            self::$_instancedValues = array();
        }

        $className = get_called_class();

        if (!isset(self::$_instancedValues[$className]))
        {
            self::$_instancedValues[$className] = array();
        }

        if (!isset(self::$_instancedValues[$className][$value]))
        {
            $debugTrace = debug_backtrace();
            $lastCaller = array_shift($debugTrace);

            while ($lastCaller['class'] !== $className && count($debugTrace) > 0)
            {
                $lastCaller = array_shift($debugTrace);
            }

            self::$_instancedValues[$className][$value] = new static($value, $lastCaller['function']);
        }

        return self::$_instancedValues[$className][$value];
    }

    public static function fromValue($value)
    {
        return self::_fromGetter('getValue', $value);
    }

    public static function fromName($value)
    {
        return self::_fromGetter('getName', $value);
    }

    public function getValue()
    {
        return $this->_value;
    }

    public function getName()
    {
        return $this->_name;
    }
}

Contoh Enum:

final class DaysOfWeek extends TypedEnum
{
    public static function Sunday() { return self::_create(0); }    
    public static function Monday() { return self::_create(1); }
    public static function Tuesday() { return self::_create(2); }   
    public static function Wednesday() { return self::_create(3); }
    public static function Thursday() { return self::_create(4); }  
    public static function Friday() { return self::_create(5); }
    public static function Saturday() { return self::_create(6); }      
}

Contoh penggunaan:

function saveEvent(DaysOfWeek $weekDay, $comment)
{
    // store week day numeric value and comment:
    $myDatabase->save('myeventtable', 
       array('weekday_id' => $weekDay->getValue()),
       array('comment' => $comment));
}

// call the function, note: DaysOfWeek::Monday() returns an object of type DaysOfWeek
saveEvent(DaysOfWeek::Monday(), 'some comment');

Perhatikan bahwa semua instance dari entri enum yang sama adalah sama:

$monday1 = DaysOfWeek::Monday();
$monday2 = DaysOfWeek::Monday();
$monday1 === $monday2; // true

Anda juga dapat menggunakannya di dalam pernyataan switch:

function getGermanWeekDayName(DaysOfWeek $weekDay)
{
    switch ($weekDay)
    {
        case DaysOfWeek::Monday(): return 'Montag';
        case DaysOfWeek::Tuesday(): return 'Dienstag';
        // ...
}

Anda juga dapat membuat entri enum dengan nama atau nilai:

$monday = DaysOfWeek::fromValue(2);
$tuesday = DaysOfWeek::fromName('Tuesday');

Atau Anda bisa mendapatkan nama (yaitu nama fungsi) dari entri enum yang ada:

$wednesday = DaysOfWeek::Wednesday()
echo $wednesDay->getName(); // Wednesday
Memperbaiki Buck
sumber
+1 untuk konstruktor pribadi. Saya tidak akan membuat kelas abstrak pembantu, hanya kelas sederhana, konstruktor pribadi dan beberapaconst Monday = DaysOfWeek('Monday');
Kangur
9

Saya menemukan perpustakaan ini di github dan saya pikir ini memberikan alternatif yang sangat layak untuk jawaban di sini.

Implementasi PHP Enum terinspirasi dari SplEnum

  • Anda dapat mengetik-petunjuk: function setAction(Action $action) {
  • Anda dapat memperkaya enum dengan metode (misalnya format,parse , ...)
  • Anda dapat memperpanjang enum untuk menambahkan nilai baru (buat enum Anda finaluntuk mencegahnya)
  • Anda bisa mendapatkan daftar semua nilai yang mungkin (lihat di bawah)

Pernyataan

<?php
use MyCLabs\Enum\Enum;

/**
 * Action enum
 */
class Action extends Enum
{
    const VIEW = 'view';
    const EDIT = 'edit';
}

Pemakaian

<?php
$action = new Action(Action::VIEW);

// or
$action = Action::VIEW();

nilai type-hint enum:

<?php
function setAction(Action $action) {
    // ...
}
Songo
sumber
1
Ini adalah jawaban yang benar (untuk saat ini, hingga enumditambahkan dalam PHP 7.x) karena memungkinkan mengetikkan petunjuk.
Tobia
1
Ini tidak hanya memungkinkan tipe-hinting, tetapi karena __toString()keajaiban, ini memungkinkan Anda untuk melakukan apa yang umumnya Anda benar-benar ingin dengan enum - menggunakannya dalam pernyataan switchatau if, membandingkan langsung dengan nilai-nilai dari consts. Pendekatan terbaik singkat dari dukungan enum asli, IMO.
LinusR
7

Jika Anda perlu menggunakan enum yang unik secara global (yaitu, bahkan ketika membandingkan elemen antara berbagai Enum) dan mudah digunakan, jangan ragu untuk menggunakan kode berikut. Saya juga menambahkan beberapa metode yang menurut saya berguna. Anda akan menemukan contoh di komentar di bagian paling atas kode.

<?php

/**
 * Class Enum
 * 
 * @author Christopher Fox <[email protected]>
 *
 * @version 1.0
 *
 * This class provides the function of an enumeration.
 * The values of Enum elements are unique (even between different Enums)
 * as you would expect them to be.
 *
 * Constructing a new Enum:
 * ========================
 *
 * In the following example we construct an enum called "UserState"
 * with the elements "inactive", "active", "banned" and "deleted".
 * 
 * <code>
 * Enum::Create('UserState', 'inactive', 'active', 'banned', 'deleted');
 * </code>
 *
 * Using Enums:
 * ============
 *
 * The following example demonstrates how to compare two Enum elements
 *
 * <code>
 * var_dump(UserState::inactive == UserState::banned); // result: false
 * var_dump(UserState::active == UserState::active); // result: true
 * </code>
 *
 * Special Enum methods:
 * =====================
 *
 * Get the number of elements in an Enum:
 *
 * <code>
 * echo UserState::CountEntries(); // result: 4
 * </code>
 *
 * Get a list with all elements of the Enum:
 *
 * <code>
 * $allUserStates = UserState::GetEntries();
 * </code>
 *
 * Get a name of an element:
 *
 * <code>
 * echo UserState::GetName(UserState::deleted); // result: deleted
 * </code>
 *
 * Get an integer ID for an element (e.g. to store as a value in a database table):
 * This is simply the index of the element (beginning with 1).
 * Note that this ID is only unique for this Enum but now between different Enums.
 *
 * <code>
 * echo UserState::GetDatabaseID(UserState::active); // result: 2
 * </code>
 */
class Enum
{

    /**
     * @var Enum $instance The only instance of Enum (Singleton)
     */
    private static $instance;

    /**
     * @var array $enums    An array of all enums with Enum names as keys
     *          and arrays of element names as values
     */
    private $enums;

    /**
     * Constructs (the only) Enum instance
     */
    private function __construct()
    {
        $this->enums = array();
    }

    /**
     * Constructs a new enum
     *
     * @param string $name The class name for the enum
     * @param mixed $_ A list of strings to use as names for enum entries
     */
    public static function Create($name, $_)
    {
        // Create (the only) Enum instance if this hasn't happened yet
        if (self::$instance===null)
        {
            self::$instance = new Enum();
        }

        // Fetch the arguments of the function
        $args = func_get_args();
        // Exclude the "name" argument from the array of function arguments,
        // so only the enum element names remain in the array
        array_shift($args);
        self::$instance->add($name, $args);
    }

    /**
     * Creates an enumeration if this hasn't happened yet
     * 
     * @param string $name The class name for the enum
     * @param array $fields The names of the enum elements
     */
    private function add($name, $fields)
    {
        if (!array_key_exists($name, $this->enums))
        {
            $this->enums[$name] = array();

            // Generate the code of the class for this enumeration
            $classDeclaration =     "class " . $name . " {\n"
                        . "private static \$name = '" . $name . "';\n"
                        . $this->getClassConstants($name, $fields)
                        . $this->getFunctionGetEntries($name)
                        . $this->getFunctionCountEntries($name)
                        . $this->getFunctionGetDatabaseID()
                        . $this->getFunctionGetName()
                        . "}";

            // Create the class for this enumeration
            eval($classDeclaration);
        }
    }

    /**
     * Returns the code of the class constants
     * for an enumeration. These are the representations
     * of the elements.
     * 
     * @param string $name The class name for the enum
     * @param array $fields The names of the enum elements
     *
     * @return string The code of the class constants
     */
    private function getClassConstants($name, $fields)
    {
        $constants = '';

        foreach ($fields as $field)
        {
            // Create a unique ID for the Enum element
            // This ID is unique because class and variables
            // names can't contain a semicolon. Therefore we
            // can use the semicolon as a separator here.
            $uniqueID = $name . ";" . $field;
            $constants .=   "const " . $field . " = '". $uniqueID . "';\n";
            // Store the unique ID
            array_push($this->enums[$name], $uniqueID);
        }

        return $constants;
    }

    /**
     * Returns the code of the function "GetEntries()"
     * for an enumeration
     * 
     * @param string $name The class name for the enum
     *
     * @return string The code of the function "GetEntries()"
     */
    private function getFunctionGetEntries($name) 
    {
        $entryList = '';        

        // Put the unique element IDs in single quotes and
        // separate them with commas
        foreach ($this->enums[$name] as $key => $entry)
        {
            if ($key > 0) $entryList .= ',';
            $entryList .= "'" . $entry . "'";
        }

        return  "public static function GetEntries() { \n"
            . " return array(" . $entryList . ");\n"
            . "}\n";
    }

    /**
     * Returns the code of the function "CountEntries()"
     * for an enumeration
     * 
     * @param string $name The class name for the enum
     *
     * @return string The code of the function "CountEntries()"
     */
    private function getFunctionCountEntries($name) 
    {
        // This function will simply return a constant number (e.g. return 5;)
        return  "public static function CountEntries() { \n"
            . " return " . count($this->enums[$name]) . ";\n"
            . "}\n";
    }

    /**
     * Returns the code of the function "GetDatabaseID()"
     * for an enumeration
     * 
     * @return string The code of the function "GetDatabaseID()"
     */
    private function getFunctionGetDatabaseID()
    {
        // Check for the index of this element inside of the array
        // of elements and add +1
        return  "public static function GetDatabaseID(\$entry) { \n"
            . "\$key = array_search(\$entry, self::GetEntries());\n"
            . " return \$key + 1;\n"
            . "}\n";
    }

    /**
     * Returns the code of the function "GetName()"
     * for an enumeration
     *
     * @return string The code of the function "GetName()"
     */
    private function getFunctionGetName()
    {
        // Remove the class name from the unique ID 
        // and return this value (which is the element name)
        return  "public static function GetName(\$entry) { \n"
            . "return substr(\$entry, strlen(self::\$name) + 1 , strlen(\$entry));\n"
            . "}\n";
    }

}


?>
Christopher Fox
sumber
1
Saya sangat suka ini. Namun, salah satu keluhan utama adalah kemampuan IDE untuk mengambil nilai untuk pelengkapan otomatis. Saya tidak yakin ini bisa melakukannya tanpa addon khusus untuk IDE. Bukannya itu tidak bisa dilakukan, hanya akan butuh beberapa pekerjaan.
corsiKa
2
Menggunakan eval()hanya supaya Anda dapat mendeklarasikan runtime Enums baru? Eek. Saya tidak merasakannya. Bagaimana Anda mencegah kelas lain dari membuat kelas Enum yang salah sebelum Anda bisa mendefinisikan yang tepat? Bukankah Enums dikenal sebelum runtime? Dan seperti @corsiKa tersirat, tidak ada pelengkapan otomatis IDE. Satu-satunya manfaat yang saya lihat adalah malas coding.
KrekkieD
7

Saya suka enum dari java juga dan untuk alasan ini saya menulis enum saya dengan cara ini, saya pikir ini adalah yang paling mirip seperti di enum Jawa, tentu saja, jika beberapa ingin menggunakan lebih banyak metode dari java harus menulisnya di sini, atau di kelas abstrak tetapi ide inti tertanam dalam kode di bawah ini


class FruitsEnum {

    static $APPLE = null;
    static $ORANGE = null;

    private $value = null;

    public static $map;

    public function __construct($value) {
        $this->value = $value;
    }

    public static function init () {
        self::$APPLE  = new FruitsEnum("Apple");
        self::$ORANGE = new FruitsEnum("Orange");
        //static map to get object by name - example Enum::get("INIT") - returns Enum::$INIT object;
        self::$map = array (
            "Apple" => self::$APPLE,
            "Orange" => self::$ORANGE
        );
    }

    public static function get($element) {
        if($element == null)
            return null;
        return self::$map[$element];
    }

    public function getValue() {
        return $this->value;
    }

    public function equals(FruitsEnum $element) {
        return $element->getValue() == $this->getValue();
    }

    public function __toString () {
        return $this->value;
    }
}
FruitsEnum::init();

var_dump(FruitsEnum::$APPLE->equals(FruitsEnum::$APPLE)); //true
var_dump(FruitsEnum::$APPLE->equals(FruitsEnum::$ORANGE)); //false
var_dump(FruitsEnum::$APPLE instanceof FruitsEnum); //true
var_dump(FruitsEnum::get("Apple")->equals(FruitsEnum::$APPLE)); //true - enum from string
var_dump(FruitsEnum::get("Apple")->equals(FruitsEnum::get("Orange"))); //false
pengguna667540
sumber
3
Saya melakukan hal yang hampir sama, dengan dua tambahan kecil: Saya telah menyembunyikan nilai statis di belakang pengambil statis. Salah satu alasannya adalah, bahwa saya visual lebih suka FruitsEnum::Apple()lebih FruitsEnum::$Apple, tetapi alasan yang lebih penting adalah untuk mencegah orang lain dari pengaturan $APPLE, sehingga melanggar enum untuk seluruh aplikasi. Yang lain adalah bendera statis pribadi sederhana $initializedyang memastikan bahwa panggilan init()menjadi no-op setelah memanggilnya untuk pertama kalinya (jadi tidak ada yang bisa mengacaukannya juga).
Martin Ender
Saya suka Martin. .init()aneh, dan saya tidak keberatan dengan pendekatan rajin.
Sebas
7
abstract class Enumeration
{
    public static function enum() 
    {
        $reflect = new ReflectionClass( get_called_class() );
        return $reflect->getConstants();
    }
}


class Test extends Enumeration
{
    const A = 'a';
    const B = 'b';    
}


foreach (Test::enum() as $key => $value) {
    echo "$key -> $value<br>";
}
jglatre
sumber
6

Mungkin sesederhana itu

enum DaysOfWeek {
    Sunday,
    Monday,
    // ...
}

di masa depan.

PHP RFC: Jenis yang Dihitung

mykhal
sumber
FYI pada 7,1 masih tidak di sini
toddmo
5

Solusi paling umum yang saya lihat untuk enum di PHP adalah membuat kelas enum generik dan kemudian memperluasnya. Anda mungkin melihat ini .

UPDATE: Atau, saya menemukan ini dari phpclasses.org.

Noah Goodrich
sumber
1
Meskipun implementasinya apik dan mungkin akan melakukan pekerjaannya, sisi buruknya adalah bahwa IDE mungkin tidak tahu cara mengisi ulang enum secara otomatis. Saya tidak dapat memeriksa yang dari phpclasses.org, karena ingin saya mendaftar.
Henrik Paul
5

Berikut ini adalah pustaka github untuk menangani enumerasi tipe-aman di php:

Perpustakaan ini menangani pembuatan kelas, caching kelas dan mengimplementasikan pola desain Penghitungan Jenis Aman, dengan beberapa metode penolong untuk menangani enum, seperti mengambil ordinal untuk pengurutan enum, atau mengambil nilai biner, untuk kombinasi enum.

Kode yang dihasilkan menggunakan file templat php lama yang sederhana, yang juga dapat dikonfigurasi, sehingga Anda dapat menyediakan templat Anda sendiri.

Ini adalah tes penuh yang ditutupi dengan phpunit.

php-enums di github (jangan ragu untuk bercabang)

Penggunaan: (lihat lihat use.php, atau unit test untuk lebih jelasnya)

<?php
//require the library
require_once __DIR__ . '/src/Enum.func.php';

//if you don't have a cache directory, create one
@mkdir(__DIR__ . '/cache');
EnumGenerator::setDefaultCachedClassesDir(__DIR__ . '/cache');

//Class definition is evaluated on the fly:
Enum('FruitsEnum', array('apple' , 'orange' , 'rasberry' , 'bannana'));

//Class definition is cached in the cache directory for later usage:
Enum('CachedFruitsEnum', array('apple' , 'orange' , 'rasberry' , 'bannana'), '\my\company\name\space', true);

echo 'FruitsEnum::APPLE() == FruitsEnum::APPLE(): ';
var_dump(FruitsEnum::APPLE() == FruitsEnum::APPLE()) . "\n";

echo 'FruitsEnum::APPLE() == FruitsEnum::ORANGE(): ';
var_dump(FruitsEnum::APPLE() == FruitsEnum::ORANGE()) . "\n";

echo 'FruitsEnum::APPLE() instanceof Enum: ';
var_dump(FruitsEnum::APPLE() instanceof Enum) . "\n";

echo 'FruitsEnum::APPLE() instanceof FruitsEnum: ';
var_dump(FruitsEnum::APPLE() instanceof FruitsEnum) . "\n";

echo "->getName()\n";
foreach (FruitsEnum::iterator() as $enum)
{
  echo "  " . $enum->getName() . "\n";
}

echo "->getValue()\n";
foreach (FruitsEnum::iterator() as $enum)
{
  echo "  " . $enum->getValue() . "\n";
}

echo "->getOrdinal()\n";
foreach (CachedFruitsEnum::iterator() as $enum)
{
  echo "  " . $enum->getOrdinal() . "\n";
}

echo "->getBinary()\n";
foreach (CachedFruitsEnum::iterator() as $enum)
{
  echo "  " . $enum->getBinary() . "\n";
}

Keluaran:

FruitsEnum::APPLE() == FruitsEnum::APPLE(): bool(true)
FruitsEnum::APPLE() == FruitsEnum::ORANGE(): bool(false)
FruitsEnum::APPLE() instanceof Enum: bool(true)
FruitsEnum::APPLE() instanceof FruitsEnum: bool(true)
->getName()
  APPLE
  ORANGE
  RASBERRY
  BANNANA
->getValue()
  apple
  orange
  rasberry
  bannana
->getValue() when values have been specified
  pig
  dog
  cat
  bird
->getOrdinal()
  1
  2
  3
  4
->getBinary()
  1
  2
  4
  8
zanshine
sumber
4

Saya telah mengambil untuk menggunakan pendekatan di bawah ini karena memberi saya kemampuan untuk memiliki tipe keselamatan untuk parameter fungsi, otomatis selesai di NetBeans dan kinerja yang baik. Satu hal yang saya tidak suka terlalu banyak adalah bahwa Anda harus menelepon [extended class name]::enumerate();setelah mendefinisikan kelas.

abstract class Enum {

    private $_value;

    protected function __construct($value) {
        $this->_value = $value;
    }

    public function __toString() {
        return (string) $this->_value;
    }

    public static function enumerate() {
        $class = get_called_class();
        $ref = new ReflectionClass($class);
        $statics = $ref->getStaticProperties();
        foreach ($statics as $name => $value) {
            $ref->setStaticPropertyValue($name, new $class($value));
        }
    }
}

class DaysOfWeek extends Enum {
    public static $MONDAY = 0;
    public static $SUNDAY = 1;
    // etc.
}
DaysOfWeek::enumerate();

function isMonday(DaysOfWeek $d) {
    if ($d == DaysOfWeek::$MONDAY) {
        return true;
    } else {
        return false;
    }
}

$day = DaysOfWeek::$MONDAY;
echo (isMonday($day) ? "bummer it's monday" : "Yay! it's not monday");
Brian Fisher
sumber
Tidak ada yang mencegah Anda mendefinisikan ulang nilai enum:DaysOfWeek::$MONDAY = 3;
KrekkieD
@BrianFisher, saya tahu ini sudah terlambat sekarang, tetapi, jika Anda tidak suka memanggil [extended class name]::enumerate();definisi, mengapa Anda tidak melakukannya dalam konstruksi?
Bisakah O 'Spam
4

Definisi kelas Enum saya di bawah ini sangat diketik , dan sangat alami untuk digunakan dan didefinisikan.

Definisi:

class Fruit extends Enum {
    static public $APPLE = 1;
    static public $ORANGE = 2;
}
Fruit::initialize(); //Can also be called in autoloader

Ganti Enum

$myFruit = Fruit::$APPLE;

switch ($myFruit) {
    case Fruit::$APPLE  : echo "I like apples\n";  break;
    case Fruit::$ORANGE : echo "I hate oranges\n"; break;
}

>> I like apples

Pass Enum sebagai parameter (Sangat diketik)

/** Function only accepts Fruit enums as input**/
function echoFruit(Fruit $fruit) {
    echo $fruit->getName().": ".$fruit->getValue()."\n";
}

/** Call function with each Enum value that Fruit has */
foreach (Fruit::getList() as $fruit) {
    echoFruit($fruit);
}

//Call function with Apple enum
echoFruit(Fruit::$APPLE)

//Will produce an error. This solution is strongly typed
echoFruit(2);

>> APPLE: 1
>> ORANGE: 2
>> APPLE: 1
>> Argument 1 passed to echoFruit() must be an instance of Fruit, integer given

Echo Enum sebagai string

echo "I have an $myFruit\n";

>> I have an APPLE

Dapatkan Enum dengan integer

$myFruit = Fruit::getByValue(2);

echo "Now I have an $myFruit\n";

>> Now I have an ORANGE

Dapatkan Enum dengan Nama

$myFruit = Fruit::getByName("APPLE");

echo "But I definitely prefer an $myFruit\n\n";

>> But I definitely prefer an APPLE

Kelas Enum:

/**
 * @author Torge Kummerow
 */
class Enum {

    /**
     * Holds the values for each type of Enum
     */
    static private $list = array();

    /**
     * Initializes the enum values by replacing the number with an instance of itself
     * using reflection
     */
    static public function initialize() {
        $className = get_called_class();
        $class = new ReflectionClass($className);
        $staticProperties = $class->getStaticProperties();

        self::$list[$className] = array();

        foreach ($staticProperties as $propertyName => &$value) {
            if ($propertyName == 'list')
                continue;

            $enum = new $className($propertyName, $value);
            $class->setStaticPropertyValue($propertyName, $enum);
            self::$list[$className][$propertyName] = $enum;
        } unset($value);
    }


    /**
     * Gets the enum for the given value
     *
     * @param integer $value
     * @throws Exception
     *
     * @return Enum
     */
    static public function getByValue($value) {
        $className = get_called_class();
        foreach (self::$list[$className] as $propertyName=>&$enum) {
            /* @var $enum Enum */
            if ($enum->value == $value)
                return $enum;
        } unset($enum);

        throw new Exception("No such enum with value=$value of type ".get_called_class());
    }

    /**
     * Gets the enum for the given name
     *
     * @param string $name
     * @throws Exception
     *
     * @return Enum
     */
    static public function getByName($name) {
        $className = get_called_class();
        if (array_key_exists($name, static::$list[$className]))
            return self::$list[$className][$name];

        throw new Exception("No such enum ".get_called_class()."::\$$name");
    }


    /**
     * Returns the list of all enum variants
     * @return Array of Enum
     */
    static public function getList() {
        $className = get_called_class();
        return self::$list[$className];
    }


    private $name;
    private $value;

    public function __construct($name, $value) {
        $this->name = $name;
        $this->value = $value;
    }

    public function __toString() {
        return $this->name;
    }

    public function getValue() {
        return $this->value;
    }

    public function getName() {
        return $this->name;
    }

}

Tambahan

Anda juga dapat menambahkan komentar untuk IDE

class Fruit extends Enum {

    /**
     * This comment is for autocomplete support in common IDEs
     * @var Fruit A yummy apple
     */
    static public $APPLE = 1;

    /**
     * This comment is for autocomplete support in common IDEs
     * @var Fruit A sour orange
     */
    static public $ORANGE = 2;
}

//This can also go to the autoloader if available.
Fruit::initialize();
Torge
sumber
4

Saya menyadari ini adalah utas yang sangat-sangat-sangat tua tetapi saya memiliki pemikiran tentang ini dan ingin tahu apa yang dipikirkan orang.

Catatan: Saya sedang bermain-main dengan ini dan menyadari bahwa jika saya baru saja memodifikasi __call()fungsi yang Anda bisa lebih dekat dengan yang sebenarnya enums. The __call()Fungsi menangani semua panggilan fungsi yang tidak diketahui. Jadi katakanlah Anda ingin membuat tiga enumsRED_LIGHT, YELLOW_LIGHT, dan GREEN_LIGHT. Anda dapat melakukannya sekarang hanya dengan melakukan hal berikut:

$c->RED_LIGHT();
$c->YELLOW_LIGHT();
$c->GREEN_LIGHT();

Setelah ditentukan, yang harus Anda lakukan adalah memanggil mereka lagi untuk mendapatkan nilai:

echo $c->RED_LIGHT();
echo $c->YELLOW_LIGHT();
echo $c->GREEN_LIGHT();

dan Anda harus mendapatkan 0, 1, dan 2. Selamat bersenang-senang! Ini juga sekarang di GitHub.

Pembaruan: Saya telah membuatnya sehingga fungsi __get()dan __set()sekarang digunakan. Ini memungkinkan Anda untuk tidak harus memanggil fungsi kecuali jika Anda mau. Sebaliknya, sekarang Anda bisa mengatakan:

$c->RED_LIGHT;
$c->YELLOW_LIGHT;
$c->GREEN_LIGHT;

Baik untuk kreasi dan mendapatkan nilai-nilai. Karena variabel belum didefinisikan pada awalnya, __get()fungsi dipanggil (karena tidak ada nilai yang ditentukan) yang melihat bahwa entri dalam array belum dibuat. Jadi ia membuat entri, memberikannya nilai terakhir yang diberikan ditambah satu (+1), menambah variabel nilai terakhir, dan mengembalikan TRUE. Jika Anda menetapkan nilai:

$c->RED_LIGHT = 85;

Kemudian __set()fungsi dipanggil dan nilai terakhir kemudian diatur ke nilai baru plus satu (+1). Jadi sekarang kita memiliki cara yang cukup baik untuk melakukan enum dan mereka dapat dibuat dengan cepat.

<?php
################################################################################
#   Class ENUMS
#
#       Original code by Mark Manning.
#       Copyrighted (c) 2015 by Mark Manning.
#       All rights reserved.
#
#       This set of code is hereby placed into the free software universe
#       via the GNU greater license thus placing it under the Copyleft
#       rules and regulations with the following modifications:
#
#       1. You may use this work in any other work.  Commercial or otherwise.
#       2. You may make as much money as you can with it.
#       3. You owe me nothing except to give me a small blurb somewhere in
#           your program or maybe have pity on me and donate a dollar to
#           [email protected].  :-)
#
#   Blurb:
#
#       PHP Class Enums by Mark Manning (markem-AT-sim1-DOT-us).
#       Used with permission.
#
#   Notes:
#
#       VIM formatting.  Set tabs to four(4) spaces.
#
################################################################################
class enums
{
    private $enums;
    private $clear_flag;
    private $last_value;

################################################################################
#   __construct(). Construction function.  Optionally pass in your enums.
################################################################################
function __construct()
{
    $this->enums = array();
    $this->clear_flag = false;
    $this->last_value = 0;

    if( func_num_args() > 0 ){
        return $this->put( func_get_args() );
        }

    return true;
}
################################################################################
#   put(). Insert one or more enums.
################################################################################
function put()
{
    $args = func_get_args();
#
#   Did they send us an array of enums?
#   Ex: $c->put( array( "a"=>0, "b"=>1,...) );
#   OR  $c->put( array( "a", "b", "c",... ) );
#
    if( is_array($args[0]) ){
#
#   Add them all in
#
        foreach( $args[0] as $k=>$v ){
#
#   Don't let them change it once it is set.
#   Remove the IF statement if you want to be able to modify the enums.
#
            if( !isset($this->enums[$k]) ){
#
#   If they sent an array of enums like this: "a","b","c",... then we have to
#   change that to be "A"=>#. Where "#" is the current count of the enums.
#
                if( is_numeric($k) ){
                    $this->enums[$v] = $this->last_value++;
                    }
#
#   Else - they sent "a"=>"A", "b"=>"B", "c"=>"C"...
#
                    else {
                        $this->last_value = $v + 1;
                        $this->enums[$k] = $v;
                        }
                }
            }
        }
#
#   Nope!  Did they just sent us one enum?
#
        else {
#
#   Is this just a default declaration?
#   Ex: $c->put( "a" );
#
            if( count($args) < 2 ){
#
#   Again - remove the IF statement if you want to be able to change the enums.
#
                if( !isset($this->enums[$args[0]]) ){
                    $this->enums[$args[0]] = $this->last_value++;
                    }
#
#   No - they sent us a regular enum
#   Ex: $c->put( "a", "This is the first enum" );
#
                    else {
#
#   Again - remove the IF statement if you want to be able to change the enums.
#
                        if( !isset($this->enums[$args[0]]) ){
                            $this->last_value = $args[1] + 1;
                            $this->enums[$args[0]] = $args[1];
                            }
                        }
                }
            }

    return true;
}
################################################################################
#   get(). Get one or more enums.
################################################################################
function get()
{
    $num = func_num_args();
    $args = func_get_args();
#
#   Is this an array of enums request? (ie: $c->get(array("a","b","c"...)) )
#
    if( is_array($args[0]) ){
        $ary = array();
        foreach( $args[0] as $k=>$v ){
            $ary[$v] = $this->enums[$v];
            }

        return $ary;
        }
#
#   Is it just ONE enum they want? (ie: $c->get("a") )
#
        else if( ($num > 0) && ($num < 2) ){
            return $this->enums[$args[0]];
            }
#
#   Is it a list of enums they want? (ie: $c->get( "a", "b", "c"...) )
#
        else if( $num > 1 ){
            $ary = array();
            foreach( $args as $k=>$v ){
                $ary[$v] = $this->enums[$v];
                }

            return $ary;
            }
#
#   They either sent something funky or nothing at all.
#
    return false;
}
################################################################################
#   clear(). Clear out the enum array.
#       Optional.  Set the flag in the __construct function.
#       After all, ENUMS are supposed to be constant.
################################################################################
function clear()
{
    if( $clear_flag ){
        unset( $this->enums );
        $this->enums = array();
        }

    return true;
}
################################################################################
#   __call().  In case someone tries to blow up the class.
################################################################################
function __call( $name, $arguments )
{
    if( isset($this->enums[$name]) ){ return $this->enums[$name]; }
        else if( !isset($this->enums[$name]) && (count($arguments) > 0) ){
            $this->last_value = $arguments[0] + 1;
            $this->enums[$name] = $arguments[0];
            return true;
            }
        else if( !isset($this->enums[$name]) && (count($arguments) < 1) ){
            $this->enums[$name] = $this->last_value++;
            return true;
            }

    return false;
}
################################################################################
#   __get(). Gets the value.
################################################################################
function __get($name)
{
    if( isset($this->enums[$name]) ){ return $this->enums[$name]; }
        else if( !isset($this->enums[$name]) ){
            $this->enums[$name] = $this->last_value++;
            return true;
            }

    return false;
}
################################################################################
#   __set().  Sets the value.
################################################################################
function __set( $name, $value=null )
{
    if( isset($this->enums[$name]) ){ return false; }
        else if( !isset($this->enums[$name]) && !is_null($value) ){
            $this->last_value = $value + 1;
            $this->enums[$name] = $value;
            return true;
            }
        else if( !isset($this->enums[$name]) && is_null($value) ){
            $this->enums[$name] = $this->last_value++;
            return true;
            }

    return false;
}
################################################################################
#   __destruct().  Deconstruct the class.  Remove the list of enums.
################################################################################
function __destruct()
{
    unset( $this->enums );
    $this->enums = null;

    return true;
}

}
#
#   Test code
#
#   $c = new enums();
#   $c->RED_LIGHT(85);
#   $c->YELLOW_LIGHT = 23;
#   $c->GREEN_LIGHT;
#
#   echo $c->RED_LIGHT . "\n";
#   echo $c->YELLOW_LIGHT . "\n";
#   echo $c->GREEN_LIGHT . "\n";

?>
Mark Manning
sumber
3

Saya tahu ini adalah utas lama, namun tidak satu pun dari penyelesaian yang saya lihat benar-benar tampak seperti enum, karena hampir semua pemecahan masalah mengharuskan Anda untuk secara manual menetapkan nilai ke item enum, atau mengharuskan Anda untuk meneruskan serangkaian kunci enum ke sebuah fungsi. Jadi saya buat solusi sendiri untuk ini.

Untuk membuat kelas enum menggunakan solusi saya, seseorang dapat dengan mudah memperluas kelas Enum di bawah ini, membuat sekelompok variabel statis (tidak perlu menginisialisasi mereka), dan membuat panggilan ke yourEnumClass :: init () tepat di bawah definisi kelas enum Anda .

sunting: Ini hanya berfungsi di php> = 5.3, tetapi mungkin dapat dimodifikasi untuk berfungsi di versi yang lebih lama juga

/**
 * A base class for enums. 
 * 
 * This class can be used as a base class for enums. 
 * It can be used to create regular enums (incremental indices), but it can also be used to create binary flag values.
 * To create an enum class you can simply extend this class, and make a call to <yourEnumClass>::init() before you use the enum.
 * Preferably this call is made directly after the class declaration. 
 * Example usages:
 * DaysOfTheWeek.class.php
 * abstract class DaysOfTheWeek extends Enum{
 *      static $MONDAY = 1;
 *      static $TUESDAY;
 *      static $WEDNESDAY;
 *      static $THURSDAY;
 *      static $FRIDAY;
 *      static $SATURDAY;
 *      static $SUNDAY;
 * }
 * DaysOfTheWeek::init();
 * 
 * example.php
 * require_once("DaysOfTheWeek.class.php");
 * $today = date('N');
 * if ($today == DaysOfTheWeek::$SUNDAY || $today == DaysOfTheWeek::$SATURDAY)
 *      echo "It's weekend!";
 * 
 * Flags.class.php
 * abstract class Flags extends Enum{
 *      static $FLAG_1;
 *      static $FLAG_2;
 *      static $FLAG_3;
 * }
 * Flags::init(Enum::$BINARY_FLAG);
 * 
 * example2.php
 * require_once("Flags.class.php");
 * $flags = Flags::$FLAG_1 | Flags::$FLAG_2;
 * if ($flags & Flags::$FLAG_1)
 *      echo "Flag_1 is set";
 * 
 * @author Tiddo Langerak
 */
abstract class Enum{

    static $BINARY_FLAG = 1;
    /**
     * This function must be called to initialize the enumeration!
     * 
     * @param bool $flags If the USE_BINARY flag is provided, the enum values will be binary flag values. Default: no flags set.
     */ 
    public static function init($flags = 0){
        //First, we want to get a list of all static properties of the enum class. We'll use the ReflectionClass for this.
        $enum = get_called_class();
        $ref = new ReflectionClass($enum);
        $items = $ref->getStaticProperties();
        //Now we can start assigning values to the items. 
        if ($flags & self::$BINARY_FLAG){
            //If we want binary flag values, our first value should be 1.
            $value = 1;
            //Now we can set the values for all items.
            foreach ($items as $key=>$item){
                if (!isset($item)){                 
                    //If no value is set manually, we should set it.
                    $enum::$$key = $value;
                    //And we need to calculate the new value
                    $value *= 2;
                } else {
                    //If there was already a value set, we will continue starting from that value, but only if that was a valid binary flag value.
                    //Otherwise, we will just skip this item.
                    if ($key != 0 && ($key & ($key - 1) == 0))
                        $value = 2 * $item;
                }
            }
        } else {
            //If we want to use regular indices, we'll start with index 0.
            $value = 0;
            //Now we can set the values for all items.
            foreach ($items as $key=>$item){
                if (!isset($item)){
                    //If no value is set manually, we should set it, and increment the value for the next item.
                    $enum::$$key = $value;
                    $value++;
                } else {
                    //If a value was already set, we'll continue from that value.
                    $value = $item+1;
                }
            }
        }
    }
}
Tiddo
sumber
3

Sekarang Anda dapat menggunakan kelas The SplEnum untuk membangunnya secara asli. Sesuai dokumentasi resmi.

SplEnum memberikan kemampuan untuk meniru dan membuat objek enumerasi secara native di PHP.

<?php
class Month extends SplEnum {
    const __default = self::January;

    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 new Month(Month::June) . PHP_EOL;

try {
    new Month(13);
} catch (UnexpectedValueException $uve) {
    echo $uve->getMessage() . PHP_EOL;
}
?>

Harap dicatat, ini adalah ekstensi yang harus diinstal, tetapi tidak tersedia secara default. Yang termasuk dalam Tipe Khusus yang dijelaskan dalam situs web php itu sendiri. Contoh di atas diambil dari situs PHP.

Krishnadas PC
sumber
3

Akhirnya, jawaban PHP 7.1+ dengan konstanta yang tidak dapat diganti.

/**
 * An interface that groups HTTP Accept: header Media Types in one place.
 */
interface MediaTypes
{
    /**
    * Now, if you have to use these same constants with another class, you can
    * without creating funky inheritance / is-a relationships.
    * Also, this gets around the single inheritance limitation.
    */

    public const HTML = 'text/html';
    public const JSON = 'application/json';
    public const XML = 'application/xml';
    public const TEXT = 'text/plain';
}

/**
 * An generic request class.
 */
abstract class Request
{
    // Why not put the constants here?
    // 1) The logical reuse issue.
    // 2) Single Inheritance. 
    // 3) Overriding is possible.

    // Why put class constants here?
    // 1) The constant value will not be necessary in other class families.
}

/**
 * An incoming / server-side HTTP request class.
 */
class HttpRequest extends Request implements MediaTypes
{
    // This class can implement groups of constants as necessary.
}

Jika Anda menggunakan ruang nama, penyelesaian kode harus berfungsi.

Namun, dalam melakukan ini, Anda kehilangan kemampuan untuk menyembunyikan konstanta dalam keluarga kelas ( protected) atau kelas saja ( private). Menurut definisi, segala sesuatu di dalam Interfaceadalah public.

Manual PHP: Antarmuka

Anthony Rutledge
sumber
Ini bukan Java. Ini bekerja dalam kasus di mana polimorfisme / pola Strategi tidak diperlukan untuk mengesampingkan konstanta di kelas induk.
Anthony Rutledge
2

Ini adalah pendapat saya tentang "dinamis" enum ... sehingga saya bisa menyebutnya dengan variabel, mis. dari formulir.

lihat verison yang diperbarui di bawah kode kunci ini ...

$value = "concert";
$Enumvalue = EnumCategory::enum($value);
//$EnumValue = 1

class EnumCategory{
    const concert = 1;
    const festival = 2;
    const sport = 3;
    const nightlife = 4;
    const theatre = 5;
    const musical = 6;
    const cinema = 7;
    const charity = 8;
    const museum = 9;
    const other = 10;

    public function enum($string){
        return constant('EnumCategory::'.$string);
    }
}

UPDATE: Cara yang lebih baik untuk melakukannya ...

class EnumCategory {

    static $concert = 1;
    static $festival = 2;
    static $sport = 3;
    static $nightlife = 4;
    static $theatre = 5;
    static $musical = 6;
    static $cinema = 7;
    static $charity = 8;
    static $museum = 9;
    static $other = 10;

}

Telepon dengan

EnumCategory::${$category};
Anders
sumber
5
Masalah dengan makhluk ini; EnumCategory::$sport = 9;. Selamat datang di museum olahraga. const adalah cara yang lebih baik untuk melakukannya.
Dan Lugg
2

Jawaban yang diterima adalah cara untuk pergi dan sebenarnya apa yang saya lakukan untuk kesederhanaan. Sebagian besar keuntungan dari pencacahan ditawarkan (dapat dibaca, cepat, dll.). Namun, satu konsep tidak ada: tipe safety. Dalam sebagian besar bahasa, enumerasi juga digunakan untuk membatasi nilai yang diizinkan. Di bawah ini adalah contoh bagaimana keamanan jenis juga dapat diperoleh dengan menggunakan konstruktor pribadi, metode instantiasi statis dan pengecekan tipe:

class DaysOfWeek{
 const Sunday = 0;
 const Monday = 1;
 // etc.

 private $intVal;
 private function __construct($intVal){
   $this->intVal = $intVal;
 }

 //static instantiation methods
 public static function MONDAY(){
   return new self(self::Monday);
 }
 //etc.
}

//function using type checking
function printDayOfWeek(DaysOfWeek $d){ //compiler can now use type checking
  // to something with $d...
}

//calling the function is safe!
printDayOfWeek(DaysOfWeek::MONDAY());

Kita bahkan dapat melangkah lebih jauh: menggunakan konstanta di kelas DaysOfWeek dapat menyebabkan penyalahgunaan: misalnya orang mungkin salah menggunakannya seperti ini:

printDayOfWeek(DaysOfWeek::Monday); //triggers a compiler error.

yang salah (memanggil konstanta integer). Kita dapat mencegah ini menggunakan variabel statis pribadi alih-alih konstanta:

class DaysOfWeeks{

  private static $monday = 1;
  //etc.

  private $intVal;
  //private constructor
  private function __construct($intVal){
    $this->intVal = $intVal;
  }

  //public instantiation methods
  public static function MONDAY(){
    return new self(self::$monday);
  }
  //etc.


  //convert an instance to its integer value
  public function intVal(){
    return $this->intVal;
  }

}

Tentu saja, tidak mungkin untuk mengakses konstanta integer (ini sebenarnya tujuannya). Metode intVal memungkinkan untuk mengkonversi objek DaysOfWeek ke representasi integernya.

Perhatikan bahwa kita bahkan dapat melangkah lebih jauh dengan menerapkan mekanisme caching dalam metode instantiation untuk menghemat memori dalam kasus enumerasi digunakan secara luas ...

Semoga ini bisa membantu

Vincent Pazeller
sumber
2

Beberapa solusi bagus di sini!

Ini versiku.

  • Sangat diketik
  • Ini bekerja dengan IDE auto-completion
  • Enums didefinisikan oleh kode dan deskripsi, di mana kode dapat berupa bilangan bulat, nilai biner, string pendek, atau pada dasarnya apa pun yang Anda inginkan. Pola ini dapat dengan mudah diperluas untuk mendukung properti orther.
  • Ini mendukung nilai (==) dan referensi (===) perbandingan dan bekerja dalam pernyataan beralih.

Saya pikir kerugian utama adalah bahwa anggota enum harus secara terpisah dideklarasikan dan dipakai, karena deskripsi dan ketidakmampuan PHP untuk membangun objek pada waktu pernyataan anggota statis. Saya kira cara di sekitar ini mungkin menggunakan refleksi dengan komentar dokumen yang diuraikan.

Enum abstrak terlihat seperti ini:

<?php

abstract class AbstractEnum
{
    /** @var array cache of all enum instances by class name and integer value */
    private static $allEnumMembers = array();

    /** @var mixed */
    private $code;

    /** @var string */
    private $description;

    /**
     * Return an enum instance of the concrete type on which this static method is called, assuming an instance
     * exists for the passed in value.  Otherwise an exception is thrown.
     *
     * @param $code
     * @return AbstractEnum
     * @throws Exception
     */
    public static function getByCode($code)
    {
        $concreteMembers = &self::getConcreteMembers();

        if (array_key_exists($code, $concreteMembers)) {
            return $concreteMembers[$code];
        }

        throw new Exception("Value '$code' does not exist for enum '".get_called_class()."'");
    }

    public static function getAllMembers()
    {
        return self::getConcreteMembers();
    }

    /**
     * Create, cache and return an instance of the concrete enum type for the supplied primitive value.
     *
     * @param mixed $code code to uniquely identify this enum
     * @param string $description
     * @throws Exception
     * @return AbstractEnum
     */
    protected static function enum($code, $description)
    {
        $concreteMembers = &self::getConcreteMembers();

        if (array_key_exists($code, $concreteMembers)) {
            throw new Exception("Value '$code' has already been added to enum '".get_called_class()."'");
        }

        $concreteMembers[$code] = $concreteEnumInstance = new static($code, $description);

        return $concreteEnumInstance;
    }

    /**
     * @return AbstractEnum[]
     */
    private static function &getConcreteMembers() {
        $thisClassName = get_called_class();

        if (!array_key_exists($thisClassName, self::$allEnumMembers)) {
            $concreteMembers = array();
            self::$allEnumMembers[$thisClassName] = $concreteMembers;
        }

        return self::$allEnumMembers[$thisClassName];
    }

    private function __construct($code, $description)
    {
        $this->code = $code;
        $this->description = $description;
    }

    public function getCode()
    {
        return $this->code;
    }

    public function getDescription()
    {
        return $this->description;
    }
}

Berikut adalah contoh konkret:

<?php

require('AbstractEnum.php');

class EMyEnum extends AbstractEnum
{
    /** @var EMyEnum */
    public static $MY_FIRST_VALUE;
    /** @var EMyEnum */
    public static $MY_SECOND_VALUE;
    /** @var EMyEnum */
    public static $MY_THIRD_VALUE;

    public static function _init()
    {
        self::$MY_FIRST_VALUE = self::enum(1, 'My first value');
        self::$MY_SECOND_VALUE = self::enum(2, 'My second value');
        self::$MY_THIRD_VALUE = self::enum(3, 'My third value');
    }
}

EMyEnum::_init();

Yang bisa digunakan seperti ini:

<?php

require('EMyEnum.php');

echo EMyEnum::$MY_FIRST_VALUE->getCode().' : '.EMyEnum::$MY_FIRST_VALUE->getDescription().PHP_EOL.PHP_EOL;

var_dump(EMyEnum::getAllMembers());

echo PHP_EOL.EMyEnum::getByCode(2)->getDescription().PHP_EOL;

Dan menghasilkan output ini:

1: Nilai pertamaku

array (3) {
[1] =>
objek (EMyEnum) # 1 (2) {
["code": "AbstractEnum": private] =>
int (1)
["description": "AbstractEnum": private] =>
string (14) "Nilai pertamaku"
}
[2] =>
objek (EMyEnum) # 2 (2) {
["code": "AbstractEnum": private] =>
int (2)
["description": "AbstractEnum" : private] =>
string (15) "Nilai kedua saya"
}
[3] =>
objek (EMyEnum) # 3 (2) {
["code": "AbstractEnum": private] =>
int (3)
["description": "AbstractEnum": private] =>
string (14) "Nilai ketiga saya"
}
}

Nilai kedua saya

Dan King
sumber
2
class DayOfWeek {
    static $values = array(
        self::MONDAY,
        self::TUESDAY,
        // ...
    );

    const MONDAY  = 0;
    const TUESDAY = 1;
    // ...
}

$today = DayOfWeek::MONDAY;

// If you want to check if a value is valid
assert( in_array( $today, DayOfWeek::$values ) );

Jangan gunakan refleksi. Itu membuatnya sangat sulit untuk berpikir tentang kode Anda dan melacak di mana sesuatu sedang digunakan, dan cenderung merusak alat analisis statis (misalnya apa yang dibangun ke dalam IDE Anda).

Jesse
sumber
2

Salah satu aspek yang hilang dari beberapa jawaban lain di sini adalah cara untuk menggunakan enum dengan tipe hinting.

Jika Anda mendefinisikan enum Anda sebagai seperangkat konstanta dalam kelas abstrak, mis

abstract class ShirtSize {
    public const SMALL = 1;
    public const MEDIUM = 2;
    public const LARGE = 3;
}

maka Anda tidak dapat mengetikkan petunjuk dalam parameter fungsi - untuk satu, karena itu tidak instantiable, tetapi juga karena jenisnya ShirtSize::SMALLadalah int, tidak ShirtSize.

Itu sebabnya enum asli di PHP akan jauh lebih baik daripada apa pun yang bisa kita dapatkan. Namun, kami dapat memperkirakan suatu enum dengan mempertahankan properti pribadi yang mewakili nilai enum, dan kemudian membatasi inisialisasi properti ini ke konstanta yang telah ditentukan sebelumnya. Untuk mencegah enum dari instantiasi secara sewenang-wenang (tanpa overhead dari pengecekan tipe daftar putih), kami menjadikan konstruktor sebagai pribadi.

class ShirtSize {
    private $size;
    private function __construct ($size) {
        $this->size = $size;
    }
    public function equals (ShirtSize $s) {
        return $this->size === $s->size;
    }
    public static function SMALL () { return new self(1); }
    public static function MEDIUM () { return new self(2); }
    public static function LARGE () { return new self(3); }
}

Maka kita bisa menggunakan ShirtSizeseperti ini:

function sizeIsAvailable ($productId, ShirtSize $size) {
    // business magic
}
if(sizeIsAvailable($_GET["id"], ShirtSize::LARGE())) {
    echo "Available";
} else {
    echo "Out of stock.";
}
$s2 = ShirtSize::SMALL();
$s3 = ShirtSize::MEDIUM();
echo $s2->equals($s3) ? "SMALL == MEDIUM" : "SMALL != MEDIUM";

Dengan cara ini, perbedaan terbesar dari perspektif pengguna adalah Anda harus menggunakan ()nama konstanta.

Satu kelemahan adalah bahwa ===(yang membandingkan kesetaraan objek) akan mengembalikan false ketika ==mengembalikan true. Untuk alasan itu, yang terbaik adalah memberikan equalsmetode, sehingga pengguna tidak harus ingat untuk menggunakan ==dan tidak ===membandingkan dua nilai enum.

EDIT: Beberapa jawaban yang ada sangat mirip, terutama: https://stackoverflow.com/a/25526473/2407870 .

Chris Middleton
sumber
2

Menginjak jawaban @Brian Cline saya pikir saya mungkin akan memberikan 5 sen saya

<?php 
/**
 * A class that simulates Enums behaviour
 * <code>
 * class Season extends Enum{
 *    const Spring  = 0;
 *    const Summer = 1;
 *    const Autumn = 2;
 *    const Winter = 3;
 * }
 * 
 * $currentSeason = new Season(Season::Spring);
 * $nextYearSeason = new Season(Season::Spring);
 * $winter = new Season(Season::Winter);
 * $whatever = new Season(-1);               // Throws InvalidArgumentException
 * echo $currentSeason.is(Season::Spring);   // True
 * echo $currentSeason.getName();            // 'Spring'
 * echo $currentSeason.is($nextYearSeason);  // True
 * echo $currentSeason.is(Season::Winter);   // False
 * echo $currentSeason.is(Season::Spring);   // True
 * echo $currentSeason.is($winter);          // False
 * </code>
 * 
 * Class Enum
 * 
 * PHP Version 5.5
 */
abstract class Enum
{
    /**
     * Will contain all the constants of every enum that gets created to 
     * avoid expensive ReflectionClass usage
     * @var array
     */
    private static $_constCacheArray = [];
    /**
     * The value that separates this instance from the rest of the same class
     * @var mixed
     */
    private $_value;
    /**
     * The label of the Enum instance. Will take the string name of the 
     * constant provided, used for logging and human readable messages
     * @var string
     */
    private $_name;
    /**
     * Creates an enum instance, while makes sure that the value given to the 
     * enum is a valid one
     * 
     * @param mixed $value The value of the current
     * 
     * @throws \InvalidArgumentException
     */
    public final function __construct($value)
    {
        $constants = self::_getConstants();
        if (count($constants) !== count(array_unique($constants))) {
            throw new \InvalidArgumentException('Enums cannot contain duplicate constant values');
        }
        if ($name = array_search($value, $constants)) {
            $this->_value = $value;
            $this->_name = $name;
        } else {
            throw new \InvalidArgumentException('Invalid enum value provided');
        }
    }
    /**
     * Returns the constant name of the current enum instance
     * 
     * @return string
     */
    public function getName()
    {
        return $this->_name;
    }
    /**
     * Returns the value of the current enum instance
     * 
     * @return mixed
     */
    public function getValue()
    {
        return $this->_value;
    }
    /**
     * Checks whether this enum instance matches with the provided one.
     * This function should be used to compare Enums at all times instead
     * of an identity comparison 
     * <code>
     * // Assuming EnumObject and EnumObject2 both extend the Enum class
     * // and constants with such values are defined
     * $var  = new EnumObject('test'); 
     * $var2 = new EnumObject('test');
     * $var3 = new EnumObject2('test');
     * $var4 = new EnumObject2('test2');
     * echo $var->is($var2);  // true
     * echo $var->is('test'); // true
     * echo $var->is($var3);  // false
     * echo $var3->is($var4); // false
     * </code>
     * 
     * @param mixed|Enum $enum The value we are comparing this enum object against
     *                         If the value is instance of the Enum class makes
     *                         sure they are instances of the same class as well, 
     *                         otherwise just ensures they have the same value
     * 
     * @return bool
     */
    public final function is($enum)
    {
        // If we are comparing enums, just make
        // sure they have the same toString value
        if (is_subclass_of($enum, __CLASS__)) {
            return get_class($this) === get_class($enum) 
                    && $this->getValue() === $enum->getValue();
        } else {
            // Otherwise assume $enum is the value we are comparing against
            // and do an exact comparison
            return $this->getValue() === $enum;   
        }
    }

    /**
     * Returns the constants that are set for the current Enum instance
     * 
     * @return array
     */
    private static function _getConstants()
    {
        if (self::$_constCacheArray == null) {
            self::$_constCacheArray = [];
        }
        $calledClass = get_called_class();
        if (!array_key_exists($calledClass, self::$_constCacheArray)) {
            $reflect = new \ReflectionClass($calledClass);
            self::$_constCacheArray[$calledClass] = $reflect->getConstants();
        }
        return self::$_constCacheArray[$calledClass];
    }
}
Loupax
sumber
untuk beberapa alasan saya tidak dapat menyebut funtions ini. Ini memberitahu saya bahwa fungsi-fungsi tersebut tidak dideklarasikan. Apa yang saya lakukan salah? [kelas Enum dasar yang terletak di file lain dan saya menggunakan include('enums.php');]. Untuk beberapa alasan, ia tidak melihat fungsi yang dideklarasikan di Enum untuk kelas anak ...
Andrew
Juga ... bagaimana cara mengaturnya dari string? sth like$currentSeason.set("Spring");
Andrew
1

Upaya saya untuk membuat enum dengan PHP ... ini sangat terbatas karena tidak mendukung objek sebagai nilai enum tetapi masih agak berguna ...

class ProtocolsEnum {

    const HTTP = '1';
    const HTTPS = '2';
    const FTP = '3';

    /**
     * Retrieve an enum value
     * @param string $name
     * @return string
     */
    public static function getValueByName($name) {
        return constant('self::'. $name);
    } 

    /**
     * Retrieve an enum key name
     * @param string $code
     * @return string
     */
    public static function getNameByValue($code) {
        foreach(get_class_constants() as $key => $val) {
            if($val == $code) {
                return $key;
            }
        }
    }

    /**
     * Retrieve associate array of all constants (used for creating droplist options)
     * @return multitype:
     */
    public static function toArray() {      
        return array_flip(self::get_class_constants());
    }

    private static function get_class_constants()
    {
        $reflect = new ReflectionClass(__CLASS__);
        return $reflect->getConstants();
    }
}
KDog
sumber
terbatas di banyak arah dan jawaban yang ada menawarkan lebih dari itu. Saya akan mengatakan ini tidak benar-benar menambahkan sesuatu yang bermanfaat.
hakre
1

Kemarin saya menulis kelas ini di blog saya . Saya pikir mungkin mudah digunakan dalam skrip php:

final class EnumException extends Exception{}

abstract class Enum
{
    /**
     * @var array ReflectionClass
     */
    protected static $reflectorInstances = array();
    /**
     * Массив конфигурированного объекта-константы enum
     * @var array
     */
    protected static $enumInstances = array();
    /**
     * Массив соответствий значение->ключ используется для проверки - 
     * если ли константа с таким значением
     * @var array
     */
    protected static $foundNameValueLink = array();

    protected $constName;
    protected $constValue;

    /**
     * Реализует паттерн "Одиночка"
     * Возвращает объект константы, но но как объект его использовать не стоит, 
     * т.к. для него реализован "волшебный метод" __toString()
     * Это должно использоваться только для типизачии его как параметра
     * @paradm Node
     */
    final public static function get($value)
    {
        // Это остается здесь для увеличения производительности (по замерам ~10%)
        $name = self::getName($value);
        if ($name === false)
            throw new EnumException("Неизвестая константа");
        $className = get_called_class();    
        if (!isset(self::$enumInstances[$className][$name]))
        {
            $value = constant($className.'::'.$name);
            self::$enumInstances[$className][$name] = new $className($name, $value);
        }

        return self::$enumInstances[$className][$name];
    }

    /**
     * Возвращает массив констант пар ключ-значение всего перечисления
     * @return array 
     */
    final public static function toArray()
    {
        $classConstantsArray = self::getReflectorInstance()->getConstants();
        foreach ($classConstantsArray as $k => $v)
            $classConstantsArray[$k] = (string)$v;
        return $classConstantsArray;
    }

    /**
     * Для последующего использования в toArray для получения массива констант ключ->значение 
     * @return ReflectionClass
     */
    final private static function getReflectorInstance()
    {
        $className = get_called_class();
        if (!isset(self::$reflectorInstances[$className]))
        {
            self::$reflectorInstances[$className] = new ReflectionClass($className);
        }
        return self::$reflectorInstances[$className];
    }

    /**
     * Получает имя константы по её значению
     * @param string $value
     */
    final public static function getName($value)
    {
        $className = (string)get_called_class();

        $value = (string)$value;
        if (!isset(self::$foundNameValueLink[$className][$value]))
        {
            $constantName = array_search($value, self::toArray(), true);
            self::$foundNameValueLink[$className][$value] = $constantName;
        }
        return self::$foundNameValueLink[$className][$value];
    }

    /**
     * Используется ли такое имя константы в перечислении
     * @param string $name
     */
    final public static function isExistName($name)
    {
        $constArray = self::toArray();
        return isset($constArray[$name]);
    }

    /**
     * Используется ли такое значение константы в перечислении
     * @param string $value
     */
    final public static function isExistValue($value)
    {
        return self::getName($value) === false ? false : true;
    }   


    final private function __clone(){}

    final private function __construct($name, $value)
    {
        $this->constName = $name;
        $this->constValue = $value;
    }

    final public function __toString()
    {
        return (string)$this->constValue;
    }
}

Pemakaian:

class enumWorkType extends Enum
{
        const FULL = 0;
        const SHORT = 1;
}
Arturgspb
sumber
2
Tapi itu kelas yang bagus dan fungsi namanya asli. Dan juga translate.google.ru mungkin membantu.
Arturgspb
2
Gunakan orang-orang krom dan terjemahkan, jika Anda programmer, Anda membaca kode!
markus
8
Secara umum, selalu lebih baik untuk memasukkan kode dalam jawaban, daripada menautkan ke sumber daya eksternal yang mungkin ada atau mungkin tidak ada dalam 'n' bulan / tahun, dll.
John Parker
Kelas saya sangat besar dan saya pikir membaca posting ini akan merepotkan.
Arturgspb
Saya pikir ada dua hal buruk di sini: ini dalam bahasa Rusia (setiap programmer harus tahu bahasa Inggris dan menggunakannya, bahkan dalam komentar) & itu tidak termasuk di sini. Lihat bantuan cara memasukkan kode besar.
gaRex