Разве плохо использовать Reflection в рабочем коде? - PullRequest
4 голосов
/ 15 октября 2010

У меня есть класс Validator, который создает экземпляр класса Validations, который содержит все методы проверки.Когда проверка выполняется, __call в Validator используется для отправки вызова от Validator->validate_<i>method</i> до Validations-><i>method</i>.

Так, например, в Validations есть метод, называемый length_of.Когда выполняется следующий код:

$v = new Validator();
$v->validate_length_of(...);

выполняется проверка length_of в классе Validations.

Чтобы убедиться, что __call не пытается отправитьдля недопустимого или закрытого метода Validation я использую ReflectionMethod для проверки указанного метода:

$method = new ReflectionMethod($this->validations, $validation_method);
if (!$method->isPublic())
{
  // error
}

Я почти уверен, что это единственный способ определить, является ли методpublic, но я не уверен, что Reflection подходит для использования в рабочем коде.Это запах кода?

Ответы [ 3 ]

6 голосов
/ 15 октября 2010

Вы действительно не должны использовать Reflection в производственном коде.Почему бы вам не использовать is_callable здесь?

if (!is_callable(array('Validations', $validation_method)) {
    throw new LogicException('method does not exist');
}

Это проверяет, что класс Validations имеет статический метод $validation_method и гарантирует, что вы можете вызывать его из текущегоконтекст.На самом деле это дает вам еще большую гибкость, чем рефлексия, потому что учитывает __call методы и тому подобные вещи, а Reflection - нет.

1 голос
/ 15 октября 2010

Если вам нужна мощь API Reflection в вашем коде, используйте его.Но отражение может быть медленным, и эталонный тест никогда не повредит, когда вы его используете.В конце концов, только вы можете решить, окажет ли это слишком большое влияние на ваше приложение.Мы по-прежнему говорим только о микросекундах.

Однако, для вашего конкретного случая использования я не понимаю, зачем вам вообще использовать Reflection.Просто используйте интерфейс и сделайте проверки в отдельных классах, реализующих этот интерфейс.См. Мой пример класса валидации .

Если вы хотите использовать __call с этим (магические методы слишком медленные, кстати), вы можете использовать class_implements дляпроверьте, реализует ли валидатор интерфейс, и тогда вы уверены, что метод validate существует, например, в основной класс Validator добавьте

public function __call($method, $args)
{
    if ( class_exists( $method )) {
        $validator = new $method;
        if($validator instanceof IValidate) {
            return call_user_func(array($validator, 'validate'), $args);
        }
        throw new BadMethodCallException('Class exists but is not a Validator');
    }
    throw new RuntimeException('Method does not exist');
}

В sidenote: Zend Framework уже имеет большое количество валидаторовВы можете построить на .Поскольку ZF является библиотекой компонентов, вы можете использовать их без необходимости переноса всего приложения в ZF.У PEAR также есть пакет проверки .

0 голосов
/ 15 октября 2010

ИМХО, я бы отказался от использования отражения в производственном коде. Вместо того, чтобы пытаться вызвать validate_ что-то , я бы создал интерфейс, который имеет необходимый метод validate. Затем для каждого класса валидатора вы просто вызываете $ valid-> validate (). Интерпретатору было бы легче кэшировать этот код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...