如何判断一个类是内部类还是用户类?

时间:2013-06-06 11:35:01

标签: php

如果某个给定的类是内部类(例如DateTime)或用户类(class MyClass)?

如果你想知道(并且我确定你这样做),这是因为ReflectionClass::newInstanceWithoutConstructor()在内部类上使用时抛出异常,并且因为我正在为深度复制对象编写库,所以它必须跳过这些内部课程。

是的,我可以捕获ReflectionException,但是由于其他原因(例如不存在的类)也抛出此异常,并且不会抛出所有系统类。所以它并不能完全满足我的需求。

7 个答案:

答案 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()数据进行任何自动加载/包含/要求,然后检查此存储中的类名?