Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
531 views
in Technique[技术] by (71.8m points)

php - Checking that a value contains only digits, regex or no?

I have a function that is used throughout my code. The function expects that the passed parameter is a positive integer. Since PHP is loosely typed, the data type is unimportant. But it is important that it contain nothing but digits. Currently, I am using a regular expression to check the value before continuing.

Here is a simplified version of my code:

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
}

I come from a Perl background and tend to reach for regular expressions often. However, I know their usage is controversial.

I considered using intval() or (int) and forcing $company_id to be an integer. However, I could end up with some unexpected values and I want it to fail fast.

The other option is:

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

Is this scenario a valid use of regular expressions? Is one way preferred over the other? If so, why? Are there any gotchas I haven't considered?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The Goal

The original question is about validating a value of unknown data type and discarding all values except those that contain nothing but digits. There seems to be only two ways to achieve this desired result.

If the goal is to fail fast, one would want to check for invalid values and then fail rather than checking for valid values and having to wrap all code in an if block.

Option 1 from Question

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

Using regex to fail if match non-digits. Con: regex engine has overhead

Option 2 from Question

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

Using ctype_digit to fail if FALSE. Con: value must be cast to string which is a (small) extra step

You must cast value to a string because ctype_digit expects a string and PHP will not cast the parameter to a string for you. If you pass an integer to ctype_digit, you will get unexpected results.

This is documented behaviour. For example:

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

Difference Between Option 1 and 2

Due to the overhead of the regex engine, option two is probably the best option. However, worrying about the difference between these two options may fall into the premature optimization category.

Note: There is also a functional difference between the two options above. The first option considers NULL and empty strings as valid values, the second option does not (as of PHP 5.1.0). That may make one method more desirable than the other. To make the regex option function the same as the ctype_digit version, use this instead.

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

Note: The 'start of string' ^ and 'end of string' $ anchors in the above regex are very important. Otherwise, abc123def would be considered valid.

Other Options

There are other methods that have been suggested here and in other questions that will not achieve the stated goals, but I think it is important to mention them and explain why they won't work as it might help someone else.

  • is_numeric allows exponential parts, floats, and hex values

  • is_int checks data type rather than value which is not useful for validation if '1' is to be considered valid. And form input is always a string. If you aren't sure where the value is coming from, you can't be sure of the data type.

  • filter_var with FILTER_VALIDATE_INT allows negative integers and values such as 1.0. This seems like the best function to actually validate an integer regardless of data type. But doesn't work if you want only digits. Note: It's important to check FALSE identity rather than just truthy/falsey if 0 is to be considered a valid value.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...