PHP 完整表单实例

在本章节中,我们将创建一个完整的PHP表单实例,包含各种常见的表单字段类型、验证规则和数据处理逻辑。这个实例将演示如何构建一个功能齐全的用户注册表单。

完整表单功能概述

我们将创建一个包含以下功能的完整表单:

  • 用户基本信息(姓名、电子邮箱、密码)
  • 联系方式(电话号码、网站)
  • 用户偏好(性别、兴趣爱好)
  • 详细信息(关于我)
  • 完整的服务器端验证
  • 友好的错误提示和成功反馈
  • 表单数据的安全处理和展示

表单HTML结构

以下是表单的HTML结构:

<!DOCTYPE html>
<html>
<head>
<style>
.form-group {
    margin-bottom: 20px;
}

.form-group label {
    display: block;
    margin-bottom: 8px;
    font-weight: 500;
    color: #333;
}

.form-control {
    width: 100%;
    padding: 10px;
    border: 1px solid #ddd;
    border-radius: 4px;
    font-size: 14px;
    transition: border-color 0.3s ease;
}

.form-control:focus {
    border-color: #4F46E5;
    outline: none;
    box-shadow: 0 0 0 2px rgba(79, 70, 229, 0.2);
}

.error {
    color: #DC2626;
    font-size: 12px;
    margin-top: 4px;
    display: block;
}

.form-check {
    margin-bottom: 10px;
}

.form-check input {
    margin-right: 8px;
}

.btn {
    padding: 10px 20px;
    background-color: #4F46E5;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 14px;
    transition: background-color 0.3s ease;
}

.btn:hover {
    background-color: #4338CA;
}

.success-message {
    color: #059669;
    background-color: #d1fae5;
    padding: 12px;
    border-radius: 4px;
    margin-bottom: 20px;
}

.form-row {
    display: flex;
    gap: 20px;
}

.form-col {
    flex: 1;
}

@media (max-width: 768px) {
    .form-row {
        flex-direction: column;
    }
}
</style>
</head>
<body>

<h2>用户注册表单</h2>

<?php if (!empty($successMessage)): ?>
    <div class="success-message"><?php echo $successMessage; ?></div>
<?php endif; ?>

<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
    <div class="form-row">
        <div class="form-col">
            <div class="form-group">
                <label for="firstName">名字 *</label>
                <input type="text" class="form-control" id="firstName" name="firstName" value="<?php echo $firstName;?>">
                <span class="error"><?php echo $firstNameErr;?></span>
            </div>
        </div>
        <div class="form-col">
            <div class="form-group">
                <label for="lastName">姓氏 *</label>
                <input type="text" class="form-control" id="lastName" name="lastName" value="<?php echo $lastName;?>">
                <span class="error"><?php echo $lastNameErr;?></span>
            </div>
        </div>
    </div>
    
    <div class="form-group">
        <label for="email">电子邮箱 *</label>
        <input type="email" class="form-control" id="email" name="email" value="<?php echo $email;?>">
        <span class="error"><?php echo $emailErr;?></span>
    </div>
    
    <div class="form-group">
        <label for="password">密码 *</label>
        <input type="password" class="form-control" id="password" name="password">
        <span class="error"><?php echo $passwordErr;?></span>
    </div>
    
    <div class="form-group">
        <label for="confirmPassword">确认密码 *</label>
        <input type="password" class="form-control" id="confirmPassword" name="confirmPassword">
        <span class="error"><?php echo $confirmPasswordErr;?></span>
    </div>
    
    <div class="form-group">
        <label for="phone">电话号码</label>
        <input type="tel" class="form-control" id="phone" name="phone" value="<?php echo $phone;?>" placeholder="+86 123 4567 8901">
        <span class="error"><?php echo $phoneErr;?></span>
    </div>
    
    <div class="form-group">
        <label for="website">个人网站</label>
        <input type="url" class="form-control" id="website" name="website" value="<?php echo $website;?>" placeholder="https://www.example.com">
        <span class="error"><?php echo $websiteErr;?></span>
    </div>
    
    <div class="form-group">
        <label>性别</label>
        <div class="form-check">
            <input type="radio" id="male" name="gender" value="male" <?php if ($gender == "male") echo "checked";?>>
            <label for="male">男</label>
        </div>
        <div class="form-check">
            <input type="radio" id="female" name="gender" value="female" <?php if ($gender == "female") echo "checked";?>>
            <label for="female">女</label>
        </div>
        <div class="form-check">
            <input type="radio" id="other" name="gender" value="other" <?php if ($gender == "other") echo "checked";?>>
            <label for="other">其他</label>
        </div>
    </div>
    
    <div class="form-group">
        <label>兴趣爱好</label>
        <div class="form-check">
            <input type="checkbox" id="coding" name="interests[]" value="coding" <?php if (in_array("coding", $interests)) echo "checked";?>>
            <label for="coding">编程</label>
        </div>
        <div class="form-check">
            <input type="checkbox" id="reading" name="interests[]" value="reading" <?php if (in_array("reading", $interests)) echo "checked";?>>
            <label for="reading">阅读</label>
        </div>
        <div class="form-check">
            <input type="checkbox" id="music" name="interests[]" value="music" <?php if (in_array("music", $interests)) echo "checked";?>>
            <label for="music">音乐</label>
        </div>
        <div class="form-check">
            <input type="checkbox" id="sports" name="interests[]" value="sports" <?php if (in_array("sports", $interests)) echo "checked";?>>
            <label for="sports">运动</label>
        </div>
    </div>
    
    <div class="form-group">
        <label for="about">关于我</label>
        <textarea class="form-control" id="about" name="about" rows="5"><?php echo $about;?></textarea>
    </div>
    
    <div class="form-group">
        <input type="checkbox" id="agreeTerms" name="agreeTerms" <?php if ($agreeTerms) echo "checked";?>>
        <label for="agreeTerms">我同意网站的<a href="#">服务条款</a>和<a href="#">隐私政策</a> *</label>
        <span class="error"><?php echo $agreeTermsErr;?></span>
    </div>
    
    <p><span class="error">* 必填字段</span></p>
    <button type="submit" class="btn" name="submit">提交注册</button>
