HTML5+PHP+JS+CSS+JSON 个人博客系统
下面是一个完整的个人博客系统实现方案,使用HTML5作为前端,PHP处理后端逻辑,JSON作为数据存储,CSS进行样式设计,并支持伪静态URL。
系统结构
/blog/
├── index.php # 首页入口
├── admin/ # 后台管理目录
│ ├── index.php # 后台首页
│ ├── login.php # 登录处理
│ └── logout.php # 退出处理
├── includes/ # 包含文件
│ ├── config.php # 配置文件
│ ├── functions.php # 公共函数
│ └── auth.php # 认证检查
├── posts/ # 文章存储目录
│ ├── sample-post.json # 示例文章
│ └── ... # 其他文章
├── static/ # 静态资源
│ ├── css/
│ │ └── style.css # 主样式表
│ ├── js/
│ │ └── main.js # 主JavaScript文件
│ └── images/ # 图片资源
└── templates/ # 模板文件
├── header.php # 页头
├── footer.php # 页脚
├── home.php # 首页模板
├── post.php # 文章页模板
└── admin/ # 后台模板
├── dashboard.php # 仪表盘
└── editor.php # 编辑器
实现代码
1. 配置文件 (includes/config.php)
<?php
// 博客配置
define('BLOG_TITLE', '我的个人博客');
define('BLOG_DESCRIPTION', '一个简单的个人博客系统');
define('BLOG_AUTHOR', '博主');
define('POSTS_DIR', __DIR__ . '/../posts/');
define('ADMIN_USERNAME', 'admin');
define('ADMIN_PASSWORD_HASH', password_hash('yourpassword', PASSWORD_DEFAULT)); // 替换为你的密码
// 开启伪静态
define('REWRITE_ENABLED', true);
// 时区设置
date_default_timezone_set('Asia/Shanghai');
2. 公共函数 (includes/functions.php)
<?php
require_once 'config.php';
// 获取所有文章
function get_all_posts() {
$posts = [];
$files = glob(POSTS_DIR . '*.json');
foreach ($files as $file) {
$content = file_get_contents($file);
$post = json_decode($content, true);
$post['slug'] = basename($file, '.json');
$posts[] = $post;
}
// 按日期排序
usort($posts, function($a, $b) {
return strtotime($b['date']) - strtotime($a['date']);
});
return $posts;
}
// 获取单篇文章
function get_post($slug) {
$file = POSTS_DIR . $slug . '.json';
if (file_exists($file)) {
$content = file_get_contents($file);
$post = json_decode($content, true);
$post['slug'] = $slug;
return $post;
}
return null;
}
// 保存文章
function save_post($slug, $data) {
$file = POSTS_DIR . $slug . '.json';
return file_put_contents($file, json_encode($data, JSON_PRETTY_PRINT));
}
// 删除文章
function delete_post($slug) {
$file = POSTS_DIR . $slug . '.json';
if (file_exists($file)) {
return unlink($file);
}
return false;
}
// 生成SEO友好的URL slug
function generate_slug($title) {
$slug = preg_replace('/[^a-z0-9]+/', '-', strtolower($title));
$slug = trim($slug, '-');
return $slug;
}
// 伪静态URL处理
function get_clean_url() {
if (REWRITE_ENABLED && isset($_SERVER['PATH_INFO'])) {
return trim($_SERVER['PATH_INFO'], '/');
}
return isset($_GET['page']) ? $_GET['page'] : 'home';
}
3. 认证检查 (includes/auth.php)
<?php
require_once 'config.php';
require_once 'functions.php';
session_start();
function is_logged_in() {
return isset($_SESSION['logged_in']) && $_SESSION['logged_in'] === true;
}
function require_login() {
if (!is_logged_in()) {
header('Location: /admin/login.php');
exit;
}
}
function login($username, $password) {
if ($username === ADMIN_USERNAME && password_verify($password, ADMIN_PASSWORD_HASH)) {
$_SESSION['logged_in'] = true;
return true;
}
return false;
}
function logout() {
session_destroy();
header('Location: /admin/login.php');
exit;
}
4. 前端入口 (index.php)
<?php
require_once 'includes/config.php';
require_once 'includes/functions.php';
$page = get_clean_url();
// 路由处理
if ($page === 'home' || empty($page)) {
// 首页
$posts = get_all_posts();
include 'templates/header.php';
include 'templates/home.php';
include 'templates/footer.php';
} elseif (preg_match('/^post\/([a-z0-9\-]+)$/', $page, $matches)) {
// 文章页
$post = get_post($matches[1]);
if ($post) {
include 'templates/header.php';
include 'templates/post.php';
include 'templates/footer.php';
} else {
header("HTTP/1.0 404 Not Found");
include 'templates/header.php';
echo '<h1>文章未找到</h1>';
include 'templates/footer.php';
}
} else {
// 404
header("HTTP/1.0 404 Not Found");
include 'templates/header.php';
echo '<h1>页面未找到</h1>';
include 'templates/footer.php';
}
5. 页头模板 (templates/header.php)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php echo BLOG_TITLE; ?> - <?php echo isset($post) ? $post['title'] : '首页'; ?></title>
<meta name="description" content="<?php echo BLOG_DESCRIPTION; ?>">
<meta name="author" content="<?php echo BLOG_AUTHOR; ?>">
<link rel="stylesheet" href="/static/css/style.css">
</head>
<body>
<header class="site-header">
<h1><a href="/"><?php echo BLOG_TITLE; ?></a></h1>
<p><?php echo BLOG_DESCRIPTION; ?></p>
<nav>
<a href="/">首页</a>
<?php if (is_logged_in()): ?>
<a href="/admin/">后台</a>
<a href="/admin/logout.php">退出</a>
<?php else: ?>
<a href="/admin/login.php">登录</a>
<?php endif; ?>
</nav>
</header>
<main class="container">
6. 页脚模板 (templates/footer.php)
</main>
<footer class="site-footer">
<p>© <?php echo date('Y'); ?> <?php echo BLOG_AUTHOR; ?>. 保留所有权利.</p>
</footer>
<script src="/static/js/main.js"></script>
</body>
</html>
7. 首页模板 (templates/home.php)
<section class="posts-list">
<h2>最新文章</h2>
<?php foreach ($posts as $post): ?>
<article class="post-summary">
<h3><a href="/post/<?php echo $post['slug']; ?>"><?php echo htmlspecialchars($post['title']); ?></a></h3>
<div class="post-meta">
<time datetime="<?php echo $post['date']; ?>"><?php echo date('Y-m-d', strtotime($post['date'])); ?></time>
</div>
<div class="post-excerpt">
<?php echo nl2br(htmlspecialchars(substr($post['content'], 0, 200) . '...')); ?>
</div>
<a href="/post/<?php echo $post['slug']; ?>" class="read-more">阅读更多</a>
</article>
<?php endforeach; ?>
</section>
8. 文章页模板 (templates/post.php)
<article class="post-full">
<h2><?php echo htmlspecialchars($post['title']); ?></h2>
<div class="post-meta">
<time datetime="<?php echo $post['date']; ?>"><?php echo date('Y-m-d H:i', strtotime($post['date'])); ?></time>
</div>
<div class="post-content">
<?php echo nl2br(htmlspecialchars($post['content'])); ?>
</div>
<?php if (is_logged_in()): ?>
<div class="post-actions">
<a href="/admin/editor.php?slug=<?php echo $post['slug']; ?>" class="edit-post">编辑</a>
<a href="/admin/delete.php?slug=<?php echo $post['slug']; ?>" class="delete-post" onclick="return confirm('确定要删除这篇文章吗?')">删除</a>
</div>
<?php endif; ?>
</article>
9. 后台登录 (admin/login.php)
<?php
require_once '../includes/auth.php';
if (is_logged_in()) {
header('Location: /admin/');
exit;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
if (login($username, $password)) {
header('Location: /admin/');
exit;
} else {
$error = '用户名或密码错误';
}
}
include '../templates/header.php';
?>
<div class="login-form">
<h2>后台登录</h2>
<?php if (isset($error)): ?>
<div class="error"><?php echo $error; ?></div>
<?php endif; ?>
<form method="post">
<div class="form-group">
<label for="username">用户名:</label>
<input type="text" id="username" name="username" required>
</div>
<div class="form-group">
<label for="password">密码:</label>
<input type="password" id="password" name="password" required>
</div>
<button type="submit">登录</button>
</form>
</div>
<?php include '../templates/footer.php'; ?>
10. 后台首页 (admin/index.php)
<?php
require_once '../includes/auth.php';
require_login();
$posts = get_all_posts();
include '../templates/header.php';
?>
<div class="admin-dashboard">
<h2>文章管理</h2>
<a href="/admin/editor.php" class="new-post">新建文章</a>
<table class="posts-table">
<thead>
<tr>
<th>标题</th>
<th>日期</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php foreach ($posts as $post): ?>
<tr>
<td><?php echo htmlspecialchars($post['title']); ?></td>
<td><?php echo date('Y-m-d', strtotime($post['date'])); ?></td>
<td>
<a href="/admin/editor.php?slug=<?php echo $post['slug']; ?>">编辑</a>
<a href="/admin/delete.php?slug=<?php echo $post['slug']; ?>" onclick="return confirm('确定要删除这篇文章吗?')">删除</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php include '../templates/footer.php'; ?>
11. 编辑器 (admin/editor.php)
<?php
require_once '../includes/auth.php';
require_login();
$slug = $_GET['slug'] ?? '';
$post = $slug ? get_post($slug) : null;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$title = trim($_POST['title']);
$content = trim($_POST['content']);
$date = date('Y-m-d H:i:s');
$new_slug = generate_slug($title);
$post_data = [
'title' => $title,
'content' => $content,
'date' => $date
];
// 如果是编辑现有文章且标题改变,需要删除旧文件
if ($post && $slug !== $new_slug) {
delete_post($slug);
}
if (save_post($new_slug, $post_data)) {
header('Location: /admin/');
exit;
} else {
$error = '保存文章时出错';
}
}
include '../templates/header.php';
?>
<div class="post-editor">
<h2><?php echo $post ? '编辑文章' : '新建文章'; ?></h2>
<?php if (isset($error)): ?>
<div class="error"><?php echo $error; ?></div>
<?php endif; ?>
<form method="post">
<div class="form-group">
<label for="title">标题:</label>
<input type="text" id="title" name="title" value="<?php echo $post ? htmlspecialchars($post['title']) : ''; ?>" required>
</div>
<div class="form-group">
<label for="content">内容:</label>
<textarea id="content" name="content" rows="15" required><?php echo $post ? htmlspecialchars($post['content']) : ''; ?></textarea>
</div>
<button type="submit">保存</button>
<a href="/admin/" class="cancel">取消</a>
</form>
</div>
<?php include '../templates/footer.php'; ?>
12. 删除文章 (admin/delete.php)
<?php
require_once '../includes/auth.php';
require_login();
$slug = $_GET['slug'] ?? '';
if ($slug && delete_post($slug)) {
header('Location: /admin/');
exit;
} else {
header('Location: /admin/?error=delete_failed');
exit;
}
13. 退出登录 (admin/logout.php)
<?php
require_once '../includes/auth.php';
logout();
14. 主样式表 (static/css/style.css)
/* 基础样式 */
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
margin: 0;
padding: 0;
color: #333;
background-color: #f9f9f9;
}
.container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
/* 页头样式 */
.site-header {
background: #333;
color: #fff;
padding: 20px 0;
text-align: center;
}
.site-header a {
color: #fff;
text-decoration: none;
}
.site-header nav a {
margin: 0 10px;
padding: 5px 10px;
border-radius: 3px;
}
.site-header nav a:hover {
background: #555;
}
/* 页脚样式 */
.site-footer {
text-align: center;
padding: 20px 0;
margin-top: 40px;
border-top: 1px solid #ddd;
}
/* 文章列表样式 */
.posts-list {
margin-top: 30px;
}
.post-summary {
background: #fff;
padding: 20px;
margin-bottom: 20px;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
.post-summary h3 {
margin-top: 0;
}
.post-meta {
color: #666;
font-size: 0.9em;
margin-bottom: 10px;
}
.post-excerpt {
margin-bottom: 15px;
}
.read-more {
display: inline-block;
background: #333;
color: #fff;
padding: 5px 10px;
text-decoration: none;
border-radius: 3px;
font-size: 0.9em;
}
/* 完整文章样式 */
.post-full {
background: #fff;
padding: 30px;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
.post-content {
margin-top: 20px;
}
/* 后台样式 */
.admin-dashboard {
background: #fff;
padding: 30px;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
.new-post {
display: inline-block;
background: #4CAF50;
color: #fff;
padding: 8px 15px;
margin-bottom: 20px;
text-decoration: none;
border-radius: 3px;
}
.posts-table {
width: 100%;
border-collapse: collapse;
}
.posts-table th, .posts-table td {
padding: 10px;
text-align: left;
border-bottom: 1px solid #ddd;
}
.posts-table th {
background: #f5f5f5;
}
.posts-table a {
margin-right: 10px;
color: #333;
}
/* 编辑器样式 */
.post-editor {
background: #fff;
padding: 30px;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
.form-group input[type="text"],
.form-group textarea {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 3px;
}
.form-group textarea {
min-height: 300px;
}
button[type="submit"] {
background: #4CAF50;
color: #fff;
border: none;
padding: 10px 20px;
border-radius: 3px;
cursor: pointer;
}
.cancel {
margin-left: 10px;
color: #333;
text-decoration: none;
}
/* 登录表单样式 */
.login-form {
max-width: 400px;
margin: 50px auto;
background: #fff;
padding: 30px;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
.login-form h2 {
margin-top: 0;
}
.error {
color: #f44336;
margin-bottom: 15px;
padding: 10px;
background: #ffebee;
border-radius: 3px;
}
/* 响应式设计 */
@media (max-width: 600px) {
.container {
padding: 10px;
}
.post-full, .post-summary, .admin-dashboard, .post-editor, .login-form {
padding: 15px;
}
}
15. 主JavaScript文件 (static/js/main.js)
document.addEventListener('DOMContentLoaded', function() {
// 可以在这里添加前端交互逻辑
console.log('博客系统已加载');
// 示例:为代码块添加语法高亮
document.querySelectorAll('pre code').forEach((block) => {
hljs.highlightBlock(block);
});
});
16. 伪静态配置 (Apache的.htaccess)
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# 首页
RewriteRule ^$ index.php [L]
# 文章页
RewriteRule ^post/([a-z0-9\-]+)$ index.php?page=post/$1 [L]
# 其他页面
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?page=$1 [L,QSA]
</IfModule>
部署说明
- 将上述文件按照目录结构放置到你的Web服务器上
- 确保服务器支持PHP (PHP 7.0+)
- 确保posts目录有写入权限 (
chmod 775 posts/) - 如果使用Apache,确保启用了mod_rewrite模块
- 修改admin/config.php中的用户名和密码
功能特点
- 无数据库设计:使用JSON文件存储文章数据
- 伪静态URL:支持友好的URL结构
- 响应式设计:适配各种设备屏幕
- 完整的前后台分离:HTML5实现前台展示,PHP处理后端逻辑
- 简单的文章管理:支持创建、编辑、删除文章
- 基础认证系统:保护后台管理功能
扩展建议
- 添加文章分类功能
- 实现文章标签系统
- 添加评论功能
- 实现文章搜索
- 添加图片上传功能
- 实现缓存机制提高性能
这个博客系统简单但功能完整,适合个人使用。你可以根据需要进一步扩展和定制。 更多详情:baijiahao.baidu.com/s?id=183050…