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?
php
enumeration
Henrik Paul
sumber
sumber
Jawaban:
Bergantung pada use case, saya biasanya menggunakan sesuatu yang sederhana seperti berikut:
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:
Dengan membuat kelas enum sederhana yang memperluas BasicEnum, Anda sekarang memiliki kemampuan untuk menggunakan metode demikian untuk validasi input sederhana:
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
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
danDaysOfWeek
tidak dapat dipakai sama sekali, mereka juga tidak boleh.sumber
abstract
danfinal
, jadi itu tidak bisa dipakai atau diperluas.abstract
danfinal
? Saya tahu di Jawa ini tidak diizinkan. Anda bisa melakukannya di php?abstract
danfinal
. Dalam hal ini, saya akan mengambil abstrak.null
dan teman dalamswitch
pernyataan. Pernah ke sana.Ada ekstensi asli juga. The SplEnum
http://www.php.net/manual/en/class.splenum.php
Perhatian:
https://www.php.net/manual/en/spl-types.installation.php
sumber
Bagaimana dengan konstanta kelas?
sumber
echoConstant
dapat diganti dengan__toString
. Dan kemudian secara sederhanaecho $c
Jawaban teratas di atas sangat fantastis. Namun, jika Anda
extend
melakukannya 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:
sumber
Saya menggunakan kelas dengan konstanta:
sumber
Saya menggunakan
interface
bukannyaclass
:sumber
class Foo implements DaysOfWeek { }
laluFoo::Sunday
... apa?class
(atauinterface
, yang hanya masalah preferensi).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
const
metode yang digunakan oleh jawaban lain di sini:Contoh penghitungan:
Menggunakan
Enum
sebagai kelas dasar dari mana semua mantri lainnya memperpanjang memungkinkan untuk metode pembantu, sepertitoArray
,isValid
, dan sebagainya. Bagi saya, mengetik enumerasi ( dan mengelola instans mereka ) akhirnya menjadi terlalu berantakan.Hipotetis
Jika , ada
__getStatic
metode sihir ( dan lebih disukai__equals
metode 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 )
sumber
Nah, untuk java sederhana seperti enum di php, saya menggunakan:
Dan untuk menyebutnya:
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.
sumber
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:
Contoh Enum:
Contoh penggunaan:
Perhatikan bahwa semua instance dari entri enum yang sama adalah sama:
Anda juga dapat menggunakannya di dalam pernyataan switch:
Anda juga dapat membuat entri enum dengan nama atau nilai:
Atau Anda bisa mendapatkan nama (yaitu nama fungsi) dari entri enum yang ada:
sumber
const Monday = DaysOfWeek('Monday');
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
function setAction(Action $action) {
format
,parse
, ...)final
untuk mencegahnya)Pernyataan
Pemakaian
nilai type-hint enum:
sumber
enum
ditambahkan dalam PHP 7.x) karena memungkinkan mengetikkan petunjuk.__toString()
keajaiban, ini memungkinkan Anda untuk melakukan apa yang umumnya Anda benar-benar ingin dengan enum - menggunakannya dalam pernyataanswitch
atauif
, membandingkan langsung dengan nilai-nilai dari consts. Pendekatan terbaik singkat dari dukungan enum asli, IMO.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.
sumber
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.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
sumber
FruitsEnum::Apple()
lebihFruitsEnum::$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$initialized
yang memastikan bahwa panggilaninit()
menjadi no-op setelah memanggilnya untuk pertama kalinya (jadi tidak ada yang bisa mengacaukannya juga)..init()
aneh, dan saya tidak keberatan dengan pendekatan rajin.sumber
Mungkin sesederhana itu
di masa depan.
PHP RFC: Jenis yang Dihitung
sumber
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.
sumber
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)
Keluaran:
sumber
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.sumber
DaysOfWeek::$MONDAY = 3;
[extended class name]::enumerate();
definisi, mengapa Anda tidak melakukannya dalam konstruksi?Definisi kelas Enum saya di bawah ini sangat diketik , dan sangat alami untuk digunakan dan didefinisikan.
Definisi:
Ganti Enum
Pass Enum sebagai parameter (Sangat diketik)
Echo Enum sebagai string
Dapatkan Enum dengan integer
Dapatkan Enum dengan Nama
Kelas Enum:
Tambahan
Anda juga dapat menambahkan komentar untuk IDE
sumber
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 sebenarnyaenums
. The__call()
Fungsi menangani semua panggilan fungsi yang tidak diketahui. Jadi katakanlah Anda ingin membuat tigaenums
RED_LIGHT, YELLOW_LIGHT, dan GREEN_LIGHT. Anda dapat melakukannya sekarang hanya dengan melakukan hal berikut:Setelah ditentukan, yang harus Anda lakukan adalah memanggil mereka lagi untuk mendapatkan nilai:
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: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: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.sumber
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
sumber
Sekarang Anda dapat menggunakan kelas The SplEnum untuk membangunnya secara asli. Sesuai dokumentasi resmi.
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.
sumber
Akhirnya, jawaban PHP 7.1+ dengan konstanta yang tidak dapat diganti.
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 dalamInterface
adalahpublic
.Manual PHP: Antarmuka
sumber
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 ...
UPDATE: Cara yang lebih baik untuk melakukannya ...
Telepon dengan
sumber
EnumCategory::$sport = 9;
. Selamat datang di museum olahraga.const
adalah cara yang lebih baik untuk melakukannya.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:
Kita bahkan dapat melangkah lebih jauh: menggunakan konstanta di kelas DaysOfWeek dapat menyebabkan penyalahgunaan: misalnya orang mungkin salah menggunakannya seperti ini:
yang salah (memanggil konstanta integer). Kita dapat mencegah ini menggunakan variabel statis pribadi alih-alih konstanta:
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
sumber
Beberapa solusi bagus di sini!
Ini versiku.
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:
Berikut adalah contoh konkret:
Yang bisa digunakan seperti ini:
Dan menghasilkan output ini:
sumber
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).
sumber
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
maka Anda tidak dapat mengetikkan petunjuk dalam parameter fungsi - untuk satu, karena itu tidak instantiable, tetapi juga karena jenisnya
ShirtSize::SMALL
adalahint
, tidakShirtSize
.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.
Maka kita bisa menggunakan
ShirtSize
seperti ini: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 memberikanequals
metode, 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 .
sumber
Menginjak jawaban @Brian Cline saya pikir saya mungkin akan memberikan 5 sen saya
sumber
include('enums.php');
]. Untuk beberapa alasan, ia tidak melihat fungsi yang dideklarasikan di Enum untuk kelas anak ...$currentSeason.set("Spring");
Upaya saya untuk membuat enum dengan PHP ... ini sangat terbatas karena tidak mendukung objek sebagai nilai enum tetapi masih agak berguna ...
sumber
Kemarin saya menulis kelas ini di blog saya . Saya pikir mungkin mudah digunakan dalam skrip php:
Pemakaian:
sumber