如何使用preg_match进行验证用户名?

I would like to create a preg_match function to validate my username, my code below not working perfectly, especially on Must contain at least 4 letter lowercase rules and number not more than 4 character and place behind letter

if (preg_match('/^[a-z0-9]{4,12}/', $_POST['username']))

Here are my username rules that I want to work :

  • Only contain letter and numbers but number is not reqired
  • Must contain at least 4 letter lowercase
  • Number not more than 4 character and place behind letter
  • Must be 4-12 characters

Thank you for any help you can offer.

You match these criteria, maybe this will be an option:

^[a-z](?=(?:[a-z]*\d){0,4}(?![a-z]*\d))(?=[a-z\d]{3,11}$)[a-z\d]+$

This will match

  • From the beginning of the string ^
  • Match a lowercase character [a-z]
  • A positive lookahead (?= which asserts that what follows is
    • A non capturing group (?:
    • Which will match a lowercase character zero or more times followed by a digit [a-z]*\d
    • Close non capturing group and repeat that from 0 to 4 times ){0,4}
    • A negative lookahead (?! Which asserts that what follows is not
    • A lowercase character zero or more times followed by a digit [a-z\d]*
    • Close negative lookahead )
  • Close positive lookahead )
  • Positive lookahead (?= which asserts that what follows is
    • Match a lowercase character or a digit from 3 till 11 times till the end of the string (?=[a-z\d]{3,11}$)
  • Close positive lookahead )
  • Match a lowercase character or a digit till the end of the string [a-z\d]+$

Out php example

Regex: ^[a-z]{4,8}[0-9]{0,4}$|^[a-z]{4,12}$

Details:

  • ^ Asserts position at start of a line
  • $ Asserts position at the end of a line
  • [] Match a single character present in the list
  • {n,m} Matches between n and m times
  • | Or

PHP code:

$strings=['testtesttest', 'testtesttestr', 'test12345', 'testtest1234', 'testte123432'];

foreach($strings as $string){
    $match = preg_match('~^[a-z]{4,8}[0-9]{0,4}$|^[a-z]{4,12}$~', $string);
    echo ($string . ' => len: (' . strlen($string) . ') ' .($match ? 'true' : 'false')."
");
}

Output:

testtesttest => len: (12) true
testtesttestr => len: (13) false
test12345 => len: (9) false
testtest1234 => len: (12) true
testte123432 => len: (12) false

Code demo