This question already has answers here:
php validate integer
(7 answers)
Closed 9 years ago.
Hey I'm trying to perform input validation in PHP to ensure that the stock values that are typed in are at least 1 positive integer and from 0-9. Should not contain any special characters.
For example, any of the following values should be valid:
7
0
32
47534
The following SHOULD NOT be valid:
asdf
35/gdf
../34.
etc..
I'm using the following if statement to check for the positive integer value of "$original_stock".
if (preg_match("/^[0-9]$/", $original_stock))
{
$error .="Original stock must be numerical.";
}
Additionally, I have a price field which should be validated as either an int or a double.
If there's an easier alternative to using regex, that's okay too!
Thanks in advance :)
Try this regexp:
/^\d+$/
The issue with your existing regexp is that it only matches strings with exactly one digit.
As for validating an int or a double:
/^\d+\.?\d*$/
Note that that regexp requires that there be at least one digit.
Use:
/^[0-9]+$/
The + means "one or more". Without it, your regex will only match a single digit. Or you could use the simpler variant:
/^\d+$/
For floats, try something like:
/^\d+(\.\d{1,2})?/
This will match one or more digits, optionally followed by a . and one or two digits. (i.e. .12 will not match.)
To save yourself some headaches, you can also use the is_int and is_float functions.
Lastly; note that your check is wrong. preg_match will return 0 if it fails, so you should write it as:
if (!preg_match("/^\+$/", $original_stock)) {
// error
}
(note the !).
You may want to use the
is_int
Don't reinvent a wheel slower than an existing one, use a motorcycle: is_int.
#Assuming $original_stock is a single value...
if (is_int($original_stock)) {
#Valid, do stuff
}
else {
#Invalid, do stuff
}
#Assuming $original_stock is an array...
$valid = true;
foreach ($original_stock as $s) {
if (!is_int($s)) {
$valid = false;
break;
}
}
if ($valid) {...}
else {...}
I just ran into this exact problem and solved it this way using the regex.
I think the problem is your caret ^.
/^[0-9]$/
I moved it inside the class and got the results I needed.
function validate_int($subject)
{
//Pattern is numbers
//if it matches anything but numbers, we want a fail
$pattern = '/[^0-9]/';
$matches = preg_match($pattern, $subject);
if($matches > 0)
return false;
else
return true;
}
Related
I have a function which will return true if input is pure numeric or alphabate else it will return false. This function is working fine.
function checktype($a)
{
if (preg_match('/^\d+$/', $a)) { //check numeric (can use other numeric regex also like /^[0-9]+$/ etc)
$return = true;
} else if (preg_match('/^[a-zA-Z]+$/', $a)) { //check alphabates
$return = true;
} else { //others
$return = false;
}
return $return;
}
var_dump(checktype('abcdfekjh')); //bool(true)
var_dump(checktype('1324654')); //bool(true)
var_dump(checktype('1324654hkjhkjh'));//bool(false)
No I tried to optimized this function by removing conditions so I modified code to:
function checktype($a)
{
$return = (preg_match('/^\d+$/', $a) || preg_match('/^[a-zA-Z]+$/', $a)) ? true:false;
return $return;
}
var_dump(checktype('abcdfekjh')); //bool(true)
var_dump(checktype('1324654')); //bool(true)
var_dump(checktype('1324654hkjhkjh'));//bool(false)
Now in third step I tried to merge both regex in single regex so I can avoid two preg_match function and got stuck here:
function checktype($a)
{
return (preg_match('regex to check either numeric or alphabates', $a)) ? true:false;
}
I tried a lot of combinations since 2 days by using OR(!) operator using not operator(?!) but no success at all.
Below some reference website from which i pick expression and made some combinations:
http://regexlib.com/UserPatterns.aspx?authorid=26c277f9-61b2-4bf5-bb70-106880138842
http://www.rexegg.com/regex-conditionals.html
OR condition in Regex
Regex not operator (come to know about NOT operator)
https://www.google.co.in/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=regular+expression+not+condition (come to know about NOT operator)
So here main question is, is there any single regex pattern to check string contains pure numeric value or pure alphabates?
Note: Alternative solution can be check string is alphanumeric and then return true or false accordingly. Also php inbuilt function like is_numeric and is_string can be used, but I am more curious to know the single regex pattern to check weather string conains pure numeric digit or pure alphaba digits.
A one regex to check if a string is all ASCII digits or all ASCII letters is
'/^(?:\d+|[a-zA-Z]+)$/'
See regex demo
This regex has two things your regexps do not have:
a grouping construct (?:....)
an alternation operator |.
Explanation:
^ - start of string
(?:\d+ - one or more digits
| - or...
[a-zA-Z]+) - one or more ASCII letters
$ - end of string
If you need to make it Unicode-aware, use [\p{L}\p{M}] instead of [a-zA-Z] (and \p{N} instead of \d, but not necessary) and use the /u modifier:
'/^(?:\p{N}+|[\p{L}\p{M}]+)$/u'
And in case you want to really check that from the beginning to end, use
'/\A(?:\p{N}+|[\p{L}\p{M}]+)\z/u'
^^ ^^
or
'/^(?:\p{N}+|[\p{L}\p{M}]+)$/Du'
The $ without /D modifier does not match the string at its "very end", it also matches if there is a newline after it as the last character.
I have some PHP code that accepts an uploaded file from an HTML form then reads through it using regex to look for specific lines (in the case below, those with "Number" followed by an integer).
The regex matches the integers like I want it to, but of course they're returned as strings in $matches. I need to check if the integer is between 0 and 9 but I um unable to do this no matter what I try.
Using intval() or (int) to first convert the matches to integers always returns 0 even though the given string contains only integers. And using in_array to compare the integer to an array of 0-9 as strings always returns false as well for some reason. Here's the trouble code...
$myFile = file($myFileTmp, FILE_IGNORE_NEW_LINES);
$numLines = count($myFile) - 1;
$matches = array();
$nums = array('0','1','2','3','4','5','6','7','8','9');
for ($i=0; $i < $numLines; $i++) {
$line = trim($myFile[$i]);
$numberMatch = preg_match('/Number(.*)/', $line, $matches);
if ($numberMatch == 1 and ctype_space($matches[1]) == False) { // works up to here
$number = trim($matches[1]); // string containing an integer only
echo(intval($number)); // conversion doesn't work - returns 0 regardless
if (in_array($number,$nums)) { // searching in array doesn't work - returns FALSE regardless
$number = "0" . $number;
}
}
}
I've tried type checking, double quotes, single quotes, trimming whitespace, UTF8 encoding...what else could it possibly be? I'm about to give up on this app entirely, please save me.
Use '===' for eq for example
if 1 == '1' then true;
if 1 === '1' false;
if 1 == true then true;
if 1 === true then false
You can show file?
You write in your question that you're using a regular expression to look for the term "Number" followed by a single digit (0-9).
A regular expression for it would be:
/Number(\d)/
It will contain in the matching group 1 the number (digit) you're looking for.
The pattern you use:
/Number(.*)/
can contain anything (but a line-break) in the first matching group. It obviously is matching too much. You then have a problem filtering that too much retro-actively.
It normally works best to first look as precise as possible than to fiddle with too much noise afterwards.
In my table1 i have varchar field where i store an id-list of other table2 (id - INT UNSIGNED AUTOINCREMENT), separated by comma.
For example: 1,3,5,12,90
Also ids should not be repeated.
I need to check if a string (coming from outside) matches this rule.
For example i need to check $_POST['id_list']
Data consistency is not important for now (for example insert this value without checking if this ids really exist in table2)
Any advice will be helpful.
The easiest way to do such check is to use regular expression (preg_match).
Lets try to find a pattern matching our rule.
Just comma-separated digits:
^[0-9]+(,[0-9]*)*$
^ - means start of string.
$ - means end of string.
[0-9]+ - means that our string MUST starts with a digits.
(,[0-9]+)* - means that our string CAN continue itself with ",$someDigits" manner, from 0 to as many you wish times.
But if our digits are "INT UNSIGNED AUTOINCREMENT" we should modify our pattern this way:
^[1-9][0-9]*(,[1-9][0-9]+)*$
to exclude cases like: 0,01,02,009,000,012
As for unique values, i think more clear will be to use splitting (explode) string by comma to array, pass it through array_unique and compare.
So the result check-function will be:
function isComaSeparatedIds($string, $allowEmpty = false) {
if ($allowEmpty AND $string === '') {
return true;
}
if (!preg_match('#^[1-9][0-9]*(,[1-9][0-9]*)*$#', $string)) {
return false;
}
$idsArray = explode(',', $string);
return count($idsArray) == count(array_unique($idsArray));
}
Also added $allowEmpty argument if u would like to allow empty strings.
For the sake of completeness I would like to mention the following solution:
<?php
$check = explode(',', $string);
if ($diff = array_diff_key($check, array_filter($check, 'ctype_digit'))) {
// at least one is not a digit
foreach ($diff as $failIndex => $failValue) {
// handle
}
}
For less than 1000 digits in the string this is a little faster than preg_match and as little extra you get the positions and the values that are not a digit.
This is a bit of a cheeky solution,but it sure does the work.
<?php
$a="1,3,5,12,90";
$b=explode(",",$a);
$str='';
for($c=0;$c<count($b);$c++)
{
if (preg_match('/^[0-9]+$/', $b[$c]))
{
$str=$str."Y";
}
}
if(count(array_unique($b))==count($b) && (count($b)==strlen($str)))
{
echo $str;
//FURTHER CODE HERE WHEN ALL ELEMENTS UNIQUE AND VALID NUMBERS
}
else
{
//FURTHER CODE HERE WHEN NOT UNIQUE OR NOT A VALID NUMBERS
}
?>
I recently found out that a method I've been using for validating user input accepts some values I'm not particularly happy with. I need it to only accept natural numbers (1, 2, 3, etc.) without non-digit characters.
My method looks like this:
function is_natural($str)
{
return preg_match('/[^0-9]+$/', $str) ? false : $str;
}
So it's supposed to return false if it finds anything else but a whole natural number. Problem is, it accepts strings like "2.3" and even "2.3,2.2"
perhaps you can clarify the difference between a "number" and a "digit" ??
Anyways, you can use
if (preg_match('/^[0-9]+$/', $str)) {
// contains only 0-9
} else {
// contains other stuff
}
or you can use
$str = (string) $str;
ctype_digit($str);
The problem with /^[0-9]+$/ is that it also accepts values like 0123.
The correct regular expression is /^[1-9][0-9]*$/.
ctype_digit() suffers the same problem.
If you also need to include zero use this regex instead: /^(?:0|[1-9][0-9]*)$/
Use ctype_digit() instead
I got an issue with ctype_digit when invoice numbers like "000000196" had to go through ctype_digit.
So I have used a:
if (preg_match('/^[1-9][0-9]?$/', $str)) {
// only integers
} else {
// string
}
I'm trying to port this java to php:
String _value = '1111122222';
if (_value.matches("(1{5}|2{5}|3{5}|4{5}|5{5}|6{5}|7{5}|8{5}|9{5}){2}")) {
// check for number with the same first 5 and last 5 digits
return true;
}
As the comment suggests, I want to test for a string like '1111122222' or '5555566666'
How can I do this in PHP?
Thanks,
Scott
You can use preg_match to do so:
preg_match('/^(1{5}|2{5}|3{5}|4{5}|5{5}|6{5}|7{5}|8{5}|9{5}){2}$/', $_value)
This returns the number of matches (i.e. either 0 or 1) or false if there was an error. Since the String’s matches method returns only true if the whole string matches the given pattern but preg_match doesn’t (a substring suffices), you need to set markers for the start and the end of the string with ^ and $.
You can also use this shorter regular expression:
^(?:(\d)\1{4}){2}$
And if the second sequence of numbers needs to be different from the former, use this:
^(\d)\1{4}(?!\1)(\d)\2{4}$
Well, you could do:
$regex = '/(\d)\1{4}(\d)\2{4}/';
if (preg_match($regex, $value)) {
return true;
}
Which should be much more efficient (and readable) than the regex you posted...
Or, an even shorter (and potentially cleaner) regex:
$regex = '/((\d)\2{4}){2}/';
$f = substr($_value, 0, 5);
$s = substr($_value, -5);
return (substr_count($f, $f[0]) == 5 && substr_count($s, $s[0]) == 5);
Conversion is below. preg_match() is the key: http://www.php.net/preg_match
$value = '1111122222';
if (preg_match('/^(1{5}|2{5}|3{5}|4{5}|5{5}|6{5}|7{5}|8{5}|9{5}){2}$/', $value)) {
// check for number with the same first 5 and last 5 digits
return true;
}