PHP 怎么存储动态表单

wen PHP项目 3

本文目录导读:

PHP 怎么存储动态表单

  1. JSON 存储(最推荐)
  2. EAV 模型(实体-属性-值)
  3. 动态表结构(适合固定字段集)
  4. 混合方案(推荐用于复杂系统)
  5. 推荐方案选择

在 PHP 中存储动态表单有几种常见方案,我来详细说明:

JSON 存储(最推荐)

<?php
// 动态表单数据存储
class DynamicFormStorage {
    // 保存动态表单数据
    public function saveFormData($formData, $userId) {
        // 将动态字段转换为 JSON
        $jsonData = json_encode($formData);
        // 方法1:存入文件
        file_put_contents("forms/user_{$userId}.json", $jsonData);
        // 方法2:存入数据库(文本字段)
        $pdo = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
        $stmt = $pdo->prepare("INSERT INTO dynamic_forms (user_id, form_data, created_at) VALUES (?, ?, NOW())");
        $stmt->execute([$userId, $jsonData]);
        return $jsonData;
    }
    // 读取动态表单数据
    public function getFormData($formId) {
        $pdo = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
        $stmt = $pdo->prepare("SELECT form_data FROM dynamic_forms WHERE id = ?");
        $stmt->execute([$formId]);
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        // 将 JSON 解码为数组
        return json_decode($row['form_data'], true);
    }
}
// 使用示例
$formData = [
    'field1' => 'value1',
    'custom_field1' => '自定义值1',
    'custom_field2' => '自定义值2',
    'created_at' => date('Y-m-d H:i:s')
];
$storage = new DynamicFormStorage();
$storage->saveFormData($formData, 1);
?>

EAV 模型(实体-属性-值)

<?php
// 数据库表结构
/*
CREATE TABLE form_submissions (
    submission_id INT PRIMARY KEY AUTO_INCREMENT,
    form_id INT,
    user_id INT,
    created_at TIMESTAMP
);
CREATE TABLE form_submission_values (
    id INT PRIMARY KEY AUTO_INCREMENT,
    submission_id INT,
    field_name VARCHAR(255),
    field_value TEXT
);
*/
class EAVFormStorage {
    private $pdo;
    public function __construct($pdo) {
        $this->pdo = $pdo;
    }
    public function saveForm($formData, $userId) {
        try {
            // 开启事务
            $this->pdo->beginTransaction();
            // 创建主记录
            $stmt = $this->pdo->prepare("INSERT INTO form_submissions (user_id) VALUES (?)");
            $stmt->execute([$userId]);
            $submissionId = $this->pdo->lastInsertId();
            // 插入每个字段
            $stmt = $this->pdo->prepare("INSERT INTO form_submission_values 
                (submission_id, field_name, field_value) VALUES (?, ?, ?)");
            foreach ($formData as $fieldName => $fieldValue) {
                if (is_array($fieldValue)) {
                    $fieldValue = json_encode($fieldValue);
                }
                $stmt->execute([$submissionId, $fieldName, $fieldValue]);
            }
            // 提交事务
            $this->pdo->commit();
            return $submissionId;
        } catch (Exception $e) {
            $this->pdo->rollBack();
            throw $e;
        }
    }
    public function getFormData($submissionId) {
        $stmt = $this->pdo->prepare("SELECT field_name, field_value 
                                   FROM form_submission_values 
                                   WHERE submission_id = ?");
        $stmt->execute([$submissionId]);
        $formData = [];
        while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
            $formData[$row['field_name']] = $row['field_value'];
        }
        return $formData;
    }
}
?>

动态表结构(适合固定字段集)

<?php
// 动态创建表结构
class DynamicTableStorage {
    private $pdo;
    public function createDynamicTable($tableName, $fields) {
        // 创建动态表的 SQL
        $sql = "CREATE TABLE IF NOT EXISTS `$tableName` (
            id INT PRIMARY KEY AUTO_INCREMENT,
            created_at TIMESTAMP,
            updated_at TIMESTAMP
        )";
        $this->pdo->exec($sql);
        // 动态添加字段
        foreach ($fields as $field) {
            $fieldName = $field['name'];
            $fieldType = $field['type']; // VARCHAR(255), INT, TEXT 等
            $alterSql = "ALTER TABLE `$tableName` 
                        ADD COLUMN `$fieldName` $fieldType";
            if (isset($field['default'])) {
                $alterSql .= " DEFAULT '{$field['default']}'";
            }
            $this->pdo->exec($alterSql);
        }
    }
    public function saveData($tableName, $data) {
        $columns = implode(', ', array_map(function($col) {
            return "`$col`";
        }, array_keys($data)));
        $placeholders = rtrim(str_repeat('?, ', count($data)), ', ');
        $sql = "INSERT INTO `$tableName` ($columns) VALUES ($placeholders)";
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute(array_values($data));
        return $this->pdo->lastInsertId();
    }
}
?>

