很多中小型企业站、信息站用PHPCMS建站时,都会遇到自带标签卡壳的情况——比如想同时调用带缩略图、自定义属性和关联文章阅读量的跨栏目内容,要么写死PHP代码嵌入模板,要么嵌套三四层自带get标签绕半天还容易出错。这篇文章就从场景出发,结合百度站长对代码规范的友好要求,一步步教你从零学PHPCMS自定义模板标签制作,重点讲高复用的万能标签开发,连前端转来只会点PHPCMS基本操作的同学也能上手,还有避坑指南帮你少踩坑。
为什么非要折腾PHPCMS自定义模板标签制作?
很多刚接触的同学会说,嵌套自带标签不也能用吗?何必多此一举?其实原因很实在:自带标签参数固定、调用单一,跨模型跨栏目的数据抓取效率低;而且嵌套太多PHP代码在模板里,前端维护时看不懂,后端改需求还要翻模板;更关键的是,百度虽然不排斥简单的模板PHP代码,但精简规范的自定义标签更利于搜索引擎抓取结构化数据,加载速度也能提个10%-20%左右——这对中小站的SEO收录和用户跳出率控制太重要了。
准备工作:先搞懂PHPCMS标签的底层逻辑
在正式开始PHPCMS自定义模板标签制作前,得先摸清楚它的“脾气”。PHPCMS V9/V9+的标签系统是基于PHP的,核心是把模板里的{tag:xxx}解析成对应的PHP函数或方法,再从数据库里拉取数据渲染出来。
首先要找到标签的存放位置:系统自带的一般在`phpcms/libs/functions/global.func.php`或者模块里的`functions/xxx.func.php`;自定义的话建议放在`phpcms/libs/functions/extend.func.php`,这个文件就是专门给开发者放自定义函数的,不会因为系统升级被覆盖。
然后要掌握标签解析的三个核心:标签名(就是{tag:}里的第一个单词)、参数解析({tag:xxx 参数1=值1 参数2=值2}这些参数要拆成数组传给函数)、数据返回与循环渲染(PHPCMS的循环标签一般用{loop $data $r},所以自定义标签返回的要是一个二维数组)。
实操:写一个万能的跨模型跨栏目调用标签
这里我们以开发一个叫`my_get_list`的标签为例,它能满足:跨任意模型、跨任意栏目(包括父栏目下所有子栏目)、按发布时间/点击量/自定义属性排序、筛选指定条件、调用自定义字段和关联数据这些需求。
第一步:写标签函数
打开`extend.func.php`,在开头加上以下代码:
```php
if (!function_exists('my_get_list')) {
function my_get_list($data) {
// 初始化数据库连接
$db = pc_base::load_model('content_model');
// 初始化返回数组
$return_data = array();
// 解析默认参数,这里的默认参数可以根据自己的需求改
$default = array(
'catid' => 0, // 栏目ID,0为不限
'modelid' => 0, // 模型ID,0为不限
'num' => 10, // 调用数量
'order' => 'updatetime DESC', // 排序方式
'where' => '', // 额外SQL条件
'thumb' => 0, // 是否只调用有缩略图的,1为是
'posid' => 0, // 推荐位ID,0为不限
'fields' => '' // 调用字段,多个用逗号分隔
);
// 合并传入参数和默认参数
$setting = array_merge($default, $data);
// 处理catid,如果是父栏目ID,要查所有子栏目
if ($setting['catid'] > 0) {
$catids = array($setting['catid']);
// 加载栏目模型
$category_db = pc_base::load_model('category_model');
// 递归查子栏目
$child_ids = $category_db->select(array('parentid' => $setting['catid']), 'catid');
foreach ($child_ids as $child) {
$catids[] = $child['catid'];
// 继续递归查孙子栏目,最多查2层
$grandchild_ids = $category_db->select(array('parentid' => $child['catid']), 'catid');
foreach ($grandchild_ids as $grandchild) {
$catids[] = $grandchild['catid'];
}
}
$setting['catid'] = implode(',', $catids);
}
// 组装SQL条件
$sql_where = 'status=99'; // 只调用已审核的内容
if ($setting['catid']) {
$sql_where .= ' AND catid IN('.$setting['catid'].')';
}
if ($setting['modelid']) {
$sql_where .= ' AND modelid='.$setting['modelid'];
}
if ($setting['thumb']) {
$sql_where .= ' AND thumb<>""';
}
if ($setting['posid']) {
// 关联推荐位表
$position_data_db = pc_base::load_model('position_data_model');
$pos_ids = $position_data_db->select(array('posid' => $setting['posid']), 'id,catid');
$id_arr = array();
foreach ($pos_ids as $pos) {
$id_arr[] = $pos['id'].'-'.$pos['catid'];
}
if ($id_arr) {
$sql_where .= ' AND CONCAT(id,"-",catid) IN("'.implode('","', $id_arr).'")';
} else {
return $return_data;
}
}
if ($setting['where']) {
$sql_where .= ' AND '.$setting['where'];
}
// 查主表数据
$main_data = $db->select($sql_where, $setting['fields'], $setting['order'], $setting['num']);
if (!$main_data) {
return $return_data;
}
// 如果调用了自定义字段,还要查附表
// 这里简化处理,因为要判断模型比较复杂,有需要的同学可以自己加模型判断查附表的逻辑
return $main_data;
}
}
```
这里要注意几个strong标注的重点:
1. 一定要先判断函数是否存在,避免和其他自定义函数冲突;
2. 初始化参数很重要,这样调用标签时不用每次都写一堆参数;
3. 递归查子栏目最多查2层就行,太多会影响加载速度;
4. 一定要加`status=99`的条件,不然草稿箱的内容也会被调用出来。
第二步:在模板里测试使用
现在打开你网站的任意模板,比如首页的`index.html`,在需要调用的地方加上:
```html
{pc:my_get_list posid=1 thumb=1 num=10 fields=id,catid,title,thumb,url,description,updatetime}
{/pc}
```
保存后刷新首页,应该就能看到调用出来的内容了。如果没有内容,可以检查一下推荐位ID、是否有已审核的带缩略图的内容。
避坑指南:PHPCMS自定义模板标签制作的常见问题
在实际做PHPCMS自定义模板标签制作时,新手很容易踩几个坑:
- 第一个是参数解析的问题,自定义标签的参数如果是字符串,比如title里有空格,一定要用单引号或者双引号括起来,不然会被解析成多个参数;
- 第二个是缓存的问题,PHPCMS默认会缓存数据,如果你修改了标签函数或者数据库里的内容,要记得去后台清理缓存;
- 第三个是SQL注入的问题,千万不要直接把用户输入的参数拼接到SQL里,这里的示例没有处理用户输入的where参数,如果要开放给前端用,一定要对where参数进行过滤;
- 第四个是系统升级的问题,千万不要修改`global.func.php`或者模块里的函数,不然系统一升级就全没了,一定要放在`extend.func.php`里。
其实PHPCMS的自定义标签系统非常灵活,除了这种列表标签,还可以做详情页标签、栏目标签、会员标签等等。只要掌握了底层逻辑,就能根据自己的需求开发出各种标签,大大提高开发效率和模板的可维护性。现在很多PHPCMS的第三方插件或者模板也是靠自定义标签做出来的,感兴趣的同学可以多研究一下。