PHP dan Enumerations

PHP dan Enumerations

iis

September 13, 2019

Saya tahu 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? Adakah yang ingat apakah orang-orang PHP memiliki pemikiran atau keputusan seputar enum?

php

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-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 meningkatkan ke setidaknya 5.3, dan SplEnum tersedia, 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, BasicEnum dan DaysOfWeek tidak bisa dipakai sama sekali, juga tidak boleh.