Bagaimana cara memeriksa kelas objek dalam lingkungan spasi nama PHP tanpa menentukan kelas namespace penuh.
Sebagai contoh misalkan saya memiliki perpustakaan objek / Entitas / Kontrak / Nama.
Kode berikut tidak berfungsi karena get_class mengembalikan kelas namespace penuh.
If(get_class($object) == 'Name') {
... do this ...
}
Kata kunci ajaib namespace mengembalikan namespace saat ini, yang tidak digunakan jika objek yang diuji memiliki namespace lain.
Saya hanya dapat menentukan classname lengkap dengan namespaces, tetapi ini tampaknya mengunci struktur kode. Juga tidak banyak digunakan jika saya ingin mengubah namespace secara dinamis.
Adakah yang bisa memikirkan cara yang efisien untuk melakukan ini. Saya kira satu opsi adalah regex.
php
class
namespaces
Greg. Menambah
sumber
sumber
Jawaban:
Anda dapat melakukan ini dengan refleksi. Khususnya, Anda bisa menggunakan
ReflectionClass::getShortName
metode ini, yang mendapatkan nama kelas tanpa namespace-nya.Pertama, Anda perlu membuat
ReflectionClass
instance, dan kemudian memanggilgetShortName
metode instance itu:Namun, saya tidak dapat membayangkan banyak keadaan di mana ini diinginkan. Jika Anda ingin agar objek tersebut adalah anggota kelas tertentu, cara mengujinya adalah dengan
instanceof
. Jika Anda ingin cara yang lebih fleksibel untuk memberi sinyal kendala tertentu, cara untuk melakukannya adalah dengan menulis antarmuka dan mengharuskan kode mengimplementasikan antarmuka itu. Sekali lagi, cara yang benar untuk melakukan ini adalah denganinstanceof
. (Anda dapat melakukannya denganReflectionClass
, tetapi kinerjanya akan jauh lebih buruk.)sumber
Tenant
tidak ada di namespace saat ini. Cobavar_dump($tenant instanceof \Library\Entity\People\Tenant)
saja. Juga, selidiki bagaimana menggunakanuse
operator, dan konsep umum di balik ruang nama PHP!$reflect = new \ReflectionClass($object);
str_replace(__NAMESPACE__ . '\\', '', __CLASS__);
. Ini juga jauh lebih cepat, dari segi kinerja.(new \ReflectionClass($obj))->getShortName();
adalah solusi terbaik berkaitan dengan kinerja.Saya ingin tahu yang mana dari solusi yang disediakan adalah yang tercepat, jadi saya telah mengumpulkan sedikit tes.
Hasil
Kode
Hasilnya benar-benar mengejutkan saya. Saya pikir solusi meledak akan menjadi cara tercepat untuk pergi ...
sumber
Saya menambahkan substr ke pengujian https://stackoverflow.com/a/25472778/2386943 dan itulah cara fastet yang saya bisa uji (CentOS PHP 5.3.3, Ubuntu PHP 5.5.9) keduanya dengan i5.
Hasil
Kode
== UPDATE ==
Seperti disebutkan dalam komentar oleh @MrBandersnatch bahkan ada cara yang lebih cepat untuk melakukan ini:
Berikut adalah hasil tes yang diperbarui dengan "SubstringStrChr" (menyimpan hingga sekitar 0,001 detik):
sumber
str_replace(__NAMESPACE__ . '\\', '', __CLASS__);
. Hasil pada mesin virtual yang lemah menunjukkan hampir dua kali lebih cepat dari semua ini.php -f bench.php Reflection: 0.44037771224976 s ClassA Basename: 0.48089025020599 s ClassA Explode: 0.54955270290375 s ClassA Substring: 0.38200764656067 s ClassA Frank's Custom Benchmark: 0.22782742977142 s ClassA
if ($pos = strrchr(static::class, '\\')) { .. } else { ... }
.$classNameShort = substr(strrchr('\\' . get_class($this), '\\'), 1);
Ini adalah cara yang lebih mudah untuk melakukan ini jika Anda menggunakan kerangka PHP Laravel:
sumber
Saya menggunakan ini:
sumber
Untuk mendapatkan nama pendek sebagai satu-liner (sejak PHP 5.4 ):
Ini adalah pendekatan yang bersih dan cepat masuk akal .
sumber
Saya menemukan diri saya dalam situasi yang unik di mana
instanceof
tidak dapat digunakan (khusus sifat-sifat namespace) dan saya membutuhkan nama pendek dengan cara yang paling efisien mungkin jadi saya telah melakukan tolok ukur sendiri. Ini mencakup semua metode & variasi yang berbeda dari jawaban dalam pertanyaan ini.Daftar seluruh hasil ada di sini tetapi di sini adalah yang utama:
$obj->getShortName()
adalah metode tercepat namun ; menggunakan refleksi hanya untuk mendapatkan nama pendek itu adalah metode yang paling lambat.'strrpos'
dapat mengembalikan nilai yang salah jika objek tidak ada dalam namespace jadi sementara'safe strrpos'
sedikit lebih lambat saya akan mengatakan ini adalah pemenangnya.'basename'
kompatibel antara Linux dan Windows Anda harus menggunakanstr_replace()
yang membuat metode ini paling lambat dari semuanya.Tabel hasil yang disederhanakan, kecepatan diukur dibandingkan dengan metode paling lambat:
sumber
Anda bisa menggunakan
explode
untuk memisahkan namespace danend
untuk mendapatkan nama kelas:sumber
Yii jalan
Yii menggunakan metode ini dalam generator kode Gii-nya
Dokumentasi metode
Informasi lebih lanjut:
https://github.com/yiisoft/yii2/blob/master/framework/helpers/BaseStringHelper.php http://www.yiiframework.com/doc-2.0/yii-helpers-basestringhelper.html#basename()-detail
sumber
Ini adalah solusi sederhana untuk PHP 5.4+
Apa yang akan kembali?
Nama kelas yang diperluas dan namespace berfungsi dengan baik untuk:
Bagaimana dengan kelas di namespace global?
sumber
Jika Anda perlu tahu nama kelas yang dipanggil dari dalam kelas, dan tidak ingin namespace, Anda bisa menggunakan yang ini
Ini bagus ketika Anda memiliki metode di dalam kelas yang diperluas oleh kelas lain. Selain itu, ini juga berfungsi jika ruang nama tidak digunakan sama sekali.
Contoh:
sumber
Berdasarkan jawaban @MaBi, saya membuat ini:
Yang dapat Anda gunakan seperti itu:
A::class
kembaliFoo\Bar\Baz\A
, tetapiA::getClassShortName()
kembaliA
.Bekerja untuk PHP> = 5.5.
sumber
Saya tahu ini adalah posting lama tapi ini yang saya gunakan - Lebih cepat dari semua yang diposting di atas panggil metode ini dari kelas Anda, jauh lebih cepat daripada menggunakan Refleksi
sumber
Ditemukan di halaman dokumentasi get_class , di mana itu diposting oleh saya di nwhiting dot com .
Tetapi ide ruang nama adalah untuk menyusun kode Anda. Itu juga berarti bahwa Anda dapat memiliki kelas dengan nama yang sama di beberapa ruang nama. Jadi secara teoritis, objek yang Anda lewati dapat memiliki nama (dilucuti) nama kelas, sementara masih menjadi objek yang sama sekali berbeda dari yang Anda harapkan.
Selain itu, Anda mungkin ingin memeriksa kelas dasar tertentu , dalam hal
get_class
ini tidak melakukan trik sama sekali. Anda mungkin ingin memeriksa operatorinstanceof
.sumber
Anda mungkin mendapatkan hasil yang tidak terduga ketika kelas tidak memiliki namespace. Yaitu
get_class
kembaliFoo
, maka$baseClass
akan menjadioo
.Ini dapat dengan mudah diperbaiki dengan awalan
get_class
dengan garis miring terbalik:Sekarang juga kelas tanpa namespace akan mengembalikan nilai yang tepat.
sumber
Regex lama yang baik tampaknya lebih cepat daripada sebagian besar metode yang ditunjukkan sebelumnya:
Jadi ini berfungsi bahkan ketika Anda memberikan nama kelas pendek atau nama kelas yang memenuhi syarat (kanonik).
Apa yang dilakukan regex adalah ia mengonsumsi semua karakter sebelumnya hingga separator terakhir ditemukan (yang juga dikonsumsi). Jadi string yang tersisa akan menjadi nama kelas pendek.
Jika Anda ingin menggunakan pemisah yang berbeda (mis. /) Maka gunakan saja pemisah itu. Ingatlah untuk menghindari backslash (mis. \) Dan juga char pattern (mis. /) Dalam pola input.
sumber
Karena "ReflectionClass" dapat bergantung pada versi, gunakan saja yang berikut:
atau bahkan jelas
sumber
Mengutip php.net:
Berdasarkan info ini dan memperluas dari jawaban arzzzen ini harus bekerja pada sistem Windows dan Nix *:
Catatan: Saya melakukan tolok ukur
ReflectionClass
terhadapbasename+str_replace+get_class
dan menggunakan refleksi sekitar 20% lebih cepat daripada menggunakan pendekatan basename, tapi YMMV.sumber
Solusi termudah dan tercepat yang bekerja di lingkungan apa pun adalah:
sumber
$Object->__class->getShortName()
benar - benar membuatku kesal tentang PHP. Pendekatan Anda berhasil, tetapi sekarang Anda menempatkan metode konkret di kelas Anda hanya untuk mengekspos apa yang seharusnya menjadi konstruksi bahasa.sumber
Jika Anda hanya menghapus ruang nama dan menginginkan apa pun setelah \ terakhir dalam nama kelas dengan namespace (atau hanya nama jika tidak ada '\') Anda dapat melakukan sesuatu seperti ini:
Pada dasarnya ini regex untuk mendapatkan kombinasi karakter atau garis miring terbalik dan hingga garis miring terbalik terakhir yang hanya mengembalikan karakter garis miring terbalik dan sampai akhir string. Menambahkan? setelah pengelompokan pertama berarti jika kecocokan pola tidak ada, itu hanya mengembalikan string penuh.
sumber
Tercepat yang saya temukan di sini untuk
PHP 7.2
diUbubntu 18.04
sumber