混合方案(推荐用于复杂系统)

<?php
// 完整示例:JSON + 元数据
class ComprehensiveFormStorage {
    private $pdo;
    public function saveDynamicFormData($formData, $formConfig) {
        // formData: 用户提交的数据
        // formConfig: 表单字段配置
        $response = [
            'success' => false,
            'data' => null
        ];
        try {
            // 验证数据
            $validated = $this->validateData($formData, $formConfig);
            // 存储方案1:完整JSON存储(保留所有原始数据)
            $jsonData = json_encode($formData);
            // 存储方案2:只存储重要字段到独立列(便于查询)
            $importantFields = [
                'user_email' => $formData['email'] ?? null,
                'user_name' => $formData['name'] ?? null,
                'form_type' => $formConfig['type'] ?? 'general'
            ];
            // 组合存储
            $sql = "INSERT INTO dynamic_form_submissions 
                    (form_type, user_email, user_name, full_data, created_at) 
                    VALUES (?, ?, ?, ?, NOW())";
            $stmt = $this->pdo->prepare($sql);
            $stmt->execute([
                $importantFields['form_type'],
                $importantFields['user_email'],
                $importantFields['user_name'],
                $jsonData
            ]);
            $response['success'] = true;
            $response['data'] = $this->pdo->lastInsertId();
        } catch (Exception $e) {
            $response['error'] = $e->getMessage();
        }
        return $response;
    }
    private function validateData($formData, $formConfig) {
        foreach ($formConfig['fields'] as $field) {
            $fieldName = $field['name'];
            $required = $field['required'] ?? false;
            $type = $field['type'] ?? 'text';
            if ($required && empty($formData[$fieldName])) {
                throw new Exception("字段 {$fieldName} 是必填的");
            }
            // 根据类型验证
            switch ($type) {
                case 'email':
                    if (!empty($formData[$fieldName]) && !filter_var($formData[$fieldName], FILTER_VALIDATE_EMAIL)) {
                        throw new Exception("邮箱格式不正确");
                    }
                    break;
                case 'number':
                    if (!empty($formData[$fieldName]) && !is_numeric($formData[$fieldName])) {
                        throw new Exception("必须是数字");
                    }
                    break;
            }
        }
        return array_filter($formData);
    }
}
// 前端动态表单生成示例
?>
<!DOCTYPE html>
<html>
<head>
    <script>
        function generateDynamicForm() {
            const container = document.getElementById('dynamic-fields');
            // 添加文本字段
            container.innerHTML += `
                <div class="form-group">
                    <label>自定义字段</label>
                    <input type="text" name="custom_text" class="form-control">
                </div>
            `;
            // 添加选择字段
            container.innerHTML += `
                <div class="form-group">
                    <label>选择某个选项</label>
                    <select name="custom_select" class="form-control">
                        <option value="option1">选项1</option>
                        <option value="option2">选项2</option>
                    </select>
                </div>
            `;
        }
    </script>
</head>
<body>
    <form action="save.php" method="POST">
        <div id="dynamic-fields"></div>
        <button type="button" onclick="generateDynamicForm()">添加字段</button>
        <button type="submit">提交</button>
    </form>
</body>
</html>

推荐方案选择

根据你的需求选择:

  • 简单应用 → JSON 存储(最简单)
  • 需要查询特定字段 → EAV 模型
  • 字段完全固定 → 动态表结构
  • 大型系统 → 混合方案(JSON + 元数据)

最佳实践建议

  1. 始终使用参数化查询防止 SQL 注入
  2. 数据验证很重要
  3. 考虑未来的扩展性
  4. 定期备份数据

需要我详细解释某个方案吗?

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