想自己开发Emlog主题,但不知道从哪开始?我第一个主题做了2个月,踩了无数坑。
现在我把经验总结出来,按这个教程做,新手2周也能做出可用的主题。我的"简洁蓝"主题就是这么来的,现在有500多个站在用。
一、开发前准备:别急着写代码
先搞清楚Emlog主题的结构,不然写半天发现不对。
1.1 Emlog主题目录结构
your-theme/
├── images/ # 图片资源
├── style.css # 样式文件(必须)
├── header.php # 头部模板(必须)
├── footer.php # 底部模板(必须)
├── index.php # 首页模板(必须)
├── log_list.php # 文章列表模板
├── log.php # 文章页模板
├── page.php # 页面模板
├── comments.php # 评论模板
└── module.php # 模块函数(可选)
必须文件: style.css、header.php、footer.php、index.php。少一个主题就不能用。
1.2 开发环境建议
我的配置:
- 本地环境:PHPStudy(Windows)或 MAMP(Mac)
- 代码编辑器:VS Code 或 PHPStorm
- 浏览器:Chrome + 开发者工具
- 测试站点:本地Emlog安装
别在线上站开发:改错了网站就挂了。一定要在本地或测试服务器开发。
二、style.css:主题的身份证
这个文件不只是样式,还包含主题信息。
2.1 基本信息(必须)
/*
Theme Name: 简洁蓝
Theme Url: https://www.xuewutheme.com/
Description: 简洁蓝色系Emlog主题,适合技术博客
Version: 1.0
Author: 大佬虾
Author Url: https://www.xuewutheme.com/
*/
注意:
- Theme Name:主题名,后台显示用
- Version:版本号,更新主题时需要
- 这些信息Emlog后台会读取,必须写对
2.2 基础样式
先写重置样式,避免浏览器默认样式干扰:
/* 重置样式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: "Microsoft YaHei", sans-serif;
line-height: 1.6;
color: #333;
background: #f5f5f5;
}
a {
color: #0066cc;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
我的经验: 先写基础样式,确保各浏览器表现一致。
三、header.php:网站头部
头部包含LOGO、导航、搜索等。
3.1 基本结构
<!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 $site_title; ?> - <?php echo $site_description; ?></title>
<link rel="stylesheet" href="<?php echo TEMPLATE_URL; ?>style.css">
<?php doAction('index_head'); ?>
</head>
<body>
<header class="site-header">
<div class="container">
<!-- LOGO -->
<div class="logo">
<a href="<?php echo BLOG_URL; ?>">
<h1><?php echo $blogname; ?></h1>
</a>
<p class="description"><?php echo $bloginfo; ?></p>
</div>
<!-- 导航 -->
<nav class="main-nav">
<ul>
<li><a href="<?php echo BLOG_URL; ?>">首页</a></li>
<?php
// 显示分类导航
$navs = getNavs();
foreach ($navs as $nav):
?>
<li><a href="<?php echo $nav['url']; ?>"><?php echo $nav['naviname']; ?></a></li>
<?php endforeach; ?>
</ul>
</nav>
<!-- 搜索框 -->
<div class="search-box">
<form action="<?php echo BLOG_URL; ?>index.php" method="get">
<input type="text" name="keyword" placeholder="搜索文章...">
<button type="submit">搜索</button>
</form>
</div>
</div>
</header>
<main class="site-main">
关键变量:
$site_title:页面标题$blogname:网站名称$bloginfo:网站描述BLOG_URL:网站根地址TEMPLATE_URL:主题目录地址
四、footer.php:网站底部
底部包含版权信息、统计代码等。
4.1 基本结构
</main> <!-- 接header.php的main标签 -->
<footer class="site-footer">
<div class="container">
<div class="footer-content">
<!-- 版权信息 -->
<div class="copyright">
<p>© <?php echo date('Y'); ?> <?php echo $blogname; ?>. All rights reserved.</p>
<p>Powered by <a href="https://www.emlog.net" target="_blank">Emlog</a></p>
<p>Theme by <a href="https://www.xuewutheme.com" target="_blank">大佬虾</a></p>
</div>
<!-- 友情链接 -->
<div class="friend-links">
<h3>友情链接</h3>
<ul>
<?php
$links = getLinks();
foreach ($links as $link):
?>
<li><a href="<?php echo $link['url']; ?>" target="_blank"><?php echo $link['sitename']; ?></a></li>
<?php endforeach; ?>
</ul>
</div>
</div>
</div>
</footer>
<?php doAction('index_footer'); ?>
</body>
</html>
注意: doAction('index_footer') 是钩子,插件可能在这里插入代码(比如统计代码)。
五、index.php:首页模板
首页显示文章列表。
5.1 基本结构
<?php if (!defined('EMLOG_ROOT')) {exit('error!');} ?>
<?php include View::getView('header'); ?>
<div class="content">
<?php if (!empty($logs)): ?>
<?php foreach ($logs as $value): ?>
<article class="post">
<h2 class="post-title">
<a href="<?php echo $value['log_url']; ?>"><?php echo $value['log_title']; ?></a>
</h2>
<div class="post-meta">
<span class="date"><?php echo gmdate('Y-m-d', $value['date']); ?></span>
<span class="category">
<a href="<?php echo $value['sort_url']; ?>"><?php echo $value['sortname']; ?></a>
</span>
<span class="comments">
<a href="<?php echo $value['log_url']; ?>#comments">评论(<?php echo $value['comnum']; ?>)</a>
</span>
<span class="views">浏览(<?php echo $value['views']; ?>)</span>
</div>
<div class="post-excerpt">
<?php echo $value['log_description']; ?>
</div>
<div class="post-more">
<a href="<?php echo $value['log_url']; ?>">阅读全文</a>
</div>
</article>
<?php endforeach; ?>
<?php else: ?>
<div class="no-content">
<p>暂无文章</p>
</div>
<?php endif; ?>
<!-- 分页 -->
<div class="pagination">
<?php echo $page_url; ?>
</div>
</div>
<?php include View::getView('footer'); ?>
关键变量:
$logs:文章列表数组$value['log_url']:文章链接$value['log_title']:文章标题$page_url:分页链接
六、log.php:文章页模板
显示单篇文章内容。
6.1 基本结构
<?php if (!defined('EMLOG_ROOT')) {exit('error!');} ?>
<?php include View::getView('header'); ?>
<div class="content">
<article class="single-post">
<h1 class="post-title"><?php echo $log_title; ?></h1>
<div class="post-meta">
<span class="date">发布时间:<?php echo gmdate('Y-m-d H:i', $date); ?></span>
<span class="category">分类:<a href="<?php echo $sort_url; ?>"><?php echo $sortname; ?></a></span>
<span class="views">浏览:<?php echo $views; ?></span>
<?php if ($author): ?>
<span class="author">作者:<?php echo $author; ?></span>
<?php endif; ?>
</div>
<div class="post-content">
<?php echo $log_content; ?>
</div>
<div class="post-tags">
<strong>标签:</strong>
<?php if (!empty($tag)): ?>
<?php foreach ($tag as $t): ?>
<a href="<?php echo Url::tag($t['tag']); ?>"><?php echo $t['tag']; ?></a>
<?php endforeach; ?>
<?php else: ?>
暂无标签
<?php endif; ?>
</div>
<!-- 上一篇下一篇 -->
<div class="post-nav">
<?php if ($neighborLog['prev']): ?>
<div class="prev">
<span>上一篇:</span>
<a href="<?php echo $neighborLog['prev']['log_url']; ?>"><?php echo $neighborLog['prev']['log_title']; ?></a>
</div>
<?php endif; ?>
<?php if ($neighborLog['next']): ?>
<div class="next">
<span>下一篇:</span>
<a href="<?php echo $neighborLog['next']['log_url']; ?>"><?php echo $neighborLog['next']['log_title']; ?></a>
</div>
<?php endif; ?>
</div>
</article>
<!-- 评论 -->
<?php include View::getView('comments'); ?>
</div>
<?php include View::getView('footer'); ?>
注意: $log_content 是文章内容,Emlog已经处理了格式。
七、module.php:自定义函数
有些功能需要自定义函数,比如最新文章、热门标签。
7.1 示例:最新文章函数
<?php
// 最新文章
function getLatestPosts($num = 10) {
$db = Database::getInstance();
$sql = "SELECT * FROM " . DB_PREFIX . "blog
WHERE hide='n' AND type='blog'
ORDER BY date DESC
LIMIT $num";
$result = $db->query($sql);
$posts = [];
while ($row = $db->fetch_array($result)) {
$row['log_url'] = Url::log($row['gid']);
$posts[] = $row;
}
return $posts;
}
// 在模板中使用
$latestPosts = getLatestPosts(5);
foreach ($latestPosts as $post) {
echo '<li><a href="' . $post['log_url'] . '">' . $post['title'] . '</a></li>';
}
?>
7.2 示例:热门标签
// 热门标签
function getHotTags($num = 20) {
$db = Database::getInstance();
$sql = "SELECT tagname, COUNT(*) as count
FROM " . DB_PREFIX . "tag
GROUP BY tagname
ORDER BY count DESC
LIMIT $num";
$result = $db->query($sql);
$tags = [];
while ($row = $db->fetch_array($result)) {
$tags[] = [
'name' => $row['tagname'],
'count' => $row['count'],
'url' => Url::tag(rawurlencode($row['tagname']))
];
}
return $tags;
}
八、响应式设计:适配手机
现在一半流量来自手机,必须做响应式。
8.1 媒体查询
/* 桌面端(默认) */
.container {
width: 1200px;
margin: 0 auto;
}
/* 平板 */
@media (max-width: 1024px) {
.container {
width: 90%;
}
.main-nav ul {
flex-wrap: wrap;
}
}
/* 手机 */
@media (max-width: 768px) {
.container {
width: 95%;
}
.main-nav {
display: none; /* 改成汉堡菜单 */
}
.post-content img {
max-width: 100%;
height: auto;
}
}
8.2 我的响应式策略
- 移动优先:先写手机样式,再写桌面
- 断点设置:768px(手机)、1024px(平板)、1200px(桌面)
- 图片优化:手机用小图,桌面用大图
- 触摸友好:按钮至少44×44像素
九、主题打包和安装
开发完要打包,让别人能用。
9.1 打包结构
简洁蓝主题.zip
└── simple-blue/ # 主题文件夹名
├── images/
├── style.css
├── header.php
├── footer.php
├── index.php
├── log.php
├── page.php
├── comments.php
├── module.php
└── screenshot.png # 主题截图(必须)
注意: 主题文件夹名要和style.css里的Theme Name对应。
9.2 安装测试
- 本地Emlog后台 → 主题 → 上传安装
- 启用主题
- 检查所有页面是否正常
- 测试响应式
- 检查PHP错误日志
我的测试清单:
- [ ] 首页显示正常
- [ ] 文章页显示正常
- [ ] 分类页显示正常
- [ ] 搜索功能正常
- [ ] 评论功能正常
- [ ] 手机端显示正常
- [ ] 没有PHP错误
十、常见问题
Q:主题安装后显示空白?
A:可能原因:
- PHP语法错误(看错误日志)
- 缺少必须文件(style.css、header.php等)
- 文件编码不对(用UTF-8无BOM)
Q:自定义函数不生效?
A:检查:
- 函数名是否冲突
- 是否在module.php里
- 模板里是否调用了
Q:样式在手机端乱了?
A:可能:
- 没做响应式
- 图片太大
- 用了固定宽度
Q:怎么更新主题?
A:步骤:
- 修改style.css里的Version
- 用户后台会提示更新
- 上传新版本覆盖
- 清除浏览器缓存
十一、我的第一个主题开发记录
第1周: 学习Emlog模板结构,看官方文档
第2周: 写基础模板,各种报错
第3周: 调试,解决兼容性问题
第4周: 做响应式,适配手机
第5周: 测试,修复bug
第6周: 发布,收集反馈
第7-8周: 根据反馈优化
踩过的坑:
- 文件编码问题(BOM头导致空白)
- PHP版本兼容(有的函数老版本没有)
- 浏览器兼容(IE真是个坑)
- 性能问题(数据库查询太多)
建议: 第一个主题别追求完美,先做出来能用,再慢慢优化。
十二、学习资源
- 官方文档:https://www.emlog.net/docs
- 主题开发教程:Emlog论坛有很多
- 参考主题:下载官方主题研究代码
- CSS学习:MDN Web Docs
- PHP学习:PHP官方手册
我的学习路径:
- 先看官方主题代码
- 改现有主题练手
- 自己从头写一个
- 发布收集反馈
- 持续优化
十三、最后建议
主题开发不难,难在坚持。我的建议:
- 从简单开始:先做单栏,再做复杂布局
- 多测试:不同浏览器、不同设备都测
- 代码规范:写好注释,方便

评论框