Php 调用运行时创建的函数
我正在尝试为我正在处理的项目动态创建DB实体泛化的基础。我基本上希望为扩展该类的任何类中的属性动态创建一组标准方法和工具。与Python/Django免费提供的工具非常相似 我从这个家伙那里得到了这个主意: 我已经实现了上面帖子中描述的调用函数Php 调用运行时创建的函数,php,Php,我正在尝试为我正在处理的项目动态创建DB实体泛化的基础。我基本上希望为扩展该类的任何类中的属性动态创建一组标准方法和工具。与Python/Django免费提供的工具非常相似 我从这个家伙那里得到了这个主意: 我已经实现了上面帖子中描述的调用函数 public function __call($method, $args) { echo "<br>Calling ".$method; if (isset($this->$method) === true) {
public function __call($method, $args) {
echo "<br>Calling ".$method;
if (isset($this->$method) === true) {
$func = $this->$method;
$func();
}
}
现在我想为他们创建一些方法:
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;
};
}
}
public function\uuuu construct(){
foreach($this->getJsonData()作为$name=>$value){
//创建标准getter
$methodName=“get”。$name;
$me=$this;
$this->$methodName=function()使用($me,$methodName,$name){
echo“
”$methodName.”被调用;
返回$me->$name;
};
}
}
感谢Louis H.指出了下面的“使用”关键字。
这基本上是动态创建一个匿名函数。该函数是可调用的,但它不再位于其对象的上下文中。它产生“致命错误:无法访问受保护的属性”
不幸的是,我被绑定到PHP版本5.3,它排除了Closure::bind。因此,中建议的解决方案在这里不起作用
我在这里有点不知所措。。。还有其他建议吗
更新
为简洁起见进行了编辑。像这样尝试(您必须使所需的变量可用于该方法)
$this->$methodName=function()使用($this,$methodName,$name){
echo“
”$methodName.”被调用;
返回$this->$$name;
};
您应该可以通过
$this
访问对象上下文,而不是更新上面的原始问题,我在这里为所有遇到相同问题的人提供了完整的解决方案:
首先,由于闭包不能具有真正的对象访问权限,因此在创建闭包函数时,我需要在“use”声明中包含实际值(请参见上面的原始构造函数):
其次uu call magic方法不仅需要调用闭包函数,还需要返回它的任何输出。因此,我不只是调用$func(),而是返回$func()
这就成功了!:-) 你到底为什么要这么做?只要使用公共属性。尝试使用traits实现此行为,那么$this将可用。@Gordon:将属性公开将允许其他人直接更改它们,这不是我要寻找的行为。我想要只读访问。我可能错过了这里的大局。有没有可能有人真的会改变他们?毕竟,这些似乎是运行时创建的类。另外,您说您不在对象范围内,并且存在公共/受保护的属性。不,这些类不是运行时创建的。它们是我正在创建的小型通用orm的一部分。我试图复制python/django模型的易用性、可读性和可维护性。我想实现的是在模型属性上运行一组标准函数。这产生了:致命错误:无法使用$this作为词法变量…:-(但将$this分配给$me,然后将$me包含在use语句中,确实有效。但它显然仍然不在对象上下文中。我得到一个“致命错误:无法访问受保护的属性”…尽管这个解决方案对我来说不太有效,但你肯定为我指明了正确的方向。因此,我会将此标记为正确答案。我已使用该解决方案更新了原始问题。
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;
};
}
}
$this->$methodName = function() use ($this, $methodName, $name){
echo "<br>".$methodName." is called";
return $this->$$name;
};
$value =& $this->$name;
$this->$methodName = function() use ($me, $methodName, &$value) {
return $value;
};