Membaca pertanyaan SO ini sepertinya melemparkan pengecualian untuk memvalidasi input pengguna tidak disukai.
Tetapi siapa yang harus memvalidasi data ini? Dalam aplikasi saya, semua validasi dilakukan di lapisan bisnis, karena hanya kelas itu sendiri yang benar-benar tahu nilai mana yang valid untuk masing-masing propertinya. Jika saya menyalin aturan untuk memvalidasi properti ke controller, ada kemungkinan bahwa aturan validasi berubah dan sekarang ada dua tempat di mana modifikasi harus dilakukan.
Apakah premis saya bahwa validasi harus dilakukan pada lapisan bisnis salah?
Apa yang saya lakukan
Jadi kode saya biasanya berakhir seperti ini:
<?php
class Person
{
private $name;
private $age;
public function setName($n) {
$n = trim($n);
if (mb_strlen($n) == 0) {
throw new ValidationException("Name cannot be empty");
}
$this->name = $n;
}
public function setAge($a) {
if (!is_int($a)) {
if (!ctype_digit(trim($a))) {
throw new ValidationException("Age $a is not valid");
}
$a = (int)$a;
}
if ($a < 0 || $a > 150) {
throw new ValidationException("Age $a is out of bounds");
}
$this->age = $a;
}
// other getters, setters and methods
}
Dalam controller, saya hanya meneruskan data input ke model, dan menangkap pengecualian yang dilemparkan untuk menunjukkan kesalahan (s) kepada pengguna:
<?php
$person = new Person();
$errors = array();
// global try for all exceptions other than ValidationException
try {
// validation and process (if everything ok)
try {
$person->setAge($_POST['age']);
} catch (ValidationException $e) {
$errors['age'] = $e->getMessage();
}
try {
$person->setName($_POST['name']);
} catch (ValidationException $e) {
$errors['name'] = $e->getMessage();
}
...
} catch (Exception $e) {
// log the error, send 500 internal server error to the client
// and finish the request
}
if (count($errors) == 0) {
// process
} else {
showErrorsToUser($errors);
}
Apakah ini metodologi yang buruk?
Metode alternatif
Haruskah saya membuat metode untuk isValidAge($a)
mengembalikan true / false dan kemudian memanggil mereka dari controller?
<?php
class Person
{
private $name;
private $age;
public function setName($n) {
$n = trim($n);
if ($this->isValidName($n)) {
$this->name = $n;
} else {
throw new Exception("Invalid name");
}
}
public function setAge($a) {
if ($this->isValidAge($a)) {
$this->age = $a;
} else {
throw new Exception("Invalid age");
}
}
public function isValidName($n) {
$n = trim($n);
if (mb_strlen($n) == 0) {
return false;
}
return true;
}
public function isValidAge($a) {
if (!is_int($a)) {
if (!ctype_digit(trim($a))) {
return false;
}
$a = (int)$a;
}
if ($a < 0 || $a > 150) {
return false;
}
return true;
}
// other getters, setters and methods
}
Dan pengontrol pada dasarnya akan sama, alih-alih coba / tangkap sekarang ada / jika:
<?php
$person = new Person();
$errors = array();
if ($person->isValidAge($age)) {
$person->setAge($age);
} catch (Exception $e) {
$errors['age'] = "Invalid age";
}
if ($person->isValidName($name)) {
$person->setName($name);
} catch (Exception $e) {
$errors['name'] = "Invalid name";
}
...
if (count($errors) == 0) {
// process
} else {
showErrorsToUser($errors);
}
Jadi apa yang harus aku lakukan?
Saya cukup senang dengan metode asli saya, dan rekan-rekan saya yang saya tunjukkan secara umum menyukainya. Meskipun demikian, haruskah saya mengubah metode alternatif? Atau apakah saya melakukan ini sangat salah dan saya harus mencari cara lain?
IValidateResults
.
ValidationException
dan pengecualian lainnya