本文目录导读:

在 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 + 元数据)
最佳实践建议:
- 始终使用参数化查询防止 SQL 注入
- 数据验证很重要
- 考虑未来的扩展性
- 定期备份数据
需要我详细解释某个方案吗?