Jawaban Pertama: Peran utama model adalah untuk menjaga integritas. Namun memproses input pengguna adalah tanggung jawab pengontrol.
Artinya, pengontrol harus menerjemahkan data pengguna (yang sebagian besar waktu hanya berupa string) menjadi sesuatu yang bermakna. Ini membutuhkan penguraian (dan mungkin bergantung pada hal-hal seperti lokal, mengingat bahwa misalnya, ada operator desimal yang berbeda, dll.).
Jadi validasi aktual, seperti pada "apakah data terbentuk dengan baik?", Harus dilakukan oleh pengontrol. Namun verifikasi, seperti pada "apakah data masuk akal?" harus dilakukan dalam model.
Untuk mengklarifikasi ini dengan contoh:
Asumsikan aplikasi Anda memungkinkan Anda untuk menambahkan beberapa entitas, dengan tanggal (masalah dengan tenggat waktu misalnya). Anda mungkin memiliki API, di mana tanggal mungkin direpresentasikan sebagai perangko waktu Unix belaka, sementara ketika berasal dari halaman HTML, itu akan menjadi satu set nilai yang berbeda atau string dalam format MM / DD / YYYY. Anda tidak ingin informasi ini ada dalam model. Anda ingin setiap pengontrol mencoba mencari tahu tanggalnya secara individual. Namun, ketika tanggal tersebut kemudian diteruskan ke model, model tersebut harus menjaga integritas. Sebagai contoh, mungkin masuk akal untuk tidak mengizinkan tanggal di masa lalu, atau tanggal, yang pada hari libur / minggu, dll.
Pengontrol Anda berisi aturan input (pemrosesan). Model Anda mengandung aturan bisnis. Anda ingin aturan bisnis Anda selalu ditegakkan, apa pun yang terjadi. Dengan asumsi Anda memiliki aturan bisnis di controller, maka Anda harus menduplikatnya, jika Anda pernah membuat controller yang berbeda.
Jawaban Kedua: Pendekatannya memang masuk akal, namun metode ini bisa dibuat lebih kuat. Alih-alih parameter terakhir menjadi array, itu harus berupa instance IContstraint
yang didefinisikan sebagai:
interface IConstraint {
function test($value);//returns bool
}
Dan untuk angka Anda dapat memiliki sesuatu sebagai
class NumConstraint {
var $grain;
var $min;
var $max;
function __construct($grain = 1, $min = NULL, $max = NULL) {
if ($min === NULL) $min = INT_MIN;
if ($max === NULL) $max = INT_MAX;
$this->min = $min;
$this->max = $max;
$this->grain = $grain;
}
function test($value) {
return ($value % $this->grain == 0 && $value >= $min && $value <= $max);
}
}
Juga saya tidak melihat apa 'Age'
yang dimaksudkan untuk mewakili, jujur. Apakah itu nama properti yang sebenarnya? Dengan asumsi ada konvensi secara default, parameter dapat dengan mudah pergi ke akhir fungsi dan menjadi opsional. Jika tidak disetel, itu akan default ke to_camel_case dari nama kolom DB.
Jadi contoh panggilan akan terlihat seperti:
register_property('age', new NumConstraint(1, 10, 30));
Inti dari menggunakan antarmuka adalah bahwa Anda dapat menambah lebih banyak kendala saat Anda pergi dan mereka dapat serumit yang Anda inginkan. Agar string cocok dengan ekspresi reguler. Untuk kencan setidaknya 7 hari ke depan. Dan seterusnya.
Jawaban Ketiga: Setiap entitas Model harus memiliki metode seperti Result checkValue(string property, mixed value)
. Pengontrol harus memanggilnya sebelum mengatur data. The Result
harus memiliki semua informasi tentang apakah cek gagal, dan dalam hal itu, memberikan alasan, sehingga controller dapat menyebarkan mereka ke tampilan yang sesuai.
Jika nilai yang salah diteruskan ke model, model harus merespons dengan meningkatkan pengecualian.
Saya tidak sepenuhnya setuju dengan "back2dos": Rekomendasi saya adalah untuk selalu menggunakan lapisan form / validasi terpisah, yang dapat digunakan oleh pengontrol untuk memvalidasi data input sebelum dikirim ke model.
Dari sudut pandang teoretis, validasi model beroperasi pada data tepercaya (kondisi sistem internal) dan idealnya harus dapat diulangi pada titik waktu mana pun sementara validasi input secara eksplisit beroperasi sekali pada data yang berasal dari sumber yang tidak terpercaya (tergantung pada kasus penggunaan dan hak pengguna).
Pemisahan ini memungkinkan untuk membuat model, pengontrol, dan bentuk yang dapat digunakan kembali yang dapat digabungkan secara longgar melalui injeksi ketergantungan. Anggap validasi input sebagai validasi daftar putih (“accept known good”) dan validasi model sebagai validasi daftar hitam (“reject bad known bad”). Validasi daftar putih lebih aman sementara validasi daftar hitam mencegah lapisan model Anda dari terlalu dibatasi untuk kasus penggunaan yang sangat spesifik.
Data model yang tidak valid harus selalu menyebabkan pengecualian untuk dibuang (jika tidak aplikasi dapat terus berjalan tanpa memperhatikan kesalahan) sementara nilai input yang tidak valid yang berasal dari sumber eksternal tidak terduga, tetapi lebih umum (kecuali Anda memiliki pengguna yang tidak pernah melakukan kesalahan).
Lihat juga: https://lastzero.net/2015/11/why-im-using-a-separate-layer-for-input-data-validation/
sumber
Ya, model harus melakukan validasi. UI juga harus memvalidasi input.
Jelas merupakan tanggung jawab model untuk menentukan nilai dan status yang valid. Terkadang aturan seperti itu sering berubah. Dalam hal ini saya akan memberi makan model dari metadata dan / atau menghiasnya.
sumber
Pertanyaan bagus!
Dalam hal pengembangan web di seluruh dunia, bagaimana jika Anda menanyakan yang berikut, juga.
"Jika input pengguna yang buruk diberikan ke pengontrol dari antarmuka pengguna, haruskah pengontrol memperbarui Lihat dalam semacam siklus berulang, memaksa perintah dan memasukkan data menjadi akurat sebelum memprosesnya ? Bagaimana? Bagaimana tampilan diperbarui di bawah normal kondisi? Apakah pandangan erat dengan model? Apakah input pengguna logika bisnis inti dari model, atau apakah itu pendahuluan untuk itu dan dengan demikian harus terjadi di dalam controller (karena data input pengguna adalah bagian dari permintaan)?
(Dampaknya, dapat, dan haruskah, satu penundaan instantiating model sampai input yang baik diperoleh?)
Pendapat saya adalah bahwa model harus mengelola keadaan murni dan murni (sebanyak mungkin), tidak terbebani oleh validasi input permintaan HTTP dasar yang harus terjadi sebelum model instantiation (dan pasti sebelum model mendapatkan data input). Karena mengelola data status (persisten, atau lainnya) dan hubungan API adalah dunia model, biarkan validasi input permintaan HTTP dasar terjadi di controller.
Meringkas.
1) Validasikan rute Anda (diurai dari URL), karena pengontrol dan metode harus ada sebelum hal lain dapat dilanjutkan. Ini pasti harus terjadi di ranah front-controller (kelas Router), sebelum sampai ke controller yang sebenarnya. Duh. :-)
2) Suatu model mungkin memiliki banyak sumber data input: permintaan HTTP, database, file, API, dan ya, jaringan. Jika Anda akan menempatkan semua validasi input Anda ke dalam model, maka Anda mempertimbangkan bagian validasi input permintaan HTTP dari persyaratan bisnis untuk program ini. Kasus ditutup.
3) Namun, itu adalah rabun untuk melalui pengeluaran instantiating banyak objek jika input permintaan HTTP tidak baik! Anda dapat mengetahui apakah ** HTTP request input ** baik ( yang disertakan dengan permintaan ) dengan memvalidasinya sebelum membuat model dan semua kerumitannya (ya, bahkan mungkin lebih validator untuk data input / output API dan DB).
Tes berikut ini:
a) Metode permintaan HTTP (GET, POST, PUT, PATCH, DELETE ...)
b) Kontrol HTML minimum (apakah Anda punya cukup?).
c) Kontrol HTML maksimum (apakah Anda memiliki terlalu banyak?).
d) Kontrol HTML yang benar (apakah Anda memiliki yang benar?).
e) Pengodean input (biasanya, apakah pengodean UTF-8?).
f) Ukuran input maksimum (adakah salah satu input di luar batas?).
Ingat, Anda mungkin mendapatkan string dan file, jadi menunggu model untuk instantiate bisa menjadi sangat mahal karena permintaan menekan server Anda.
Apa yang saya jelaskan di sini mengenai maksud dari permintaan yang masuk melalui controller. Mengabaikan verifikasi niat membuat aplikasi Anda lebih rentan. Niat hanya bisa baik (bermain dengan aturan fundamental Anda) atau buruk (melampaui aturan fundamental Anda).
Maksud untuk permintaan HTTP adalah proposisi semua atau tidak sama sekali. Semuanya lewat, atau permintaan tidak valid . Tidak perlu mengirim apa pun ke model.
Tingkat dasar ini HTTP meminta niat memiliki apa-apa hubungannya dengan kesalahan input user biasa dan validasi. Dalam aplikasi saya, permintaan HTTP harus valid dalam lima cara di atas agar saya menghormatinya. Dalam pertahanan-mendalam cara berbicara, Anda tidak pernah bisa validasi input pengguna pada server-side jika setiap lima hal ini gagal.
Ya, ini berarti bahkan input file harus sesuai dengan upaya front-end Anda untuk memverifikasi dan memberi tahu pengguna ukuran file maksimal yang diterima. Hanya HTML? Tidak Ada JavaScript? Baik, tetapi pengguna harus diberitahu tentang konsekuensi dari mengunggah file yang terlalu besar (terutama, bahwa mereka akan kehilangan semua data formulir dan dikeluarkan dari sistem).
4) Apakah ini berarti bahwa data input permintaan HTTP bukan bagian dari logika bisnis aplikasi? Tidak, itu hanya berarti komputer adalah perangkat yang terbatas dan sumber daya harus digunakan dengan bijak. Masuk akal untuk menghentikan aktivitas jahat lebih cepat, bukan nanti. Anda membayar lebih banyak dalam sumber daya komputasi untuk menunggu untuk menghentikannya nanti.
5) Jika input permintaan HTTP buruk, seluruh permintaan buruk . Begitulah cara saya melihatnya. Definisi input permintaan HTTP yang baik berasal dari persyaratan bisnis model, tetapi harus ada beberapa titik demarkasi sumber daya. Berapa lama Anda akan membiarkan permintaan buruk hidup sebelum membunuhnya dan berkata, "Oh, hei, sudahlah. Permintaan buruk."
Penghakiman tidak hanya karena pengguna telah membuat kesalahan input yang masuk akal, tetapi bahwa permintaan HTTP sangat di luar batas sehingga harus dinyatakan berbahaya dan segera dihentikan.
6) Jadi, untuk uang saya, permintaan HTTP (METHOD, URL / rute, dan data) adalah SEMUA baik, atau TIDAK ADA yang bisa dilanjutkan. Model yang kuat sudah memiliki tugas validasi untuk dikhawatirkan, tetapi seorang penggembala sumber daya yang baik mengatakan, "Cara saya, atau cara tinggi. Ayo benar, atau jangan datang sama sekali."
Ini adalah program Anda. "Ada lebih dari satu cara untuk melakukannya." Beberapa cara lebih mahal dalam waktu dan uang daripada yang lain. Memvalidasi data permintaan HTTP nanti (dalam model) harus lebih mahal sepanjang masa aplikasi (terutama jika meningkatkan atau keluar).
Jika validator Anda modular, memvalidasi input HTTP * dasar ** di controller seharusnya tidak menjadi masalah. Cukup gunakan kelas Validator yang strategis, di mana validator terkadang juga terdiri dari validator khusus (email, telepon, token formulir, captcha, ...).
Beberapa orang melihat ini sebagai langkah yang salah, tetapi HTTP masih dalam masa pertumbuhan ketika Gang of Four menulis Pola Desain: Elemen Perangkat Lunak Berorientasi Objek yang Dapat Digunakan Kembali .
================================================== ========================
Sekarang, karena ini berkaitan dengan validasi input pengguna normal (setelah permintaan HTTP dianggap valid), itu memperbarui tampilan ketika pengguna mengacaukan yang perlu Anda pikirkan! Jenis validasi input pengguna ini harus terjadi dalam model.
Anda tidak memiliki jaminan JavaScript di front-end. Ini berarti Anda tidak memiliki cara untuk menjamin pembaruan asinkron UI Anda dengan status kesalahan. Peningkatan progresif sejati juga akan mencakup kasus penggunaan sinkron.
Akuntansi untuk use case sinkron adalah seni yang semakin hilang karena beberapa orang tidak ingin melalui waktu, dan kerumitan, melacak keadaan semua trik UI mereka (tampilkan / sembunyikan kontrol, nonaktifkan / aktifkan kontrol , indikasi kesalahan, pesan kesalahan) di back-end (biasanya dengan melacak status dalam array).
Pembaruan : Dalam diagram, saya mengatakan bahwa
View
seharusnya referensiModel
. Tidak. Anda harus meneruskan data keView
dariModel
untuk mempertahankan sambungan yang longgar.sumber