</form>

</body>
</html>

PHP表单验证和处理

以下是完整的PHP表单验证和处理代码:

<?php
// 定义变量并设置为空值
$firstName = $lastName = $email = $phone = $website = $gender = $about = "";
$password = $confirmPassword = "";
$agreeTerms = false;
$interests = array();

// 错误信息变量
$firstNameErr = $lastNameErr = $emailErr = $passwordErr = $confirmPasswordErr = "";
$phoneErr = $websiteErr = $agreeTermsErr = "";
$successMessage = "";

// 检查表单是否已提交
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    // 验证名字
    if (empty($_POST["firstName"])) {
        $firstNameErr = "名字是必填的";
    } else {
        $firstName = test_input($_POST["firstName"]);
        // 检查名字是否只包含字母和空格
        if (!preg_match("/^[a-zA-Z\s]+$", $firstName)) {
            $firstNameErr = "名字只能包含字母和空格";
        }
    }
    
    // 验证姓氏
    if (empty($_POST["lastName"])) {
        $lastNameErr = "姓氏是必填的";
    } else {
        $lastName = test_input($_POST["lastName"]);
        // 检查姓氏是否只包含字母和空格
        if (!preg_match("/^[a-zA-Z\s]+$", $lastName)) {
            $lastNameErr = "姓氏只能包含字母和空格";
        }
    }
    
    // 验证电子邮件
    if (empty($_POST["email"])) {
        $emailErr = "电子邮箱是必填的";
    } else {
        $email = test_input($_POST["email"]);
        // 检查电子邮件格式
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            $emailErr = "无效的电子邮箱格式";
        }
    }
    
    // 验证密码
    if (empty($_POST["password"])) {
        $passwordErr = "密码是必填的";
    } else {
        $password = $_POST["password"];
        // 密码强度验证(至少8位,包含字母和数字)
        if (strlen($password) < 8 || !preg_match("/[a-zA-Z]/", $password) || !preg_match("/[0-9]/", $password)) {
            $passwordErr = "密码至少需要8位,并且包含字母和数字";
        }
    }
    
    // 验证确认密码
    if (empty($_POST["confirmPassword"])) {
        $confirmPasswordErr = "请确认您的密码";
    } else {
        $confirmPassword = $_POST["confirmPassword"];
        // 检查两次密码是否一致
        if ($password != $confirmPassword) {
            $confirmPasswordErr = "两次输入的密码不一致";
        }
    }
    
    // 验证电话号码
    if (!empty($_POST["phone"])) {
        $phone = test_input($_POST["phone"]);
        // 简单的电话号码验证(支持国际格式)
        if (!preg_match("/^[+]?[0-9\s\-\(\)]{7,20}$/", $phone)) {
            $phoneErr = "无效的电话号码格式";
        }
    }
    
    // 验证网站URL
    if (!empty($_POST["website"])) {
        $website = test_input($_POST["website"]);
        // 检查URL是否包含协议,如果没有则添加http://
        if (!preg_match("/^https?:\/\//", $website)) {
            $website = "http://" . $website;
        }
        // 验证URL格式
        if (!filter_var($website, FILTER_VALIDATE_URL)) {
            $websiteErr = "无效的网站URL格式";
        }
    }
    
    // 获取性别
    if (isset($_POST["gender"])) {
        $gender = test_input($_POST["gender"]);
    }
    
    // 获取兴趣爱好
    if (isset($_POST["interests"])) {
        $interests = array_map('test_input', $_POST["interests"]);
    }
    
    // 获取关于我
    if (!empty($_POST["about"])) {
        $about = test_input($_POST["about"]);
    }
    
    // 验证是否同意条款
    if (!isset($_POST["agreeTerms"])) {
        $agreeTermsErr = "您必须同意服务条款和隐私政策";
    } else {
        $agreeTerms = true;
    }
    
    // 如果没有错误,处理表单数据
    if (empty($firstNameErr) && empty($lastNameErr) && empty($emailErr) && 
        empty($passwordErr) && empty($confirmPasswordErr) && empty($phoneErr) && 
        empty($websiteErr) && empty($agreeTermsErr)) {
            
        // 这里可以添加数据库存储逻辑
        // 为了示例,我们将简单地显示成功消息
        
        // 在实际应用中,您应该:
        // 1. 对密码进行哈希处理
        // $hashedPassword = password_hash($password, PASSWORD_DEFAULT);
        // 2. 将数据插入数据库
        // $sql = "INSERT INTO users (firstName, lastName, email, password, ...) VALUES (?, ?, ?, ?, ...)";
        
        $successMessage = "注册成功!欢迎加入我们," . $firstName . "!";
        
        // 重置表单数据(可选)
        // $firstName = $lastName = $email = $phone = $website = $gender = $about = "";
        // $password = $confirmPassword = "";
        // $agreeTerms = false;
        // $interests = array();
    }
}

