我正在尝试创建一个方法,允许我使用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中的值。
有什么想法吗?
答案 0 :(得分: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;
}
}
答案 1 :(得分:0)
如果查看异常的堆栈跟踪,您会注意到此行触发了设置__set
的调用:
$this->$name = $value;
然后在__set
中,$this->setVal($n, $v)
使用默认值false,从而抛出异常。要解决此问题,您可以将__set
中的来电修改为:
$this->setVal($n, $v, true);
答案 2 :(得分: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;
}
虽然我不确定你的代码是什么意思。
答案 3 :(得分:0)
在测试了这么多选项后......对我来说是最好的选择
我选择了这个因为
__set
和__get
可以通过扩展类代码:
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)
我希望这会有所帮助
谢谢
:)
答案 4 :(得分: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
。