繁体   English   中英

检查一个值只包含数字,正则表达式还是否?

[英]Checking that a value contains only digits, regex or no?

我有一个在我的代码中使用的函数。 该函数期望传递的参数是正整数。 由于PHP是松散类型的,因此数据类型并不重要。 但是,它包含什么,但数字是很重要的。 目前,我正在使用正则表达式在继续之前检查值。

这是我的代码的简化版本:

function do_something($company_id) {
    if (preg_match('/\D/', $company_id)) exit('Invalid parameter');
    //do several things that expect $company_id to be an integer
}

我来自Perl背景,往往会经常使用正则表达式。 但是,我知道他们的用法是有争议的。

我考虑使用intval()(int)强制 $company_id为整数。 但是,我最终会得到一些意想不到的值,我希望它快速失败

另一种选择是:

if (!ctype_digit((string) $company_id)) exit('Invalid parameter');

这种情况是否是正则表达式的有效使用? 一种方式优于另一种方式吗? 如果是这样,为什么? 有没有我没考虑过的陷阱?

目标

最初的问题是验证未知数据类型的值并丢弃除除数字之外的所有值。 似乎只有两种方法可以实现这种期望的结果。

如果目标是快速失败 ,则需要检查无效值然后失败而不是检查有效值并且必须将所有代码包装在if块中。

问题的备选方案1

if (preg_match('/\D/', $company_id)) exit('Invalid parameter');

如果匹配非数字, regex使用regex失败。 Con:正则表达式引擎有开销

问题的备选方案2

if (!ctype_digit((string) $company_id)) exit('Invalid parameter');

如果为FALSE,则使用ctype_digit失败。 Con:值必须转换为字符串,这是一个(小)额外步骤

您必须将值转换为字符串,因为ctype_digit需要一个字符串,PHP不会将参数转换为字符串。 如果将整数传递给ctype_digit ,则会得到意外的结果。

这是记录在案的行为。 例如:

ctype_digit('42'); // true
ctype_digit(42); // false (ASCII 42 is the * character)

选项1和2之间的差异

由于正则表达式引擎的开销,选项二可能是最好的选择。 但是,担心这两个选项之间的差异可能属于过早的优化类别。

注意:上述两个选项之间也存在功能差异。 第一个选项将NULL和空字符串视为有效值,第二个选项不考虑(从PHP 5.1.0开始)。 这可能使一种方法比另一种方法更令人满意。 要使regex选项功能与ctype_digit版本相同,请改用它。

if (!preg_match('/^\d+$/', $company_id)) exit('Invalid parameter');

注:“字符串的开始” ^和“串”端$上面锚regex是非常重要的。 否则, abc123def将被视为有效。

其他选择

在这里和其他问题中已经提出了其他方法,这些方法无法实现既定目标 ,但我认为重要的是要提及它们并解释为什么它们不会起作用,因为它可能会帮助其他人。

  • is_numeric允许指数部分,浮点数和十六进制值

  • 如果'1'被认为有效,则is_int检查数据类型而不是对验证无用的值。 表单输入始终是一个字符串。 如果您不确定值的来源,则无法确定数据类型。

  • filter_var with FILTER_VALIDATE_INT允许使用负整数和值,例如1.0 这似乎是实际验证整数的最佳函数,无论数据类型如何。 但如果你想要数字,则不起作用。 注意:如果要将0视为有效值,则检查FALSE 标识非常重要,而不仅仅是truthy / falsey。

filter_var + FILTER_VALIDATE_INT怎么FILTER_VALIDATE_INT

if (FALSE === ($id = filter_var($_GET['id'], FILTER_VALIDATE_INT))) {
    // $_GET['id'] does not look like a valid int
} else {
    // $id is a int because $_GET['id'] looks like a valid int
}

此外,它还有min_range / max_range选项。

这个函数的基本思想或多或少等同于:

function validate_int($string) {
    if (!ctype_digit($string)) {
        return FALSE;
    } else {
        return intval($string);
    }
}

此外,如果您期望一个整数,您可以使用is_int 不幸的是,类型提示仅限于objets和array。

两种方法都会将变量转换为字符串。 preg_match不接受integer类型的主题,因此一旦传递给函数,它将被转换为字符串。 在这种情况下, ctype_digit绝对是最好的解决方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM