禅道二次开发

 人参与 | 时间:2026-10-17 06:51:16

禅道开源版的禅道次开代码里,`module`目录下的禅道次开每个文件夹就是一个功能模块。比如`bug`、禅道次开`task`、禅道次开`story`,禅道次开每个模块都有自己的禅道次开`control.php`、`model.php`、禅道次开`view`目录。禅道次开二次开发要做的禅道次开,就是禅道次开在这套MVC骨架里塞自己的逻辑,而不是禅道次开另起炉灶。

我见过有人直接改`zentao/module/bug/control.php`,禅道次开把创建bug的禅道次开页面字段删了两个。升级到新版本时,禅道次开这些修改全被覆盖,禅道次开只能对着diff一行行往回找。正确的做法是走禅道的扩展机制——在`extension`目录下建同名模块,或者用`config/ext`里的钩子。禅道官方文档管这叫“扩展”,说白了就是让你别碰核心代码。

先搞懂禅道的路由和命名约定

禅道的URL长这样:`index.php?m=bug&f=create&t=html`。`m`是模块名,`f`是方法名。它没有用现代框架那种RESTful路由,而是靠`m`和`f`两个参数定位到`module/bug/control.php`里的`create`方法。这个方法里通常会调`$this->bug->create()`,也就是`model.php`里的同名方法,最后`$this->display()`渲染`view/create.html.php`。

想加一个“批量关闭bug”的功能,就在`extension/bug/control/`下建`batchClose.php`,写一个`batchClose`方法。禅道加载时会优先读`extension`目录,找不到才回落到核心代码。这样升级时你的文件还在,不会丢。

数据库操作别绕弯子

禅道封装了`$this->dao`对象。写查询用`$this->dao->select('*')->from(TABLE_BUG)->where('id')->eq($bugID)->fetch()`。`TABLE_BUG`是常量,定义在`config/config.php`里,实际表名带前缀`zt_`。直接写SQL也能跑,但用dao层的好处是自动处理表前缀和字段转义。

有个坑:禅道的dao在`fetch()`失败时返回`false`,不是空数组。我见过有人写`if(empty($bug))`判断,结果`false`和空数组都进同一个分支,逻辑就乱了。用`if($bug === false)`更稳。

视图层改起来最琐碎

禅道视图用的是原生PHP模板,没有Twig或Blade。`view/create.html.php`里直接混着HTML和``。想加一个自定义字段,得同时改三处:`config/lang/zh-cn/bug.php`加语言项,`model.php`的`create`方法里加字段验证,`view`模板里加input标签。漏一处就报错。

更省事的办法是用禅道的“自定义”功能。后台→开发→自定义,可以给bug表单加字段,不用写代码。但自定义字段的类型有限,只支持文本、下拉、多选这几种。要加日期范围选择器或者联动下拉,还是得写扩展。

调试和日志

禅道默认不开SQL日志。在`config/my.php`里加`$config->debug = true;`,页面底部会输出所有SQL和耗时。`my.php`是个人配置文件,不会被版本控制覆盖。我习惯在开发时打开,上线前关掉。

还有个土办法:在`model.php`里写`file_put_contents('/tmp/zentao_debug.log', print_r($data, true), FILE_APPEND);`。比Xdebug轻量,适合线上临时排查。记得用完删掉。

禅道二次开发的核心就一句话:用扩展目录覆盖核心逻辑,别直接改源码。听起来简单,但真到改的时候,很多人还是忍不住去动`module`下的文件。改完一时爽,升级火葬场。

顶: 44892踩: 245