Наименее небрежный способ применения допустимых значений или диапазонов для свойств класса - PullRequest
1 голос
/ 02 июля 2010

Скажи гипотетически, у меня есть класс ...

class Main {

    $prop1 = 2;
    $prop2 = 23;
    ...
    $prop42 = "what";

    function __construct($arg_array) {
        foreach ($arg_array as $key => $val) {
            $this->$key = $val;
            }
        }
    }

Скажи, что я создаю и возражаю ...


$attributes = array("prop1"=>1, "prop2"=>35235, "prop3"=>"test");
$o = new Main($attributes);

Предоставление значений свойств по умолчанию, если они не предоставлены пользователем,очевидно.Но что если я захочу применить произвольные ограничения на значения, предоставленные пользователем для свойств объекта?Что, если я хочу, чтобы $prop1 было int, было бы не меньше 1 и не больше 5. И, $prop42 было бы типа string, не меньше, чем 'A', ине больше, чем «Z»?С этой целью, что было бы самым чистым способом, поддерживая сценарий как можно более коротким и приятным, используя любую возможную языковую функцию или трюк?

Я застрял в __construct() проверке предоставленных значений по массиву правилпостроено так ...

$allowable = array(
    "prop1" => array(
        'type' => 'int',
        'allowable_values' => array(
            'min' => 1,
            'max' => 5
            )
        ),
    "prop2" => array(
        'type' => 'int',
        'allowable_values' => array(
            1,
            235,
            37,
            392,
            13,
            409,
            3216
            )
        ),
    ...
    "prop42" => array(
        'type' => 'string',
        'allowable_values' => array(
            'min' => 'A',
            'max' => 'Z'
            )
        )
    );

Как вы можете видеть по prop2, моя функция проверки начинает становиться довольно запутанной со стольким количеством блоков if-then-iterate-again, сколько мне придетсяучитывать не только диапазоны, но и список допустимых значений.С кодом проверки и этим массивом правил мой сценарий становится довольно громоздким.

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

Ответы [ 2 ]

1 голос
/ 02 июля 2010

геттеры и сеттеры

class Main {
  private $prop1;
  private $prop2;
  private $prop3;

  public function __construct( $p1 , $p2 , $p3 )
  {
    $this->setProp1($p1);
    $this->setProp2($p2);
    $this->setProp3($p3);
  }

  public function setProp1($p1)
  {
    // conditional checking for prop1
    if(!$ok) throw new Exception('problem with prop1');
    $this->prop1 = $p1;
  }

  //.. and so on
}
0 голосов
/ 02 июля 2010

Я столкнулся с подобной проблемой на днях. Вот что я бы сделал:

   private $props;
   private $rules; 

   function __construct($params) {

      // or you can get the rules from another file, 
      // or a singleton as I suggested

      $this->rules = array (array('type' => 'range', 'min' => 10, 'max' => 20), 
        array('type' => 'in_set', 'allowed' => array(1,2,3)));

      for ($i=0; $i<count($params); $i++) {

         if ($this->check($params[$i], $this->rules($i))
            $this->props[$i] = $params[$i];
         else
            throw new Exception('Error adding prop ' . $i);
      }

   }


   function check($value, $rule) {
      switch($rule['type']) {
         case 'range':
            return ($rule['min'] <= $value && $value <= $rule['max']);  

         case 'in_set':
            return (in_array($value, $rule['allowed']));

         // and so on
      }
   }

Если у вас много параметров, вы можете использовать массив и проходить через него. Если ваши правила проверки всегда будут одинаковыми, вы можете поместить их в отдельный файл и загрузить их в свой конструктор или что-то еще.

РЕДАКТИРОВАТЬ: Кстати, на самом деле нет смысла тестировать тип в PHP. Это не очень надежно и не нужно.

РЕДАКТИРОВАТЬ 2: вместо глобальной переменной с правилами, вы можете использовать Singleton :

...