PHP方法参数的类型检查 - 是否值得?

12

我想知道你认为在PHP中检查参数的最佳实践是什么?也就是说,在实施参数类型检查与不进行参数类型检查的项目中,你是否真正看到了明显较少的错误?我正在考虑像这样的事情:

public function __construct($screenName, $createdAt) {  
        if (!is_string($screenName) || !is_string($createdAt) {
            return FALSE;
        }
}

5
如果你需要类型检查,使用静态语言。 - user395760
1
我曾经在规划和编写良好的项目中看到过更少的错误。这算吗? ;) 顺便说一下:$createdAt也可以是时间戳(int)或对象(DateTime)。 - KingCrunch
@KingCrunch:我不知道您使用的是哪个PHP版本,但据我所知,is_string对整数值和对象仍然返回false。 - hakre
@delnan:如果你错过了,这个问题是关于PHP的 ;) - hakre
@hakre:这就是我的意思。对于一个名为$createdAt的参数,我最后会假设它是string类型,但在这里不被接受(实际上在这里是被接受的,因为构造函数中的return false;没有任何效果,如果类型不匹配,什么也不会发生,但这只是因为示例有点不完整)。我的意思是,在这种情况下严格的类型限制可能会导致更多的混淆,而不是帮助某人。 - KingCrunch
显示剩余4条评论
4个回答

11

通常情况下,在使用PHP应用程序中,使用标量变量“types”实际上是绑定到字符串输入(HTTP请求)的。PHP使将字符串输入转换为数字更加容易,这样您就可以将其用于计算等操作。

然而,像您提供的示例中建议的那样检查标量值是否为is_string并没有太多意义。因为标量家族中的几乎任何类型的变量都是字符串,或者至少可以用作字符串。因此,对于您的类示例,问题是,检查变量类型是否实际上有意义呢?

对于您提出的代码来说,它没有任何意义,因为您在构造函数中使用return false;退出。这将结束构造函数的运行并返回一个未经适当初始化的对象。

相反,如果构造函数的参数未提供所需的值类型,则应抛出异常,例如InvalidArgumentException

不考虑这一点,并且默认构造函数需要区分字符串、整数、布尔或任何其他标量类型,那么您应该进行检查。

如果您不依赖于精确的标量类型,则可以将其转换为字符串。

只要确保对象内部隐藏的数据始终完全正确,并且不可能将错误的数据插入到私有成员中即可。


7
这要看情况。对于高级对象((stdClass $obj,array $arr,MyClass $mine)),我通常会使用PHP内置的类型提示type-hinting,但是对于低级值,特别是数字和字符串,就不那么有益了。
例如,如果您有字符串'12345',那么很难区分它和数字12345之间的区别。
对于其他所有内容,将数组意外转换为字符串将是显而易见的。如果类实例被转换为字符串且没有__toString,PHP将报错。因此,您唯一真正的问题是具有__toString方法的类,这种情况可能非常少见。我真的想知道它是否值得这样的开销。

3

检查函数参数是一种非常好的实践。我怀疑人们通常不这样做是因为他们的函数变得越来越大,代码变得更加丑陋和难以阅读。现在,在PHP 7中,您可以对标量类型进行类型提示,但仍然没有解决方案,用于当您希望参数是两种类型之一时:数组或\ Traversable实例(两者都可以使用foreach遍历)。

在这种情况下,我建议看一下args模块,它来自NSPL。您示例中的__constructor将如下所示:

public function __construct($screenName, $createdAt)
{
    expectsAll(string, [$screenName, $createdAt]);
}

// or require a non-empty array, string or instance of \ArrayAccess
function first($sequence)
{
    expects([nonEmpty, arrayAccess, string], $sequence);
    return $sequence[0];
}

更多示例 在这里


0

当你是唯一与方法交互的人时,更好的文档非常重要。标准的方法定义注释可以为您提供良好的文档化方法,这些方法可以轻松编译成 API,然后在许多 IDE 中使用。

然而,当您将您的库或输入暴露给其他人时,进行类型检查并在代码无法与其输入配合使用时抛出错误是很好的。对用户输入进行类型检查可以保护您免受错误和黑客攻击,并且作为一个库,让其他开发人员知道他们提供的输入不是您所期望的有时是很好的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接