我有一个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
}
我很确定这是确定方法是否公开的唯一方法,但我不确定反射是否适合生产代码。这是代码味吗?
答案 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)