Discuz! 应用开发中遇到的两个坑
坑一:common()方法并不是所有类都会执行的。
这是Discuz!插件开发文档里的描述:
common() 所有模块执行前被调用 全局嵌入点类
代码如下:
class plugin_test {
function common() {
echo 123;
}
}
class plugin_test_forum extends plugin_test {
function viewthread_top_output() {
echo 234;
}
}
访问论坛页面,并不会触发到父类plugin_test的common方法执行。
坑二:系统函数updatetable()存在bug。
先看函数定义(代码较多,中间部分省略只做注释):
if(!$query = DB::query("SHOW CREATE TABLE ".DB::table($newtable), 'SILENT')) {
// 创建表逻辑
} else {
$value = DB::fetch($query);
$oldcols = updatetable_getcolumn($value['Create Table']);
$updates = array();
$allfileds =array_keys($newcols);
foreach ($newcols as $key => $value) {
if($key == 'PRIMARY') {
// 添加主键
} elseif ($key == 'KEY') {
// 添加索引
} elseif ($key == 'UNIQUE') {
// 添加索引
} else {
// 添加字段
}
}
if(!empty($updates)) {
$usql = "ALTER TABLE ".DB::table($newtable)." ".implode(', ', $updates);
if(!DB::query($usql, 'SILENT')) {
return array(-1, $newtable);
}
}
}
通过代码能够看出,这个方法是可以根据表中的结构决定是否需要添加字段。
由于本人需要往post表添加字段,所以需要判断是否已有字段才进行添加。
实际使用中发现,永远不会执行到添加字段的逻辑,if(!$query = DB::query("SHOW CREATE TABLE ".DB::table($newtable), 'SILENT'))这个判断永远成立。
问题的根源在install的sql本身,代码如下:
CREATE TABLE IF NOT EXISTS `pre_forum_post` (
`extstring` varchar(15) NOT NULL,
) ENGINE=MyISAM;
注意上面这里的这个匹配
preg_match_all("/CREATE\s+TABLE.+?pre\_(.+?)\s*\((.+?)\)\s*(ENGINE|TYPE)\s*=\s*(\w+)/is", $sql, $matches);
$newtables = empty($matches[1])?array():$matches[1];
会导致newtables = forum_post`,执行的结果当然是false。
所以sql里不要写`,这里算是考虑不严的一个bug吧。