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吧。

标签: Discuz

添加新评论