我可以做什么来代替多个If语句?PHP寄存器脚本

我可以做什么来代替多个If语句?PHP寄存器脚本,php,if-statement,sql-injection,statements,Php,If Statement,Sql Injection,Statements,正如您在下面的脚本中所看到的,我在检查注册输入时使用了多个if语句。有更简单、更少的意大利面吗 脚本按原样工作,但我希望它更整洁 <?php if (isset($_POST['register'])) { $uname = trim($_POST['uName']); $email = trim($_POST['email']); $pass = trim($_POST['pass']); $passCon = trim($_POST['passCon

正如您在下面的脚本中所看到的,我在检查注册输入时使用了多个if语句。有更简单、更少的意大利面吗

脚本按原样工作,但我希望它更整洁

<?php

if (isset($_POST['register'])) {

    $uname = trim($_POST['uName']);
    $email = trim($_POST['email']);
    $pass = trim($_POST['pass']);
    $passCon = trim($_POST['passCon']);

    $uname = strip_tags($uname);
    $email = strip_tags($email);
    $pass = strip_tags($pass);
    $passCon = strip_tags($passCon);

    if (!empty($pass)) {
        if (!empty($email)) {
            if (!empty($uname)) {
                if ($pass == $passCon) {

                    $query = "SELECT username FROM users WHERE username='$uname'";
                    $result = mysqli_query($conn, $query);
                    $checkUsername = mysqli_num_rows($result);

                    if ($checkUsername == 0) {

                        $query = "SELECT email FROM users WHERE email='$email'";
                        $result = mysqli_query($conn, $query);
                        $count = mysqli_num_rows($result);

                        if ($count == 0) {

                            $password = hash('sha256', $pass);
                            $queryInsert = "INSERT INTO users(id, username, email, password, date) VALUES('', '$uname', '$email', '$password', '" . time() . "')";
                            $res = mysqli_query($conn, $queryInsert);

                            if ($res) {
                                $errTyp = "success";
                                $errMsg = "successfully registered, you may login now";
                            }
                        } else {
                            $errTyp = "warning";
                            $errMsg = "Sorry Email already in use";
                        }
                    } else {
                        $errTyp = "warning";
                        $errMsg = "Sorry Username already in use";
                    }
                } else {
                    $errTyp = "warning";
                    $errMsg = "Passwords didn't match";
                }
            } else {
                $errTyp = "warning";
                $errMsg = "You didn't enter a Username";
            }
        } else {
            $errTyp = "warning";
            $errMsg = "You didn't enter an email address";
        }
    } else {
        $errTyp = "warning";
        $errMsg = "You didn't enter a password";
    }
}

您面临的问题并不罕见。许多程序员都面临过这个问题。让我来帮你重组剧本

首先,让我们去掉嵌套的
if-else
语句。他们混淆和混淆了真正发生的事情

第1版:

if (!isset($_POST['register']))
    redirect('register.php'); // Let's assume that redirect() redirects the user to a different web page and exit()s the script.

$uname = $_POST['uName'];
$email = $_POST['email'];
$pass = $_POST['pass'];
$passRepeat = $_POST['passRepeat'];

if (empty($pass)) {
    $errorMessage = "You didn't enter a password";
}

if (empty($email)) {
    $errorMessage = "You didn't enter an email address";
}

if (empty($uname)) {
    $errorMessage = "You didn't enter a Username";
}

if ($pass !== $passRepeat) {
    $errMsg = "Passwords didn't match";
}

$query = "SELECT username FROM users WHERE username='$uname'";
$result = mysqli_query($conn, $query);
$checkUsername = mysqli_num_rows($result);

if ($checkUsername !== 0) {
    $errMsg = 'Sorry Username already in use';
}

$query = "SELECT email FROM users WHERE email='$email'";
$result = mysqli_query($conn, $query);
$count = mysqli_num_rows($result);

if ($count !== 0) {
    $errMsg = 'Sorry Email already in use';
}

$password = hash('sha256', $pass);
$queryInsert = "INSERT INTO users(id, username, email, password, date) VALUES('', '$uname', '$email', '$password', '" . time() . "')";
$res = mysqli_query($conn, $queryInsert);
请注意,尽管这避免了嵌套的if语句,但这与原始代码不同,因为错误会消失。让我们来解决这个问题。当我们这样做时,为什么要在第一个错误发生后返回?让我们立即返回所有错误

第2版:

$errors = array();

if (empty($pass)) {
    $errors[] = "You didn't enter a password";
}

if (empty($email)) {
    $errors[] = "You didn't enter an email address";
}

if (empty($uname)) {
    $errors[] = "You didn't enter a username";
}

if ($pass !== $passRepeat) {
    $errors[] = "Passwords didn't match";
}

$query = "SELECT username FROM users WHERE username='$uname'";
$result = mysqli_query($conn, $query);
$usernameExists = mysqli_num_rows($result) > 0;

if ($usernameExists) {
    $errors[] = 'Sorry Username already in use';
}

$query = "SELECT email FROM users WHERE email='$email'";
$result = mysqli_query($conn, $query);
$emailExists = mysqli_num_rows($result) > 0;

if ($emailExists) {
    $errors[] = 'Sorry Email already in use';
}

if (count($errors) === 0) {
    $password = hash('sha256', $pass);
    $queryInsert = "INSERT INTO users(id, username, email, password, date) VALUES('', '$uname', '$email', '$password', '" . time() . "')";
    $res = mysqli_query($conn, $queryInsert);

    redirect('register_success.php');
} else {
    render_errors($errors);
}
到目前为止相当干净!注意,我们可以用for循环替换
if(empty($var))
语句。然而,我认为在这种情况下,这是过分的


作为旁注,请记住此代码易受攻击。解决该问题超出了问题的范围。

您面临的问题并不罕见。许多程序员都面临过这个问题。让我来帮你重组剧本

首先,让我们去掉嵌套的
if-else
语句。他们混淆和混淆了真正发生的事情

第1版:

if (!isset($_POST['register']))
    redirect('register.php'); // Let's assume that redirect() redirects the user to a different web page and exit()s the script.

$uname = $_POST['uName'];
$email = $_POST['email'];
$pass = $_POST['pass'];
$passRepeat = $_POST['passRepeat'];

if (empty($pass)) {
    $errorMessage = "You didn't enter a password";
}

if (empty($email)) {
    $errorMessage = "You didn't enter an email address";
}

if (empty($uname)) {
    $errorMessage = "You didn't enter a Username";
}

if ($pass !== $passRepeat) {
    $errMsg = "Passwords didn't match";
}

$query = "SELECT username FROM users WHERE username='$uname'";
$result = mysqli_query($conn, $query);
$checkUsername = mysqli_num_rows($result);

if ($checkUsername !== 0) {
    $errMsg = 'Sorry Username already in use';
}

$query = "SELECT email FROM users WHERE email='$email'";
$result = mysqli_query($conn, $query);
$count = mysqli_num_rows($result);

if ($count !== 0) {
    $errMsg = 'Sorry Email already in use';
}

$password = hash('sha256', $pass);
$queryInsert = "INSERT INTO users(id, username, email, password, date) VALUES('', '$uname', '$email', '$password', '" . time() . "')";
$res = mysqli_query($conn, $queryInsert);
请注意,尽管这避免了嵌套的if语句,但这与原始代码不同,因为错误会消失。让我们来解决这个问题。当我们这样做时,为什么要在第一个错误发生后返回?让我们立即返回所有错误

第2版:

$errors = array();

if (empty($pass)) {
    $errors[] = "You didn't enter a password";
}

if (empty($email)) {
    $errors[] = "You didn't enter an email address";
}

if (empty($uname)) {
    $errors[] = "You didn't enter a username";
}

if ($pass !== $passRepeat) {
    $errors[] = "Passwords didn't match";
}

$query = "SELECT username FROM users WHERE username='$uname'";
$result = mysqli_query($conn, $query);
$usernameExists = mysqli_num_rows($result) > 0;

if ($usernameExists) {
    $errors[] = 'Sorry Username already in use';
}

$query = "SELECT email FROM users WHERE email='$email'";
$result = mysqli_query($conn, $query);
$emailExists = mysqli_num_rows($result) > 0;

if ($emailExists) {
    $errors[] = 'Sorry Email already in use';
}

if (count($errors) === 0) {
    $password = hash('sha256', $pass);
    $queryInsert = "INSERT INTO users(id, username, email, password, date) VALUES('', '$uname', '$email', '$password', '" . time() . "')";
    $res = mysqli_query($conn, $queryInsert);

    redirect('register_success.php');
} else {
    render_errors($errors);
}
到目前为止相当干净!注意,我们可以用for循环替换
if(empty($var))
语句。然而,我认为在这种情况下,这是过分的

作为旁注,请记住此代码易受攻击。解决这个问题超出了问题的范围。

少点意大利面?从功能分解开始,然后将环境卫生任务与验证任务分离。我将省略我所采取的许多步骤(例如验证/$\u POST/filter\u input\u array()形式是否具有正确的输入数量,以及正确的键是否位于$\u POST superglobal/input\u POST中,等等,您可能需要考虑一下)。根据你的具体需要改变我的一些技巧。之后你的节目应该少点意大利面。:-)

消毒然后验证。可以说,你必须让他们分开

功能分解消毒

使单个任务成为自己的代码块

如果所有表单字段的所有清理步骤(trim()、strip_tags()等)都相同,则创建一个清理器函数来执行该操作。请注意,只需使用一个循环,即可改进修剪和剥离标记的一次性方法。将原始值保存在变量中,然后在while循环中进行trim()、strip_tags()等操作将结果与原始结果进行比较。如果它们是相同的,则断开。如果它们不同,请再次将表单字段的当前值保存在变量中,并让循环再次运行

function sanitize($formValue)
{
    $oldValue = $formValue;

    do
    {
        $formValue = trim($formValue);
        $formValue = strip_tags($formValue);

        //Anything else you want to do.

        $formValue = trim($formValue);

        if($formValue === $oldValue)
        {
            break;
        }

        $oldValue = $formValue;
    }
    while(1); //Infinite loop

    return $formValue;
}
然后,只需在循环中运行此函数

$sanitized = [];

foreach($_POST as $key => $value)
{
    $sanitized[$key] = sanitize($value);
}

/* You can keep track your variable anyway you want.*/
再往前看,设计基于输入源($\u POST、$\u GET、$\u SESSION、$\u文件、$\u COOKIE等)的清理、类层次结构真的很方便。此外,基于filter\u input\u array()使用的类层次结构确实让您在游戏中处于领先地位。验证呢

通过功能分解进行验证

您可以将每个表单字段视为需要自己的验证功能。然后,块中只包含检查一个表单字段所需的逻辑。关键是,让验证器函数返回测试结果(真/假),从而保留布尔逻辑

在PHP中,可以使用变量函数将函数命名为与它们检查的字段相同的名称。所以,要执行这些验证器,只需这样做

$errorMsgs = [];

foreach($sanitized as $key => $value)
{
    $key($value, $errorMsgs[$key])
}
然后,一般来说,您只需要查看$errorMsgs数组中是否存在任何错误。通过处理$errorMsgs数组来实现这一点

$error = false;

foreach($errorMsgs as $key => $value)
{
    if(isset($value))
    {
         //There is an error in the $key field
         $error = true;
    }
}


..and then.

if($error === true)
{
     //Prompt user in some way and terminate processing.
}

// Send email, login, etc ....
进一步说,您可以创建一个通用的、验证器的、超类

所有这些都在说。我以一种面向对象的方式进行所有清理和验证,以减少代码重复。Sanitizer超类有子类(PostSanitizer、GetSanitizer等)。验证器超类具有可以对字符串、整数或浮点执行的所有测试。验证器超类的子类是特定于页面/表单的。但是,当需要表单令牌之类的东西时,它的验证方法可以在Validator超类中找到,因为它可以在任何表单上使用

一个好的验证程序可以跟踪:

1) 在关联数组中输入值

2) 关联数组中的测试结果(布尔值)。测试结果(真/假)可以转换为CSS类或“1”和“0”的JSON字符串