// 清理输入数据的函数
function test_input($data) {
    $data = trim($data);
    $data = stripslashes($data);
    $data = htmlspecialchars($data);
    return $data;
}
?>

完整的PHP表单代码

将上述HTML和PHP代码组合在一起,就得到了完整的PHP表单实例:

<?php
// 定义变量并设置为空值
$firstName = $lastName = $email = $phone = $website = $gender = $about = "";
$password = $confirmPassword = "";
$agreeTerms = false;
$interests = array();

// 错误信息变量
$firstNameErr = $lastNameErr = $emailErr = $passwordErr = $confirmPasswordErr = "";
$phoneErr = $websiteErr = $agreeTermsErr = "";
$successMessage = "";

// 检查表单是否已提交
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    // 验证名字
    if (empty($_POST["firstName"])) {
        $firstNameErr = "名字是必填的";
    } else {
        $firstName = test_input($_POST["firstName"]);
        // 检查名字是否只包含字母和空格
        if (!preg_match("/^[a-zA-Z\s]+$", $firstName)) {
            $firstNameErr = "名字只能包含字母和空格";
        }
    }
    
    // 验证姓氏
    if (empty($_POST["lastName"])) {
        $lastNameErr = "姓氏是必填的";
    } else {
        $lastName = test_input($_POST["lastName"]);
        // 检查姓氏是否只包含字母和空格
        if (!preg_match("/^[a-zA-Z\s]+$", $lastName)) {
            $lastNameErr = "姓氏只能包含字母和空格";
        }
    }
    
    // 验证电子邮件
    if (empty($_POST["email"])) {
        $emailErr = "电子邮箱是必填的";
    } else {
        $email = test_input($_POST["email"]);
        // 检查电子邮件格式
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            $emailErr = "无效的电子邮箱格式";
        }
    }
    
    // 验证密码
    if (empty($_POST["password"])) {
        $passwordErr = "密码是必填的";
    } else {
        $password = $_POST["password"];
        // 密码强度验证(至少8位,包含字母和数字)
        if (strlen($password) < 8 || !preg_match("/[a-zA-Z]/", $password) || !preg_match("/[0-9]/", $password)) {
            $passwordErr = "密码至少需要8位,并且包含字母和数字";
        }
    }
    
    // 验证确认密码
    if (empty($_POST["confirmPassword"])) {
        $confirmPasswordErr = "请确认您的密码";
    } else {
        $confirmPassword = $_POST["confirmPassword"];
        // 检查两次密码是否一致
        if ($password != $confirmPassword) {
            $confirmPasswordErr = "两次输入的密码不一致";
        }
    }
    
    // 验证电话号码
    if (!empty($_POST["phone"])) {
        $phone = test_input($_POST["phone"]);
        // 简单的电话号码验证(支持国际格式)
        if (!preg_match("/^[+]?[0-9\s\-\(\)]{7,20}$/", $phone)) {
            $phoneErr = "无效的电话号码格式";
        }
    }
    
    // 验证网站URL
    if (!empty($_POST["website"])) {
        $website = test_input($_POST["website"]);
        // 检查URL是否包含协议,如果没有则添加http://
        if (!preg_match("/^https?:\/\//", $website)) {
            $website = "http://" . $website;
        }
        // 验证URL格式
        if (!filter_var($website, FILTER_VALIDATE_URL)) {
            $websiteErr = "无效的网站URL格式";
        }
    }
    
    // 获取性别
    if (isset($_POST["gender"])) {
        $gender = test_input($_POST["gender"]);
    }
    
    // 获取兴趣爱好
    if (isset($_POST["interests"])) {
        $interests = array_map('test_input', $_POST["interests"]);
    }
    
    // 获取关于我
    if (!empty($_POST["about"])) {
        $about = test_input($_POST["about"]);
    }
    
    // 验证是否同意条款
    if (!isset($_POST["agreeTerms"])) {
        $agreeTermsErr = "您必须同意服务条款和隐私政策";
    } else {
        $agreeTerms = true;
    }
    
    // 如果没有错误,处理表单数据
    if (empty($firstNameErr) && empty($lastNameErr) && empty($emailErr) && 
        empty($passwordErr) && empty($confirmPasswordErr) && empty($phoneErr) && 
        empty($websiteErr) && empty($agreeTermsErr)) {
            
        // 这里可以添加数据库存储逻辑
        // 为了示例,我们将简单地显示成功消息
        
        // 在实际应用中,您应该:
        // 1. 对密码进行哈希处理
        // $hashedPassword = password_hash($password, PASSWORD_DEFAULT);
        // 2. 将数据插入数据库
        // $sql = "INSERT INTO users (firstName, lastName, email, password, ...) VALUES (?, ?, ?, ?, ...)";
        
        $successMessage = "注册成功!欢迎加入我们," . $firstName . "!";
        
        // 重置表单数据(可选)
        // $firstName = $lastName = $email = $phone = $website = $gender = $about = "";
        // $password = $confirmPassword = "";
        // $agreeTerms = false;
        // $interests = array();
    }
}

