PHP instanceof над строками и неинициализируемыми классами - PullRequest
3 голосов
/ 06 декабря 2010

Мне нужно , чтобы проверить, расширяет ли конкретный класс или реализует определенный интерфейс.

Обратите внимание , что имя класса является переменной строкой, т. Е. Выигралне может быть экземпляром этого класса.

Пользователи должны выбирать класс из списка классов, а система должна проверять, реализует ли класс определенный интерфейс или нет.Список классов является переменным (в соответствии с программным обеспечением PHP, запущенным в настоящее время), некоторые из этих классов могут быть инициализированы, а другие - нет.

Вот код, который я использую:

function is_instance_of($obj,$cls){
    if(is_string($obj))$obj=new $obj();
    if(PHP_MAJOR_VERSION>4)return $obj instanceof $cls;
    if(PHP_MAJOR_VERSION>3)return is_a($obj,strtolower($cls));
    return false;
}

var_dump(is_instance_of('MyClass','IMyInterface')); // in theory, true
var_dump(is_instance_of('Closure','IMyInterface')); // FATAL ERROR

Этот последний тест показывает следующую ошибку:

Исправляемая фатальная ошибка: создание переменной 'Closure' не разрешено в C: \ Users \ abcdefghijklmn \ debug.php в строке XX

Вещи, которые я пытался:

  • Использование $obj=new @$obj();: - ошибка скрыта, но она все еще выходит из строя / умирает.
  • Использование try{}catch(){} вокруг ошибочного блока: - Ничего не происходит
  • Использование 'class' instanceof 'class' (где $ obj - строка): - безоговорочно возвращает false

Обратите внимание, что обязательная инициализация класса, используемая в этом методе ... отстой.Создание экземпляров означает ненужное потребление памяти, потерю скорости и большую склонность к ошибкам (представьте себе какой-нибудь странный класс, который при создании экземпляра без параметров продолжает уничтожать ваш жесткий диск;)).Так что, если есть какой-то другой способ, я бы просто хотел узнать об этом.


Редактировать: Это (надеюсь) окончательный код: -

/**
 * Cross-version instanceof replacement.
 * @param object $obj The instance to check.
 * @param stirng $cls The class/interface name to look for.
 * @return boolean Whether an object extends or implements a particular class
 *     or interface.
 * @link http://stackoverflow.com/questions/4365567/php-instanceof-over-strings-and-non-initializable-classes
 */
function is_instance_of($obj,$cls){
    if(is_string($obj) || PHP_MAJOR_VERSION>4){
        $rc=new ReflectionClass($obj);
        return $rc->implementsInterface($cls);
    }else{
        if(PHP_MAJOR_VERSION>3)return is_a($obj,strtolower($cls));
        return false;
    }
}

Ответы [ 2 ]

2 голосов
/ 06 декабря 2010

Попробуйте использовать вместо PHP ReflectionClass , например,

$rc = new ReflectionClass($obj);
return $rc->implementsInterface($cls);
0 голосов
/ 06 декабря 2010

Используйте ReflectionClass:

function is_instance_of($obj,$cls){
    $ref=new ReflectionClass($obj);
    return in_array($cls, array_keys($ref->getInterfaces());
}
...