原始代码:
<div class="container">
<div class="row">
<div class="col-lg-12">
<div class="card card-friendlink link-bottom">
<div class="card-header">在线用户--<?php
$arronline=assoc_unique(online_list_cache(),'uid');//获取在线用户信息并且根据uid值去重复
echo count($arronline);
?></div>
<div class="card-body p-a-sm p-b-xs">
<?php
$rew=$conf['url_rewrite_on']==0 ? '?':'';//伪静态
foreach($arronline as $online_user) { //Changed By Eveson
echo "<a class=\"mr-2 float-left\" href=\"".getlistn().$rew."user-{$online_user['uid']}.htm\" target=\"_blank\" >{$online_user['username']}</a>";//此处感觉应该引入js或者html文件
}
function assoc_unique($arr, $key) { //根据指定的key值为数组去重
$tmp_arr = array();
foreach($arr as $k => $v) {
if(in_array($v[$key], $tmp_arr)) {
unset($arr[$k]);
} else {
$tmp_arr[] = $v[$key];
}
}
sort($arr);
return $arr;
}
function getlistn(){//返回修罗主程序所处相对目录
return substr($_SERVER['PHP_SELF'],0,strlen($_SERVER['PHP_SELF'])-10);
}
?>
</div>
</div>
</div>
</div>
这是一个典型的“面条式”代码示例,虽然功能上可以实现,但从插件开发的角度来看,它存在多个严重的问题,是我们在开发中应该避免的反面教材。
问题在哪:
-
原始代码将assoc_unique和getlistn函数定义在HTML输出逻辑之后,导致PHP解析时可能会先调用未声明的函数,引发致命错误(Fatal error: Call to undefined function)
-
路径计算逻辑脆弱:getlistn()通过硬编码截取$_SERVER['PHP_SELF']末尾10字符(大约为“/index.php”的长度,算上符号10个字符),实际路径长度可能变化(如子目录部署),导致生成错误URL,实际上整个xiuno只需要相对路径即可
-
手动拼接$rew变量判断伪静态,不如使用统一的URL生成函数
-
代码结构混乱:PHP函数定义与HTML模板混杂,降低可维护性;xiuno bbs推荐你直接用PHP作为模板引擎,但不是说你可以这样过度混乱的去写
-
重复定义风险:原始代码未检查函数是否存在(我们不能做假设性的判断)
-
过时语法:使用已废弃的float-left等旧版Bootstrap类
修改版:
<?php
if(!function_exists('assoc_unique')){
function assoc_unique($arr, $key) { //根据指定的key值为数组去重
$tmp_arr = array();
foreach($arr as $k => $v) {
if(in_array($v[$key], $tmp_arr)) {
unset($arr[$k]);
} else {
$tmp_arr[] = $v[$key];
}
}
sort($arr);
return $arr;
}
}
//获取在线用户信息并且根据uid值去重复
$arronline=assoc_unique(online_list_cache(),'uid');
?>
<div class="row">
<div class="col-lg-12">
<div class="card card-friendlink link-bottom">
<div class="card-header">在线用户 (<?php echo count($arronline); ?>) </div>
<div class="card-body" hx-boost="true" hx-target="#body" hx-swap="innerHTML">
<?php foreach($arronline as $online_user) : ?>
<a class="btn btn-link" href="<?= url('user-' . $online_user['uid']) ?>"><?= htmlspecialchars($online_user['username'], ENT_QUOTES, 'UTF-8') ?></a>
<?php endforeach; ?>
</div>
</div>
</div>
</div>
修改版的优化思路:
-
将PHP数据处理逻辑完全移至HTML模板之前,结构清晰,一目了然。
-
使用 if(!function_exists(...)) 包装函数定义,有效避免了函数重定义冲突。
-
使用安全的URL生成函数:使用xiuno bbs唯一指定URL生成函数 url() ,它能智能地根据当前配置(如是否开启伪静态等)生成正确的URL,彻底解决了手动拼接的隐患。这是与主程序交互的正确方式。
- 使用防御性编程:虽然我们从来都没在用户名上吃瘪,且所有人都会输入正常的用户名,但以防万一
-
使用更优雅的模板语法:采用 foreach(...) : ... endforeach; 替代大括号{},在HTML环境中更清晰。使用短标签 <?= 让输出语句更简洁。
- 以及,短标签 <?= ... ?> 是PHP一直可用的方式,不需要开启short_open_tag即可使用
-
重新改进HTML结构与样式:使用 btn-link 来给链接增加边距,并且不再需要任何float就可以正确排版,视觉效果更好。移除了不必要的内联样式。
-
添加了HTMX属性,这不是必须的,但这个例子是来自于我正在开发的HTMX现代化计划的一部分,所以就留着了
通过这样的重构,代码从一段“能用但危险”的脚本转变为了一个结构清晰、健壮可靠且易于维护的插件组件。