3) 关联数组中的错误消息

…然后根据测试结果(按键)最终决定如何处理输入值和/或错误消息。如果存在错误(假设测试结果数组中的值为false),请使用具有相应键的错误消息

我前面的示例将最终的错误检查和错误消息数据结构压缩为一个数组,但是使用单独的数据结构允许更大的灵活性(将错误消息与检测到的错误分离)。只需像这样将每个验证变量函数的结果存储到
$testResults
数组中即可

function sanitize($formValue)
{
    $oldValue = $formValue;

    do
    {
        $formValue = trim($formValue);
        $formValue = strip_tags($formValue);

        //Anything else you want to do.

        $formValue = trim($formValue);

        if($formValue === $oldValue)
        {
            break;
        }

        $oldValue = $formValue;
    }
    while(1); //Infinite loop

    return $formValue;
}

$sanitized = [];

foreach($_POST as $key => $value)
{
    $sanitized[$key] = sanitize($value);
}

$testResults = [];
$errorMsgs = [];

foreach($sanitized as $key => $value)
{
    $testResults[$key] = $key($value, $errorMsgs[$key])
}

if(!in_array(false, $testResults, true))
{
     return true  //Assuming that, ultimately, you need to know if everything worked or not, and will take action on this elsewhere. It's up to you to make the correct functions/methods, but this general foundation can get you going.
}

return false; //Obviously. Do not submit the form. Show the errors (CSS and error messages).
然后,只需检查
$testResults
数组中是否存在
false
。使用专用程序从$errorMsgs获取相应的错误消息