PHP反射——这是错误还是预期行为?
我正在创建一个使用ReflectionProperty的类,并且得到了奇怪的结果 本质上,调用PHP反射——这是错误还是预期行为?,php,reflection,Php,Reflection,我正在创建一个使用ReflectionProperty的类,并且得到了奇怪的结果 本质上,调用$reflectionProperty->getType()->getName()返回一些完全无关数组的值。它在看似随机的条件下做到这一点 见下文: //这将用作类型提示属性。 类DummyClass{ 公共函数构造($arr){ } //以反射方式设置其属性值的类 类基类{ /**@var ReflectionProperty[]*/ 私有静态$publicProps=[]; /** *获取具体类的公
$reflectionProperty->getType()->getName()
返回一些完全无关数组的值。它在看似随机的条件下做到这一点
见下文:
//这将用作类型提示属性。
类DummyClass{
公共函数构造($arr){
}
//以反射方式设置其属性值的类
类基类{
/**@var ReflectionProperty[]*/
私有静态$publicProps=[];
/**
*获取具体类的公共ReflectionProperties,并缓存它们
*因此,我们不需要为这个具体类再次执行反射。
*
*@return ReflectionProperty[]
*@ReflectionException
*/
私有函数getPublicProps(){
如果(!static::$publicProps){
$concreteClass=get_class($this);
静态::$publicProps=(新的ReflectionClass($concreteClass))
->getProperties(ReflectionProperty::是公共的);
}
返回静态::$publicProps;
}
/**
*对于此类中的每个公共属性,将值设置为$propArr中的相应值。
*
*@param$propArr
*@ReflectionException
*/
公共功能构造($propArr){
$concreteClass=get_class($this);
echo“创建$concreteClass的新实例
”;
foreach($this->getPublicProps()作为$prop){
//获取要设置的属性、其类和要传递给构造函数的值
$propName=$prop->getName();
$propClass=$prop->getType()->getName();
$propValue=$propArr[$propName];
$propValueStr=var_导出($propValue,true);
//打印出我们要做的事情,断言$propClass是正确的。
echo“--设置:->$propName=new$propClass($propValueStr)
”;
断言($propClass==“DummyClass”、“$propClass!==DummyClass”);
//创建实例并分配它
$refClass=新的ReflectionClass($propClass);
$this->$propName=$refClass->newInstanceArgs([$propValue]);
}
}
}
//上述类的一个具体实现,只有1个类型提示属性。
类ConcreteClass扩展了基类{
公共DummyClass$prop1;
}
//应该创建ConcreteClass的实例
//使用->prop1=新的DummyClass([“foo”=>“abc123”])
$testArr1=[
“prop1”=>[“foo”=>“abc123”]
];
//应该创建ConcreteClass的实例
//使用->prop1=新的DummyClass([“boo”=>“abc123def456”])
$testArr2=[
“prop1”=>[“boo”=>“abc123def456”]
];
$tc1=新混凝土等级($testArr1);
echo“创建了TestClass1…
”;
$tc2=新混凝土等级($testArr2);
echo“创建了TestClass2…
”;
死亡
结果是:
Creating new instance of ConcreteClass
Setting: ->prop1 = new DummyClass(array ( 'foo' => 'abc123', ))
Created TestClass1...
Creating new instance of ConcreteClass
Setting: ->prop1 = new abc123def456(array ( 'boo' => 'abc123def456', ))
Error: assert(): abc123def456 !== DummyClass failed
请注意,$propClass
的值是abc123def456
——这是如何发生的
更多的古怪
- 将“abc123def456”的值更改为“12345678”即可工作
- 将“abc123def456”的值更改为“123456789”将不起作用
- 省略var_export(),它将起作用。(不过,在其他情况下,它可能仍会断裂)
我的直觉告诉我这是一个PHP错误,但我可能做错了什么,和/或这可能会被记录在某个地方。我想澄清一下,因为目前我唯一可靠的解决方案是不缓存反映的$publicProps。这导致每次我创建一个新的
ConcreteClass
,都会不必要地调用ReflectionClass->getProperties()
,这是我想要避免的。结果发现这是PHP中的一个错误:
此处的最小复制:
在7.4.9中已修复:php7.4.9运行良好,因此错误已修复。查看变更日志-是的,看起来像个bug。我试着在Windows上玩我的本地7.4.0,得到了非常奇怪的结果,不仅是奇怪的结果,而且如果我多次执行,脚本也会崩溃。我甚至将您的代码缩减为,但如果您运行两次,它仍然会使该版本的PHP崩溃(现在还不确定这是否相关,lol)。@u_mulder谢谢。确实是这个bug,这里的复制量很小:。如果你提供一个答案,我会接受。你可以回答你自己的问题,我只是用小提琴运行了你的代码,并看到了行为改变的版本。)@u_mulder好的,可以。我不知道礼节是什么,我想你可能想在回答问题时得到分数。再次感谢。