我正在尝试为我正在处理的项目动态创建数据库实体泛化的基础。我基本上想要为任何扩展它的类中的属性动态创建一组标准方法和工具。就像使用Python / Django免费获得的工具一样。
我从这个家伙那里得到了这个想法:http://www.stubbles.org/archives/65-Extending-objects-with-new-methods-at-runtime.html
所以我已经实现了__call函数,如上面的帖子所述,
public function __call($method, $args) {
echo "<br>Calling ".$method;
if (isset($this->$method) === true) {
$func = $this->$method;
$func();
}
}
我有一个函数,它通过get_object_vars,
为我提供了对象public / protected属性public function getJsonData() {
$var = get_object_vars($this);
foreach($var as &$value) {
if (is_object($value) && method_exists($value, 'getJsonData')) {
$value = $value->getJsonData;
}
}
return $var;
}
现在我想为它们创建一些方法:
public function __construct() {
foreach($this->getJsonData() as $name => $value) {
// Create standard getter
$methodName = "get".$name;
$me = $this;
$this->$methodName = function() use ($me, $methodName, $name) {
echo "<br>".$methodName." is called";
return $me->$name;
};
}
}
感谢Louis H.在下面指出了“use”关键字。 这基本上可以动态创建一个匿名函数。该函数是可调用的,但它不再位于其对象的上下文中。它产生“致命错误:无法访问受保护的属性”
不幸的是,我已经绑定了PHP版本5.3,它排除了Closure :: bind。因此Lazy loading class methods in PHP中建议的解决方案不起作用。
我在这里很难过......还有其他建议吗?
更新
为简洁而编辑。
答案 0 :(得分:2)
尝试这样(你必须使你需要的变量可用于该方法)
$this->$methodName = function() use ($this, $methodName, $name){
echo "<br>".$methodName." is called";
return $this->$$name;
};
您应该可以通过$this
访问对象上下文。
答案 1 :(得分:0)
我没有更新上面的原始问题,而是在这里为完全解决相同问题的人提供完整的解决方案:
首先,由于闭包不能有真正的对象访问,我需要在创建闭包函数时用“use”声明包含实际值(参见上面的原始__construct函数):
$value =& $this->$name;
$this->$methodName = function() use ($me, $methodName, &$value) {
return $value;
};
其次,__ call魔术方法不仅需要调用闭包函数,还需要从中返回任何输出。所以我不是只调用$ func(),而是返回$ func();
这就是诀窍! : - )