本文目录导读:

我来帮你创建一个PHP CRUD快速生成器,可以自动生成增删改查的代码。
通用CRUD类 (BaseCrud.php)
<?php
/**
* 通用CRUD操作类
* 自动生成增删改查功能
*/
class BaseCrud {
private $conn;
private $table;
private $primaryKey = 'id';
private $allowedFields = [];
private $searchFields = [];
private $uploadFields = [];
public function __construct($connection, $table, $config = []) {
$this->conn = $connection;
$this->table = $table;
if (isset($config['primaryKey'])) {
$this->primaryKey = $config['primaryKey'];
}
if (isset($config['allowedFields'])) {
$this->allowedFields = $config['allowedFields'];
}
if (isset($config['searchFields'])) {
$this->searchFields = $config['searchFields'];
}
if (isset($config['uploadFields'])) {
$this->uploadFields = $config['uploadFields'];
}
// 如果没有指定允许的字段,自动获取所有字段
if (empty($this->allowedFields)) {
$this->getTableFields();
}
}
// 自动获取数据表字段
private function getTableFields() {
$sql = "SHOW COLUMNS FROM {$this->table}";
$result = $this->conn->query($sql);
while ($row = $result->fetch_assoc()) {
$this->allowedFields[] = $row['Field'];
}
}
// 创建记录
public function create($data) {
$filteredData = $this->filterFields($data);
// 处理上传文件
$filteredData = $this->handleUploads($filteredData);
$columns = implode(', ', array_keys($filteredData));
$placeholders = implode(', ', array_fill(0, count($filteredData), '?'));
$types = $this->getDataTypes($filteredData);
$values = array_values($filteredData);
$sql = "INSERT INTO {$this->table} ($columns) VALUES ($placeholders)";
$stmt = $this->conn->prepare($sql);
$stmt->bind_param($types, ...$values);
if ($stmt->execute()) {
return $this->conn->insert_id;
}
return false;
}
// 读取记录(分页)
public function read($id = null, $page = 1, $limit = 10, $search = '') {
$offset = ($page - 1) * $limit;
if ($id) {
// 获取单条记录
$sql = "SELECT * FROM {$this->table} WHERE {$this->primaryKey} = ?";
$stmt = $this->conn->prepare($sql);
$stmt->bind_param("i", $id);
$stmt->execute();
$result = $stmt->get_result();
return $result->fetch_assoc();
} else {
// 获取列表
$where = '';
$params = [];
$types = '';
if ($search && !empty($this->searchFields)) {
$searchConditions = [];
foreach ($this->searchFields as $field) {
$searchConditions[] = "$field LIKE ?";
$params[] = "%$search%";
$types .= "s";
}
$where = " WHERE " . implode(" OR ", $searchConditions);
}
// 获取总数
$countSql = "SELECT COUNT(*) as total FROM {$this->table}" . $where;
$stmt = $this->conn->prepare($countSql);
if (!empty($params)) {
$stmt->bind_param($types, ...$params);
}
$stmt->execute();
$total = $stmt->get_result()->fetch_assoc()['total'];
// 获取数据
$sql = "SELECT * FROM {$this->table}" . $where . " LIMIT ? OFFSET ?";
if (!empty($params)) {
$types .= "ii";
$params[] = $limit;
$params[] = $offset;
} else {
$types = "ii";
$params = [$limit, $offset];
}
$stmt = $this->conn->prepare($sql);
$stmt->bind_param($types, ...$params);
$stmt->execute();
$result = $stmt->get_result();
$rows = $result->fetch_all(MYSQLI_ASSOC);
return [
'data' => $rows,
'total' => $total,
'page' => $page,
'limit' => $limit,
'total_pages' => ceil($total / $limit)
];
}
}
// 更新记录
public function update($id, $data) {
$filteredData = $this->filterFields($data);
$filteredData = $this->handleUploads($filteredData);
$sets = [];
$params = [];
$types = '';
foreach ($filteredData as $key => $value) {
$sets[] = "$key = ?";
$params[] = $value;
$types .= $this->getFieldType($value);
}
// 添加ID
$types .= "i";
$params[] = $id;
$sql = "UPDATE {$this->table} SET " . implode(', ', $sets) . " WHERE {$this->primaryKey} = ?";
$stmt = $this->conn->prepare($sql);
$stmt->bind_param($types, ...$params);
return $stmt->execute();
}
// 删除记录
public function delete($id) {
$sql = "DELETE FROM {$this->table} WHERE {$this->primaryKey} = ?";
$stmt = $this->conn->prepare($sql);
$stmt->bind_param("i", $id);
return $stmt->execute();
}
// 批量删除
public function batchDelete($ids) {
$placeholders = implode(',', array_fill(0, count($ids), '?'));
$types = str_repeat('i', count($ids));
$sql = "DELETE FROM {$this->table} WHERE {$this->primaryKey} IN ($placeholders)";
$stmt = $this->conn->prepare($sql);
$stmt->bind_param($types, ...$ids);
return $stmt->execute();
}
// 过滤字段
private function filterFields($data) {
$filtered = [];
foreach ($this->allowedFields as $field) {
if (isset($data[$field])) {
$filtered[$field] = $data[$field];
}
}
return $filtered;
}
// 获取数据类型
private function getDataTypes($data) {
$types = '';
foreach ($data as $value) {
$types .= $this->getFieldType($value);
}
return $types;
}
// 判断字段类型
private function getFieldType($value) {
if (is_int($value)) return 'i';
if (is_double($value)) return 'd';
if (is_string($value)) return 's';
return 's';
}
// 处理文件上传
private function handleUploads($data) {
$uploadDir = __DIR__ . '/../../uploads/';
if (!is_dir($uploadDir)) {
mkdir($uploadDir, 0777, true);
}
foreach ($this->uploadFields as $field) {
if (isset($_FILES[$field]) && $_FILES[$field]['error'] === 0) {
$file = $_FILES[$field];
$filename = time() . '_' . basename($file['name']);
$targetPath = $uploadDir . $filename;
if (move_uploaded_file($file['tmp_name'], $targetPath)) {
$data[$field] = 'uploads/' . $filename;
}
}
}
return $data;
}
}
数据库连接类 (Database.php)
<?php
/**
* 数据库连接类(单例模式)
*/
class Database {
private static $instance = null;
private $conn;
private function __construct($config) {
$this->conn = new mysqli(
$config['host'],
$config['username'],
$config['password'],
$config['database'],
$config['port'] ?? 3306
);
if ($this->conn->connect_error) {
die("Connection failed: " . $this->conn->connect_error);
}
$this->conn->set_charset($config['charset'] ?? 'utf8mb4');
}
public static function getInstance($config = null) {
if (self::$instance === null && $config) {
self::$instance = new self($config);
}
return self::$instance;
}
public function getConnection() {
return $this->conn;
}
public function close() {
if ($this->conn) {
$this->conn->close();
}
}
}
CRUD生成器 (CrudGenerator.php)
<?php
/**
* CRUD代码生成器
* 根据数据库表自动生成CRUD代码
*/
class CrudGenerator {
private $conn;
public function __construct($connection) {
$this->conn = $connection;
}
// 获取所有表
public function getTables() {
$sql = "SHOW TABLES";
$result = $this->conn->query($sql);
$tables = [];
while ($row = $result->fetch_row()) {
$tables[] = $row[0];
}
return $tables;
}
// 获取表结构
public function getTableStructure($table) {
$sql = "SHOW COLUMNS FROM $table";
$result = $this->conn->query($sql);
$fields = [];
while ($row = $result->fetch_assoc()) {
$fields[] = [
'name' => $row['Field'],
'type' => $row['Type'],
'null' => $row['Null'],
'key' => $row['Key'],
'default' => $row['Default'],
'extra' => $row['Extra']
];
}
return $fields;
}
// 生成配置数组
public function generateConfig($table) {
$fields = $this->getTableStructure($table);
$config = [
'table' => $table,
'primaryKey' => 'id',
'allowedFields' => [],
'searchFields' => [],
'uploadFields' => []
];
foreach ($fields as $field) {
$config['allowedFields'][] = $field['name'];
if ($field['key'] === 'PRI') {
$config['primaryKey'] = $field['name'];
}
// 判断字段类型,选择搜索字段
if (strpos($field['type'], 'varchar') !== false ||
strpos($field['type'], 'text') !== false) {
$config['searchFields'][] = $field['name'];
}
// 判断上传字段
if (strpos($field['name'], 'image') !== false ||
strpos($field['name'], 'picture') !== false ||
strpos($field['name'], 'file') !== false) {
$config['uploadFields'][] = $field['name'];
}
}
return $config;
}
// 生成控制器文件
public function generateController($table) {
$config = $this->generateConfig($table);
$className = $this->toCamelCase($table);
$controllerName = $className . 'Controller';
$code = "<?php\n";
$code .= "/**\n";
$code .= " * {$controllerName} - 自动生成\n";
$code .= " */\n";
$code .= "class {$controllerName} {\n";
$code .= " private \$crud;\n";
$code .= " \n";
$code .= " public function __construct(\$db) {\n";
$code .= " \$config = " . var_export($config, true) . ";\n";
$code .= " \$this->crud = new BaseCrud(\$db, '{$table}', \$config);\n";
$code .= " }\n";
$code .= " \n";
$code .= " // 创建记录\n";
$code .= " public function create(\$data) {\n";
$code .= " \$id = \$this->crud->create(\$data);\n";
$code .= " return ['success' => true, 'id' => \$id];\n";
$code .= " }\n";
$code .= " \n";
$code .= " // 读取记录\n";
$code .= " public function read(\$id = null, \$page = 1, \$limit = 10, \$search = '') {\n";
$code .= " return \$this->crud->read(\$id, \$page, \$limit, \$search);\n";
$code .= " }\n";
$code .= " \n";
$code .= " // 更新记录\n";
$code .= " public function update(\$id, \$data) {\n";
$code .= " return \$this->crud->update(\$id, \$data);\n";
$code .= " }\n";
$code .= " \n";
$code .= " // 删除记录\n";
$code .= " public function delete(\$id) {\n";
$code .= " return \$this->crud->delete(\$id);\n";
$code .= " }\n";
$code .= "}\n";
return $code;
}
// 生成前端页面
public function generateView($table) {
$fields = $this->getTableStructure($table);
$config = $this->generateConfig($table);
$html = "<!DOCTYPE html>\n";
$html .= "<html lang='zh-CN'>\n";
$html .= "<head>\n";
$html .= " <meta charset='UTF-8'>\n";
$html .= " <title>{$table}管理</title>\n";
$html .= " <link href='https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css' rel='stylesheet'>\n";
$html .= "</head>\n";
$html .= "<body>\n";
$html .= " <div class='container mt-4'>\n";
$html .= " <h2>{$table}管理</h2>\n";
// 搜索表单
$html .= " <div class='row mb-3'>\n";
$html .= " <div class='col-md-6'>\n";
$html .= " <form class='d-flex' method='GET'>\n";
$html .= " <input type='text' name='search' class='form-control me-2' placeholder='搜索...'>\n";
$html .= " <button type='submit' class='btn btn-primary'>搜索</button>\n";
$html .= " </form>\n";
$html .= " </div>\n";
$html .= " <div class='col-md-6 text-end'>\n";
$html .= " <button class='btn btn-success' onclick='showAddModal()'>添加记录</button>\n";
$html .= " </div>\n";
$html .= " </div>\n";
// 数据表格
$html .= " <table class='table table-striped'>\n";
$html .= " <thead>\n";
$html .= " <tr>\n";
foreach ($fields as $field) {
$html .= " <th>{$field['name']}</th>\n";
}
$html .= " <th>操作</th>\n";
$html .= " </tr>\n";
$html .= " </thead>\n";
$html .= " <tbody id='dataTable'>\n";
$html .= " </tbody>\n";
$html .= " </table>\n";
// 分页
$html .= " <nav>\n";
$html .= " <ul class='pagination' id='pagination'>\n";
$html .= " </ul>\n";
$html .= " </nav>\n";
// 添加/编辑模态框
$html .= " <div class='modal' id='editModal'>\n";
$html .= " <div class='modal-dialog'>\n";
$html .= " <div class='modal-content'>\n";
$html .= " <div class='modal-header'>\n";
$html .= " <h5 class='modal-title' id='modalTitle'>添加记录</h5>\n";
$html .= " <button type='button' class='btn-close' data-bs-dismiss='modal'></button>\n";
$html .= " </div>\n";
$html .= " <div class='modal-body'>\n";
$html .= " <form id='editForm'>\n";
foreach ($fields as $field) {
if ($field['key'] === 'PRI' || $field['extra'] === 'auto_increment') continue;
$html .= " <div class='mb-3'>\n";
$html .= " <label class='form-label'>{$field['name']}</label>\n";
if (strpos($field['type'], 'text') !== false && strpos($field['type'], 'int') === false) {
$html .= " <textarea class='form-control' name='{$field['name']}'></textarea>\n";
} else {
$html .= " <input class='form-control' name='{$field['name']}' type='text'>\n";
}
$html .= " </div>\n";
}
$html .= " <button type='submit' class='btn btn-primary'>保存</button>\n";
$html .= " </form>\n";
$html .= " </div>\n";
$html .= " </div>\n";
$html .= " </div>\n";
$html .= " </div>\n";
$html .= " </div>\n";
// JavaScript代码
$html .= " <script src='https://code.jquery.com/jquery-3.6.0.min.js'></script>\n";
$html .= " <script src='https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js'></script>\n";
$html .= " <script>\n";
$html .= " let currentId = null;\n";
$html .= " \n";
$html .= " function loadData(page = 1) {\n";
$html .= " let search = $('input[name=search]').val() || '';\n";
$html .= " $.get('api.php?action=list&page='+page+'&search='+search, function(response) {\n";
$html .= " if (response.success) {\n";
$html .= " renderTable(response.data.data);\n";
$html .= " renderPagination(response.data);\n";
$html .= " }\n";
$html .= " });\n";
$html .= " }\n";
$html .= " \n";
$html .= " function renderTable(data) {\n";
$html .= " let html = '';\n";
$html .= " data.forEach(function(row) {\n";
$html .= " html += '<tr>';\n";
foreach ($fields as $field) {
$html .= " html += '<td>'+row.{$field['name']}+'</td>';\n";
}
$html .= " html += '<td>';\n";
$html .= " html += '<button class=\"btn btn-sm btn-primary\" onclick=\"editRecord('+\"" . "'" . "'"+'+row.{$config['primaryKey']}+')">编辑</button> ';\n";
$html .= " html += '<button class=\"btn btn-sm btn-danger\" onclick=\"deleteRecord('+\"" . "'" . "'"+'+row.{$config['primaryKey']}+')">删除</button>';\n";
$html .= " html += '</td>';\n";
$html .= " html += '</tr>';\n";
$html .= " });\n";
$html .= " $('#dataTable').html(html);\n";
$html .= " }\n";
$html .= " \n";
$html .= " function renderPagination(data) {\n";
$html .= " let html = '';\n";
$html .= " for (let i = 1; i <= data.total_pages; i++) {\n";
$html .= " html += '<li class=\"page-item' + (i === data.page ? ' active' : '') + '\">';\n";
$html .= " html += '<a class=\"page-link\" href=\"javascript:void(0)\" onclick=\"loadData('+i+')\">'+i+'</a>';\n";
$html .= " html += '</li>';\n";
$html .= " }\n";
$html .= " $('#pagination').html(html);\n";
$html .= " }\n";
$html .= " \n";
$html .= " function showAddModal() {\n";
$html .= " currentId = null;\n";
$html .= " $('#modalTitle').text('添加记录');\n";
$html .= " $('#editForm')[0].reset();\n";
$html .= " new bootstrap.Modal(document.getElementById('editModal')).show();\n";
$html .= " }\n";
$html .= " \n";
$html .= " function editRecord(id) {\n";
$html .= " currentId = id;\n";
$html .= " $.get('api.php?action=one&id='+id, function(response) {\n";
$html .= " if (response.success) {\n";
$html .= " let row = response.data;\n";
foreach ($fields as $field) {
if ($field['key'] === 'PRI' || $field['extra'] === 'auto_increment') continue;
$html .= " $('input[name={$field['name']}], textarea[name={$field['name']}]').val(row.{$field['name']});\n";
}
$html .= " $('#modalTitle').text('编辑记录');\n";
$html .= " new bootstrap.Modal(document.getElementById('editModal')).show();\n";
$html .= " }\n";
$html .= " });\n";
$html .= " }\n";
$html .= " \n";
$html .= " $('#editForm').on('submit', function(e) {\n";
$html .= " e.preventDefault();\n";
$html .= " let data = $(this).serialize();\n";
$html .= " let url = currentId ? 'api.php?action=update&id='+currentId : 'api.php?action=create';\n";
$html .= " \n";
$html .= " $.post(url, data, function(response) {\n";
$html .= " if (response.success) {\n";
$html .= " new bootstrap.Modal(document.getElementById('editModal')).hide();\n";
$html .= " loadData();\n";
$html .= " }\n";
$html .= " });\n";
$html .= " });\n";
$html .= " \n";
$html .= " function deleteRecord(id) {\n";
$html .= " if (confirm('确定删除这条记录吗?')) {\n";
$html .= " $.post('api.php?action=delete&id='+id, function(response) {\n";
$html .= " if (response.success) {\n";
$html .= " loadData();\n";
$html .= " }\n";
$html .= " });\n";
$html .= " }\n";
$html .= " }\n";
$html .= " \n";
$html .= " // 初始加载\n";
$html .= " loadData();\n";
$html .= " </script>\n";
$html .= "</body>\n";
$html .= "</html>\n";
return $html;
}
// 生成API接口文件
public function generateApi($table) {
$config = $this->generateConfig($table);
$code = "<?php\n";
$code .= "/**\n";
$code .= " * API接口 - {$table}\n";
$code .= " */\n";
$code .= "require_once 'config.php';\n";
$code .= "require_once 'Database.php';\n";
$code .= "require_once 'BaseCrud.php';\n";
$code .= "require_once '{$this->toCamelCase($table)}Controller.php';\n";
$code .= "\n";
$code .= "// 初始化数据库连接\n";
$code .= "\$db = Database::getInstance(\$config)->getConnection();\n";
$code .= "\$controller = new {$this->toCamelCase($table)}Controller(\$db);\n";
$code .= "\n";
$code .= "// 处理请求\n";
$code .= "\$action = \$_GET['action'] ?? 'list';\n";
$code .= "\n";
$code .= "switch (\$action) {\n";
$code .= " case 'list':\n";
$code .= " \$page = \$_GET['page'] ?? 1;\n";
$code .= " \$limit = \$_GET['limit'] ?? 10;\n";
$code .= " \$search = \$_GET['search'] ?? '';\n";
$code .= " \$result = \$controller->read(null, \$page, \$limit, \$search);\n";
$code .= " echo json_encode(['success' => true, 'data' => \$result]);\n";
$code .= " break;\n";
$code .= " \n";
$code .= " case 'one':\n";
$code .= " \$id = \$_GET['id'];\n";
$code .= " \$result = \$controller->read(\$id);\n";
$code .= " echo json_encode(['success' => true, 'data' => \$result]);\n";
$code .= " break;\n";
$code .= " \n";
$code .= " case 'create':\n";
$code .= " \$result = \$controller->create(\$_POST);\n";
$code .= " echo json_encode(\$result);\n";
$code .= " break;\n";
$code .= " \n";
$code .= " case 'update':\n";
$code .= " \$id = \$_GET['id'];\n";
$code .= " \$result = \$controller->update(\$id, \$_POST);\n";
$code .= " echo json_encode(['success' => \$result]);\n";
$code .= " break;\n";
$code .= " \n";
$code .= " case 'delete':\n";
$code .= " \$id = \$_GET['id'];\n";
$code .= " \$result = \$controller->delete(\$id);\n";
$code .= " echo json_encode(['success' => \$result]);\n";
$code .= " break;\n";
$code .= "}\n";
return $code;
}
// 生成所有文件
public function generateAll($table, $outputDir) {
$files = [
$outputDir . '/' . $this->toCamelCase($table) . 'Controller.php' => $this->generateController($table),
$outputDir . '/' . $table . '.html' => $this->generateView($table),
$outputDir . '/api_' . $table . '.php' => $this->generateApi($table)
];
foreach ($files as $path => $content) {
file_put_contents($path, $content);
}
return $files;
}
// 表名转驼峰
private function toCamelCase($string) {
$words = explode('_', $string);
$className = '';
foreach ($words as $word) {
$className .= ucfirst($word);
}
return $className;
}
}
使用示例
<?php
// 配置文件 config.php
$config = [
'host' => 'localhost',
'username' => 'root',
'password' => '',
'database' => 'test_db',
'port' => 3306,
'charset' => 'utf8mb4'
];
?>
<?php
// 使用示例 index.php
require_once 'Database.php';
require_once 'BaseCrud.php';
require_once 'CrudGenerator.php';
// 初始化数据库
$db = Database::getInstance($config)->getConnection();
// 方式1:直接使用BaseCrud类
$crud = new BaseCrud($db, 'users', [
'primaryKey' => 'id',
'allowedFields' => ['name', 'email', 'phone', 'status'],
'searchFields' => ['name', 'email', 'phone'],
'uploadFields' => [] // 如果有上传字段
]);
// 创建记录
$newId = $crud->create([
'name' => '张三',
'email' => 'zhangsan@example.com',
'phone' => '13800138000',
'status' => 1
]);
// 读取记录(分页)
$result = $crud->read(null, 1, 10, '张三');
print_r($result);
// 更新记录
$crud->update($newId, ['status' => 0]);
// 删除记录
$crud->delete($newId);
// 方式2:使用CRUD生成器自动生成代码
$generator = new CrudGenerator($db);
// 获取所有表
$tables = $generator->getTables();
// 获取表结构
$structure = $generator->getTableStructure('users');
// 生成所有CRUD文件
$files = $generator->generateAll('users', __DIR__ . '/generated');
print_r($files);
?>
这个PHP CRUD生成器提供了:
- 自动字段识别 - 自动获取数据库表结构
- 完整CRUD操作 - 增删改查、分页、搜索
- 代码生成器 - 自动生成控制器、视图、API接口
- 安全处理 - 使用预处理语句防止SQL注入
- 灵活配置 - 可以自定义字段、搜索条件、上传文件等
- 前端页面生成 - 自动生成Bootstrap风格的页面