介绍
我们对 emlog pro 的模板开发,只需符合本「字典」规范即可,无序探究 emlog pro 是怎么运行的。只要是已经成型的完整网站前端代码,都能一定程度转化为 emlog pro 模版。
因此,为了保障模板的显示质量,以及你的艺术和创意性能够不受 emlog 系统的干扰,强烈要求你在制作模板之前,先通过这个流程【纸上画出草图和创意】--【电脑画出设计稿】--【HTML CSS JS 切图还原】--【工程优化】......... 完事俱全后,再按照本字典,对接 emlog pro。
如果目标就是制作一个 emlog 的模板,那么可以先浏览一遍本字典,大概了解 emlog 对哪些参数的支持比较好,以免以后麻烦。
当然,在此之前,你得略微熟悉 PHP 的语法,知道怎么输出,怎么写函数,变量等等。
系统自带模板「default」 只是一个示范参考,不能做到万事俱全,模板开发事宜,一切以本文内容为准。
这不是模板开发教程!这不是模板开发教程!这不是模板开发教程!这是模板开发的「字典」,供 emlog 开发者复制、粘贴、查询、参考使用的开发规范,或 emlog pro 模板的游戏规则。
预祝使用愉快!
( ps: 制作一个合格的开发字典是个有挑战性的事,目前这种形式只是一种解决方案,如有更好建议,敬请提出。)
模板文件系统
模板位置
emlog 的模版位置位于 ./content/templates/< 模版文件夹 >。
模板文件(夹)命名规范
模板的「文件夹」名称,为模板的英文名称。
代码语言:javascript复制如 default、sunshine。
./content/templates/default/
./content/templates/sunshine/
模板文件夹内部,系统的硬性要求有五个文件,即模板里必须要包含以下五个文件,否则系统会报错。
文件名 | 介绍 |
---|---|
header.php | 模板中,博客的 html 头部 |
log_list.php | 模板中,博客的首页(一般为博客文章的列出) |
echo_log.php | 模板中,博客某个文章的文章阅读页 |
page.php | 模板中,博客某个页面的页面显示页(这个后台有设置,用户也可用其他文件显示,比如 page1.php,但 page.php 是默认,必须有) |
404.php | 404 页面 |
preview.jpg | 模板在后台「模板外观设置」页面里的预览图。建议尺寸为 300×225 或这个比例。 |
当然,也有个文件可有,可没有
文件名 | 介绍 |
---|---|
pw.php | 文章密码输入页(如果没有这个文件,则使用系统默认的密码输入页) |
除了上面这些文件,其余的 php 文件结构,大家可据自己的编码和架构风格来确定,如果是全新制作的模板,可参考系统自带模板 default 的模板代码结构(比如 module.php、side.php、css 文件夹)。
模板文件的调用模式
系统对模板的调用模式
上面的七个文件,是 emlog 系统可以直接获取的七个文件,像 DNA 一样刻在了 emlog 系统核心代码里,一切我们的博客行为,都是系统搭配以上文件来调用的。
这些搭配模式 emlog 只是方便常见的博客行为而设计。大家可灵活运用,来适配自己的模板中博客交互设计方式。
emlog pro 后端程序是以路由映射表来控制我们博客页面的显示,我们可理解成「搭配模式」,或「调用模式」。
现在我们假设,我们有了一个博客,首页域名为 http://127.0.0.1/ ,而且我们也暂时没开「伪静态」。
显示「首页」模式
即访问 http://127.0.0.1/
系统输出 header.php log_list.php
输出就是,执行上面两文件的 php 代码内容。当然,非直接执行,是系统通过一些措施来执行,上面两个 php 文件可以访问系统的很多变量。比如 php 常量 BLOG_URL
(博客的地址)。
阅读某个「博文」模式
如访问 http://127.0.0.1/?post=4 (4 是文章 ID,每个文章或页面都有它独有的 ID 号)
系统输出 header.php echo_log.php
显示某个「页面」模式
如访问 http://127.0.0.1/?post=6 (6 是页面 ID)
系统输出 header.php page.php
如果用户在后台设置了其他页面模板,如 page0001,则调用输出相应文件.
系统输出 header.php page0001.php
显示「作者文章」模式
如访问 http://127.0.0.1/?author=1 (1 是作者 ID)
系统输出 header.php log_list.php
我们看到,这个和「首页」模式一样。其实此时,emlog pro 向模板传递的数据不一样。这次,只传递了属于这个作者文章的数据。
下面几个模式也一样道理。
显示「归档文章」模式
如访问 http://127.0.0.1/?record=20221110 (显示日期为 2022 年 11 月 10 日的文章)
系统输出 header.php log_list.php
显示「搜索文章」模式
如访问 http://127.0.0.1/?keyword=emlog(搜索 emlog 后,系统的显示)
系统输出 header.php log_list.php
显示「分类文章」模式
如访问 http://127.0.0.1/?sort=1 (1 是这个文章分类的 ID)
系统输出 header.php log_list.php
显示「标签文章」模式
如访问 http://127.0.0.1/?tag=1 (1 是这个标签分类的 ID)
系统输出 header.php log_list.php
显示「404」模式
如访问 http://127.0.0.1/?post=400 (400 是一个不存在的文章 ID)
系统输出 404.php
显示「密码输入」模式
如访问 http://127.0.0.1/?post=25 (25 是一个有设置密码的文章的 ID)
系统输出 pw.php 或 系统默认的密码输入界面。
前端(模板)怎么知道当前调用模式
这个,目前最简单的办法,就是在前端进行判断。
如果我们的模板或我们的个性比较独特,不想使用 log_list.php 等文件的话,可将 log_list.php 等文件空白(空白可以,但一定要有这个文件,当然,如非特别必要,还是建议使用这些系统建议的文件),可以只使用 header.php。
在 hearder.php 文件中,使用类似如下代码进行逻辑判断,这些代码,在 header.php 中是有效的。
代码语言:javascript复制<?php
if(isset($record) && isset($page)) {
echo "当前是「归档」模式,日期数据是".$record."<br>";
echo "当前是第".$page."页";
}
if(isset($author) && isset($page)) {
echo "当前是「作者」模式,查询作者的 ID 是".$author."<br>";
echo "当前是第".$page."页";
}
if(isset($keyword) && isset($page)) {
echo "当前是「搜索」模式,搜索数据是".$keyword."<br>";
echo "当前是第".$page."页";
}
if(isset($sortid) && isset($page)) {
echo "当前是「分类」模式,查询分类的 ID 是".$sortid."<br>";
echo "当前是第".$page."页";
}
if(isset($tag) && isset($page)) {
echo "当前是「标签」模式,标签数据是".$tag."<br>";
echo "当前是第".$page."页";
}
if(isset($type)) {
if(!empty($password)){
echo "<br>当前是已经根据之前 cookie 中储存的文章密码而跳转到的文章界面";
}
if($type === "blog"){
echo "<br>当前是「文章」阅读模式";
}
if ($type === "page") {
echo "<br>当前是「页面」显示模式";
}
}
至于 「404」模式和「密码输入」模式,这个轮不到 header.php 判断,emlog pro 系统会直接只输出 404.php 或 pw.php(或默认的密码输入界面)。
怎么自定义模式
例:自定义「用户搜索模式」
除了上面的模式,我们可能还会有其他的模式需求,比如「用户搜索」模式。
这个,如何想实现伪静态的话,有点麻烦。有这方面需求,建议使用系统面板中的页面来搞定,如果没有,像其他一样,使用 GET 协议来搞定。
假定我们使用 GET,我们访问的链接是 http://127.0.0.1/?userkeyword=Tom ,那么我们代码就可像上面那样判断了。
代码语言:javascript复制$sunshine_uk = isset($_GET["userkeyword"]) ? addslashes($_GET["userkeyword"]) : "";
// 为防止出现变量冲突,这些直接在全局声明的变量,最好要带上如 sunshine_ 这样的前缀
if(!empty($sunshine_uk)) {
echo "当前是「用户搜索」模式,参数值是".$sunshine_uk;
}
目前,模式有了,但业务代码,只能自己去写了......
例:移动设备模式
如果我们的模板并非响应式的,是桌面端一套模板、移动端一套模板,那也可在 header.php 中进行逻辑判断,这里可以使用如下函数。
代码语言:javascript复制function is_mobile() {
$user_agent = $_SERVER['HTTP_USER_AGENT'];
$mobile_browser = Array(
"mqqbrowser", // 手机 QQ 浏览器
"opera mobi", // 手机 opera
"juc","iuc", // uc 浏览器
"fennec","ios","applewebKit/420","applewebkit/525","applewebkit/532","ipad","iphone","ipaq","ipod",
"iemobile", "windows ce", // windows phone
"240×320","480×640","acer","android","anywhereyougo.com","asus","audio","blackberry","blazer","coolpad" ,"dopod", "etouch", "hitachi","htc","huawei", "jbrowser", "lenovo","lg","lg-","lge-","lge", "mobi","moto","nokia","phone","samsung","sony","symbian","tablet","tianyu","wap","xda","xde","zte"
);
$is_mobile = false;
foreach ($mobile_browser as $device) {
if (stristr($user_agent, $device)) {
$is_mobile = true;
break;
}
}
return $is_mobile;
}
if(is_mobile()){
echo "当前是移动设备模式";
}else{
echo "当前是桌面设备模式";
}
使用 View::getView(); 引入我们的模板文件
View::getView() 的用法如下。
代码语言:javascript复制// 一般,我们在模板 php 代码中引入除上述七个系统必要的文件之外的 php 文件时
// 可能会使用 require_once include 语句,如下
require_once 'function.php';
include 'footer.php';
// 而在 emlog 模板中,我们统一使用如下语句来代替后面的内容
require_once View::getView("function");
include View::getView("footer");
使用 View::getView() 与直接使用 require、include 的区别有一个。
- 在系统找不到这个文件时,不会直接报错,而是前台提示“模板已被损坏,请更换模板”
模板的代码规范
emlog pro 版本的模板,必须符合以下的代码规范。否则将是不合格的模板。
模板体积
体积应以精简为本。最好不要超过 5MB,否则无法在官方商店上线。
模板信息
模板信息要写在 header.php 中,内容很简单。我们假设以「阳光」为例,以下是一个案例。
含义依次为「模板名(最好是中文名)」、「模板的官方 url」、「模板版本号」、「模板的简介」、「模板作者昵称」、「模板作者的个人主页 url」。
这些内容建议尽量不要留空。
代码语言:javascript复制/*
Template Name:阳光
Template Url:https://www.test.com/sunshine/
Version:1.3.3
Description:这是一个以「阳光」为主题的模板,简约大方,适合做个人生活、心情记录使用
Author:张三
Author Url:https://www.test.com
*/
防跨权限访问
为防止模板文件被直接访问(有暴露系统敏感信息的隐患),固在模板中的所有 php 文件的最开头,都应有如下代码。
代码语言:javascript复制if(!defined('EMLOG_ROOT')) {exit('error!');}
模板文件调用 getView
模板中的 php 文件可分为两种。
- 一些模板程序中的函数库、组件库等。
- 主要是前端 HTML 代码,做为视图显示模板。
对于第一类,函数库、组件库文件,比如这个 php 文件中有一些计算日期类的函数等等,使用以下语句引入。如 function.php。
代码语言:javascript复制require_once View::getView("function");
对于第二类,主要是储存前端 HTML 代码的 php 文件,比如 side.php、footer.php,我们使用以下语句引入。
代码语言:javascript复制include View::getView("footer");
模板钩子(挂载点)
为了紧密配合 emlog pro 系统钩子机制的正常运行,每个模板中都应有如下六个挂载点。
挂载点代码 | 挂载点含义 | 挂载点位置 |
---|---|---|
<?php doAction('index_head') ?> | HTML 头部。用于向博客添加 CSS 等内容。 | 模板中 HTML 里 <head>标签的最后面。 |
<?php doAction('index_navi_ext') ?> | 导航栏上的扩展。可用于向导航栏上添加内容,比如插件的页面,或一些类似搜索的小组件。 | 模板中导航栏 HTML 代码的最后面。 |
<?php doAction('index_loglist_top');?> | 首页的内容区最开始。可用于添加主页的公告等。 | 模板中,首页导航栏外后,首页主体内容的最开头。 |
<?php doAction('log_related', $logData) ?> | 添加文章相关内容,比如“打赏”、“收藏、“分享”。 | 模板中,文章阅读页,紧邻文章阅读结尾的区域。 |
<?php doAction('diff_side'); ?> | 侧边栏控制点。【非必须】 | 侧边栏组件上方。 |
<?php doAction('index_footer') ?> | 足部扩展。用于系统和插件在博客页脚处输出内容以及添加 JS 脚本内容。 | 博客模板页脚处内容区。 |
因为各模板各皆有差异,详细位置不做严格要求,但一定要保证挂载点在插件调用时能发挥其应有的作用。
安全方面
因前端模板的性质比较特殊,不能将 XSS 隐患一概过滤,但还是应十分谨慎。
对于用户输入的内容,以及系统输出的内容,如果不是 emlog pro 自带的交互功能,而理论上也不应包含 < script > 的地方,都应使用 php 进行代码过滤。(比如接收网址里的 GET 参数)
示例如下:
代码语言:javascript复制$action = isset($_GET["action"]) ? addslashes($_GET["action"]) : "";
SEO
网站 SEO 优化以个人经验量力而行。这里给出两个建议。
- 在做完模板后,可验证一下 W3C :https://validator.w3.org/ 可以避免犯一些 HTML 语法上的错误。当然它的这些建议仅供参考。
- 可以使用 Chrome 浏览器自带的 dev tool 工具中的 lighthouse 工具来跑一下分,它会给出一些 SEO 上的优化建议。
模板的信息获取
<?=
模板 head 头部
描述 | 代码 | 输出示例 | 备注 |
---|---|---|---|
站点标题 | <?= $site_title ?> | 张三的博客 | 用户可在后台 SEO 中设置 ,这是站点浏览器标签页标题 |
站点关键字 | <?= $site_key ?> | 张三 大学生 运动 摄影 个人网站 | 用户可在后台 SEO 中设置 |
站点描述/文章描述 | <?= $site_description ?> | 张三分享自己的生活,写一些心灵感悟。 | 1.在首页,它是站点描述。2.在文章阅读页,它是文章的摘要。 |
站点的首页 URL | <?= BLOG_URL ?> | http://127.0.0.1 | 可用于引入站点的浏览器图标等 |
站点模板的 URL | <?= TEMPLATE_URL ?> | http://127.0.0.1/content/templates | 可用于向前台引入模板一些 CSS 文件等。 |
模板页顶
描述 | 代码 | 输出示例 | 备注 |
---|---|---|---|
站点的首页 URL | <?= BLOG_URL ?> | http://127.0.0.1 | 可用于设置博客标题< a >标签 href |
博客标题 | <?= $blogname ?> | 张三博客 | HTML 页面显示的博客标题 |
博客副标题 | <?= $bloginfo ?> | 记录心情、生活、照片..... | HTML 页面显示的博客副标题 |
导航栏缓存
缓存,也就是