在生产代码中使用Reflection是不是很糟糕?

时间:2010-10-14 21:18:15

标签: php reflection

我有一个Validator类,它创建一个Validations类的实例,其中包含所有验证方法。执行验证后,__call中的Validator用于将来电Validator->validate_method发送给Validations->method

例如,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
}

我很确定这是确定方法是否公开的唯一方法,但我不确定反射是否适合生产代码。这是代码味吗?

3 个答案:

答案 0 :(得分:6)

你真的不应该在生产代码中使用Reflection。你为什么不在这里使用is_callable

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

这将检查Validations类是否具有静态方法$validation_method,并确保您可以从当前上下文中调用它。实际上,这为您提供了比反射更多的灵活性,因为这会将__call方法和类似的东西考虑在内,而Reflection则没有。

答案 1 :(得分:1)

如果您需要在代码中使用Reflection API的强大功能,那么请使用它。但是反射可能很慢,而且使用它时基准测试永远不会受到影响。最后,您只能决定它是否对您的应用程序产生太大影响。我们只谈论它仍然是微秒。

但是,对于您的特定用例,我不明白为什么您会使用Reflection。只需使用一个接口并将验证转换为实现该接口的单独类。查看我的example Validation class

如果你想使用__call(魔术方法也很慢),可以使用class_implements检查验证器是否实现了接口,然后你确定验证方法存在,例如在主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');
}

旁注:the Zend Framework already has an extensive number of Validators you can build on。由于ZF是一个组件库,因此您无需将整个应用程序迁移到ZF即可使用它们。 PEAR也有一个Validation package.

答案 2 :(得分:0)

恕我直言,我会偏离在生产代码中使用反射。我没有尝试调用validate_ 某些东西,而是创建一个需要验证方法的接口。然后对于每个valiadtor类,只需调用$ valid-> validate()。解释器更容易缓存该代码。