Классы, инкапсуляция и пользовательский ввод [закрыт]
Как правильно отправлять пользовательский ввод в класс?
Класс Foo:
<?php
class Foo
{
private $_bar;
private setBar($bar)
{
$this->_bar = $bar;
}
}
?>
Используя класс foo...
<?php
$foo = new Foo();
$foo->setBar((int) $_POST['input']);
?>
Или мне следует сделать следующее?
Класс Foo:
<?php
class Foo
{
private $_bar;
private setBar($bar)
{
$this->_bar = (int) $bar;
}
}
?>
Используя класс foo...
<?php
$foo = new Foo();
$foo->setBar($_POST['input']);
?>
Должен ли я конвертировать данные внутри метода get или передавать данные в уже преобразованные классы? Каков наилучший подход? Почему?
4 answers
Еще лучше было бы проверить с помощью исключения. Если вы добавите другой метод, например:
public function calculateSalary() {
// uses bar, wants int
return 100 * $this->_bar;
}
И кто-то использует класс следующим образом:
$foo = new Foo();
$foo->setBar('My Name Here');
echo $foo->calculateSalary(); // will give a result since php is forgiving
Чтобы избежать подобных неудач, я пишу сеттеры, подобные этому:
public function setFoo($number) {
if(!is_numeric($number)) {
throw new Exception(__METHOD__." wants a number!");
}
$this->_foo = $number;
}
Аргументы против #1: пользователь может не включать (int)
, и поэтому в объекте заданы данные с неправильным типом.
Аргументы против #2: (см. Пример выше). PHP переводит строку в 0
, если она используется при вычислении. Это означает, что ты вероятно, вы получите ошибку, даже не зная об этом, пока не проверите результаты.
bar
является int. Таким образом, setBar
должен получить int (первый вариант). Если вы хотите принудительно ввести его в int, я бы ожидал, что функция будет называться setBarFromString
(или что-то в этом роде).
setBar
может возникнуть исключение при получении не-int.
Лучше сделать проверку на внутреннем уровне возможной, чтобы не было возможности хранить недопустимые значения внутри класса (или базы данных или...). Конечно, это не означает, что вы не могли бы также выполнить проверку на внешнем уровне, чтобы сэкономить некоторые циклы. Поэтому я бы выбрал второй пример.
Определите API вашего класса и работайте оттуда в обратном направлении.
В этом случае, принуждение класса хранить int
, вероятно, имеет наибольший смысл, и вы можете гарантировать это только во втором примере.