php 实现相册功能
数据库设计
创建相册系统需要设计数据库表来存储用户、相册和图片信息。常见的表结构包括:
-
users表:存储用户信息
CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL, password VARCHAR(255) NOT NULL, email VARCHAR(100) NOT NULL ); -
albums表:存储相册信息
CREATE TABLE albums ( id INT AUTO_INCREMENT PRIMARY KEY, user_id INT NOT NULL, title VARCHAR(100) NOT NULL, description TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users(id) ); -
photos表:存储图片信息
CREATE TABLE photos ( id INT AUTO_INCREMENT PRIMARY KEY, album_id INT NOT NULL, filename VARCHAR(255) NOT NULL, title VARCHAR(100), description TEXT, uploaded_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (album_id) REFERENCES albums(id) );
文件上传处理
实现图片上传功能需要处理文件上传表单:
// 检查是否有文件上传
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['photo'])) {
$uploadDir = 'uploads/';
$allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
$maxSize = 2 * 1024 * 1024; // 2MB
$file = $_FILES['photo'];
// 验证文件类型和大小
if (in_array($file['type'], $allowedTypes) && $file['size'] <= $maxSize) {
$filename = uniqid() . '_' . basename($file['name']);
$targetPath = $uploadDir . $filename;
if (move_uploaded_file($file['tmp_name'], $targetPath)) {
// 保存到数据库
$stmt = $pdo->prepare("INSERT INTO photos (album_id, filename, title) VALUES (?, ?, ?)");
$stmt->execute([$_POST['album_id'], $filename, $_POST['title']]);
}
}
}
图片展示
创建相册浏览页面显示图片:
// 获取相册中的图片
$stmt = $pdo->prepare("SELECT * FROM photos WHERE album_id = ?");
$stmt->execute([$albumId]);
$photos = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 显示图片
foreach ($photos as $photo) {
echo '<div class="photo">';
echo '<img src="uploads/' . htmlspecialchars($photo['filename']) . '" alt="' . htmlspecialchars($photo['title']) . '">';
echo '<h3>' . htmlspecialchars($photo['title']) . '</h3>';
echo '</div>';
}
缩略图生成
使用GD库生成缩略图:
function createThumbnail($sourcePath, $destPath, $thumbWidth = 200) {
list($width, $height, $type) = getimagesize($sourcePath);
switch ($type) {
case IMAGETYPE_JPEG:
$source = imagecreatefromjpeg($sourcePath);
break;
case IMAGETYPE_PNG:
$source = imagecreatefrompng($sourcePath);
break;
case IMAGETYPE_GIF:
$source = imagecreatefromgif($sourcePath);
break;
default:
return false;
}
$thumbHeight = floor($height * ($thumbWidth / $width));
$thumb = imagecreatetruecolor($thumbWidth, $thumbHeight);
imagecopyresampled($thumb, $source, 0, 0, 0, 0, $thumbWidth, $thumbHeight, $width, $height);
switch ($type) {
case IMAGETYPE_JPEG:
imagejpeg($thumb, $destPath);
break;
case IMAGETYPE_PNG:
imagepng($thumb, $destPath);
break;
case IMAGETYPE_GIF:
imagegif($thumb, $destPath);
break;
}
imagedestroy($source);
imagedestroy($thumb);
return true;
}
安全性考虑
确保相册系统的安全性需要采取以下措施:
- 对用户上传的文件进行严格的类型检查
- 重命名上传的文件避免目录遍历攻击
- 使用预处理语句防止SQL注入
- 对输出内容进行HTML转义防止XSS攻击
- 设置适当的文件权限
- 实现用户认证和授权机制
分页功能
当图片数量较多时,实现分页显示:
$perPage = 12;
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
$offset = ($page - 1) * $perPage;
$stmt = $pdo->prepare("SELECT SQL_CALC_FOUND_ROWS * FROM photos WHERE album_id = ? LIMIT ? OFFSET ?");
$stmt->execute([$albumId, $perPage, $offset]);
$photos = $stmt->fetchAll(PDO::FETCH_ASSOC);
$total = $pdo->query("SELECT FOUND_ROWS()")->fetchColumn();
$totalPages = ceil($total / $perPage);
// 显示分页导航
for ($i = 1; $i <= $totalPages; $i++) {
echo '<a href="?page=' . $i . '">' . $i . '</a> ';
}






