目标
原始问题是关于验证未知数据类型的值并丢弃除了只包含数字以外的所有值。似乎只有两种方法可以实现这一期望结果。
如果目标是快速失败,则应检查无效值,然后失败,而不是检查有效值并将所有代码包装在if
块中。
选项1来自问题
if (preg_match('/\D/', $company_id)) exit('Invalid parameter');
使用 regex
来匹配非数字并失败。缺点是正则表达式引擎会增加开销。
问题中的选项 2
if (!ctype_digit((string) $company_id)) exit('Invalid parameter');
使用
ctype_digit
来判断是否为FALSE。缺点是需要将值转换为字符串,这是(一个小的)额外步骤。
您必须将值转换为字符串,因为
ctype_digit
期望一个字符串,而PHP不会为您将参数转换为字符串。如果您将整数传递给
ctype_digit
,则会得到意外的结果。
这是已记录的行为。例如:
ctype_digit('42'); // true
ctype_digit(42); // false (ASCII 42 is the * character)
选项1和选项2之间的区别
由于正则表达式引擎的开销,选项2可能是最好的选择。但是,过分关注这两个选项之间的差异可能会陷入过早优化的类别。
注意: 上述两个选项之间也存在功能上的差异。第一个选项将NULL
和空字符串视为有效值,而第二个选项不会(从PHP 5.1.0开始)。这可能使其中一种方法比另一种更可取。要使regex
选项与ctype_digit
版本的功能相同,请改用以下内容。
if (!preg_match('/^\d+$/', $company_id)) exit('Invalid parameter');
注意:上述regex
中的“字符串开始”^
和“字符串结束”$
锚非常重要。否则,abc123def
将被视为有效。
其他选项
这里和其他问题中提出了其他方法,但它们无法实现所述目标,但我认为提到它们并解释为什么它们不起作用可能会帮助其他人。
is_numeric
允许指数部分、浮点数和十六进制值。
is_int
检查数据类型而不是值,这对于验证如果'1'
应该被视为有效是没有用的。表单输入始终是一个字符串。如果您不确定值来自何处,则无法确定数据类型。
filter_var
与FILTER_VALIDATE_INT
允许负整数和诸如1.0
之类的值。这似乎是实际验证整数的最佳函数,无论数据类型如何。但如果你只想要数字,它就不起作用了。注意:如果0
被视为有效值,则重要的是检查FALSE
的身份而不仅仅是真假值。
ctype_digit
函数有什么问题吗? - Michaelctype_digit
唯一的缺点就是它必须先转换为一个字符串。然而,我发现regex
更易于阅读,并且我习惯使用它。我正在尝试确定是否有充分的理由进行切换。 - toxalot