如果某个给定的类是内部类(例如DateTime
)或用户类(class MyClass
)?
如果你想知道(并且我确定你这样做),这是因为ReflectionClass::newInstanceWithoutConstructor()在内部类上使用时抛出异常,并且因为我正在为深度复制对象编写库,所以它必须跳过这些内部课程。
是的,我可以捕获ReflectionException
,但是由于其他原因(例如不存在的类)也抛出此异常,并且不会抛出所有系统类。所以它并不能完全满足我的需求。
答案 0 :(得分:14)
比使用shell_exec
更清洁的解决方案是使用反射:
$reflection = new ReflectionClass('SomeClass');
if($reflection->isUserDefined()) {
// 'SomeClass' is not an PHP internal
}
您也可以传递一个对象而不是字符串('SomeClass'
)。有关更多信息,请查找Reflection和
PHP手册中的ReflectionClass::isUserDefined()
答案 1 :(得分:3)
有趣的问题,我可以想到的一种方法是检查命名空间,例如,所有类都将在namespace MyApp
下定义,然后检查:
if(class_exists('\\DateTime')){
continue;
}
有点难看,我知道。
答案 2 :(得分:2)
基于ДамянСтанчев建议的思考:
您可以通过shell_exec()
运行一个PHP解释器,它将显示get_declared_classes()
。捕获它的输出,你应该有一个“干净”的系统类列表。
扩展Mogria的答案,这个应该可以正常工作(不要因为这个而归功于我,因为Mogria的答案是正确的; - )):
function getUserDefinedClasses() {
return array_filter(get_declared_classes(),
function ($class) {
$reflectionClass = new ReflectionClass($class);
return $reflectionClass->isUserDefined();
});
}
答案 3 :(得分:0)
您应该能够通过扩展您尝试复制的类并覆盖__construct
函数来模仿反射行为:
<?php
class MyClass extends ExtendingClass {
public function __construct() {
/* Override default constructor */
}
}
?>
使用eval
:
<?php
function newInstanceWithoutConstructor($class) {
$className = $class . "Extended" . rand(0, 99999999);
while (class_exists($className)) {
$className = $class . "Extended" . rand(0, 99999999);
}
eval("class " . $className . " extends " . $class . " { public function __construct() { } }");
return new $className();
}
$newInstance = newInstanceWithoutConstructor("DateTime");
?>
HOWEVER :在这种情况下使用eval
会很有用,但如果用户提交的任何内容都可以以任何方式提交以更改{的内容,则会显示相当大的安全漏洞{1}}。如果您了解这些限制和安全隐患,您应该能够使用它。
答案 4 :(得分:0)
您不能在脚本开头使用get_declared_classes()
,将数据存储在数组中,然后使用存储的数据和来自array_diff()
的响应执行get_declared_classes()
并检查如果你正在检查的课程使用in_array()
?
答案 5 :(得分:0)
这个example打印出你的类似乎位于列表末尾的所有类。也许这会有所帮助。
答案 6 :(得分:0)
如何在之前存储calling get_declared_classes()数据进行任何自动加载/包含/要求,然后检查此存储中的类名?