PHP, seperti yang kita ketahui, memiliki ketikan yang lemah . Bagi yang tidak, PHP.net mengatakan:
PHP tidak memerlukan (atau mendukung) definisi tipe eksplisit dalam deklarasi variabel; tipe variabel ditentukan oleh konteks di mana variabel digunakan.
Suka atau benci, PHP membuat ulang variabel saat itu juga. Jadi, kode berikut ini valid:
$var = "10";
$value = 10 + $var;
var_dump($value); // int(20)
PHP juga memungkinkan Anda untuk melemparkan variabel secara eksplisit, seperti:
$var = "10";
$value = 10 + $var;
$value = (string)$value;
var_dump($value); // string(2) "20"
Itu semua keren ... tetapi, untuk kehidupan saya, saya tidak dapat membayangkan alasan praktis untuk melakukan ini.
Saya tidak punya masalah dengan pengetikan yang kuat dalam bahasa yang mendukungnya, seperti Java. Tidak apa-apa, dan saya benar-benar memahaminya. Juga, saya menyadari - dan sepenuhnya memahami kegunaan - tipe mengisyaratkan dalam parameter fungsi.
Masalah yang saya miliki dengan tipe casting dijelaskan oleh kutipan di atas. Jika PHP dapat bertukar tipe sesuka hati , ia dapat melakukannya bahkan setelah Anda memaksakan suatu tipe; dan dapat melakukannya on-the-fly ketika Anda membutuhkan jenis tertentu dalam sebuah operasi. Itu membuat yang berikut ini valid:
$var = "10";
$value = (int)$var;
$value = $value . ' TaDa!';
var_dump($value); // string(8) "10 TaDa!"
Jadi apa gunanya?
Ambil contoh teoretis dari dunia ini di mana casting tipe yang ditentukan pengguna masuk akal dalam PHP :
- Anda memaksa variabel pemeran
$foo
sebagaiint
→(int)$foo
. - Anda mencoba untuk menyimpan nilai string dalam variabel
$foo
. - PHP melempar pengecualian !! ← Itu masuk akal. Tiba-tiba alasan casting tipe yang ditentukan pengguna ada!
Fakta bahwa PHP akan beralih hal-hal sesuai kebutuhan membuat titik dari tipe casting yang didefinisikan pengguna tidak jelas. Misalnya, dua contoh kode berikut ini setara:
// example 1
$foo = 0;
$foo = (string)$foo;
$foo = '# of Reasons for the programmer to type cast $foo as a string: ' . $foo;
// example 2
$foo = 0;
$foo = (int)$foo;
$foo = '# of Reasons for the programmer to type cast $foo as a string: ' . $foo;
Setahun setelah awalnya mengajukan pertanyaan ini, tebak siapa yang mendapati dirinya menggunakan typecasting di lingkungan praktis? Hormat kami.
Syaratnya adalah untuk menampilkan nilai uang di situs web untuk menu restoran. Desain situs mengharuskan agar trailing zero dipangkas, sehingga tampilan terlihat seperti berikut:
Menu Item 1 .............. $ 4
Menu Item 2 .............. $ 7.5
Menu Item 3 .............. $ 3
Cara terbaik yang saya temukan untuk melakukan itu adalah membuang variabel sebagai pelampung:
$price = '7.50'; // a string from the database layer.
echo 'Menu Item 2 .............. $ ' . (float)$price;
PHP memotong nol trailing float, dan kemudian menampilkan kembali float sebagai string untuk penggabungan.
sumber
(string)
gips di mana-mana ?$intval.'bar'
melempar pengecualian, saya masih tidak setuju. Itu tidak membuang pengecualian dalam bahasa apa pun. (Semua bahasa yang saya tahu melakukan pemeran otomatis atau a.toString()
). Jika Anda mengatakan$intval = $stringval
melempar pengecualian, maka Anda berbicara tentang bahasa yang sangat diketik. Saya tidak bermaksud terdengar kasar, jadi, maaf jika saya melakukannya. Saya hanya berpikir itu bertentangan dengan apa yang digunakan oleh setiap pengembang, dan jauh, jauh lebih tidak nyaman.Jawaban:
Dalam bahasa yang diketik dengan lemah, casting tipe ada untuk menghapus ambiguitas dalam operasi yang diketik, ketika sebaliknya kompiler / juru bahasa akan menggunakan urutan atau aturan lain untuk membuat asumsi operasi yang digunakan.
Biasanya saya akan mengatakan PHP mengikuti pola ini, tetapi dari kasus-kasus yang saya periksa, PHP telah berperilaku kontra-intuitif di masing-masing.
Berikut adalah kasus-kasus itu, menggunakan JavaScript sebagai bahasa perbandingan.
String Concatentation
Jelas ini bukan masalah di PHP karena ada string concatenation (
JavaScript.
) dan penambahan (+
) operator yang terpisah.Perbandingan String
Seringkali dalam sistem komputer "5" lebih besar dari "10" karena tidak menafsirkannya sebagai angka. Tidak demikian halnya di PHP, yang, meskipun keduanya adalah string, menyadari bahwa itu adalah angka dan menghilangkan kebutuhan untuk pemain):
JavaScript PHPFungsi mengetik tanda tangan
PHP mengimplementasikan pemeriksaan tipe kosong pada tanda tangan fungsi, tapi sayangnya itu sangat cacat sehingga jarang digunakan.
Saya pikir saya mungkin melakukan sesuatu yang salah, tetapi komentar pada dokumen menegaskan bahwa tipe built-in selain array tidak dapat digunakan dalam tanda tangan fungsi PHP - meskipun pesan kesalahan menyesatkan.
PHPDan tidak seperti bahasa lain yang saya tahu, bahkan jika Anda menggunakan tipe yang dimengerti, null tidak bisa lagi diteruskan ke argumen itu (
must be an instance of array, null given
). Bodoh sekali.Interpretasi Boolean
[ Sunting ]: Yang ini baru. Saya memikirkan kasus lain, dan sekali lagi logikanya terbalik dari JavaScript.
JavaScript PHPJadi sebagai kesimpulan, satu-satunya kasus berguna yang dapat saya pikirkan adalah ... (drumroll)
Ketik pemotongan
Dengan kata lain, ketika Anda memiliki nilai satu jenis (katakanlah string) dan Anda ingin menafsirkannya sebagai jenis lain (int) dan Anda ingin memaksanya untuk menjadi salah satu set nilai yang valid dalam jenis itu:
Saya tidak bisa melihat upcasting (ke jenis yang mencakup lebih banyak nilai) yang benar-benar akan memberi Anda keuntungan.
Jadi, sementara saya tidak setuju dengan usulan penggunaan pengetikan (Anda pada dasarnya mengusulkan pengetikan statis , tetapi dengan ambiguitas bahwa hanya jika itu dicekokkan secara paksa ke dalam jenis pengetikan yang akan menyebabkan kesalahan - yang akan menyebabkan kebingungan), saya pikir itu bagus pertanyaan, karena casting ternyata memiliki tujuan yang sangat sedikit di PHP.
sumber
E_NOTICE
begitu? :)E_NOTICE
mungkin baik-baik saja, tetapi bagi saya keadaan ambigu menyangkut - bagaimana Anda tahu dengan melihat satu bit kode jika variabel berada di negara itu (telah dilemparkan ke tempat lain)? Juga, saya menemukan kondisi lain dan menambahkannya ke jawaban saya.echo "010" == 010
danecho "0x10" == 0x10
;-)Anda sedang mencampur konsep tipe lemah / kuat dan dinamis / statis.
PHP lemah dan dinamis, tetapi masalah Anda terletak pada konsep tipe dinamis. Itu berarti, variabel tidak memiliki tipe, nilai tidak.
'Casting tipe' adalah ekspresi yang menghasilkan nilai baru dari tipe yang berbeda dari aslinya; itu tidak melakukan apa pun pada variabel (jika ada yang terlibat).
Satu situasi di mana saya secara teratur mengetikkan nilai-nilai cor adalah pada parameter SQL numerik. Anda seharusnya membersihkan / menghindar dari nilai input apa pun yang Anda masukkan ke dalam pernyataan SQL, atau (jauh lebih baik) menggunakan query parameter. Tetapi, jika Anda menginginkan beberapa nilai yang HARUS berupa bilangan bulat, jauh lebih mudah untuk hanya melemparkannya.
Mempertimbangkan:
jika saya meninggalkan baris pertama,
$id
akan menjadi vektor yang mudah untuk injeksi SQL. Para pemain memastikan bahwa itu adalah bilangan bulat yang tidak berbahaya; setiap upaya untuk memasukkan beberapa SQL hanya akan menghasilkan permintaanid=0
sumber
mysql_real_escape_string($id);
belum diselesaikan oleh metode ini?mysql_real_escape_string()
memiliki kerentanan untuk tidak melakukan apa pun ke string seperti '0x01ABCDEF' (yaitu representasi heksadesimal bilangan bulat). Dalam beberapa pengkodean multibyte (bukan Unicode lucklily) string seperti ini dapat digunakan untuk memecah kueri (karena akan dievaluasi oleh MySQL untuk sesuatu yang berisi penawaran). Itu sebabnya tidakmysql_real_escape_string()
jugais_int()
adalah pilihan terbaik untuk berurusan dengan nilai integer. Typecasting adalah.Satu penggunaan untuk casting tipe dalam PHP yang saya temukan:
Saya sedang mengembangkan aplikasi android yang membuat permintaan http ke skrip PHP di server untuk mengambil data dari database. Script menyimpan data dalam bentuk objek PHP (atau array asosiatif) dan dikembalikan sebagai objek JSON ke aplikasi. Tanpa tipe casting saya akan menerima sesuatu seperti ini:
Tapi, menggunakan casting tipe PHP
(int)
pada id pengguna ketika menyimpannya objek PHP, saya malah mengembalikannya ke aplikasi:Kemudian ketika objek JSON diuraikan dalam aplikasi, itu menyelamatkan saya dari keharusan mengurai id ke Integer!
Lihat, sangat bermanfaat.
sumber
Salah satu contoh adalah objek dengan metode __toString:
$str = $obj->__toString();
vs$str = (string) $obj;
. Ada lebih sedikit mengetik di yang kedua, dan hal-hal tambahan adalah tanda baca, yang membutuhkan waktu lebih lama untuk mengetik. Saya juga berpikir itu lebih mudah dibaca, meskipun yang lain mungkin tidak setuju.Lain adalah membuat array tunggal-elemen:
array($item);
vs(array) $item;
. Ini akan menempatkan semua jenis skalar (integer, sumber daya, dll.) Di dalam array.Altenatif, jika
$item
merupakan objek, propertinya akan menjadi kunci nilai-nilainya. Namun, saya pikir konversi objek-> array agak aneh: properti pribadi dan dilindungi adalah bagian dari array, dan diganti namanya. Mengutip dokumentasi PHP : variabel pribadi memiliki nama kelas yang diawali dengan nama variabel; variabel yang dilindungi memiliki '*' yang diawali dengan nama variabel.Penggunaan lain adalah mengubah data GET / POST menjadi tipe yang sesuai untuk basis data. MySQL dapat menangani ini sendiri, tetapi saya pikir server yang lebih sesuai dengan ANSI mungkin menolak data. Alasan saya hanya menyebutkan database adalah bahwa dalam kebanyakan kasus lain, data akan memiliki operasi yang dilakukan di atasnya sesuai dengan jenisnya di beberapa titik (yaitu int / mengapung biasanya akan memiliki perhitungan yang dilakukan pada mereka, dll).
sumber
int
ataufloat
akan terjadi saat membuat kueri).(array) $item
apakah rapi , tetapi bermanfaat?Skrip ini:
akan berjalan dengan baik untuk
script.php?tags[]=one
tetapi akan gagal untukscript.php?tags=one
, karena_GET['tags']
mengembalikan array dalam kasus pertama tetapi tidak dalam yang kedua. Karena skrip ditulis untuk mengharapkan array (dan Anda kurang memiliki kendali atas string kueri yang dikirim ke skrip), masalahnya dapat diselesaikan dengan memberikan hasil dari_GET
:sumber
Ini juga dapat digunakan sebagai metode cepat dan kotor untuk memastikan data yang tidak dipercaya tidak akan merusak sesuatu misalnya jika menggunakan layanan jarak jauh yang memiliki validasi omong kosong dan hanya boleh menerima angka.
Jelas ini cacat dan juga ditangani secara implisit oleh operator perbandingan dalam pernyataan if, tetapi sangat membantu dalam memastikan Anda tahu persis apa yang dilakukan kode Anda.
sumber
$_POST['amount']
berisi string sampah, php akan mengevaluasi bahwa itu tidak lebih besar dari nol. Jika itu berisi string yang mewakili angka positif, itu akan mengevaluasi benar.Salah satu "penggunaan" dari variabel PHP re-casting on-the-fly yang sering saya lihat digunakan adalah ketika mengambil data dari sumber eksternal (input pengguna atau database). Ini memungkinkan para pembuat kode (perhatikan bahwa saya tidak mengatakan pengembang) mengabaikan (atau bahkan tidak belajar) tipe data berbeda yang tersedia dari sumber yang berbeda.
Satu coder (perhatikan bahwa saya tidak mengatakan pengembang) yang kodenya saya warisi dan masih pertahankan sepertinya tidak tahu bahwa ada perbedaan antara string
"20"
yang dikembalikan dalam$_GET
variabel super, ke antara operasi integer20 + 20
ketika dia menambahkannya ke nilai dalam database. Dia hanya beruntung bahwa PHP menggunakan.
untuk penggabungan string dan tidak+
seperti bahasa lainnya, karena saya telah melihat kodenya "menambahkan" dua string (avarcahr
dari MySQL dan nilai dari$_GET
) dan mendapatkan int.Apakah ini contoh praktis? Hanya dalam arti bahwa itu memungkinkan coders lolos dengan tidak tahu apa tipe data yang mereka kerjakan. Saya pribadi membencinya.
sumber