PHP项目个人资料修改如何开发功能

wen PHP项目 26

本文目录导读:

PHP项目个人资料修改如何开发功能

  1. 数据库设计
  2. 前端HTML表单
  3. 后端PHP处理
  4. JavaScript前端验证和AJAX提交
  5. 安全最佳实践
  6. 优化建议

我来详细介绍PHP项目中个人资料修改功能的开发流程和最佳实践。

数据库设计

用户表结构

CREATE TABLE `users` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `username` varchar(50) NOT NULL,
    `email` varchar(100) NOT NULL,
    `phone` varchar(20) DEFAULT NULL,
    `avatar` varchar(255) DEFAULT NULL,
    `bio` text DEFAULT NULL,
    `gender` enum('male','female','other') DEFAULT NULL,
    `birthday` date DEFAULT NULL,
    `website` varchar(255) DEFAULT NULL,
    `updated_at` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

前端HTML表单

<!-- profile/edit.php -->
<form id="profileForm" action="update_profile.php" method="POST" enctype="multipart/form-data">
    <div class="form-group">
        <label>头像</label>
        <div class="avatar-upload">
            <img src="<?php echo $user['avatar']; ?>" id="avatarPreview">
            <input type="file" name="avatar" accept="image/*" onchange="previewAvatar(this)">
        </div>
    </div>
    <div class="form-group">
        <label>用户名</label>
        <input type="text" name="username" value="<?php echo htmlspecialchars($user['username']); ?>" required>
    </div>
    <div class="form-group">
        <label>邮箱</label>
        <input type="email" name="email" value="<?php echo htmlspecialchars($user['email']); ?>" required>
    </div>
    <div class="form-group">
        <label>手机号</label>
        <input type="tel" name="phone" value="<?php echo htmlspecialchars($user['phone']); ?>">
    </div>
    <div class="form-group">
        <label>个人简介</label>
        <textarea name="bio" rows="4"><?php echo htmlspecialchars($user['bio']); ?></textarea>
    </div>
    <div class="form-group">
        <label>性别</label>
        <select name="gender">
            <option value="male" <?php echo $user['gender'] == 'male' ? 'selected' : ''; ?>>男</option>
            <option value="female" <?php echo $user['gender'] == 'female' ? 'selected' : ''; ?>>女</option>
            <option value="other" <?php echo $user['gender'] == 'other' ? 'selected' : ''; ?>>其他</option>
        </select>
    </div>
    <div class="form-group">
        <label>生日</label>
        <input type="date" name="birthday" value="<?php echo $user['birthday']; ?>">
    </div>
    <div class="form-group">
        <label>个人网站</label>
        <input type="url" name="website" value="<?php echo htmlspecialchars($user['website']); ?>">
    </div>
    <button type="submit">保存修改</button>
</form>

后端PHP处理

获取用户当前信息

// get_profile.php
session_start();
require_once 'db_connection.php';
$user_id = $_SESSION['user_id'];
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$user_id]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
return $user;

更新个人资料处理

