Search code examples
phpregexrangepreg-matchinverse

Return 0 when regex match is found (PHP)


I am hoping to return 0 when 2011-2016 is found in the string. For the life of me I cannot figure out a regex that will return 0 when a match is found and 1 when there is no match. Yes I could easily negate the entire statement but I was hoping to find a solution so that my code could stay tidy. Slightly OCD? yes, hope you can help, here's the PHP code. Be nice I am still learning. The code which I am hoping to change is in function passCheck variable $patternArray under the last element of the array. That is the pattern I have currently. I am hoping to return 0 when 2011-2016 is found in the string. I have looked into the looking ahead stuff and maybe its just late but I cant wrap my head around it (may not be the right approach).

<?php function digitsStr($pass)
     {
        $nums=array();
        $splt=str_split($pass);
        $count=count($splt);
        for($i=0;$count>$i;$i++)
        {
            if(preg_match("/\d/", $splt[$i])==1)
            {
                array_push($nums, $splt[$i]);
                unset($splt[$i]);
            }
        }
        $nums=array_merge($nums, $splt);
        $str=implode($nums);
        return $str;
    }
    ?>

    <?php function passCheck($string)
    {
        $string=digitsStr($string);
        $len=strlen($string);
        $msgArray=array("Must be 8-16 characters long ",
            "Cannot contain a white space ",
            "Does not contain at least 2 digits ",
            "Must contain at least 1 uppercase ",
            "Must contain at least 1 lowercase ",
            "Must contain one special charcter",
            "Cannot contain years 2011-2016");
        $patternArray=array("/^.{8,16}$/",
            "/\S{".$len."}/",
            "/\d{2,}/",
            "/[A-Z]/",
            "/[a-z]/",
            "/([!-\/]|[:-@])/",
            "/201(?![1-6])/");
        for($i=0;count($patternArray)>$i;$i++)
        {
            if(preg_match($patternArray[$i], $string)==0)
            {
                echo $msgArray[$i];
            }
        }
    }
    ?>

    <?php 
    $string="#M2010ATt123";
    passCheck($string)
    ?>

Solution

  • First of all, preg_match returns true or false, it doesn't return 0 or 1. Since PHP is weekly typed, this doesn't matter always, but it can. It is better to be aware of it.

    You should add to the logic that you can tell if a pattern must match or if it must not.

    Like this :

    $patternArray = array(
        array("/^.{8,16}$/", true),
        array("/\s/", false),
        array("/\d.*\d/", true), 
        array("/[A-Z]/", true), 
        array("/[a-z]/", true), 
        array("/([!-\/]|[:-@])/", true), 
        array("/201[1-6]/", false) 
    );   
    for($i=0;count($patternArray)>$i;$i++) {
        if(preg_match($patternArray[$i][0], $string) == $patternArray[$i][1])
    

    Note also that I corrected the pattern for 'at least 2 numbers'. Your pattern required that they followed each other. I changed the pattern for 'must not contain a space'. Like this you do not need an additional variable.