Kaedah dan argumen dalam komponen CFML
Cara menulis kaedah komponen CFML: argumen wajib dan lalai, hujah bernama, argumentCollection, jenis pulangan, dan ralat sebenar daripada Lucee 7.1.

Kandungan
- Kaedah dan argumen dalam komponen CFML
- Tiga skop yang perlu dibezakan
- Argumen wajib, lalai dan jenis
- Hujah bernama mengalahkan susunan
- Apabila jenis tidak sepadan
- Mengapa local penting dalam gelung
- Banyak argumen atau satu struktur?
- argumentCollection untuk struktur
- Pembahagian dengan sifar dan ralat lain
- Pengesahan input di satu tempat
- Corak yang mengelakkan separuh pepijat
- Membaca mesej ralat enjin
- Adakah required cukup untuk keselamatan?
- Bolehkah argumen bernilai null?
- Soalan lazim
- Bolehkah satu kaedah menerima bilangan argumen berubah-ubah?
- Perlukah setiap argumen diisytiharkan jenisnya?
- Apa beza param dalam fungsi dengan nilai lalai?
- Mengapa kaedah saya memulangkan ralat "key doesn't exist"?
Kaedah dan argumen dalam komponen CFML
Bahagian pertama siri ini menunjukkan apa itu .cfc dan mengapa ia berbaloi. Bahagian ini masuk ke bahagian yang paling kerap menimbulkan salah faham: kaedah dan argumen.
Kebanyakan pepijat komponen bukan pada logik. Ia pada andaian tentang apa yang enjin buat dengan nilai yang dihantar. Adakah "7" menjadi nombor? Apa jadi kalau argumen wajib tertinggal? Adakah jenis pulangan benar-benar disemak? Artikel ini menjawab dengan output sebenar daripada Lucee 7.1.1.17.
Tiga skop yang perlu dibezakan
Dalam satu kaedah komponen, ada tiga tempat nilai boleh tinggal.
argumentsmemegang semua nilai yang dihantar masuk. Ia hanya wujud dalam panggilan itulocalialah pemboleh ubah sementara dalam kaedah. Ia hilang apabila kaedah tamatvariablesialah keadaan objek. Ia kekal selagi objek itu hidup
Kesilapan biasa ialah menggunakan variables untuk sesuatu yang sepatutnya local, terutamanya dalam gelung. Nilai itu akan tertinggal selepas kaedah tamat, dan panggilan berikutnya mewarisi sisa panggilan sebelumnya.
Peraturan mudah: kalau nilai itu hanya bermakna dalam satu panggilan, letakkan dalam local. Kalau ia sebahagian daripada keadaan objek, barulah variables.
Argumen wajib, lalai dan jenis
Komponen ujian di bawah mengandungi tiga kaedah dengan bentuk argumen berbeza.
component output="false" {
public numeric function tambah(required numeric a, required numeric b) {
return arguments.a + arguments.b;
}
public string function sapaan(required string nama, string gelaran = "") {
return len(arguments.gelaran) ? arguments.gelaran & " " & arguments.nama : arguments.nama;
}
public numeric function bahagi(required numeric a, required numeric b) {
return arguments.a / arguments.b;
}
}
required bermaksud panggilan tanpa argumen itu akan gagal. Nilai lalai (= "") bermaksud argumen itu pilihan.
Apabila b tidak dihantar, mesej sebenar enjin ialah:
The parameter [b] to function [tambah] is required but was not passed in.
Mesej ini menyebut nama argumen dan nama fungsi. Itu cukup untuk membetulkan panggilan tanpa membuka fail.
Hujah bernama mengalahkan susunan
CFML membenarkan hujah dihantar mengikut nama, bukan kedudukan.
k = new komponen.Kaedah();
writeOutput(k.tambah(b = 5, a = 3)); // 8
Susunan diterbalikkan, hasilnya tetap 8. Untuk kaedah dengan banyak argumen, ini menghalang pepijat yang sukar dilihat, contohnya tertukar harga dengan kuantiti.
Namun ada harga: hujah bernama lebih panjang, dan dalam kod lama yang menggunakan kedudukan, mencampur kedua-dua gaya dalam satu panggilan mengundang kekeliruan. Pilih satu gaya bagi setiap komponen.
Apabila jenis tidak sepadan
Lucee melonggarkan penukaran jenis pada argumen. Menghantar rentetan "7" kepada argumen numeric berjaya, dan hasilnya 9.
writeOutput(k.tambah("7", 2)); // 9
Ini mudah, tetapi juga bermakna data daripada borang tidak akan ditolak hanya kerana jenisnya salah. Kalau nilai mesti integer positif, semak secara eksplisit dalam kaedah.
Jenis pulangan berkelakuan lebih ketat. Kaedah yang diisytiharkan numeric tetapi memulangkan teks gagal serta-merta:
Cannot cast String [bukan nombor] to a value of type [numeric]
Maksudnya, jenis pulangan ialah kontrak yang dikuatkuasakan enjin, manakala jenis argumen ialah cadangan yang dibantu enjin. Kedua-duanya berguna, tetapi jangan anggap argumen sebagai pengesahan.
Mengapa local penting dalam gelung
Perbezaan local dan variables kelihatan kecil sehingga anda menulis gelung.
public array function senaraiHarga(required array harga) {
var hasil = [];
for (var i = 1; i <= arrayLen(arguments.harga); i++) {
var baris = {};
baris.asal = arguments.harga[i];
baris.cukai = arguments.harga[i] * 0.06;
arrayAppend(hasil, baris);
}
return hasil;
}
Semua pemboleh ubah di dalamnya ialah local kerana var. Jika baris ditulis sebagai variables.baris, objek itu menyimpan satu salinan sahaja, dan panggilan seterusnya menulis ganti nilai sebelumnya. Dalam gelung, kesannya ialah semua baris dalam array merujuk struct yang sama, dan hasil akhirnya kelihatan seperti data bertindih.
Dalam Lucee, var di dalam fungsi meletakkan pemboleh ubah dalam skop local. Dalam cfscript moden, kata kunci var masih disyorkan untuk kejelasan, walaupun sebahagian pembangun lebih suka menulis local.baris secara eksplisit.
Banyak argumen atau satu struktur?
Kaedah dengan tujuh argumen sukar dipanggil dengan betul. Setiap pemanggil perlu mengingati susunan, dan setiap perubahan menambah risiko.
Dua bentuk yang lebih selamat:
// bentuk 1: struktur sebagai satu argumen
public struct function kira(required struct pesanan) {
var jumlah = arguments.pesanan.harga * arguments.pesanan.kuantiti;
return { ok: true, jumlah: jumlah };
}
// bentuk 2: komponen sebagai pembawa data
public struct function kira(required komponen.Pesanan pesanan) {
return { ok: true, jumlah: arguments.pesanan.jumlah() };
}
Bentuk pertama cepat dan sesuai untuk data daripada borang. Bentuk kedua lebih ketat kerana Pesanan boleh mengesahkan dirinya sendiri, tetapi ia menambah satu fail lagi.
Bagi kebanyakan aplikasi, bentuk pertama sudah cukup. Yang penting bukan bentuknya, tetapi konsistensi: jangan campur kaedah yang menerima lima argumen berasingan dengan kaedah yang menerima struktur untuk kerja yang sama.
argumentCollection untuk struktur
Apabila argumen sudah berada dalam struktur, contohnya data borang, gunakan argumentCollection.
args = { a: 10, b: 4 };
writeOutput(k.tambah(argumentCollection = args)); // 14
Kunci struktur mesti sepadan dengan nama argumen. Kunci tambahan akan diabaikan, dan itu boleh menyembunyikan salah taip: { a: 10, bb: 4 } akan gagal kerana b wajib, tetapi { a: 10, b: 4, c: 99 } berjalan tanpa amaran.
Pembahagian dengan sifar dan ralat lain
Kaedah bahagi() dengan penyebut sifar memulangkan ralat:
Division by zero is not possible
Dalam aplikasi sebenar, ini bukan sesuatu yang perlu ditangkap dengan try di mana-mana. Lebih baik semak penyebut dalam kaedah dan pulangkan keputusan yang jelas, atau biarkan ia gagal pada peringkat yang boleh dilaporkan.
Pengesahan input di satu tempat
Kerana argumen jenis tidak menolak nilai yang salah, pengesahan perlu ditulis. Letakkan di awal kaedah, dan pulangkan bentuk yang sama untuk semua kes.
public struct function tambahPesanan(required numeric harga, numeric kuantiti = 1) {
if (!isNumeric(arguments.harga) || arguments.harga <= 0) {
return { ok: false, ralat: "Harga mesti lebih besar daripada sifar" };
}
if (arguments.kuantiti < 1 || arguments.kuantiti > 99) {
return { ok: false, ralat: "Kuantiti antara 1 hingga 99" };
}
return { ok: true, jumlah: arguments.harga * arguments.kuantiti };
}
Pemanggil hanya perlu menyemak ok. Tiada pengecualian yang perlu ditangkap, dan tiada bentuk pulangan yang berbeza-beza.
Corak yang mengelakkan separuh pepijat
Tiga tabiat kecil yang menyelamatkan banyak masa:
- Tetapkan nilai lalai untuk semua argumen pilihan, dan jangan biarkan
nullmasuk ke dalam pengiraan - Kembalikan jenis yang tetap. Jangan pula kadang-kadang pulangkan struct, kadang-kadang pulangkan rentetan ralat
- Simpan pengesahan input di satu tempat, biasanya dalam kaedah yang sama yang menggunakan nilai itu
Contoh yang mematuhi ketiga-tiganya:
public struct function kira(required numeric harga, numeric kuantiti = 1) {
if (arguments.harga < 0 || arguments.kuantiti < 1) {
return { ok: false, ralat: "Nilai tidak sah" };
}
return { ok: true, jumlah: arguments.harga * arguments.kuantiti };
}
Pemanggil sentiasa menerima bentuk yang sama, jadi tiada kejutan.
Membaca mesej ralat enjin
Tiga mesej yang paling kerap muncul, dan maksudnya:
The parameter [b] to function [tambah] is required but was not passed in.— panggilan tidak menghantar argumen wajib. Semak nama argumen, bukan hanya bilanganCannot cast String [bukan nombor] to a value of type [numeric]— kaedah memulangkan jenis yang berbeza daripada yang diisytiharkan. Biasanya berlaku apabila satu cabangreturnmemulangkan teks ralat dan cabang lain memulangkan nomborDivision by zero is not possible— penyebut sifar. Semak sebelum membahagi, bukan selepas ralat muncul
Membaca mesej ini dengan teliti menjimatkan satu pusingan cubaan, kerana setiap satunya menunjuk terus kepada argumen atau baris yang salah.
Adakah required cukup untuk keselamatan?
Tidak. required hanya memastikan nilai hadir, bukan bahawa nilainya munasabah. Nilai daripada form masih perlu disemak julat, panjang dan jenis sebelum digunakan dalam pertanyaan atau sistem fail.
Bolehkah argumen bernilai null?
Boleh, dan ia punca ralat yang mengelirukan. Jika null dibenarkan masuk, semakan seperti arguments.harga <= 0 akan gagal dengan mesej yang tidak berkaitan. Tetapkan nilai lalai dan tolak null di awal kaedah.
Soalan lazim
Bolehkah satu kaedah menerima bilangan argumen berubah-ubah?
Boleh, dengan argumentCollection atau dengan menghantar array. CFML tidak menyokong overload, iaitu dua kaedah dengan nama sama tetapi argumen berbeza. Panggilan akan menggunakan definisi terakhir yang dimuatkan.
Perlukah setiap argumen diisytiharkan jenisnya?
Ya, untuk dokumentasi dan untuk membolehkan editor membantu. Tetapi jangan bergantung padanya sebagai pengesahan keselamatan; nilai daripada borang masih perlu disemak.
Apa beza param dalam fungsi dengan nilai lalai?
Nilai lalai ditetapkan pada definisi argumen dan lebih jelas dibaca. param berguna apabila nilai datang daripada skop luar fungsi, contohnya url atau form, bukan daripada argumen.
Mengapa kaedah saya memulangkan ralat "key doesn't exist"?
Biasanya kerana struktur yang dipulangkan tidak mempunyai kunci yang diminta pemanggil, atau kerana nama kunci berbeza huruf. CFML tidak sensitif huruf untuk nama kunci struktur, tetapi kod yang membina JSON secara manual selalunya sensitif.
Bahagian seterusnya membincangkan pemboleh ubah variables berbanding local dengan lebih mendalam, termasuk bagaimana keadaan objek bocor antara permintaan apabila komponen disimpan dalam application scope. Kalau anda belum baca bahagian pertama, mulakan dengan Komponen CFML: apa itu .cfc.