クラスプロパティの許容値または範囲を実施するための最小のずさんな方法
質問
仮説的に私はクラスを持っていると言います...
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-Then-Again-Again」ブロックでかなり厄介になり始めています。検証コードとこのルール配列により、私のスクリプトはかなりかさばっています。
問題は、クラスまたはクラスのプロパティ、検証コード、またはスクリプトのその他の側面を、プロパティの範囲と価値施行を可能にするために、できるだけ短く簡潔にする方法です。これをよりエレガントに処理する言語機能やトリックはありますか?この言語の限界であるレンガの壁に到達しましたか?他の言語から、これを簡単に実装できる例はありますか?
解決
先日、同様の問題に遭遇しました。これが私がすることです:
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:ルールを使用してグローバル変数を持つ代わりに、 シングルトン:
他のヒント
ゲッターとセッター
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
}