Php 在生产代码中使用反射是否不好?

Php 在生产代码中使用反射是否不好?,php,reflection,Php,Reflection,我有一个Validator类,它创建一个Validations类的实例,该类包含所有验证方法。执行验证时,验证程序中的\u调用用于将调用验证程序->验证方法分派到验证->方法 例如,Validations中有一种方法称为length\u of。运行以下代码时: $v = new Validator(); $v->validate_length_of(...); 执行Validations类中的length\u验证 为了确保\u调用不会尝试分派到无效或非公共的验证方法,我使用Reflect

我有一个
Validator
类,它创建一个
Validations
类的实例,该类包含所有验证方法。执行验证时,
验证程序
中的
\u调用
用于将调用
验证程序->验证方法
分派到
验证->方法

例如,
Validations
中有一种方法称为
length\u of
。运行以下代码时:

$v = new Validator();
$v->validate_length_of(...);
执行
Validations
类中的
length\u
验证

为了确保
\u调用
不会尝试分派到无效或非公共的
验证
方法,我使用
ReflectionMethod
检查指定的方法:

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

我很确定这是确定一个方法是否是公共的唯一方法,但我不确定在生产代码中使用反射是否合适。这是一种代码味道吗?

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


这将检查
Validations
类是否有一个静态方法
$validation\u method
,并确保可以从当前上下文调用它。实际上,这比反射提供了更大的灵活性,因为它考虑了
\u调用
方法和反射没有考虑的类似内容。

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

然而,对于您的特定用例,我不明白您为什么要使用反射。只需使用一个接口,并将验证放入实现该接口的单独类中。看我的

如果您想使用
\u call
(顺便说一句,魔术方法太慢了),您可以使用来检查验证程序是否实现了该接口,然后确定验证方法存在,例如在主验证程序类add中

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');
}

旁注:。由于ZF是一个组件库,您可以使用它们,而无需将整个应用程序迁移到ZF。PEAR也有一个

IMHO,我会偏离在生产代码中使用反射。我将创建一个具有所需验证方法的接口,而不是尝试调用validate_。然后,对于每个Validator类,只需调用$valid->validate()。解释器将更容易缓存该代码

抱歉,我的问题不清楚,
验证
中的方法不是静态方法。在这种情况下,使用
新验证
(或
验证
的现有实例)作为数组中的第一个元素,而不是
验证
)您忘记了数组;)你必须把一个数组传递给
是可调用的
(如果你这样使用它的话。)啊,糟了,我确实这么做了。这真是个愚蠢的举动,尤其是因为我在班上到处都使用回调为什么不能在生产代码中使用反射?除了“知道你在做什么并保持简单”之外,我看不出有什么原因。可见性修改器就是这里的味道。只需删除“private”并使用“method_exists”。@stereofrog我不想访问私有方法。我试图不允许访问私有方法。“我会离开”——可能是世界上最大的打字错误。
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');
}