1

setVal()関数を使用してクラス内でプロパティを設定できるメソッドを作成しようとしています。ユーザーが「forceSet」関数を使用せずにクラス外から値を設定しようとすると、例外。

問題は、$forceSetがtrueであっても例外をスローすることです。クラスでプロパティを手動でプライベートアクセスに設定すると、すべてが正常に機能しますが、このクラスでさまざまなプロパティを動的に設定できるようにしたいので、これはオプションではありません。

class test
{
    private $_allowedCols = array('title', 'name', 'surname');

    public function __set($n,$v)
    {
        $this->setVal($n, $v);
    }

    public function setVal($name, $value, $forceSet=false)
    {
        if (!$forceSet && !in_array($this->_allowedCols, $name))
        {
            throw new Exception('cant set value');
        }
        $this->$name = $value;
    }
}

$b = new test;
$b->setVal('blah', 'test', true);
print_r($b);
exit;

私ができるようにしたいのは、$_POSTのすべての値をオブジェクトのプロパティに設定することです。$ _allowedColsと照合して、必要な値のみがオブジェクトに入力されていることを確認したいのですが、$_allowedColsにないコードから値を強制的に入力したい場合があります。

何か案は?

4

5 に答える 5

1

ハックは機能しますが、内部配列を使用する方がクリーンな場合があります。何かのようなもの:

class test
{
    private $data = array();

    public function __set($n,$v)
    {
        if (isset($this->data[$n])) return $this->data[$n] = $v;

        throw new Exception('cant set value');
    }
    public function __get($n)
    {
        if (isset($this->data[$n])) return $this->data[$n];

        throw new Exception('cant retrieve value');
    }
    public function setVal($name, $value)
    {
        $this->data[$name] = $value;
    }
}

しかし、あなたがあなたのアプローチに固執したいなら、それから:

class test
{
    private $forceFlag = false;

    public function __set($name,$value)
    {
        if ($this->forceFlag) return $this->$name = $value;
        throw new Exception('cant set value');
    }
    public function setVal($name, $value)
    {
        $this->forceFlag = true;
        $this->$name = $value;
        $this->forceFlag = false;
    }
}
于 2012-04-04T19:11:37.593 に答える
0

PHPがすぐに提供する機能のために多くのコードを書いているようです。

$b = new test;
$b->blah = 'test';
print_r($b);

__setこれもsetVal(ue)関数も必要ありません。

ただし、アクセスを制御する場合は、アクセスをメンバーにバインドしていないことを確認する必要があります。代わりに、プライベートメンバーとしてマップ内に保存します。

class test
{
    private $values;
    public function __set($n,$v)
    {
        $this->setVal($n, $v);
    }

    public function setVal($name, $value, $forceSet=false)
    {
        if (!$forceSet)
        {
            throw new Exception('cant set value');
        }
        $this->values[$name] = $value;
    }
}

これにより、設定されたメンバーが確実に存在するため、__set再度トリガーされることはありません。

于 2012-04-04T19:08:41.977 に答える
0

非常に多くのオプションをテストした後..これは私にとって最適なものです

私がこれを選んだのは

  1. 例外を使用すると、スクリプト全体が終了するか、値が宣言されるたびに例外をキャッチする必要があります
  2. __setクラスを__get拡張することで簡単にオーバーライドできます
  3. 複数のクラスで使用できる実装
  4. 別のgetterメソッドを追加せずにオブジェクトを直接使用できるようにする方法
  5. ロックすると競合が発生する可能性があります
  6. スクリプトは既存のアプリケーション構造を変更しません
  7. シングルトンで使用できます..

コード:

abstract class Hashtable
{
    final $hashTable = array()  ;

    final function __set($n,$v)
    {
        return false ;
    }

    final function __get($n)
    {
        return @$this->hashTable[$n] ;
    }

    final function _set($n, $v)
    {
        $this->hashTable[$n] = $v ;

    }
}

class Test extends Hashtable {} ;

$b = new Test();
$b->_set("bar","foo",true);
$b->_set("hello","world",true);
//$b->setVal("very","bad"); // false
$b->bar = "fail" ;
var_dump($b,$b->bar);

出力

object(Test)[1]
  public 'hashTable' => 
    array
      'bar' => string 'foo' (length=3)
      'hello' => string 'world' (length=5)
string 'foo' (length=3)

これがお役に立てば幸いです

ありがとう

:)

于 2012-04-04T18:57:30.517 に答える
0

例外のスタックトレースを見ると、setの呼び出しが次の__set行によってトリガーされていることがわかります。

$this->$name = $value;

次に、__setでは$this->setVal($n, $v)、デフォルト値のfalseを使用して、例外をスローします。これを修正するには、呼び出しを次のように変更__setします。

$this->setVal($n, $v, true);
于 2012-04-04T18:53:58.210 に答える
0

上記のコードでは、次の行があります。

$this->$name = $value;

...呼び出し:

test::__set('blah', 'test');

...test::$blahが定義されていないため、次のように呼び出されます。

test::setVal('blah', 'test', false);

考えられるが完全ではない回避策は次のとおりです。

public function setVal($name, $value, $forceSet=false)
{
    if (!$forceSet && isset($value)) 
    {
        throw new Exception('cant set value');
    }
    $this->$name = null;
    $this->$name = $value;
}

あなたのコードのポイントが何であるかはわかりませんが。

于 2012-04-04T18:53:58.863 に答える