// 清理输入数据的函数
function test_input($data) {
    $data = trim($data);
    $data = stripslashes($data);
    $data = htmlspecialchars($data);
    return $data;
}
?>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户注册表单</title>
<style>
.form-group {
    margin-bottom: 20px;
}

.form-group label {
    display: block;
    margin-bottom: 8px;
    font-weight: 500;
    color: #333;
}

.form-control {
    width: 100%;
    padding: 10px;
    border: 1px solid #ddd;
    border-radius: 4px;
    font-size: 14px;
    transition: border-color 0.3s ease;
}

.form-control:focus {
    border-color: #4F46E5;
    outline: none;
    box-shadow: 0 0 0 2px rgba(79, 70, 229, 0.2);
}

.error {
    color: #DC2626;
    font-size: 12px;
    margin-top: 4px;
    display: block;
}

.form-check {
    margin-bottom: 10px;
}

.form-check input {
    margin-right: 8px;
}

.btn {
    padding: 10px 20px;
    background-color: #4F46E5;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 14px;
    transition: background-color 0.3s ease;
}

.btn:hover {
    background-color: #4338CA;
}

.success-message {
    color: #059669;
    background-color: #d1fae5;
    padding: 12px;
    border-radius: 4px;
    margin-bottom: 20px;
}

.form-row {
    display: flex;
    gap: 20px;
}

.form-col {
    flex: 1;
}

@media (max-width: 768px) {
    .form-row {
        flex-direction: column;
    }
}
</style>
</head>
<body>

<h2>用户注册表单</h2>

<?php if (!empty($successMessage)): ?>
    <div class="success-message"><?php echo $successMessage; ?></div>
<?php endif; ?>

