Elliott
Elliott

Reputation: 3864

Validate user-submitted username string for qualifying length and character constraints

The regex below is to validate a username.

I have this so far, but isn't working.

$username = $_POST['username'];
if (!eregi("^([a-zA-Z][0-9_.]){4,26}$",$username)) {
    return false;
} else {
    echo "username ok";
}

Upvotes: 20

Views: 63437

Answers (3)

Jim
Jim

Reputation: 18853

You are asking for a lot in one regex, this may be possible but it is not the best way, you want to let the user know why their username is erroring out.

function checkUsername($username) {
    $username = trim($username);
    if (empty($username)) {
        return "username was left blank.";
    }elseif (strlen($username) < 4) {
        return "username was too short";
    }elseif (strlen($username) > 26) {
        return "username was too long";
    }elseif (!preg_match('~^[a-z]{2}~i', $username)) {
        return "username must start with two letters";
    }elseif (preg_match('~[^a-z0-9_.]+~i', $username)) {
        return "username contains invalid characters.";
    }elseif (substr_count($username, ".") > 1) {
        return "username may only contain one or less periods.";
    }elseif (substr_count($username, "_") > 1) {
        return "username may only contain one or less underscores.";
    }

    return true;
} 

Then to check you would do:

$validUsername = checkUsername($username);

if ($validusername !== true) {
     echo "An error occured: " . $validUsername;
}

This way the user knows there was an error and can fix it easier instead of being blind to what the error is. Also you should stop using ereg it has been depreciated use preg_match instead.

NOTE the use of the !== to check, this also checks type since it can return a string (which would return true with a loose comparison). Just an FYI.

Upvotes: 6

kennytm
kennytm

Reputation: 523284

You could use the regex

/^(?=[a-z]{2})(?=.{4,26})(?=[^.]*\.?[^.]*$)(?=[^_]*_?[^_]*$)[\w.]+$/iD

as in

<?php

$username=$_POST['username'];

if (!preg_match('/^(?=[a-z]{2})(?=.{4,26})(?=[^.]*\.?[^.]*$)(?=[^_]*_?[^_]*$)[\w.]+$/iD',
                $username))
{
 return false;
}
else
{
 echo "username ok";
}

?>
  • The ^(?=[a-z]{2}) ensure the string "Start with atleast 2 letters".
  • The (?=.{4,26}) ensure it "Must be between 4-26 characters long".
  • The (?=[^.]*\.?[^.]*$) ensures the following characters contains at most one . until the end.
  • Similarly (?=[^_]*_?[^_]*$) ensures at most one _.
  • The [\w.]+$ commits the match. It also ensures only alphanumerics, _ and . will be involved.

(Note: this regex assumes hello_world is a valid user name.)

Upvotes: 40

Kevin Sedgley
Kevin Sedgley

Reputation: 1069

The part where you said:

and one underscore and one dot

would steer me away from regular expressions to be honest!

I would do something like:

if(!eregi('^[a-zA-Z]{2}$', substr(0,2))) {
    // .... check for only 2 dots here later ....
}

Upvotes: 0

Related Questions