本文目录导读:

我来为您创建一个完整的PHP动态配置管理后台,包含数据库设计、后端API和前端界面。
数据库设计
-- 创建配置表
CREATE TABLE `configurations` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`config_key` varchar(100) NOT NULL COMMENT '配置键名',
`config_value` text COMMENT '配置值',
`config_type` enum('text','textarea','number','select','checkbox','json') DEFAULT 'text' COMMENT '配置类型',
`config_group` varchar(50) DEFAULT 'general' COMMENT '配置分组',
`description` varchar(255) DEFAULT NULL COMMENT '配置说明',
`options` text COMMENT '选项值(JSON格式)',
`is_required` tinyint(1) DEFAULT '0' COMMENT '是否必填',
`created_at` timestamp DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_config_key` (`config_key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 示例数据
INSERT INTO `configurations` (`config_key`, `config_value`, `config_type`, `config_group`, `description`, `options`, `is_required`) VALUES
('site_name', 'My Website', 'text', 'general', '网站名称', NULL, 1),
('site_url', 'https://example.com', 'text', 'general', '网站URL', NULL, 1),
('site_description', '这是网站描述', 'textarea', 'general', '网站描述', NULL, 0),
('items_per_page', '20', 'number', 'pagination', '每页显示数量', NULL, 1),
('theme_color', 'blue', 'select', 'appearance', '主题颜色', '["blue","red","green","dark"]', 0),
('enable_registration', '1', 'checkbox', 'user', '开放注册', NULL, 0),
('api_settings', '{"timeout":30,"retry":3}', 'json', 'api', 'API设置', NULL, 0);
后端PHP代码
config.php - 数据库连接
<?php
// config.php
session_start();
define('DB_HOST', 'localhost');
define('DB_USER', 'root');
define('DB_PASS', '');
define('DB_NAME', 'config_demo');
// 创建数据库连接
$conn = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$conn->set_charset("utf8mb4");
// 辅助函数
function json_response($data, $status = 200) {
http_response_code($status);
header('Content-Type: application/json');
echo json_encode($data);
exit;
}
function validate_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
?>
get_configs.php - 获取配置列表
<?php
require_once 'config.php';
header('Content-Type: application/json');
$sql = "SELECT * FROM configurations ORDER BY config_group, config_key";
$result = $conn->query($sql);
$configs = [];
while ($row = $result->fetch_assoc()) {
// 解析JSON选项
if ($row['options']) {
$row['options'] = json_decode($row['options'], true);
}
// 解析JSON值
if ($row['config_type'] === 'json' && $row['config_value']) {
$row['config_value'] = json_decode($row['config_value'], true);
}
$configs[] = $row;
}
json_response(['success' => true, 'data' => $configs]);
?>
save_config.php - 保存配置
<?php
require_once 'config.php';
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
json_response(['success' => false, 'message' => 'Invalid request method'], 400);
}
// 获取请求数据
$input = json_decode(file_get_contents('php://input'), true);
if (!$input || !isset($input['id']) || !isset($input['value'])) {
json_response(['success' => false, 'message' => 'Invalid data'], 400);
}
$id = intval($input['id']);
$value = $input['value'];
// 获取配置信息
$stmt = $conn->prepare("SELECT * FROM configurations WHERE id = ?");
$stmt->bind_param("i", $id);
$stmt->execute();
$result = $stmt->get_result();
$config = $result->fetch_assoc();
if (!$config) {
json_response(['success' => false, 'message' => 'Configuration not found'], 404);
}
// 根据类型处理值
$valueToSave = $value;
switch ($config['config_type']) {
case 'checkbox':
$valueToSave = $value ? '1' : '0';
break;
case 'json':
if (is_array($value)) {
$valueToSave = json_encode($value);
} else {
// 尝试解析JSON字符串
$decoded = json_decode($value, true);
if (json_last_error() === JSON_ERROR_NONE) {
$valueToSave = json_encode($decoded);
} else {
json_response(['success' => false, 'message' => 'Invalid JSON format'], 400);
}
}
break;
case 'number':
if (!is_numeric($value)) {
json_response(['success' => false, 'message' => 'Invalid number'], 400);
}
break;
default:
$valueToSave = validate_input((string)$value);
}
// 更新配置
$stmt = $conn->prepare("UPDATE configurations SET config_value = ?, updated_at = NOW() WHERE id = ?");
$stmt->bind_param("si", $valueToSave, $id);
if ($stmt->execute()) {
json_response(['success' => true, 'message' => 'Configuration saved successfully']);
} else {
json_response(['success' => false, 'message' => 'Failed to save configuration'], 500);
}
?>
delete_config.php - 删除配置
<?php
require_once 'config.php';
if ($_SERVER['REQUEST_METHOD'] !== 'DELETE') {
json_response(['success' => false, 'message' => 'Invalid request method'], 400);
}
$id = isset($_GET['id']) ? intval($_GET['id']) : 0;
if (!$id) {
json_response(['success' => false, 'message' => 'Invalid ID'], 400);
}
$stmt = $conn->prepare("DELETE FROM configurations WHERE id = ?");
$stmt->bind_param("i", $id);
if ($stmt->execute()) {
json_response(['success' => true, 'message' => 'Configuration deleted successfully']);
} else {
json_response(['success' => false, 'message' => 'Failed to delete configuration'], 500);
}
?>
add_config.php - 添加配置
<?php
require_once 'config.php';
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
json_response(['success' => false, 'message' => 'Invalid request method'], 400);
}
$input = json_decode(file_get_contents('php://input'), true);
// 验证必填字段
if (!isset($input['config_key']) || !isset($input['config_key'])) {
json_response(['success' => false, 'message' => 'Config key is required'], 400);
}
$config_key = validate_input($input['config_key']);
$config_value = isset($input['config_value']) ? validate_input($input['config_value']) : '';
$config_type = isset($input['config_type']) ? validate_input($input['config_type']) : 'text';
$config_group = isset($input['config_group']) ? validate_input($input['config_group']) : 'general';
$description = isset($input['description']) ? validate_input($input['description']) : '';
$is_required = isset($input['is_required']) ? intval($input['is_required']) : 0;
$options = isset($input['options']) ? json_encode($input['options']) : NULL;
// 检查key是否已存在
$stmt = $conn->prepare("SELECT id FROM configurations WHERE config_key = ?");
$stmt->bind_param("s", $config_key);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
json_response(['success' => false, 'message' => 'Config key already exists'], 400);
}
$stmt = $conn->prepare("INSERT INTO configurations (config_key, config_value, config_type, config_group, description, options, is_required) VALUES (?, ?, ?, ?, ?, ?, ?)");
$stmt->bind_param("ssssssi", $config_key, $config_value, $config_type, $config_group, $description, $options, $is_required);
if ($stmt->execute()) {
json_response(['success' => true, 'message' => 'Configuration added successfully', 'id' => $conn->insert_id]);
} else {
json_response(['success' => false, 'message' => 'Failed to add configuration'], 500);
}
?>
get_config_value.php - 获取单个配置值
<?php
require_once 'config.php';
// 获取特定配置值(用于前端)
$key = isset($_GET['key']) ? validate_input($_GET['key']) : '';
if (!$key) {
json_response(['success' => false, 'message' => 'Config key is required'], 400);
}
$stmt = $conn->prepare("SELECT config_value, config_type FROM configurations WHERE config_key = ? LIMIT 1");
$stmt->bind_param("s", $key);
$stmt->execute();
$result = $stmt->get_result();
if ($row = $result->fetch_assoc()) {
// 根据类型转换值
$value = $row['config_value'];
switch ($row['config_type']) {
case 'number':
$value = (float)$value;
break;
case 'checkbox':
$value = (bool)$value;
break;
case 'json':
$value = json_decode($value, true);
break;
}
json_response(['success' => true, 'data' => $value]);
} else {
json_response(['success' => false, 'message' => 'Configuration not found'], 404);
}
?>
前端界面
index.php - 管理后台主页面
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">配置管理后台</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
<style>
.config-section {
margin-bottom: 30px;
}
.config-section h3 {
border-bottom: 2px solid #007bff;
padding-bottom: 10px;
margin-bottom: 20px;
}
.config-item {
margin-bottom: 15px;
}
.config-card {
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
border: 1px solid #dee2e6;
border-radius: 8px;
}
.config-card .card-body {
padding: 15px;
}
.edit-btn, .delete-btn {
cursor: pointer;
}
.toast-container {
position: fixed;
top: 20px;
right: 20px;
z-index: 1050;
}
.loading {
display: none;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
#sidebar {
min-height: 100vh;
background: #343a40;
color: white;
padding: 20px;
}
#sidebar a {
color: white;
text-decoration: none;
display: block;
padding: 10px;
margin-bottom: 5px;
border-radius: 5px;
}
#sidebar a:hover {
background: #007bff;
}
#sidebar a.active {
background: #007bff;
}
</style>
</head>
<body>
<div class="container-fluid">
<div class="row">
<!-- 侧边栏 -->
<nav id="sidebar" class="col-md-2 d-md-block">
<h4 class="text-center mb-4">配置管理</h4>
<a href="#general" class="active" data-group="general"><i class="fas fa-cog"></i> 通用设置</a>
<a href="#appearance" data-group="appearance"><i class="fas fa-palette"></i> 外观设置</a>
<a href="#user" data-group="user"><i class="fas fa-user"></i> 用户设置</a>
<a href="#api" data-group="api"><i class="fas fa-code"></i> API设置</a>
<a href="#system" data-group="system"><i class="fas fa-server"></i> 系统设置</a>
<hr>
<a href="#add-config" data-bs-toggle="modal" data-bs-target="#addConfigModal">
<i class="fas fa-plus"></i> 添加配置
</a>
</nav>
<!-- 主内容 -->
<main class="col-md-10 ms-sm-auto px-md-4">
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">配置管理</h1>
<div class="btn-toolbar mb-2 mb-md-0">
<button class="btn btn-primary" onclick="refreshConfigs()">
<i class="fas fa-refresh"></i> 刷新
</button>
</div>
</div>
<div id="loading" class="loading">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
<div id="config-content"></div>
</main>
</div>
</div>
<!-- Toast通知 -->
<div class="toast-container" id="toastContainer"></div>
<!-- 添加配置 Modal -->
<div class="modal fade" id="addConfigModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">添加新配置</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="addConfigForm">
<div class="mb-3">
<label class="form-label">配置键名 *</label>
<input type="text" class="form-control" id="configKey" required>
</div>
<div class="mb-3">
<label class="form-label">配置值</label>
<textarea class="form-control" id="configValue"></textarea>
</div>
<div class="mb-3">
<label class="form-label">配置类型</label>
<select class="form-control" id="configType">
<option value="text">文本</option>
<option value="textarea">多行文本</option>
<option value="number">数字</option>
<option value="select">下拉选择</option>
<option value="checkbox">复选框</option>
<option value="json">JSON</option>
</select>
</div>
<div class="mb-3">
<label class="form-label">配置分组</label>
<select class="form-control" id="configGroup">
<option value="general">通用设置</option>
<option value="appearance">外观设置</option>
<option value="user">用户设置</option>
<option value="api">API设置</option>
<option value="system">系统设置</option>
</select>
</div>
<div class="mb-3">
<label class="form-label">描述</label>
<textarea class="form-control" id="configDescription"></textarea>
</div>
<div class="mb-3 form-check">
<input type="checkbox" class="form-check-input" id="configRequired">
<label class="form-check-label">必填</label>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary" onclick="addConfig()">添加</button>
</div>
</div>
</div>
</div>
<!-- 编辑配置 Modal -->
<div class="modal fade" id="editModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">编辑配置</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="editForm">
<input type="hidden" id="editId">
<div class="mb-3">
<label class="form-label">配置值</label>
<div id="editValueContainer"></div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary" onclick="saveEdit()">保存</button>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
let currentGroup = 'general';
let allConfigs = [];
// 初始化
$(document).ready(function() {
refreshConfigs();
// 侧边栏点击事件
$('.sidebar-item').click(function(e) {
e.preventDefault();
const group = $(this).data('group');
currentGroup = group;
filterByGroup(group);
// 设置激活状态
$('.sidebar-item').removeClass('active');
$(this).addClass('active');
});
});
// 刷新配置
function refreshConfigs() {
$('#loading').show();
$('#config-content').empty();
$.ajax({
url: 'get_configs.php',
method: 'GET',
success: function(response) {
allConfigs = response.data;
filterByGroup(currentGroup);
$('#loading').hide();
},
error: function(xhr) {
showToast('加载配置失败', 'error');
$('#loading').hide();
}
});
}
// 按分组筛选
function filterByGroup(group) {
const filtered = allConfigs.filter(config => config.config_group === group);
renderConfigs(filtered);
}
// 渲染配置
function renderConfigs(configs) {
const content = $('#config-content');
content.empty();
if (configs.length === 0) {
content.html(`
<div class="alert alert-info">
<i class="fas fa-info-circle"></i> 该分组暂无配置项
</div>
`);
return;
}
const html = configs.map(config => {
let valueDisplay = formatValue(config);
return `
<div class="card config-card mb-3">
<div class="card-body">
<div class="row align-items-center">
<div class="col-md-4">
<h6 class="mb-1">${config.config_key}</h6>
<small class="text-muted">${config.description || ''}</small>
</div>
<div class="col-md-6">
${valueDisplay}
</div>
<div class="col-md-2 text-end">
<button class="btn btn-sm btn-outline-primary edit-btn" onclick="openEditModal(${config.id})">
<i class="fas fa-edit"></i>
</button>
<button class="btn btn-sm btn-outline-danger delete-btn" onclick="deleteConfig(${config.id})">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
</div>
</div>
`;
}).join('');
content.html(html);
}
// 格式化值显示
function formatValue(config) {
const value = config.config_value;
switch(config.config_type) {
case 'checkbox':
return `
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox"
${value == '1' ? 'checked' : ''} disabled>
<label class="form-check-label">${value == '1' ? '启用' : '禁用'}</label>
</div>
`;
case 'select':
return `<span class="badge bg-primary">${value}</span>`;
case 'json':
try {
const obj = typeof value === 'string' ? JSON.parse(value) : value;
return `<code>${JSON.stringify(obj, null, 2)}</code>`;
} catch(e) {
return `<code>${value}</code>`;
}
case 'textarea':
return `<span class="text-muted">${value?.substring(0, 100)}...</span>`;
default:
return `<span>${value}</span>`;
}
}
// 打开编辑模态框
function openEditModal(id) {
const config = allConfigs.find(c => c.id === id);
if (!config) return;
$('#editId').val(config.id);
$('#editValueContainer').empty();
let inputHtml = '';
switch(config.config_type) {
case 'text':
inputHtml = `<input type="text" class="form-control" id="editValue" value="${config.config_value}">`;
break;
case 'textarea':
inputHtml = `<textarea class="form-control" id="editValue" rows="3">${config.config_value}</textarea>`;
break;
case 'number':
inputHtml = `<input type="number" class="form-control" id="editValue" value="${config.config_value}">`;
break;
case 'select':
const options = config.options || [];
let selectHtml = '<select class="form-control" id="editValue">';
options.forEach(option => {
selectHtml += `<option value="${option}" ${option === config.config_value ? 'selected' : ''}>${option}</option>`;
});
selectHtml += '</select>';
inputHtml = selectHtml;
break;
case 'checkbox':
inputHtml = `
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="editValue" ${config.config_value == '1' ? 'checked' : ''}>
<label class="form-check-label">启用</label>
</div>
`;
break;
case 'json':
const jsonValue = typeof config.config_value === 'string' ? config.config_value : JSON.stringify(config.config_value, null, 2);
inputHtml = `<textarea class="form-control" id="editValue" rows="5">${jsonValue}</textarea>`;
break;
default:
inputHtml = `<input type="text" class="form-control" id="editValue" value="${config.config_value}">`;
}
$('#editValueContainer').html(inputHtml);
const modal = new bootstrap.Modal(document.getElementById('editModal'));
modal.show();
}
// 保存编辑
function saveEdit() {
const id = $('#editId').val();
let value = $('#editValue').val();
// 处理checkbox
if (value === undefined) {
value = $('#editValue').is(':checked') ? '1' : '0';
}
$.ajax({
url: 'save_config.php',
method: 'POST',
data: JSON.stringify({
id: id,
value: value
}),
contentType: 'application/json',
success: function(response) {
if (response.success) {
showToast('配置保存成功', 'success');
refreshConfigs();
const modal = bootstrap.Modal.getInstance(document.getElementById('editModal'));
modal.hide();
} else {
showToast(response.message || '保存失败', 'error');
}
},
error: function(xhr) {
showToast('保存失败', 'error');
}
});
}
// 删除配置
function deleteConfig(id) {
if (!confirm('确定要删除这个配置吗?')) return;
$.ajax({
url: `delete_config.php?id=${id}`,
method: 'DELETE',
success: function(response) {
if (response.success) {
showToast('配置删除成功', 'success');
refreshConfigs();
} else {
showToast(response.message || '删除失败', 'error');
}
},
error: function(xhr) {
showToast('删除失败', 'error');
}
});
}
// 添加配置
function addConfig() {
const data = {
config_key: $('#configKey').val(),
config_value: $('#configValue').val() || '',
config_type: $('#configType').val(),
config_group: $('#configGroup').val(),
description: $('#configDescription').val() || '',
is_required: $('#configRequired').is(':checked') ? 1 : 0
};
$.ajax({
url: 'add_config.php',
method: 'POST',
data: JSON.stringify(data),
contentType: 'application/json',
success: function(response) {
if (response.success) {
showToast('配置添加成功', 'success');
refreshConfigs();
// 关闭模态框并重置表单
const modal = bootstrap.Modal.getInstance(document.getElementById('addConfigModal'));
modal.hide();
$('#addConfigForm')[0].reset();
} else {
showToast(response.message || '添加失败', 'error');
}
},
error: function(xhr) {
showToast('添加失败', 'error');
}
});
}
// 显示Toast通知
function showToast(message, type = 'success') {
const bgClass = type === 'success' ? 'bg-success' : 'bg-danger';
const toast = `
<div class="toast ${bgClass} text-white" role="alert">
<div class="toast-header">
<strong class="me-auto">通知</strong>
<button type="button" class="btn-close" data-bs-dismiss="toast"></button>
</div>
<div class="toast-body">${message}</div>
</div>
`;
$('#toastContainer').append(toast);
const toastElement = $(toast);
const toastObj = new bootstrap.Toast(toastElement[0]);
toastObj.show();
// 自动移除
setTimeout(() => {
toastElement.remove();
}, 3000);
}
</script>
</body>
</html>
使用说明
部署步骤:
- 创建数据库
config_demo - 导入SQL文件创建数据表
- 上传所有PHP文件到服务器
- 修改
config.php中的数据库连接信息 - 通过浏览器访问
index.php
功能特点:
- ✅ 支持多种配置类型(文本、多行文本、数字、下拉选择、复选框、JSON)
- ✅ 分组管理配置
- ✅ 实时保存编辑
- ✅ 删除和添加配置
- ✅ 响应式界面
- ✅ 中文界面
- ✅ Toast通知
- ✅ 数据验证
这个后台系统可以方便地管理网站的各种配置项,并且易于扩展和定制!