<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
    <div class="form-row">
        <div class="form-col">
            <div class="form-group">
                <label for="firstName">名字 *</label>
                <input type="text" class="form-control" id="firstName" name="firstName" value="<?php echo $firstName;?>">
                <span class="error"><?php echo $firstNameErr;?></span>
            </div>
        </div>
        <div class="form-col">
            <div class="form-group">
                <label for="lastName">姓氏 *</label>
                <input type="text" class="form-control" id="lastName" name="lastName" value="<?php echo $lastName;?>">
                <span class="error"><?php echo $lastNameErr;?></span>
            </div>
        </div>
    </div>
    
    <div class="form-group">
        <label for="email">电子邮箱 *</label>
        <input type="email" class="form-control" id="email" name="email" value="<?php echo $email;?>">
        <span class="error"><?php echo $emailErr;?></span>
    </div>
    
    <div class="form-group">
        <label for="password">密码 *</label>
        <input type="password" class="form-control" id="password" name="password">
        <span class="error"><?php echo $passwordErr;?></span>
    </div>
    
    <div class="form-group">
        <label for="confirmPassword">确认密码 *</label>
        <input type="password" class="form-control" id="confirmPassword" name="confirmPassword">
        <span class="error"><?php echo $confirmPasswordErr;?></span>
    </div>
    
    <div class="form-group">
        <label for="phone">电话号码</label>
        <input type="tel" class="form-control" id="phone" name="phone" value="<?php echo $phone;?>" placeholder="+86 123 4567 8901">
        <span class="error"><?php echo $phoneErr;?></span>
    </div>
    
    <div class="form-group">
        <label for="website">个人网站</label>
        <input type="url" class="form-control" id="website" name="website" value="<?php echo $website;?>" placeholder="https://www.example.com">
        <span class="error"><?php echo $websiteErr;?></span>
    </div>
    
    <div class="form-group">
        <label>性别</label>
        <div class="form-check">
            <input type="radio" id="male" name="gender" value="male" <?php if ($gender == "male") echo "checked";?>>
            <label for="male">男</label>
        </div>
        <div class="form-check">
            <input type="radio" id="female" name="gender" value="female" <?php if ($gender == "female") echo "checked";?>>
            <label for="female">女</label>
        </div>
        <div class="form-check">
            <input type="radio" id="other" name="gender" value="other" <?php if ($gender == "other") echo "checked";?>>
            <label for="other">其他</label>
        </div>
    </div>
    
    <div class="form-group">
        <label>兴趣爱好</label>
        <div class="form-check">
            <input type="checkbox" id="coding" name="interests[]" value="coding" <?php if (in_array("coding", $interests)) echo "checked";?>>
            <label for="coding">编程</label>
        </div>
        <div class="form-check">
            <input type="checkbox" id="reading" name="interests[]" value="reading" <?php if (in_array("reading", $interests)) echo "checked";?>>
            <label for="reading">阅读</label>
        </div>
        <div class="form-check">
            <input type="checkbox" id="music" name="interests[]" value="music" <?php if (in_array("music", $interests)) echo "checked";?>>
            <label for="music">音乐</label>
        </div>
        <div class="form-check">
            <input type="checkbox" id="sports" name="interests[]" value="sports" <?php if (in_array("sports", $interests)) echo "checked";?>>
            <label for="sports">运动</label>
        </div>
    </div>
    
    <div class="form-group">
        <label for="about">关于我</label>
        <textarea class="form-control" id="about" name="about" rows="5"><?php echo $about;?></textarea>
    </div>
    
    <div class="form-group">
        <input type="checkbox" id="agreeTerms" name="agreeTerms" <?php if ($agreeTerms) echo "checked";?>>
        <label for="agreeTerms">我同意网站的<a href="#">服务条款</a>和<a href="#">隐私政策</a> *</label>
        <span class="error"><?php echo $agreeTermsErr;?></span>
    </div>
    
    <p><span class="error">* 必填字段</span></p>
    <button type="submit" class="btn" name="submit">提交注册</button>
</form>

</body>
</html>

数据安全最佳实践

在处理表单数据时,请务必遵循以下安全最佳实践:

  • 始终验证所有用户输入:永远不要信任用户输入的数据,始终在服务器端进行验证。
  • 对密码进行哈希处理:不要以明文形式存储密码,使用password_hash()函数对密码进行哈希处理。
  • 防止SQL注入:使用预处理语句或参数化查询来防止SQL注入攻击。
  • 防止XSS攻击:使用htmlspecialchars()函数对用户输入进行转义,以防止跨站脚本攻击。
  • 使用HTTPS:在传输敏感数据时,始终使用HTTPS协议来加密数据。
  • 实施CSRF保护:使用CSRF令牌来防止跨站请求伪造攻击。
  • 限制文件上传:如果表单允许文件上传,请限制文件类型和大小。

提示:在实际项目中,您可能需要将表单处理逻辑和HTML展示逻辑分离,遵循MVC(模型-视图-控制器)设计模式,这将使您的代码更加清晰、可维护和可测试。