本文目录导读:

我来给你一个完整的PHP实战项目方案,从基础到进阶,包含真实项目案例和代码示例。
🚀 实战项目:在线图书管理系统
这是一个完整的CRUD项目,涵盖用户认证、数据管理、文件上传等核心功能。
项目结构
book-manager/
├── config/
│ └── database.php
├── includes/
│ ├── auth.php
│ ├── functions.php
│ └── header.php
├── admin/
│ ├── login.php
│ ├── dashboard.php
│ ├── books/
│ │ ├── index.php
│ │ ├── create.php
│ │ ├── edit.php
│ │ └── delete.php
│ └── uploads/
├── assets/
│ ├── css/
│ └── js/
└── index.php
数据库设计
CREATE DATABASE book_manage;
USE book_manage;
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
email VARCHAR(100),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE books (
id INT PRIMARY KEY AUTO_INCREMENT,VARCHAR(200) NOT NULL,
author VARCHAR(100) NOT NULL,
isbn VARCHAR(13) UNIQUE,
price DECIMAL(10,2),
cover_image VARCHAR(255),
description TEXT,
published_date DATE,
created_by INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (created_by) REFERENCES users(id)
);
配置文件
<?php
// config/database.php
define('DB_HOST', 'localhost');
define('DB_USER', 'root');
define('DB_PASS', '');
define('DB_NAME', 'book_manage');
function getConnection() {
try {
$conn = new PDO(
"mysql:host=" . DB_HOST . ";dbname=" . DB_NAME,
DB_USER,
DB_PASS
);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $conn;
} catch(PDOException $e) {
die("Connection failed: " . $e->getMessage());
}
}
?>
用户认证系统
<?php
// includes/auth.php
session_start();
function isLoggedIn() {
return isset($_SESSION['user_id']);
}
function requireLogin() {
if (!isLoggedIn()) {
header('Location: /book-manager/admin/login.php');
exit();
}
}
function login($username, $password) {
$conn = getConnection();
$stmt = $conn->prepare("SELECT id, username, password FROM users WHERE username = ?");
$stmt->execute([$username]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if ($user && password_verify($password, $user['password'])) {
$_SESSION['user_id'] = $user['id'];
$_SESSION['username'] = $user['username'];
return true;
}
return false;
}
function logout() {
session_destroy();
header('Location: login.php');
exit();
}
?>
登录页面
<?php
// admin/login.php
require_once '../config/database.php';
require_once '../includes/auth.php';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
if (login($username, $password)) {
header('Location: dashboard.php');
exit();
} else {
$error = "用户名或密码错误";
}
}
?>
<!DOCTYPE html>
<html>
<head>登录 - 图书管理系统</title>
<link rel="stylesheet" href="../assets/css/style.css">
</head>
<body class="login-page">
<div class="login-container">
<h2>图书管理系统登录</h2>
<?php if (isset($error)): ?>
<div class="alert alert-danger"><?php echo $error; ?></div>
<?php endif; ?>
<form method="POST">
<div class="form-group">
<label>用户名</label>
<input type="text" name="username" required>
</div>
<div class="form-group">
<label>密码</label>
<input type="password" name="password" required>
</div>
<button type="submit" class="btn btn-primary">登录</button>
</form>
</div>
</body>
</html>
图书列表(含分页和搜索)
<?php
// admin/books/index.php
require_once '../../config/database.php';
require_once '../../includes/auth.php';
requireLogin();
$conn = getConnection();
$search = $_GET['search'] ?? '';
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
$limit = 10;
$offset = ($page - 1) * $limit;
// 构建查询
$where = '';
if ($search) {
$where = "WHERE title LIKE :search OR author LIKE :search";
}
// 获取总数
$countQuery = "SELECT COUNT(*) as total FROM books $where";
$stmt = $conn->prepare($countQuery);
if ($search) {
$stmt->bindValue(':search', "%$search%");
}
$stmt->execute();
$total = $stmt->fetch(PDO::FETCH_ASSOC)['total'];
$totalPages = ceil($total / $limit);
// 获取图书列表
$query = "SELECT * FROM books $where ORDER BY created_at DESC LIMIT :limit OFFSET :offset";
$stmt = $conn->prepare($query);
if ($search) {
$stmt->bindValue(':search', "%$search%");
}
$stmt->bindValue(':limit', $limit, PDO::PARAM_INT);
$stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
$stmt->execute();
$books = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<?php include '../includes/header.php'; ?>
<div class="container">
<div class="page-header">
<h1>图书管理</h1>
<a href="create.php" class="btn btn-success">新增图书</a>
</div>
<!-- 搜索表单 -->
<form method="GET" class="search-form">
<input type="text" name="search" value="<?php echo htmlspecialchars($search); ?>"
placeholder="搜索标题或作者...">
<button type="submit" class="btn btn-primary">搜索</button>
</form>
<!-- 图书列表 -->
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>封面</th>
<th>标题</th>
<th>作者</th>
<th>价格</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php foreach ($books as $book): ?>
<tr>
<td><?php echo $book['id']; ?></td>
<td>
<?php if ($book['cover_image']): ?>
<img src="../uploads/<?php echo $book['cover_image']; ?>"
width="50" height="70" alt="封面">
<?php endif; ?>
</td>
<td><?php echo htmlspecialchars($book['title']); ?></td>
<td><?php echo htmlspecialchars($book['author']); ?></td>
<td>¥<?php echo number_format($book['price'], 2); ?></td>
<td>
<a href="edit.php?id=<?php echo $book['id']; ?>" class="btn btn-sm">编辑</a>
<a href="delete.php?id=<?php echo $book['id']; ?>"
class="btn btn-sm btn-danger"
onclick="return confirm('确定删除吗?')">删除</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<!-- 分页 -->
<?php if ($totalPages > 1): ?>
<nav>
<ul class="pagination">
<?php if ($page > 1): ?>
<li><a href="?page=<?php echo $page - 1; ?>&search=<?php echo urlencode($search); ?>">« 上一页</a></li>
<?php endif; ?>
<?php for ($i = 1; $i <= $totalPages; $i++): ?>
<li class="<?php echo $i === $page ? 'active' : ''; ?>">
<a href="?page=<?php echo $i; ?>&search=<?php echo urlencode($search); ?>"><?php echo $i; ?></a>
</li>
<?php endfor; ?>
<?php if ($page < $totalPages): ?>
<li><a href="?page=<?php echo $page + 1; ?>&search=<?php echo urlencode($search); ?>">下一页 »</a></li>
<?php endif; ?>
</ul>
</nav>
<?php endif; ?>
</div>
添加图书(含文件上传)
<?php
// admin/books/create.php
require_once '../../config/database.php';
require_once '../../includes/auth.php';
requireLogin();
$conn = getConnection();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$title = $_POST['title'];
$author = $_POST['author'];
$isbn = $_POST['isbn'];
$price = $_POST['price'];
$description = $_POST['description'];
$published_date = $_POST['published_date'];
// 验证
$errors = [];
if (empty($title)) $errors[] = "标题不能为空";
if (empty($author)) $errors[] = "作者不能为空";
// 处理文件上传
$coverImage = null;
if (isset($_FILES['cover_image']) && $_FILES['cover_image']['error'] === 0) {
$allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
$fileType = $_FILES['cover_image']['type'];
if (in_array($fileType, $allowedTypes)) {
$fileExt = pathinfo($_FILES['cover_image']['name'], PATHINFO_EXTENSION);
$fileName = time() . '_' . uniqid() . '.' . $fileExt;
$uploadPath = '../../uploads/' . $fileName;
if (move_uploaded_file($_FILES['cover_image']['tmp_name'], $uploadPath)) {
$coverImage = $fileName;
} else {
$errors[] = "文件上传失败";
}
} else {
$errors[] = "只允许上传JPEG、PNG、GIF格式的图片";
}
}
if (empty($errors)) {
$stmt = $conn->prepare("INSERT INTO books (title, author, isbn, price, description, published_date, cover_image, created_by)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
$stmt->execute([
$title, $author, $isbn, $price, $description,
$published_date, $coverImage, $_SESSION['user_id']
]);
header('Location: index.php?message=success');
exit();
}
}
?>
<?php include '../includes/header.php'; ?>
<div class="container">
<h2>新增图书</h2>
<?php if (!empty($errors)): ?>
<div class="alert alert-danger">
<ul>
<?php foreach ($errors as $error): ?>
<li><?php echo $error; ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<form method="POST" enctype="multipart/form-data">
<div class="form-group">
<label>书名 *</label>
<input type="text" name="title" value="<?php echo $_POST['title'] ?? ''; ?>" required>
</div>
<div class="form-group">
<label>作者 *</label>
<input type="text" name="author" value="<?php echo $_POST['author'] ?? ''; ?>" required>
</div>
<div class="form-group">
<label>ISBN</label>
<input type="text" name="isbn" value="<?php echo $_POST['isbn'] ?? ''; ?>">
</div>
<div class="form-group">
<label>价格</label>
<input type="number" step="0.01" name="price" value="<?php echo $_POST['price'] ?? ''; ?>">
</div>
<div class="form-group">
<label>出版日期</label>
<input type="date" name="published_date" value="<?php echo $_POST['published_date'] ?? ''; ?>">
</div>
<div class="form-group">
<label>封面图片</label>
<input type="file" name="cover_image" accept="image/*">
</div>
<div class="form-group">
<label>简介</label>
<textarea name="description" rows="4"><?php echo $_POST['description'] ?? ''; ?></textarea>
</div>
<button type="submit" class="btn btn-primary">保存</button>
<a href="index.php" class="btn btn-secondary">返回</a>
</form>
</div>
公共函数库
<?php
// includes/functions.php
function sanitizeInput($data) {
return htmlspecialchars(strip_tags(trim($data)));
}
function redirect($url) {
header("Location: $url");
exit();
}
function formatPrice($price) {
return '¥' . number_format($price, 2);
}
function generateCSRFToken() {
if (!isset($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
return $_SESSION['csrf_token'];
}
function verifyCSRFToken($token) {
return isset($_SESSION['csrf_token']) && hash_equals($_SESSION['csrf_token'], $token);
}
?>
安全实践
// 密码哈希处理
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);
// 验证码示例
session_start();
$randomCode = rand(1000, 9999);
$_SESSION['captcha'] = $randomCode;
// 创建简单的验证码图片
header('Content-Type: image/png');
$image = imagecreatetruecolor(120, 40);
$bg = imagecolorallocate($image, 255, 255, 255);
$textColor = imagecolorallocate($image, 0, 0, 0);
imagefilledrectangle($image, 0, 0, 120, 40, $bg);
imagestring($image, 5, 30, 10, $randomCode, $textColor);
imagepng($image);
imagedestroy($image);
前端样式
/* assets/css/style.css */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
line-height: 1.6;
color: #333;
background-color: #f5f5f5;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
.page-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30px;
padding-bottom: 20px;
border-bottom: 1px solid #dee2e6;
}
.btn {
display: inline-block;
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
transition: all 0.3s;
}
.btn-primary {
background-color: #007bff;
color: white;
}
.btn-success {
background-color: #28a745;
color: white;
}
.btn-danger {
background-color: #dc3545;
color: white;
}
.btn-secondary {
background-color: #6c757d;
color: white;
text-decoration: none;
}
.table {
width: 100%;
background-color: white;
border-collapse: collapse;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.table th,
.table td {
padding: 12px;
text-align: left;
border-bottom: 1px solid #dee2e6;
}
.table th {
background-color: #f8f9fa;
font-weight: 600;
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: 500;
}
.form-group input,
.form-group textarea,
.form-group select {
width: 100%;
padding: 8px 12px;
border: 1px solid #ced4da;
border-radius: 4px;
font-size: 14px;
}
.alert {
padding: 12px 20px;
margin-bottom: 20px;
border-radius: 4px;
}
.alert-danger {
background-color: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.alert-success {
background-color: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.pagination {
display: flex;
list-style: none;
padding: 20px 0;
justify-content: center;
}
.pagination li {
margin: 0 5px;
}
.pagination a,
.pagination .active {
display: block;
padding: 8px 12px;
border: 1px solid #dee2e6;
border-radius: 4px;
text-decoration: none;
color: #007bff;
}
.pagination .active {
background-color: #007bff;
color: white;
}
📚 进阶实战项目推荐
在线商城系统
- 商品管理(SKU、库存、分类)
- 购物车功能
- 订单管理
- 支付集成(微信/支付宝)
- 优惠券系统
博客/CMS系统
- 文章管理(Markdown编辑)
- 用户权限(管理员/编辑/作者)
- 评论系统
- 分类标签
- SEO优化
API开发项目
// RESTful API示例
// api/books.php
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
$method = $_SERVER['REQUEST_METHOD'];
$conn = getConnection();
switch ($method) {
case 'GET':
// 获取图书列表
$stmt = $conn->query("SELECT * FROM books");
$books = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode(['status' => 'success', 'data' => $books]);
break;
case 'POST':
// 创建图书
$data = json_decode(file_get_contents('php://input'), true);
$stmt = $conn->prepare("INSERT INTO books (title, author) VALUES (?, ?)");
$stmt->execute([$data['title'], $data['author']]);
echo json_encode(['status' => 'success', 'id' => $conn->lastInsertId()]);
break;
}
🎯 部署与上线
生产环境配置
# .htaccess 安全配置
Options -Indexes
ServerSignature Off
# 防止URL注入
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-zA-Z0-9/]+)$ index.php?route=$1 [QSA,L]
# 保护配置文件
<FilesMatch "\.(env|ini|log)$">
Order allow,deny
Deny from all
</FilesMatch>
性能优化
// 使用Redis缓存
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
// 检查缓存
$cached = $redis->get('books_list');
if ($cached) {
$books = json_decode($cached, true);
} else {
// 查询数据库
$stmt = $conn->query("SELECT * FROM books");
$books = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 设置缓存,10分钟过期
$redis->setex('books_list', 600, json_encode($books));
}
💡 学习建议
- 从简单开始:先完成一个简单的CRUD系统
- 逐步增加功能:慢慢加入用户认证、文件上传、分页等特性
- 代码规范:使用PSR-4自动加载规范,确保代码整洁
- 安全第一:从开始就注意SQL注入、XSS攻击防护
- 版本控制:使用Git管理代码,方便回滚和协作
这个实战项目涵盖了PHP开发的绝大多数核心概念,建议你按照项目结构逐步实现,并在理解的基础上尝试添加新功能(如API接口、数据导出、批量操作等),这将帮助你快速提升PHP实战能力。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播