Penggunaan perpustakaan ini tidak lagi disarankan, terutama untuk proyek baru. PHP 8.1 mendukung enum secara asli.
Lihat #332.
Implementasi enumerasi yang sederhana, dapat diperluas, dan kuat untuk Laravel.
Enumkan pasangan nilai kunci sebagai konstanta kelas
Rangkaian metode berfitur lengkap
Instansiasi enum
Enum yang ditandai/Bitwise
Ketik petunjuk
Pengecoran atribut
Generator tukang enum
Aturan validasi untuk meneruskan kunci atau nilai enum sebagai parameter input
Dukungan lokalisasi
Dapat diperpanjang melalui Makro
Dibuat oleh Ben Sampson
Memandu
Instalasi
Bermigrasi ke Enum PHP Asli
Perpustakaan Enum
Penggunaan Dasar
Definisi Enum
Instansiasi
Properti Instans
Transmisi Instans
Kesetaraan Instance
Ketik Petunjuk
Enum yang Ditandai/Bitwise
Pengecoran Atribut
Migrasi
Validasi
Lokalisasi
Menyesuaikan Deskripsi
Menyesuaikan Deskripsi Kelas
Menyesuaikan Deskripsi Nilai
Memperluas Kelas Dasar Enum
Integrasi Laravel Nova
Integrasi PHPStan
Daftar Komando Pengrajin
Referensi Kelas Enum
Rintisan bertopik
Anda sedang membaca dokumentasi untuk 6.x
.
Jika Anda menggunakan Laravel 8 silakan lihat dokumen untuk 4.x
Jika Anda menggunakan Laravel 7 silakan lihat dokumen untuk 2.x
Jika Anda menggunakan Laravel 6 atau lebih rendah, silakan lihat dokumen untuk 1.x
.
Silakan lihat panduan peningkatan untuk informasi tentang cara meningkatkan ke versi terbaru.
Saya menulis postingan blog tentang penggunaan laravel-enum: https://sampo.co.uk/blog/using-enums-in-laravel
Membutuhkan PHP 8, dan Laravel 9 atau 10.
komposer membutuhkan bensampo/laravel-enum
PHP 8.1 mendukung enum secara asli. Anda dapat memigrasikan penggunaan BenSampoEnumEnum
ke enum PHP asli menggunakan langkah-langkah berikut.
Pastikan Anda memenuhi persyaratan berikut:
PHP 8.1 atau lebih tinggi
Laravel 10 atau lebih tinggi
Rector 0.17 atau lebih tinggi, rector.php
Anda menyertakan semua file yang relevan
Versi terbaru perpustakaan ini
Bergantung pada ukuran proyek Anda, Anda dapat memilih untuk memigrasikan semua enum sekaligus, atau memigrasikan hanya beberapa atau satu enum dalam satu waktu.
Konversikan semua enum sekaligus: php artisan enum:to-native
Berikan nama kelas enum yang sepenuhnya memenuhi syarat untuk membatasi konversi: php artisan enum:to-native "AppEnumsUserType"
Hal ini diperlukan jika ada enum yang digunakan selama fase bootstrap Laravel, konversi penggunaannya akan mengganggu Larastan dan mencegah pengoperasian Rector yang kedua.
Tinjau dan validasi perubahan kode untuk kasus edge yang terlewat:
Lihat Belum Diimplementasikan
Enum::coerce()
: Jika hanya nilai yang diteruskan, Anda dapat menggantinya dengan tryFrom()
. Jika kunci atau instance juga dapat diteruskan, Anda mungkin memerlukan logika tambahan untuk membahas hal ini.
Enum::$description
dan Enum::getDescription()
: Menerapkan alternatif.
coba/tangkap-blok yang menangani BenSampoEnumExceptionsInvalidEnumKeyException
atau BenSampoEnumExceptionsInvalidEnumMemberException
. Tangkap ValueError
yang dilemparkan oleh enum asli, atau beralih menggunakan tryFrom()
dan tangani null
.
Setelah semua enum dikonversi, Anda dapat menghapus ketergantungan Anda pada perpustakaan ini.
Jelajahi dan unduh dari daftar enum kontribusi komunitas yang umum digunakan.
Perpustakaan enum →
Anda dapat menggunakan perintah Artisan berikut untuk menghasilkan kelas enum baru:
tukang php make:enum UserType
Sekarang, Anda hanya perlu menambahkan kemungkinan nilai enum Anda sebagai konstanta.
<?php menyatakan(strict_types=1);namespace AppEnums;menggunakan BenSampoEnumEnum;kelas akhir UserType extends Enum {const Administrator = 0;const Moderator = 1;const Pelanggan = 2;const SuperAdministrator = 3; }
Itu saja! Perhatikan bahwa karena nilai enum didefinisikan sebagai konstanta biasa, Anda cukup mengaksesnya seperti konstanta kelas lainnya.
UserType::Administrator // Memiliki nilai 0
Akan berguna untuk membuat instance enum untuk meneruskannya antar fungsi dengan manfaat petunjuk tipe.
Selain itu, tidak mungkin membuat instance enum dengan nilai yang tidak valid, oleh karena itu Anda dapat yakin bahwa nilai yang diteruskan selalu valid.
Untuk kenyamanan, enum dapat dibuat instance-nya dengan berbagai cara:
// Kelas PHP standar baru, meneruskan nilai enum yang diinginkan sebagai parameter$enumInstance = new UserType(UserType::Administrator);// Sama seperti konstruktor, membuat instance berdasarkan value$enumInstance = UserType::fromValue(UserType::Administrator) ;// Gunakan kunci enum alih-alih value$enumInstance = UserType::fromKey('Administrator');// Memanggil nama kunci secara statis sebagai sebuah metode, memanfaatkan __callStatic magic$enumInstance = UserType::Administrator();// Mencoba membuat instance Enum baru menggunakan kunci atau nilai yang diberikan. Mengembalikan null jika Enum tidak dapat dipakai.$enumInstance = UserType::coerce($someValue);
Jika Anda ingin IDE Anda melengkapi secara otomatis pembantu instantiasi statis, Anda dapat membuat anotasi PHPDoc melalui perintah artisan.
Secara default, semua Enum di app/Enums
akan diberi anotasi (Anda dapat mengubah folder dengan meneruskan jalur ke --folder
).
php artisan enum: anotasi
Anda dapat membuat anotasi pada satu kelas dengan menentukan nama kelas.
php artisan enum: beri anotasi "AppEnumsUserType"
Setelah Anda memiliki instance enum, Anda dapat mengakses key
, value
dan description
sebagai properti.
$userType = UserType::fromValue(UserType::SuperAdministrator);$userType->key; // SuperAdministrator$userType->nilai; // 3$Jenispengguna->deskripsi; // Administrator Super
Hal ini sangat berguna jika Anda meneruskan instance enum ke tampilan blade.
Instance Enum dapat dilemparkan ke string saat mengimplementasikan metode ajaib __toString()
.
Ini juga berarti bahwa mereka dapat digaungkan dalam tampilan blade, misalnya.
$userType = UserType::fromValue(UserType::SuperAdministrator); (string) $tipe pengguna // '3'
Anda dapat memeriksa kesetaraan sebuah instance terhadap nilai apa pun dengan meneruskannya ke metode is
. Untuk kenyamanan, ada juga metode isNot
yang merupakan kebalikan dari metode is
.
$admin = Tipe Pengguna::Administrator();$admin->is(UserType::Administrator); // benar$admin->adalah($admin); // true$admin->is(UserType::Administrator()); // true$admin->is(UserType::Moderator); // false$admin->is(UserType::Moderator()); // false$admin->is('nilai acak'); // PALSU
Anda juga dapat memeriksa apakah nilai instance cocok dengan array nilai yang mungkin menggunakan metode in
, dan menggunakan notIn
untuk memeriksa apakah nilai instance tidak ada dalam array nilai. Iterables juga dapat diperiksa.
$admin = Tipe Pengguna::Administrator();$admin->in([UserType::Moderator, UserType::Administrator]); // true$admin->in([UserType::Moderator(), UserType::Administrator()]); // true$admin->in([UserType::Moderator, UserType::Subscriber]); // false$admin->in(['nilai acak']); // false$admin->notIn([UserType::Moderator, UserType::Administrator]); // false$admin->notIn([UserType::Moderator(), UserType::Administrator()]); // false$admin->notIn([UserType::Moderator, UserType::Subscriber]); // true$admin->notIn(['nilai acak']); // BENAR
Enum yang dipakai bukanlah enum tunggal, melainkan objek baru yang dibuat setiap saat. Jadi, perbandingan ketat ===
dari instance enum yang berbeda akan selalu menghasilkan false
, berapa pun nilainya. Sebaliknya, perbandingan longgar ==
akan bergantung pada nilainya.
$admin = Tipe Pengguna::Administrator();$admin === Tipe Pengguna::Administrator(); // falseUserType::Administrator() === UserType::Administrator(); // false$admin === Tipe Pengguna::Moderator(); // salah$admin === $admin; // true$admin == Tipe Pengguna::Administrator(); // true$admin == Tipe Pengguna::Administrator; // true$admin == Tipe Pengguna::Moderator(); // false$admin == Tipe Pengguna::Moderator; // PALSU
Salah satu keuntungan dari instance enum adalah memungkinkan Anda menggunakan petunjuk tipe, seperti yang ditunjukkan di bawah ini.
fungsi canPerformAction(UserType $userType) {if ($userType->is(UserType::SuperAdministrator)) {kembali benar; }mengembalikan salah; }$userType1 = UserType::fromValue(UserType::SuperAdministrator);$userType2 = UserType::fromValue(UserType::Moderator);canPerformAction($userType1); // Mengembalikan truecanPerformAction($userType2); // Mengembalikan salah
Enum standar mewakili satu nilai pada satu waktu, tetapi enum yang ditandai atau bitwise mampu mewakili beberapa nilai secara bersamaan. Ini menjadikannya sempurna ketika Anda ingin mengekspresikan beberapa pilihan dari serangkaian opsi terbatas. Contoh yang baik dari hal ini adalah izin pengguna di mana terdapat sejumlah izin yang mungkin tetapi pengguna tidak dapat memiliki satu pun, sebagian, atau seluruh izin tersebut.
Anda dapat membuat enum yang ditandai menggunakan perintah artisan berikut:
php artisan make:enum UserPermissions --flagged
Saat mendefinisikan nilai, Anda harus menggunakan pangkat 2, cara termudah untuk melakukannya adalah dengan menggunakan operator <<
shift kiri seperti:
UserPermissions kelas terakhir memperluas FlagedEnum {const ReadComments = 1 << 0;const WriteComments = 1 << 1;const EditComments = 1 << 2;const DeleteComments = 1 << 3;// Yang berikutnya adalah `1 << 4` dan seterusnya. ..}
Anda dapat menggunakan bitwise atau |
untuk menetapkan nilai pintasan yang mewakili sekumpulan nilai tertentu.
UserPermissions kelas terakhir memperluas FlaggedEnum {const ReadComments = 1 << 0;const WriteComments = 1 << 1;const EditComments = 1 << 2;const DeleteComments = 1 << 3;// Shortcutsconst Member = self::ReadComments | diri::TulisKomentar; // Membaca dan menulis.const Moderator = self::Member | diri::EditKomentar; // Semua izin yang dimiliki Anggota, ditambah Edit.const Admin = self::Moderator | self::DeleteComments; // Semua izin yang dimiliki Moderator, ditambah Hapus.}
Ada beberapa cara untuk membuat instance enum yang ditandai:
// Kelas PHP standar baru, meneruskan nilai enum yang diinginkan sebagai array nilai atau array instance enum$permissions = new UserPermissions([UserPermissions::ReadComments, UserPermissions::EditComments]);$permissions = new UserPermissions([UserPermissions: :ReadComments(), UserPermissions::EditComments()]);// Metode flag statis, sekali lagi meneruskan nilai enum yang diinginkan sebagai array nilai atau array enum instance$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::EditComments]);$permissions = UserPermissions::flags([UserPermissions::ReadComments(), UserPermissions::EditComments()]);
Pengecoran atribut bekerja dengan cara yang sama seperti enum nilai tunggal.
Enum yang ditandai tidak boleh mengandung nilai sama sekali. Setiap enum yang ditandai memiliki konstanta yang telah ditentukan sebelumnya yaitu None
yang sebanding dengan 0
.
Izin Pengguna::bendera([])->nilai === Izin Pengguna::Tidak ada; // BENAR
Selain metode enum standar, ada serangkaian metode bermanfaat yang tersedia di enum yang ditandai.
Catatan: Di mana pun properti statis diteruskan, Anda juga dapat meneruskan instance enum.
Atur flag untuk enum ke array flag yang diberikan.
$permissions = UserPermissions::flags([UserPermissions::ReadComments]);$permissions->flags([UserPermissions::EditComments, UserPermissions::DeleteComments]); // Bendera sekarang: EditComments, DeleteComments.
Tambahkan bendera yang diberikan ke enum
$permissions = UserPermissions::flags([UserPermissions::ReadComments]);$permissions->addFlag(UserPermissions::EditComments); // Bendera sekarang: ReadComments, EditComments.
Tambahkan tanda yang diberikan ke enum
$permissions = UserPermissions::flags([UserPermissions::ReadComments]);$permissions->addFlags([UserPermissions::EditComments, UserPermissions::WriteComments]); // Bendera sekarang: ReadComments, EditComments, WriteComments.
Tambahkan semua tanda ke enum
$permissions = UserPermissions::flags([UserPermissions::ReadComments]);$permissions->addAllFlags(); // Enum sekarang memiliki semua flag
Hapus tanda yang diberikan dari enum
$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->removeFlag(UserPermissions::ReadComments); // Bendera sekarang: WriteComments.
Hapus tanda yang diberikan dari enum
$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments, UserPermissions::EditComments]);$permissions->removeFlags([UserPermissions::ReadComments, UserPermissions::WriteComments]); // Bendera sekarang: EditComments.
Hapus semua tanda dari enum
$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->removeAllFlags();
Periksa apakah enum memiliki tanda yang ditentukan.
$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->hasFlag(UserPermissions::ReadComments); // Benar$izin->hasFlag(UserPermissions::EditComments); // PALSU
Periksa apakah enum memiliki semua tanda yang ditentukan.
$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->hasFlags([UserPermissions::ReadComments, UserPermissions::WriteComments]); // True$permissions->hasFlags([UserPermissions::ReadComments, UserPermissions::EditComments]); // PALSU
Periksa apakah enum tidak memiliki tanda yang ditentukan.
$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->notHasFlag(UserPermissions::EditComments); // Benar$izin->notHasFlag(UserPermissions::ReadComments); // PALSU
Periksa apakah enum tidak memiliki tanda yang ditentukan.
$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->notHasFlags([UserPermissions::ReadComments, UserPermissions::EditComments]); // True$permissions->notHasFlags([UserPermissions::ReadComments, UserPermissions::WriteComments]); // PALSU
Mengembalikan flag sebagai array instance.
$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->getFlags(); // [Izin Pengguna::ReadComments(), Izin Pengguna::WriteComments()];
Periksa apakah ada beberapa tanda yang disetel pada enum.
$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);$permissions->hasMultipleFlags(); // Benar;$permissions->removeFlag(UserPermissions::ReadComments)->hasMultipleFlags(); // PALSU
Dapatkan bitmask untuk enum.
Izin Pengguna::Member()->getBitmask(); // 11;Izin Pengguna::Moderator()->getBitmask(); // 111;Izin Pengguna::Admin()->getBitmask(); // 1111;Izin Pengguna::DeleteComments()->getBitmask(); // 1000;
Untuk menggunakan enum yang ditandai secara langsung dalam kueri Eloquent Anda, Anda dapat menggunakan sifat QueriesFlaggedEnums
pada model Anda yang memberi Anda metode berikut:
Pengguna::hasFlag('izin', Izin Pengguna::DeleteComments())->get();
Pengguna::notHasFlag('izin', Izin Pengguna::DeleteComments())->get();
Pengguna::hasAllFlags('izin', [UserPermissions::EditComment(), UserPermissions::ReadComment()])->get();
Pengguna::hasAnyFlags('izin', [UserPermissions::DeleteComments(), UserPermissions::EditComments()])->get();
Anda dapat memasukkan atribut model ke enum menggunakan casting khusus bawaan Laravel. Ini akan melemparkan atribut ke instance enum saat mendapatkan dan kembali ke nilai enum saat menyetel. Karena Enum::class
mengimplementasikan kontrak Castable
, Anda hanya perlu menentukan nama kelas enum:
gunakan BenSampoEnumTestsEnumsUserType; gunakan IlluminateDatabaseEloquentModel; Contoh kelas memperluas Model {protected $casts = ['random_flag' => 'boolean', // Contoh standar laravel cast'user_type' => UserType::class, // Contoh enum cast]; }
Sekarang, saat Anda mengakses atribut user_type
model Example
Anda, nilai dasar akan dikembalikan sebagai enum UserType
.
$example = Contoh::first();$example->user_type // Contoh dari UserType
Tinjau metode dan properti yang tersedia pada instans enum untuk mendapatkan hasil maksimal dari casting atribut.
Anda dapat menyetel nilainya dengan meneruskan nilai enum atau instance enum lainnya.
$example = Contoh::first();// Setel menggunakan enum value$example->user_type = UserType::Moderator;// Setel menggunakan enum instance$example->user_type = UserType::Moderator();
$model->toArray()
Saat menggunakan toArray
(atau mengembalikan model/model dari pengontrol Anda sebagai respons) Laravel akan memanggil metode toArray
pada instance enum.
Secara default, ini hanya akan mengembalikan nilai dalam tipe aslinya. Anda mungkin juga ingin memiliki akses ke properti lain (kunci, deskripsi), misalnya untuk kembali ke aplikasi javascript.
Untuk menyesuaikan perilaku ini, Anda dapat mengganti metode toArray
pada instance enum.
// Contoh kelas Enumfinal UserType memperluas Enum {const ADMINISTRATOR = 0;const MODERATOR = 1; }$instance = Tipe Pengguna::Moderator();// Fungsi publik default toArray() {kembalikan $ini->nilai; }// Mengembalikan int(1)// Mengembalikan semua fungsi properti publik keArray() {kembalikan $ini; }// Mengembalikan array yang berisi semua properti// array(3) {// ["value"]=>// int(1)"// ["key"]=>// string(9) "MODERATOR "// ["deskripsi"]=>// string(9) "Moderator"// }
Banyak database mengembalikan semuanya sebagai string (misalnya, bilangan bulat dapat dikembalikan sebagai string '1'
). Untuk mengurangi gesekan bagi pengguna perpustakaan, kami menggunakan paksaan tipe untuk mengetahui nilai yang diinginkan. Jika Anda lebih memilih untuk mengontrol ini, Anda dapat mengganti metode statis parseDatabase
di kelas enum Anda:
kelas terakhir UserType memperluas Enum {const Administrator = 0;const Moderator = 1;fungsi statis publik parseDatabase($value) {kembali (int) $nilai; } }
Mengembalikan null
dari metode parseDatabase
akan menyebabkan atribut pada model juga menjadi null
. Ini bisa berguna jika database Anda menyimpan nilai kosong yang tidak konsisten seperti string kosong, bukan NULL
.
Jika Anda mentransmisikan atribut pada model Anda ke enum, paket laravel-ide-helper dapat digunakan untuk secara otomatis menghasilkan docblock properti untuk Anda.
Karena enum menerapkan konsistensi pada tingkat kode, maka tidak perlu melakukannya lagi di tingkat basis data, oleh karena itu tipe yang disarankan untuk kolom basis data adalah string
atau int
bergantung pada nilai enum Anda. Ini berarti Anda dapat menambah/menghapus nilai enum dalam kode Anda tanpa mengkhawatirkan lapisan database Anda.
gunakan AppEnumsUserType; gunakan IlluminateSupportFacadesSchema; gunakan IlluminateDatabaseSchemaBlueprint; gunakan IlluminateDatabaseMigrationsMigration; kelas CreateUsersTable memperluas Migrasi {/** * Jalankan migrasi. * * @return void */fungsi publik naik(): void{ Skema::tabel('pengguna', fungsi (Cetak Biru $tabel): void {$tabel->peningkatan besar('id');$tabel->cap waktu();$tabel->string('tipe') ->default(Tipe Pengguna::Moderator); }); } }
enum
Alternatifnya, Anda dapat menggunakan kelas Enum
dalam migrasi Anda untuk menentukan kolom enum. Nilai enum harus didefinisikan sebagai string.
gunakan AppEnumsUserType; gunakan IlluminateSupportFacadesSchema; gunakan IlluminateDatabaseSchemaBlueprint; gunakan IlluminateDatabaseMigrationsMigration; kelas CreateUsersTable memperluas Migrasi {/** * Jalankan migrasi. * * @return void */fungsi publik naik(): void{ Skema::tabel('pengguna', fungsi (Cetak Biru $tabel): void {$tabel->bigInddings('id');$tabel->cap waktu();$tabel->enum('tipe', Tipe Pengguna:: dapatkanNilai()) ->default(Tipe Pengguna::Moderator); }); } }
Anda dapat memvalidasi bahwa nilai enum yang diteruskan ke pengontrol adalah nilai yang valid untuk enum tertentu dengan menggunakan aturan EnumValue
.
gunakan BenSampoEnumRulesEnumValue; penyimpanan fungsi publik (Permintaan $ permintaan) {$ini->validasi($permintaan, ['user_type' => ['wajib', EnumValue baru(UserType::class)], ]); }
Secara default, pemeriksaan tipe diatur ke ketat, tetapi Anda dapat melewatinya dengan meneruskan false
ke parameter opsional kedua dari kelas EnumValue.
new EnumValue(UserType::class, false) // Matikan pemeriksaan tipe yang ketat.
Anda juga dapat memvalidasi kunci menggunakan aturan EnumKey
. Ini berguna jika Anda menggunakan kunci enum sebagai parameter URL untuk menyortir atau memfilter misalnya.
gunakan BenSampoEnumRulesEnumKey; penyimpanan fungsi publik (Permintaan $ permintaan) {$ini->validasi($request, ['user_type' => ['wajib', baru <span class="pl-v"