Подтвердить что ты не робот

Как определить, является ли класс внутренним классом или классом пользователя?

Есть ли способ в PHP рассказать (программно, очевидно), если данный класс является внутренним классом (например, DateTime) или классом пользователя ( class MyClass)?

Если вы задаетесь вопросом (и я уверен, что вы это делаете), это потому, что ReflectionClass:: newInstanceWithoutConstructor() выдает исключение при использовании на внутренних классах и поскольку я пишу библиотеку для глубоких копий объектов, она должна пропустить эти внутренние классы.

Да, я мог бы просто поймать ReflectionException, но это исключение вызывается и по другим причинам (например, несуществующий класс) и не выбрано для всех системных классов. так что это точно не соответствует моим потребностям.

4b9b3361

Ответ 1

Более чистый раствор, чем использование shell_exec, который должен использовать отражение:

$reflection = new ReflectionClass('SomeClass'); 
if($reflection->isUserDefined()) {
   // 'SomeClass' is not an PHP internal
}

Вместо строки ('SomeClass') вы также можете передать объект. Для получения дополнительной информации Reflection и ReflectionClass::isUserDefined() в руководстве по PHP

Ответ 2

Интересный вопрос, один из способов, которым я могу думать, - проверить пространство имен, например, все ваши классы будут определены в namespace MyApp, а затем проверьте:

if(class_exists('\\DateTime')){
    continue;
}

Какой-то уродливый, я знаю.

Ответ 3

Пища для размышлений, основанная на Дамян Станчев:

Вы можете просто запустить PHP-интерпретатор через shell_exec(), который вытолкнет get_declared_classes(). Захватите вывод этого, и у вас должен быть "чистый" список системных классов.


Расширение ответа Mogria, это должно работать нормально (не приносите мне в этом благодарность, так как это был ответ Mogria, который правильно понял: -)):

function getUserDefinedClasses() {
    return array_filter(get_declared_classes(),
                        function ($class) {
                           $reflectionClass = new ReflectionClass($class);
                           return $reflectionClass->isUserDefined();
                         });
}

Ответ 4

Вы должны быть способны имитировать поведение отражения, расширив класс, который вы пытаетесь скопировать, и переопределите функцию __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");
?>

ОДНАКО: использование eval может быть полезно в этом случае, но также показывает довольно большое отверстие безопасности, если любой пользователь, представленный пользователем, может каким-либо образом изменить содержимое $class, Если вы понимаете эти ограничения и последствия для безопасности, вы должны иметь возможность использовать это.

Ответ 5

Не можете ли вы использовать get_declared_classes() в начале вашего script, сохраните данные в массиве и затем выполните array_diff() с сохраненными данными и ответом от get_declared_classes() и проверьте, не класс ли вы 'проверка выполняется в разнице с помощью in_array()?

Ответ 6

Этот пример выводит все классы с вашими классами, которые, как представляется, находятся в конце списка. Возможно, это может помочь.

Ответ 7

Как насчет сохранения вызова get_declared_classes() данных до выполняется любая автозагрузка/включение/требование, а затем проверка класса имя в этом хранилище?