涉及文件
分析文件:eadmin/admin/template/AddListtemp.php核心函数:
ReplaceListVars()(e/class/connect.php)渲染入口:
ListHtml() / ListHtmlIndex()(e/class/functions.php)最重要的$r对象的字段就是主表字段
docode("使用程序代码")勾选后,列表内容模板 list.var 不再被当作纯字符串替换,而是先作为 PHP 代码 eval() 执行,执行完再继续做标准的 [!--字段--] 占位符替换。整条链路如下。
1. 数据流:勾选框 → 数据库 → 渲染
表单层
AddListtemp.php:188 中的勾选框:
<input name="docode" type="checkbox" id="docode" value="1"<?=$r['docode']==1?' checked':''?>>
<a title="list.var使用程序代码">使用程序代码</a>
入库层
ListListtemp.php:40-42 把勾选值强转成 0/1,写入 enewslisttemp.docode 字段(修改时同理在 ListListtemp.php:80-82):
$docode=(int)$add['docode'];
$sql=$empire->updatesql("insert into ...enewslisttemp(...,docode) values(...,'$docode')","ins");
读取层
渲染前从模板表查询时把 docode 一并取出,例如:
- 动态列表页
e/action/ListInfo/index.php:257 - 静态生成
e/class/functions.php:2406
2. 核心实现:eval() 前置执行
ReplaceListVars() 是每条信息行都会调用的"列表变量替换"函数。签名见 connect.php:4787:
function ReplaceListVars($no,$listtemp,$subnews,$subtitle,$formatdate,$url,$haveclass,$r,$field,$docode=0){
global $empire,$public_r,$class_r,$class_zr,$fun_r,$dbtbpre,$emod_r,$class_tr,$level_r,$navclassid,$etable_r,$etable_t;
...
if($docode==1)
{
$listtemp=stripSlashes($listtemp);
eval($listtemp); // ← 关键:list.var 作为 PHP 执行
}
$ylisttemp=$listtemp;
...
// 之后才是常规 str_replace('[!--字段--]', ...)
调用方在 functions.php:3360 与 functions.php:3423(ListHtml 静态生成)和 functions.php:3653(ListHtmlIndex)把 $docode 透传进去:
$docode=$listtemp_r['docode'];
...
$repvar=ReplaceListVars($no,$listvar,$subnews,$subtitle,$formatdate,$url,$haveclass,$k,$field,$docode);
3. docode 勾选后"支持的变量" = eval 作用域内可见的变量
因为 eval() 在 ReplaceListVars() 函数局部作用域内执行,所以模板里能直接访问的变量就是该函数的局部变量与 global 声明。这正是 docode 模式下用户写 PHP 时能拿到的全部"变量":
| 变量 | 含义 | 来源 |
|---|---|---|
$r |
当前这条信息的整行数据库记录(id/title/classid/userid/onclick/newstime/titlepic…含模型自定义字段) | 函数参数 $k(fetch 出的行) |
$no |
信息编号(行序号) | 函数参数 |
$listtemp |
list.var 模板字符串本身——用户代码应修改它来输出最终内容 | 函数参数 |
$field |
['mid']、['fr'](字段名数组)、['fcount'] |
ReturnReplaceListF() |
$add |
栏目名(带链接 HTML,由 sys_ReturnBqClassname 生成) |
函数内计算 |
$subnews/$subtitle/$formatdate/$url/$haveclass |
截取字数、时间格式、URL、是否有栏目 | 函数参数 |
$empire $public_r $class_r $class_zr $class_tr $emod_r $level_r $navclassid $dbtbpre $fun_r $etable_r $etable_t |
全局 CMS 上下文 | global 声明 |
其中最关键的是 $r(当前信息记录)和 $listtemp(待输出模板)。常见写法是:
<?php
// list.var 内容示例(docode 模式)
if($r['onclick']>100){
$listtemp='<li class="hot">[!--title--] ([!--onclick--])</li>';
}else{
$listtemp='<li>[!--title--]</li>';
}
?>
4. docode 与普通变量替换是"叠加"关系,不是"二选一"
这是最容易被误解的点。看 connect.php:4797-4860 的执行顺序:
-
先
eval($listtemp)— 用户 PHP 跑完,$listtemp可能已被改成新字符串 -
再 用
for循环对$emod_r[$mid]['listtempf']里列出的每个字段做$listtemp=str_replace('[!--'.$f.'--]',$value,$listtemp)(connect.php:4860) -
再 替换一组固定占位符:
[!--id--][!--classid--][!--class.name--][!--ttid--][!--tt.name--][!--tt.url--][!--userfen--][!--titleurl--][!--no.num--][!--plnum--][!--userid--][!--username--][!--onclick--][!--oldtitle--][!--totaldown--][!--this.classlink--][!--this.classname--]
(
connect.php:4863-4886)
所以即便勾选了 docode,AddListtemp.php 第 289-344 行"(2)、列表内容模板(list.var)支持的变量"里列出的全部 [!--xxx--] 占位符仍然有效——它们是在 eval 之后由系统继续替换的。docode 只是让你能在替换之前用 PHP 动态决定模板长什么样、做条件分支/循环/字段计算。
5. 安全开关 candocode
模板保存时调用 RepPhpAspJspcode() 对 listvar 做过滤(ListListtemp.php:31)。看 functions.php:335-349:
function RepPhpAspJspcode($string){
global $public_r;
if(!$public_r['candocode']){ // ← 系统设置开关
$string=str_replace("<?","<?",$string);
$string=str_replace("<%","<%",$string);
...
}
return $string;
}
- 系统参数
candocode关闭时,<?<%<script>会被转义,即使勾了 docode,PHP 代码也无法在eval里正常执行(被当字符串了)。 - 只有后台开启"允许模板使用代码"(
$public_r['candocode']),docode 的eval才真正能跑用户写的 PHP。这是 docode 的总闸。
小结
docode 的实现本质就是在 ReplaceListVars() 里对 list.var 内容做一次 eval(),且发生在常规 str_replace('[!--字段--]',…) 之前。所谓"docode 模式下支持的变量",并不是一份新变量表,而是 eval 作用域暴露给用户 PHP 的函数局部变量($r/$listtemp/$no/$field/$add 及一批 global);执行完后,原 AddListtemp.php 列出的所有 [!--xxx--] 占位符仍按原机制继续替换。安全上由 $public_r['candocode'] 总闸与保存时的 RepPhpAspJspcode 共同控制——这是一个允许后台管理员在模板里写 PHP 的能力,需谨慎开放。
关键代码位置索引
| 文件 | 行号 | 作用 |
|---|---|---|
eadmin/admin/template/AddListtemp.php |
188 | docode 勾选框 UI |
eadmin/admin/template/AddListtemp.php |
289-344 | list.var 支持的变量说明 |
eadmin/admin/template/ListListtemp.php |
40-42 | 新增模板时写入 docode |
eadmin/admin/template/ListListtemp.php |
80-82 | 修改模板时更新 docode |
e/class/connect.php |
4787 | ReplaceListVars() 函数签名 |
e/class/connect.php |
4797-4801 | eval($listtemp) 核心执行 |
e/class/connect.php |
4860 | 模型字段占位符替换 |
e/class/connect.php |
4863-4886 | 固定占位符替换 |
e/class/functions.php |
335-349 | RepPhpAspJspcode() 安全过滤 |
e/class/functions.php |
2406 | 静态生成时查询 docode |
e/class/functions.php |
3360, 3423 | ListHtml() 透传 docode |
e/class/functions.php |
3653, 3727 | ListHtmlIndex() 透传 docode |
e/action/ListInfo/index.php |
257 | 动态列表页查询 docode |