// update_profile.php
<?php
session_start();
require_once 'db_connection.php';
header('Content-Type: application/json');
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $user_id = $_SESSION['user_id'];
    $errors = [];
    // 验证输入
    $username = trim($_POST['username'] ?? '');
    $email = trim($_POST['email'] ?? '');
    $phone = trim($_POST['phone'] ?? '');
    $bio = trim($_POST['bio'] ?? '');
    $gender = $_POST['gender'] ?? '';
    $birthday = $_POST['birthday'] ?? '';
    $website = trim($_POST['website'] ?? '');
    // 验证用户名
    if (empty($username)) {
        $errors[] = '用户名不能为空';
    }
    // 验证邮箱
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $errors[] = '邮箱格式不正确';
    }
    // 验证手机号(中国手机号)
    if (!empty($phone) && !preg_match('/^1[3-9]\d{9}$/', $phone)) {
        $errors[] = '手机号格式不正确';
    }
    // 验证网站URL
    if (!empty($website) && !filter_var($website, FILTER_VALIDATE_URL)) {
        $errors[] = '网站URL格式不正确';
    }
    // 检查用户名是否已存在
    $stmt = $pdo->prepare("SELECT id FROM users WHERE username = ? AND id != ?");
    $stmt->execute([$username, $user_id]);
    if ($stmt->fetch()) {
        $errors[] = '用户名已被使用';
    }
    // 检查邮箱是否已存在
    $stmt = $pdo->prepare("SELECT id FROM users WHERE email = ? AND id != ?");
    $stmt->execute([$email, $user_id]);
    if ($stmt->fetch()) {
        $errors[] = '邮箱已被使用';
    }
    if (!empty($errors)) {
        echo json_encode(['success' => false, 'errors' => $errors]);
        exit;
    }
    try {
        // 处理头像上传
        $avatar_path = null;
        if (isset($_FILES['avatar']) && $_FILES['avatar']['error'] === UPLOAD_ERR_OK) {
            $allowed_types = ['image/jpeg', 'image/png', 'image/gif'];
            $max_size = 2 * 1024 * 1024; // 2MB
            $file_info = finfo_open(FILEINFO_MIME_TYPE);
            $mime_type = finfo_file($file_info, $_FILES['avatar']['tmp_name']);
            finfo_close($file_info);
            if (!in_array($mime_type, $allowed_types)) {
                echo json_encode(['success' => false, 'errors' => ['只支持JPG、PNG、GIF格式的图片']]);
                exit;
            }
            if ($_FILES['avatar']['size'] > $max_size) {
                echo json_encode(['success' => false, 'errors' => ['图片大小不能超过2MB']]);
                exit;
            }
            // 生成唯一文件名
            $extension = pathinfo($_FILES['avatar']['name'], PATHINFO_EXTENSION);
            $filename = uniqid() . '_' . time() . '.' . $extension;
            $upload_dir = 'uploads/avatars/';
            if (!is_dir($upload_dir)) {
                mkdir($upload_dir, 0755, true);
            }
            $upload_path = $upload_dir . $filename;
            if (move_uploaded_file($_FILES['avatar']['tmp_name'], $upload_path)) {
                $avatar_path = $upload_path;
                // 删除旧头像
                $stmt = $pdo->prepare("SELECT avatar FROM users WHERE id = ?");
                $stmt->execute([$user_id]);
                $old_avatar = $stmt->fetchColumn();
                if ($old_avatar && file_exists($old_avatar)) {
                    unlink($old_avatar);
                }
            }
        }
        // 构建更新SQL
        $sql = "UPDATE users SET username = ?, email = ?, phone = ?, bio = ?, 
                gender = ?, birthday = ?, website = ?";
        $params = [$username, $email, $phone, $bio, $gender, $birthday, $website];
        if ($avatar_path) {
            $sql .= ", avatar = ?";
            $params[] = $avatar_path;
        }
        $sql .= ", updated_at = NOW() WHERE id = ?";
        $params[] = $user_id;
        $stmt = $pdo->prepare($sql);
        $stmt->execute($params);
        echo json_encode([
            'success' => true, 
            'message' => '个人资料更新成功',
            'avatar' => $avatar_path ?? null
        ]);
    } catch (PDOException $e) {
        echo json_encode(['success' => false, 'errors' => ['更新失败,请稍后重试']]);
    }
}
?>

JavaScript前端验证和AJAX提交

// profile.js
document.getElementById('profileForm').addEventListener('submit', function(e) {
    e.preventDefault();
    // 客户端验证
    const username = document.querySelector('[name="username"]').value;
    const email = document.querySelector('[name="email"]').value;
    const phone = document.querySelector('[name="phone"]').value;
    if (username.length < 2 || username.length > 20) {
        showError('用户名长度应在2-20个字符之间');
        return;
    }
    if (!isValidEmail(email)) {
        showError('请输入有效的邮箱地址');
        return;
    }
    if (phone && !isValidPhone(phone)) {
        showError('请输入有效的手机号');
        return;
    }
    // 显示加载状态
    const submitBtn = document.querySelector('button[type="submit"]');
    submitBtn.disabled = true;
    submitBtn.textContent = '保存中...';
    // 使用FormData处理文件上传
    const formData = new FormData(this);
    fetch('update_profile.php', {
        method: 'POST',
        body: formData
    })
    .then(response => response.json())
    .then(data => {
        if (data.success) {
            showSuccess('个人资料更新成功!');
            if (data.avatar) {
                document.getElementById('avatarPreview').src = data.avatar;
            }
        } else {
            showErrors(data.errors);
        }
    })
    .catch(error => {
        showError('网络错误,请稍后重试');
    })
    .finally(() => {
        submitBtn.disabled = false;
        submitBtn.textContent = '保存修改';
    });
});
// 头像预览
function previewAvatar(input) {
    if (input.files && input.files[0]) {
        const reader = new FileReader();
        reader.onload = function(e) {
            document.getElementById('avatarPreview').src = e.target.result;
        };
        reader.readAsDataURL(input.files[0]);
    }
}

安全最佳实践

防止XSS攻击

// 输出时转义HTML
function escapeHtml($string) {
    return htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
}

CSRF保护

// 生成CSRF Token
session_start();
if (empty($_SESSION['csrf_token'])) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
// 在表单中添加
echo '<input type="hidden" name="csrf_token" value="' . $_SESSION['csrf_token'] . '">';
// 验证CSRF Token
if (!hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
    die('CSRF token validation failed');
}

防止SQL注入

  • 使用PDO预处理语句(已实现)
  • 避免直接拼接SQL语句

优化建议

  1. 限流处理:限制用户频繁修改资料
  2. 操作日志:记录重要的资料修改操作
  3. 缓存更新:更新用户信息时清除相关缓存
  4. 异步处理:对头像等大文件进行异步处理

这是一个完整的个人资料修改功能实现,包含了前后端验证、文件处理、安全防护等关键功能,可以根据实际需求进行调整和扩展。

抱歉,评论功能暂时关闭!