phpregexcharacter-class

php: check if a variable has/lacks particular characters


I actually have two questions but they are almost the same thing.

no1, I want to use PHP to check if a variable contains anything that is not a forward slash or a number, I am aware that I can use strpos() for this but if I do something like

if (strpos($my_variable, "/")) {
    if (1 === preg_match('~[0-9]~', $string)) {
        //do something
    }
}

the above code first if statement checks if the variable contains forward slash then the next checks if the variable contains letters, but if someone types something like 'asdfgfds2345/' as their date of birth it will go through because the string contains a forward slash and numbers but I what my PHP script to do something like this

if(/*my_variable contains letters,special characters and any other thing that is not a number or a forward slash*/){
 do something}

next question: I want to use PHP to check if a variable contains anything that is not a lowercase letter, an underscore or a hyphen, I am also aware that I can use strpos() for this but if I can't keep doing something like this something like this

if (strpos($my_variable, "/")) {
    //redirect
} else {
    if (strpos($my_variable, "?")) {
        //redirect
    } else {
        if (strpos($my_variable, "$")) {
            //redirect
        } else {
            //do something
        }
    }
}

if I try to do the above it will take me a long time to finish this page so is there a way that I can do this

$chars = "$""#""/""*";
if ($myvariable contains any of the letters in $char){
    //do something
}

I know that the above code is wrong in all ways but I am just trying to show you what I want to achieve

thanks in advance


Solution

  • Date of Birth Matching:

    If you want to verify the date of birth format (assuming [D]D/[M]M/YY[YY], possible single-digit values for day and month), you can do it as follows:

    // This would match for any numbers:
    if (preg_match('~^\d{1,2}/\d{1,2}/\d{2}(\d{2})?$~', $var)) {
        // proceed with valid date
    } else {
        // protest much
    }
    

    Here we're using ^ and $ anchors (for ^ beginning and $ end of subject) to assert that the subject $var must be only this (rather than include it): [D]D/[M]M/YY[YY], or 1-2 digits, slash, 1-2 digits, slash, 2 or 4 digits (notice the (\d{2})? optional match).

    One could further tune the regex to also match acceptable number ranges, but I trust this will do for now. Rather check the ranges post-process; you'll probably want to convert this into a timestamp (possibly with strtotime) and/or SQL datetime for further use in any case.

    Another handy thing you can do is capture the date components right away. In the following example, we're using named capture groups for clarity:

    if (preg_match('~^(?<day>\d{1,2})/(?<month>\d{1,2})/(?<year>\d{2}(\d{2})?)$~', $var, $date)) {
        var_dump($date); // see what we captured.
    } else {
        // nothing to see here, except a protest.
    }
    

    Notice how the $date variable, containing the matches, carries on from the conditional check line. You can validate and parse in one move, yay! Results (assuming 20/02/1980 input) in:

    array(8) {
        [0] · string(10) "20/02/1980" // this is the complete subject
        ["day"] · string(2) "20"
        [1] · string(2) "20"
        ["month"] · string(2) "02"
        [2] · string(2) "02"
        ["year"] · string(4) "1980"
        [3] · string(4) "1980"
        [4] · string(2) "80" // this will only appear for 4-digit years
    }
    

    (Non-)Matching Any Characters:

    "I want to use PHP to check if a variable contains anything that is not a lowercase letter, an underscore or a hyphen". It's as simple as this:

    if (preg_match('~[^a-z_-]~', $var)) {
        // matches something other than a-z, _ and -
    } else {
        // $var only has acceptable characters
    }
    

    Here the ^ operator negates the character range (only inside [], otherwise it's start-of-subject). If you want to do a positive check (e.g. has #, &, X), simply preg_match('~[#&X]~', $var). Spending a bit of time understanding regular expressions is time well-invested. I still often drift to RegularExpressions.Info to refresh memory or study how to implement more complex expressions, however there are also plenty of other resources out there. Happy matching,