Reputation: 2736
I am trying to validate an input to match a salary or a salary range - the issue is that the user can enter a number of possible values.
For example, below is valid:
2000
2,000
2000.00
2,000.00
2000 - 4000
2,000-4,000
2,000.00-4,000.00
$2,000.00-$4,000.00
£2,000.00-£4,000.00
Initially we set out to allow everything except for letters but that would allow something like 2!000 which would not be valid
At the moment we have gotten:
if (preg_match('/^\d|\d,\d+(\.(\d{2}))?$/', $i)) {
return true;
}
That does work for the first 4 examples but it allows things like 2a000 which is not valid - is there a way to list everything the string cannot contain (letters and symbols for example except for currency, period and comma) but still then do a pattern match so we can validate numbers for example?
Upvotes: 3
Views: 586
Reputation: 2329
This one is quite strict so that all your entries from second group pass and none of the first group.
^[$£]?\d,?000(\.00)?([ -]+[$£]?\d,?000(\.00)?)?$
You can do something much more benevolent too. Such as replace the [$£]
by \D
to allow arbitrary currencies etc.
Upvotes: -1
Reputation: 1270
If you get a hyphen -, it indicates that you have range. To keep it simple I would explode() on hyphen and validate each part in a loop with $numberFormatter = new NumberFormatter( 'en_US', NumberFormatter::CURRENCY ); var_dump( $numberFormatter->formatCurrency(1234.56789, "USD" ) );
If the formatter is able to return a string, it’s an indication that input is valid.
This would work even if salary is submitted instead of range.
Upvotes: 0
Reputation: 163632
You might capture $
or £
in a group and then for consistency use a backreference to match the same symbol in the second part (which is optional).
To shorten the pattern a bit, you could use a subroutine (?2)
to repeat matching the digits in capture group 2.
^([$£]?)((?:\d{1,3}(?:,\d{3})*|\d+)\b(?:\.\d{2})?)(?:\h*-\h*\1(?2))?$
In parts
^
Start of string(
Capture group 1
[$£]?
Optionally match $
or £
)
Close group(
Capture group 2
(?:\d{1,3}(?:,\d{3})*
Match 1-3 digits and repeat 0+ times matching ,
and 3 digits|
Or\d+
Match 1+ digits\b
Word boundary(?:\.\d{2})?
Optionally match a dot and 2 digits)
Close group(?:
Non capturing group
\h*-\h*\1
Match -
between 0+ horizontal whitespace chars, followed by a backreference to what is captured in group 1 (optional $
or £
)(?2)
Repeat the pattern in group 2 to match the digits)?
Close group and make it optional$
End of stringUpvotes: 4