Проверка параметров конструктора, проверка правильности типа параметров - PullRequest
6 голосов
/ 05 января 2011

При написании моего первого PHP-класса и при обнаружении проблемы мой метод __construct следующий:

public function __construct($foo,$bar) {
       $this->foo = $foo;
       $this->bar = $bar;
}

Требуются и $foo, и $bar, без них методы не будутРабота.Это нормально, когда они не определены, когда объект создается, например, так:

$var = new Class();

Поскольку это вызывает исключение (например, класс требует 2 параметра, ни один не установлен).Но если они установлены, но не имеют правильный тип, например, так:

$var = new Class('33','ddd');

Мои методы не будут работать, поскольку переменные имеют неправильный тип.

Где я должен проверять эти?В конструкторе или в каждом методе?

Мое решение, которое я сейчас использую, работает, но я не уверен, что это правильный путь:

// $foo needs to be a string with letters only
// $bar needs to be an integer
public function __construct($foo,$bar) {
       $this->foo = $foo;
       $this->bar = $bar;
       if(!is_numeric($bar)){
           // Throw exception
       }
       elseif(other validation case)
       etc...
}

Концепции ОО-программирования довольно новы для меня, поэтому ссылки на любой имеющийся у вас справочный материал были бы очень благодарны.

Ответы [ 8 ]

18 голосов
/ 05 января 2011

Я бы, вероятно, сделал что-то подобное, чтобы предотвратить беспорядок внутри ctor и позволить классу установить для них значения внутри себя:

class MyClass …

    protected $_foo;

    /**
     * @param  String   $foo    String with letters only
     * @param  Integer  $bar    Any Integer
     * @return void
     * @throws InvalidArgumentException when $foo is not letters only
     * @throws InvalidArgumentException when $bar is not an Integer
     */
    public function __construct($foo, $bar) 
    {
        $this->_setFoo($foo);
        $this->_setBar($bar)
    }

    /**
     * @param  String   $foo    String with letters only
     * @return void
     * @throws InvalidArgumentException when String is not letters only
     */
    protected function _setFoo($foo)
    {
        if (FALSE === $this->_consistsOfLettersOnly($foo)) {
            throw new InvalidArgumentException(
                '$foo should consists of letters only'
            );
        }
        $this->_foo = $foo;
    }  

    …

Это имеет дополнительное преимущество: если вам нужно публично выставитьпозже, вам просто нужно изменить ключевое слово видимости.

Делать проверку в свой собственный метод не обязательно, но я думаю, что это делает код более читабельным.Если вы обнаружите, что другое свойство в этом классе нуждается в такой же проверке, вы также можете использовать его более легко.

2 голосов
/ 05 января 2011

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

public function __construct($foo=null, $bar=null)

Тем не менее, вы можете использовать type hinting для аргументов в PHP, но яПоверьте, это работает только для массивов и классов.(Не удивительно, поскольку в PHP нет такого понятия, как целочисленный или строковый тип.)

Как уже говорили другие, вы также должны убедиться, что вы выполняете проверку в любых ваших установщиках или (еще лучше)просто вызовите сеттеры из конструктора, чтобы убедиться в отсутствии дублирования кода.

0 голосов
/ 01 мая 2019
declare('strict_types=1');

public function __construct(
    int $foo, 
    string $bar, 
    Request $request // type hint even classes
) {
       $this->foo = $foo;
       $this->bar = $bar;
}
0 голосов
/ 05 марта 2015

Вы не должны делать ничего, кроме установки значений в конструкторе. Если вам нужно проверить параметры конструктора в установщиках (возможно, частных) или использовать аргументы определенного типа, то PHP проверит для вас тип, например:

__construct(SomeType $foo, AnotherType $bar);

Например, вы можете использовать типы данных SPL:

__construct(SplInt $integer, SplString $string);

Подробнее о типах данных SPL

0 голосов
/ 05 января 2011

Немного проработав ответ @ xil3, я бы сказал, что все, что Дан искал / нуждался в следующем:

private $_foo;
private $_bar;

public function __construct($foo,$bar) {
  if(is_int($foo)) {
    $this->setFoo($foo);
  }
  if(is_string($bar)) {
    $this->setBar($bar);
  }
}

public function setFoo(int $foo) {
  $this->_foo = $foo;
}

public function setBar(string $bar) {
  $this->_foo = $bar;
}

...

Разрешение создания экземпляра его объекта без параметров без фатального, с ограничениями типов на установщиках.

0 голосов
/ 05 января 2011

Ваши проблемы не связаны с тем, что вы пишете объектно-ориентированный код - это потому, что PHP является свободно типизированным языком .Это означает, что переменные могут содержать любые данные, от int до Object.Вы можете применить какое-либо приведение типа следующим образом:

$foo = (int)$foo;
$bar = (str)$bar;
0 голосов
/ 05 января 2011

Лучший способ - использовать геттеры и сеттеры, например:

private $_foo;
private $_bar;

public function __construct($foo,$bar) {
  $this->setFoo($foo);
  $this->setBar($bar);
}

public function setFoo($foo) {
  // validate here

  $this->_foo = $foo;
}

public function getFoo() {
  return $this->_foo;
}

...

Так чище ...

0 голосов
/ 05 января 2011

Если требуются $ foo и $ bar, лучше всего проверить их в __construct (если нет: используйте установщик и проверьте там). Если вы делаете это в каждом методе, вы просто получите дублированный код. Представьте, что если тип данных изменится, вам придется изменить каждый метод ...

Если вы хотите быть очень разборчивым, вы можете позвонить is_numeric, прежде чем присваивать $ bar $ this-> bar, так как присваивание не требуется, если проверка числового значения не удалась.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...