Pertanyaan PHP dan Enumerations


Saya tahu bahwa PHP tidak memiliki Enumerations asli. Tapi saya sudah terbiasa dengan mereka dari dunia Jawa. Saya akan senang menggunakan enum sebagai cara untuk memberikan nilai yang telah ditetapkan yang dapat dipahami oleh fitur penyelesaian 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 samar-samar, mereka dapat ditimpa saat runtime dan IDE jarang (tidak pernah?) Tahu cara melakukan autofill kunci mereka.

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


980
2017-10-31 18:51


asal


Jawaban:


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

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

$today = DaysOfWeek::Sunday;

Namun, kasus penggunaan lainnya mungkin memerlukan validasi konstanta dan nilai yang lebih banyak. Berdasarkan komentar di bawah ini tentang refleksi, dan beberapa catatan lain, inilah contoh yang diperluas yang mungkin lebih baik melayani berbagai kasus yang 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 untuk validasi masukan 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 tambahan, setiap kali saya menggunakan refleksi setidaknya sekali pada kelas statis / const tempat data tidak akan berubah (seperti dalam enum), saya menyimpan hasil dari pemanggilan refleksi tersebut, karena menggunakan objek refleksi segar setiap kali akhirnya akan memiliki dampak kinerja yang nyata (Disimpan dalam array assocciative untuk beberapa enum).

Sekarang kebanyakan orang punya akhirnya ditingkatkan ke setidaknya 5,3, dan SplEnum tersedia, yang tentu saja merupakan pilihan yang layak juga - selama Anda tidak keberatan dengan gagasan tradisional yang tidak intuitif memiliki enum yang sebenarnya Instansiasi di seluruh basis kode Anda. Dalam contoh di atas, BasicEnum dan DaysOfWeek tidak dapat dipakai sama sekali, tidak seharusnya.


1320
2017-10-31 18:59



Ada ekstensi asli juga. Itu SplEnum

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

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


156
2017-10-31 18:57



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();

35
2018-02-03 20:14



Jawaban teratas di atas sangat fantastis. Namun, jika Anda extend dalam dua cara berbeda, maka ekstensi mana yang dilakukan pertama kali menghasilkan panggilan ke fungsi akan membuat cache. Singgahan ini kemudian akan digunakan oleh semua panggilan berikutnya, terlepas dari ekstensi panggilan mana pun yang diprakarsai 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];
}

27
2017-10-31 18:56



Saya menggunakan kelas dengan konstanta:

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

print Enum::NAME;

25
2017-11-24 14:51



saya menggunakan interface dari pada class:

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

var $today = DaysOfWeek::Sunday;

24
2017-12-23 20:04



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 menyebutnya:

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

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


20
2018-06-11 13:17