代码之家  ›  专栏  ›  技术社区  ›  bob-the-destroyer

用于强制类属性的允许值或范围的最小草率方法

  •  1
  • bob-the-destroyer  · 技术社区  · 14 年前

    假设我有课…

    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 回复  |  直到 14 年前
        1
  •  0
  •   quantumSoup    14 年前

    前几天我也遇到过类似的问题。我要做的是:

       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 :

        2
  •  1
  •   nathan    14 年前

    吸气剂和二传手

    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
    }