为什么我的函数内的正则表达式在 PHP 中不起作用?

Why my regex inside a function doesn't work in PHP?

我必须验证我表单中的一些数据,其中 none 有效,但我想要一些 用户名验证方面的帮助 希望我能修复其他问题稍后解决。

这是我的表格,没什么异常:

<form action="inscription_traitement.php" method="post">
    <label>Nom d'utilisateur : </label><br/>
    <input type="text" name="username"/>
    <label>Adresse e-mail : </label><br/>
    <input type="text" name="mail"/>
    <label>Mot de passe : </label><br/>
    <input type="password" name="password"/>
    <label>Répétez votre mot de passe : </label><br/>
    <input type="password" name="password_r"/>
    <input type="submit" name="submit" value="S'inscrire"/><input type="reset" value="Annuler"/>
</form>

然后重定向到我的验证文件(问题在invalidUsername()):

<?php
if (isset($_POST["submit"])){
    
    $username = $_POST["username"];
    $mail = $_POST["mail"];
    $password = $_POST["password"];
    $password_r = $_POST["password_r"];
    

    require_once "database_connection.php";
    require_once "functions.php";


    // Here is the problem
    if(invalidUsername($username) !== false){
        header("Location: inscription.php?error=invalid_username");
        exit();
    }
    if(usernameExists($db, $username) !== false){
        header("Location: inscription.php?error=username_exists");
        exit();
    }
    if(invalidMail($mail) !== false){
        header("Location: inscription.php?error=invalid_mail");
        exit();
    }
    if(mailExists($db, $mail) !== false){
        header("Location: inscription.php?error=mail_exists");
        exit();
    }
    if(invalidPassword($password) !== false){
        header("Location: inscription.php?error=invalid_password");
        exit();
    }
    if (passwordMatch($password, $password_r) !== false){
        header("Location: inscription.php?error=password_match");
        exit();
    }

    createUser($db, $username, $mail, $password);
}
else{
    header("location: inscription.php");
}?>

最后我创建了一个 文件,重新组合了我所有的函数 ,我们感兴趣的是 invalidUsername():

<?php

// here is the problem
function invalidUsername($username){
    $usernameRegex = "/[A-Za-z0-9-_]{5,15}/";
    if(!preg_match($usernameRegex, $username)){
        return true;
    }else{
        return false;
    }
}

function usernameExists($db, $username){
    $username = mysql_real_escape_string($username);
    $query = mysql_query("SELECT * FROM player WHERE p_username = ".$username.";");
    try{
        $stmt = $db->prepare($query);
        $stmt->execute();
    }catch(PDOException $e){
        header("Location: inscription.php?error=\".$e.\"");
        return true;
    }
    return false;
}

function invalidMail($mail){
    if(!filter_var($mail, FILTER_VALIDATE_EMAIL)){
        return true;
    }else{
        return false;
    }
}

function mailExists($db, $mail){
    $query = "SELECT * FROM player WHERE p_mail_adress = ?;";
    $stmt = $db->prepare($query);
    try{
        $stmt->execute(array($mail));
    }catch(Exception $e){
        header("Location: inscription.php?error=stmt_error");
        return true;
    }
    return false;
}

function invalidPassword($password){
    $passwordRegex = "/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,20}$/";
    if(!preg_match($passwordRegex, $password)){
        return true;
    }else{
        return false;
    }
}

function passwordMatch($password, $password_r){
    if($password != $password_r){
        return true;
    }else{
        return false;
    }
}

function createUser($db, $username, $mail, $password){
    $ip_adress = $_SERVER['REMOTE_ADDR'];
    $query = "INSERT INTO player(p_username, p_mail_adress, p_password, p_ip, p_score, p_is_online) VALUES(?, ?, ?, ?, ?, ?);";
    $stmt = $db->prepare($query);
    try{
        $stmt->execute(array($username, $mail, $password, $ip_adress, 0, 0));
    }catch(Exception $e){
        header("Location: inscription.php?error=$e");
    }
    header("Location: inscription.php?bienvenu");
}?>

问题如下:invalidUsername() 函数return me true (意思是验证没有通过) 一直,即使我在我的用户名字段中输入了正确的数据。我在线尝试了我的正则表达式并且它有效。我不明白我哪里搞砸了,逻辑对我来说似乎很好。

如果对你有帮助,我用的是Easyphp Devserver 17

破折号匹配字符 从 X 到 Y:

a-z = 从“a”到“z”的匹配
0-9 = 匹配从“0”到“9”

最后一个破折号的解释方式相同:

9-_ = 从“9”匹配到“_”

这显然是胡说八道。您可以通过将破折号放在末尾来解决此问题。

/[A-Za-z0-9_-]{5,15}/

正则表达式:

[0-9]  # A single digit
[_]    # An underscore 
[0-9]  # A single digit

根据 PHP 手册:

preg_match() returns 1 if the pattern matches given subject, 0 if it does not, or false on failure.

在线推荐 preg_match 小编: https://www.phpliveregex.com/#tab-preg-match

这将解决您的问题。我无法验证您提供的字符串参数。

有两个问题:

  • 字符 class 中的连字符放置在最新的 PHP 版本中是严格的,它应该位于模式的开头或结尾以避免任何问题
  • 模式必须被锚定,即它必须匹配整个字符串,否则,{5,15} 限制量词没有意义。

你需要使用

function invalidUsername($username){
    $usernameRegex = "/^[\w-]{5,15}$/D";
    return (bool)preg_match($usernameRegex, $username));
}

详情:

  • ^ - 字符串开头
  • [\w-]{5,15} - 五到十五个 ASCII 字母、数字、下划线或连字符
  • $ - 字符串结尾
  • D - 该标志表示字符串结尾 $ 锚点仅匹配字符串结尾。

在你的帮助下我找到了解决方案。在我的验证文件中,我调用了“database_connection.php”,变量 $username 和 $password 覆盖了我在验证文件中的变量:

<?php
    $hostname  = "localhost";
    $database   = "db_name";
    $username  = "root";
    $password   = "";
    try
    {
        $db = new PDO('mysql:host='.$hostname.';dbname='.$database, $username, $password);    
    }
    catch(Exception $e)
    {
        die('Erreur : '.$e->getMessage());
    }
?>

只有一件事要做:
更改我的“database_connection.php”中的变量名称:

$db_username  = "root";
$db_password   = "";

或者你可以在你的函数中重新定义你的变量,不推荐这样做:

<?php
     $username = $_POST["username"];
     function invalidUsername($username){
          $usernameRegex = "/^[\w-]{5,15}$/D";
          return (bool)preg_match($usernameRegex, $username);
     }
?>