Классы, инкапсуляция и пользовательский ввод [закрыт]


Как правильно отправлять пользовательский ввод в класс?

Класс 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 или передавать данные в уже преобразованные классы? Каков наилучший подход? Почему?

Author: Lightness Races in Orbit, 2011-09-20

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, если она используется при вычислении. Это означает, что ты вероятно, вы получите ошибку, даже не зная об этом, пока не проверите результаты.

 3
Author: chelmertz, 2011-09-20 16:01:42

bar является int. Таким образом, setBar должен получить int (первый вариант). Если вы хотите принудительно ввести его в int, я бы ожидал, что функция будет называться setBarFromString (или что-то в этом роде).

setBar может возникнуть исключение при получении не-int.

 1
Author: Nanne, 2011-09-20 14:02:59

Лучше сделать проверку на внутреннем уровне возможной, чтобы не было возможности хранить недопустимые значения внутри класса (или базы данных или...). Конечно, это не означает, что вы не могли бы также выполнить проверку на внешнем уровне, чтобы сэкономить некоторые циклы. Поэтому я бы выбрал второй пример.

 0
Author: Carlos Campderrós, 2011-09-20 14:01:28

Определите API вашего класса и работайте оттуда в обратном направлении.

В этом случае, принуждение класса хранить int, вероятно, имеет наибольший смысл, и вы можете гарантировать это только во втором примере.

 0
Author: Lightness Races in Orbit, 2011-09-20 14:02:14