Saya memiliki beberapa aplikasi lama yang membuang banyak pesan "xyz tidak terdefinisi" dan "offset tak terdefinisi" saat berjalan pada tingkat kesalahan E_NOTICE, karena keberadaan variabel tidak secara eksplisit diperiksa menggunakan isset()
dan selir.
Saya sedang mempertimbangkan untuk mengatasinya agar kompatibel dengan E_NOTICE, karena pemberitahuan tentang variabel yang hilang atau offset dapat menjadi penyelamat, mungkin ada beberapa peningkatan kinerja kecil yang bisa diperoleh, dan secara keseluruhan cara yang lebih bersih.
Namun, saya tidak suka apa yang menyebabkan ratusan isset()
empty()
dan array_key_exists()
dilakukan pada kode saya. Itu membengkak, menjadi kurang dapat dibaca, tanpa mendapatkan apa pun dalam hal nilai atau makna.
Bagaimana saya dapat menyusun kode saya tanpa pemeriksaan variabel yang berlebihan, sekaligus juga kompatibel dengan E_NOTICE?
sumber
Jawaban:
Bagi mereka yang tertarik, saya telah memperluas topik ini menjadi artikel kecil, yang memberikan informasi di bawah ini dalam bentuk terstruktur yang agak lebih baik: Panduan Definitif Untuk isset PHP Dan kosong
IMHO Anda harus berpikir tentang tidak hanya membuat aplikasi "E_NOTICE kompatibel", tetapi juga merestrukturisasi semuanya. Memiliki ratusan poin dalam kode Anda yang secara teratur mencoba menggunakan variabel yang tidak ada terdengar seperti program yang terstruktur dengan buruk. Mencoba mengakses variabel yang tidak ada seharusnya tidak pernah terjadi, bahasa lain menolak ini pada waktu kompilasi. Fakta bahwa PHP memungkinkan Anda untuk melakukannya tidak berarti Anda harus melakukannya.
Peringatan ini ada untuk membantu Anda, bukan untuk mengganggu Anda. Jika Anda mendapat peringatan, "Anda mencoba bekerja dengan sesuatu yang tidak ada!" , reaksi Anda seharusnya "Ups, saya buruk, biarkan saya memperbaikinya secepatnya." Bagaimana lagi Anda akan membedakan antara "variabel yang bekerja dengan baik tanpa definisi" dan kode yang benar - benar salah yang dapat menyebabkan kesalahan serius ? Ini juga alasan mengapa Anda selalu, selalu , mengembangkan dengan pelaporan kesalahan berubah menjadi 11 dan terus memasukkan kode Anda sampai tidak ada satu pun
NOTICE
yang dikeluarkan. Menonaktifkan pelaporan kesalahan hanya untuk lingkungan produksi, untuk menghindari kebocoran informasi dan memberikan pengalaman pengguna yang lebih baik bahkan saat menghadapi kode buggy.Untuk menguraikan:
Anda akan selalu membutuhkan
isset
atauempty
di suatu tempat dalam kode Anda, satu-satunya cara untuk mengurangi kemunculannya adalah dengan menginisialisasi variabel Anda dengan benar. Bergantung pada situasinya, ada berbagai cara untuk melakukannya:Argumen fungsi:
Tidak perlu untuk memeriksa apakah
$bar
atau$baz
ditetapkan dalam fungsi karena Anda hanya mengatur mereka, semua yang perlu Anda khawatir tentang adalah jika nilai mengevaluasi mereka untuktrue
ataufalse
(atau apapun yang lain).Variabel biasa di mana saja:
Inisialisasi variabel Anda di bagian atas blok kode tempat Anda akan menggunakannya. Ini memecahkan
!isset
masalah, memastikan bahwa variabel Anda selalu memiliki nilai default yang diketahui, memberi pembaca gambaran tentang apa yang akan dikerjakan kode berikut dan dengan demikian juga berfungsi sebagai semacam dokumentasi mandiri.Array:
Hal yang sama seperti di atas, Anda menginisialisasi array dengan nilai default dan menimpanya dengan nilai aktual.
Dalam kasus yang tersisa, katakanlah template tempat Anda mengeluarkan nilai yang mungkin atau mungkin tidak disetel oleh pengontrol, Anda hanya perlu memeriksa:
Jika Anda sering menggunakannya
array_key_exists
, Anda harus mengevaluasi untuk apa Anda menggunakannya. Satu-satunya saat hal itu membuat perbedaan adalah di sini:Seperti yang dinyatakan di atas, jika Anda menginisialisasi variabel Anda dengan benar, Anda tidak perlu memeriksa apakah kuncinya ada atau tidak, karena Anda tahu itu ada. Jika Anda mendapatkan array dari sumber eksternal, nilai akan kemungkinan besar tidak akan
null
tetapi''
,0
,'0'
,false
atau sesuatu seperti itu, yaitu nilai yang Anda dapat mengevaluasi denganisset
atauempty
, tergantung pada niat Anda. Jika Anda secara teratur menyetel kunci array kenull
dan ingin artinya tidak berarti apa punfalse
, yaitu jika dalam contoh di atas hasil yang berbedaisset
danarray_key_exists
membuat perbedaan pada logika program Anda, Anda harus bertanya pada diri sendiri mengapa. Keberadaan variabel seharusnya tidak penting, hanya nilainya yang harus menjadi konsekuensinya. Jika kuncinya adalahtrue
/false
flag, maka gunakantrue
atau . Satu-satunya pengecualian untuk ini adalah perpustakaan pihak ke-3 yang ingin memiliki arti, tetapi karena sangat sulit untuk dideteksi di PHP, saya belum menemukan perpustakaan apa pun yang melakukan ini.false
, bukannull
null
null
sumber
if ($array["xyz"])
alih - alihisset()
atauarray_key_exists()
yang menurut saya agak sah, tentu saja bukan masalah struktural (perbaiki saya jika saya salah). Menambahkanarray_key_exists()
hanya terlihat seperti pemborosan yang mengerikan bagi saya.array_key_exists
alih-alih yang sederhanaisset($array['key'])
atau!empty($array['key'])
. Tentu, keduanya menambahkan 7 atau 8 karakter ke kode Anda, tapi saya tidak akan menyebut itu masalah. Ini juga membantu untuk memperjelas kode Anda:if (isset($array['key']))
berarti variabel ini memang opsional dan mungkin tidak ada, sedangkanif ($array['key'])
hanya berarti "jika benar". Jika Anda mendapat pemberitahuan untuk yang terakhir, Anda tahu logika Anda kacau di suatu tempat.Cukup tulis fungsi untuk itu. Sesuatu seperti:
yang dapat Anda gunakan sebagai
Lakukan hal yang sama untuk hal-hal sepele seperti
get_number()
,get_boolean()
,get_array()
dan sebagainya.sumber
<input name="something[]" />
. Ini akan menyebabkan kesalahan (karena trim tidak dapat diterapkan ke array) menggunakan kode di atas, dalam hal ini harus digunakanis_string
dan mungkinstrval
. Ini bukan hanya kasus di mana seseorang harus menggunakanget_array
baik karena input pengguna (jahat) mungkin apa saja dan parser input pengguna tidak boleh membuang kesalahan.Saya percaya salah satu cara terbaik untuk mengatasi masalah ini adalah dengan mengakses nilai array GET dan POST (COOKIE, SESSION, dll.) Melalui kelas.
Buat kelas untuk setiap array tersebut dan deklarasikan
__get
serta__set
metode ( overloading ).__get
menerima satu argumen yang akan menjadi nama nilai. Metode ini harus memeriksa nilai ini dalam larik global terkait, baik menggunakanisset()
atauempty()
dan mengembalikan nilai jika ada ataunull
(atau nilai default lainnya) sebaliknya.Setelah itu Anda dapat mengakses nilai array dengan percaya diri dengan cara ini:
$POST->username
dan melakukan validasi apa pun jika diperlukan tanpa menggunakanisset()
s atauempty()
s. Jikausername
tidak ada dalam larik global terkait makanull
akan dikembalikan, jadi tidak ada peringatan atau pemberitahuan yang akan dibuat.sumber
Saya tidak keberatan menggunakan
array_key_exists()
fungsi tersebut. Sebenarnya, saya lebih suka menggunakan fungsi khusus ini daripada mengandalkan fungsihackyang dapat mengubah perilaku mereka di masa depanseperti(menyerang untuk menghindari kerentanan ).empty
danisset
Bagaimanapun, saya menggunakan fungsi sederhana yang berguna dalam hal ini, dan beberapa situasi lain dalam menangani indeks array :
Katakanlah Anda memiliki array berikut:
Bagaimana Anda mendapatkan "nilai" dari array? Sederhana:
Kami sudah memiliki array uni dan multi-dimensi yang tercakup, apa lagi yang bisa kami lakukan?
Ambil potongan kode berikut ini misalnya:
Cukup membosankan bukan? Berikut adalah pendekatan lain menggunakan
Value()
fungsi tersebut:Sebagai contoh tambahan, ambil
RealIP()
fungsi untuk tes:Rapi, ya? ;)
sumber
isset
danempty
merupakan konstruksi bahasa , bukan fungsi. Kedua, jika ada fungsi pustaka inti / konstruksi bahasa mengubah perilakunya, Anda mungkin akan kacau atau tidak. Bagaimana jikaarray_key_exists
perilakunya berubah? Jawabannya tidak akan, selama Anda menggunakannya sebagai dokumen. Danisset
didokumentasikan untuk digunakan dengan tepat. Fungsi kasus terburuk tidak digunakan lagi pada satu atau dua versi rilis utama. Sindrom NIH buruk!array_key_exists()
untuk memeriksa apakah ada kunci dalam array ?!array_key_exists()
itu dibuat persis untuk itu , saya lebih mengandalkan untuk tujuan ini dariisset()
dan khususempty()
yang deskripsi resmi adalah: "menentukan apakah suatu variabel kosong", tidak menyebutkan apa-apa jika itu benar-benar ada. Komentar dan suara negatif Anda adalah salah satu yang paling konyol yang pernah saya saksikan sepanjang bulan .isset
danempty
tidak lebih atau kurang dapat diandalkan daripadaarray_key_exists
dan dapat melakukan pekerjaan yang persis sama. Contoh Anda yang kedua dan bertele-tele dapat ditulis$domain = isset($domain['host']) ? $domain['host'] : 'N/A';
hanya dengan fitur bahasa inti, tidak perlu panggilan atau deklarasi fungsi tambahan (perhatikan bahwa saya tidak selalu menganjurkan penggunaan operator terner; o)). Untuk variabel skalar biasa, Anda masih perlu menggunakanisset
atauempty
, dan Anda dapat menggunakannya untuk array dengan cara yang persis sama. "Keandalan" adalah alasan buruk untuk tidak melakukannya.Aku disini bersama mu. Tapi desainer PHP telah membuat kesalahan yang jauh lebih buruk dari itu. Singkatnya, mendefinisikan fungsi kustom untuk pembacaan nilai apa pun, tidak ada jalan lain.
sumber
params["width"] = params["width"] || 5
untuk menyetel default alih-alih semua omong kosong denganisset()
panggilan.register_globals
danmagic_quotes
. Masalah yang dikembangkan ini membuat variabel yang tidak diinisialisasi terlihat hampir tidak berbahaya jika dibandingkan.Saya menggunakan fungsi ini
Contoh
sumber
Selamat datang di operator penggabungan nol (PHP> = 7.0.1):
PHP mengatakan:
sumber
Buat fungsi yang mengembalikan
false
jika tidak disetel, dan, jika ditentukan,false
jika kosong. Jika valid itu mengembalikan variabel. Anda dapat menambahkan lebih banyak opsi seperti yang terlihat pada kode di bawah ini:sumber
Perangkat lunak tidak secara ajaib dijalankan oleh rahmat Tuhan. Jika Anda mengharapkan sesuatu yang hilang, Anda harus menanganinya dengan benar.
Jika Anda mengabaikannya, Anda mungkin membuat lubang keamanan di aplikasi Anda. Dalam bahasa statis, mengakses variabel yang tidak ditentukan itu tidak mungkin. Itu tidak akan hanya mengkompilasi atau merusak aplikasi Anda jika null.
Selain itu, itu membuat aplikasi Anda tidak dapat dikelola, dan Anda akan menjadi gila ketika hal-hal yang tidak terduga terjadi. Ketegasan bahasa adalah suatu keharusan dan PHP, secara desain, salah dalam banyak aspek. Ini akan membuat Anda menjadi programmer yang buruk jika Anda tidak menyadarinya.
sumber
Saya tidak yakin apa definisi Anda tentang keterbacaan, tetapi penggunaan yang tepat dari blok empty (), isset () dan try / throw / catch, cukup penting untuk keseluruhan proses.
Jika E_NOTICE Anda berasal dari $ _GET atau $ _POST, maka E_NOTICE Anda harus diperiksa dengan empty () bersama dengan semua pemeriksaan keamanan lain yang harus dilalui data tersebut.
Jika berasal dari feed atau pustaka eksternal, itu harus dibungkus dengan try / catch.
Jika berasal dari database, $ db_num_rows () atau yang setara harus diperiksa.
Jika berasal dari variabel internal, mereka harus diinisialisasi dengan benar. Seringkali, jenis pemberitahuan ini berasal dari menetapkan variabel baru untuk mengembalikan fungsi yang mengembalikan FALSE saat gagal. Mereka harus digabungkan dalam pengujian yang, jika terjadi kegagalan, dapat menetapkan variabel nilai default yang dapat diterima yang dapat ditangani kode, atau melontarkan pengecualian yang dapat ditangani kode.
Hal-hal ini membuat kode lebih panjang, menambahkan blok ekstra, dan menambahkan tes ekstra, tetapi saya tidak setuju dengan Anda karena saya pikir mereka pasti menambah nilai ekstra.
sumber
Bagaimana dengan menggunakan
@
operator?Sebagai contoh:
Anda mungkin mengatakan ini buruk karena Anda tidak memiliki kendali atas apa yang terjadi "di dalam" $ foo (jika itu adalah panggilan fungsi yang berisi kesalahan PHP misalnya), tetapi jika Anda hanya menggunakan teknik ini untuk variabel, ini setara dengan:
sumber
if(isset($foo))
sebenarnya sudah cukup. Ini akan kembaliTRUE
jika ekspresi mengevaluasi keTRUE
.