本文目录导读:

前置准备
- 环境搭建:本地搭建 Dolibarr 测试环境(推荐使用 Docker 或 XAMPP)。
- 权限设置:确保
htdocs目录和custom/目录有写入权限。 - 开发者文档:参考 Dolibarr Developer Guide 和 Hooks 文档。
模块物理结构(推荐)
Dolibarr 模块放在 htdocs/custom/ 目录下,每个模块是一个独立文件夹,标准结构如下:
my_module/
├── core/
│ └── modules/
│ └── modMyModule.class.php # 模块描述类 (Descriptor)
├── class/
│ └── myobject.class.php # 核心业务类
├── sql/
│ └── llx_myobject.sql # 数据库建表SQL
├── langs/
│ └── en_US/
│ └── myshop.lang # 语言文件
├── tpl/ # 模板文件(可选)
├── img/ # 图标
├── admin/
│ └── mymodule_setup.php # 模块设置页面
├── htdocs/
│ └── mymodule/
│ ├── card.php # 对象详情页
│ ├── list.php # 列表页
│ └── index.php # 入口页
├── mymodule.class.php # 业务逻辑类(可选)
├── core/triggers/
│ └── interface_99_modMyModule_MyTrigger.class.php # 触发器
├── core/hooks/
│ └── myhook.class.php # 钩子
└── README.md
核心开发步骤
1 创建模块描述类(Descriptor)
文件:custom/my_module/core/modules/modMyModule.class.php
<?php
require_once DOL_DOCUMENT_ROOT.'/core/modules/DolibarrModules.class.php';
class modMyModule extends DolibarrModules
{
public $numero = 100001; // 唯一ID(必须>100000)
public $family = 'base'; // 分类
public $module_position = 10; // 菜单排序
public $name = 'MyModule'; // 内部名称
public $description = 'My Custom Module'; // 描述
public $version = '1.0.0';
public $const_name = 'MYMODULE'; // 常量前缀
public $special = 0;
public $picto = 'myobject@my_module'; // 图标(可选)
public $dir = __DIR__;
public function __construct()
{
parent::__construct();
$this->editor_name = 'Your Company';
$this->editor_url = 'https://example.com';
$this->Db = Database::getInstance();
// 定义模块包含的权限
$this->rights[] = [
'id' => 'myobject_read', 'lib' => 'Read objects',
'level' => 1, 'perms' => '$user->rights->myobject->read'
];
$this->rights[] = [
'id' => 'myobject_write', 'lib' => 'Write objects',
'level' => 2, 'perms' => '$user->rights->myobject->write'
];
// 定义菜单
$this->menu[] = [
'fk_menu' => 0, 'type' => 'top', 'titre' => 'MyModule',
'url' => '/custom/my_module/htdocs/mymodule/list.php',
'langs' => 'my_module@my_module', 'enabled' => '$user->rights->myobject->read'
];
}
public function init()
{
$sql = file_get_contents(__DIR__.'/../../sql/llx_myobject.sql');
// 使用 $this->Db->query() 执行
// ...
return 1;
}
public function remove()
{
// 删除表、常量等
return 1;
}
public function update($tab, $var)
{
// 升级脚本
return $this->_load_tables('/custom/my_module/sql/');
}
}
2 创建数据库表(SQL)
文件:sql/llx_myobject.sql
CREATE TABLE IF NOT EXISTS llx_myobject (
rowid INTEGER AUTO_INCREMENT PRIMARY KEY,
ref VARCHAR(128) NOT NULL,
label VARCHAR(255),
status TINYINT DEFAULT 0,
fk_user_creat INTEGER,
date_creation DATETIME,
tms TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
import_key VARCHAR(14)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
3 创建业务类(Class)
文件:class/myobject.class.php
<?php
require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
class MyObject extends CommonObject
{
public $table_element = 'myobject';
public $fields = [
'rowid' => ['type' => 'integer'],
'ref' => ['type' => 'varchar(128)'],
'label' => ['type' => 'varchar(255)'],
'status'=> ['type' => 'tinyint']
];
public function create(User $user)
{
$this->db->begin();
$sql = "INSERT INTO ".MAIN_DB_PREFIX.$this->table_element." (ref, label, status, date_creation, fk_user_creat) ";
$sql.= "VALUES ('".$this->db->escape($this->ref)."', '".$this->db->escape($this->label)."', '".$this->db->escape($this->status)."', NOW(), '".$user->id."')";
$resql = $this->db->query($sql);
if ($resql) {
$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element);
$this->db->commit();
return $this->id;
} else {
$this->error = $this->db->error;
$this->db->rollback();
return -1;
}
}
public function fetch($id)
{
// 类似标准 fetch 实现
}
public function update(User $user, $notrigger = 0)
{
// 更新数据
}
public function delete(User $user)
{
// 删除逻辑
}
}
4 创建页面
列表页 htdocs/mymodule/list.php(简化示例):
<?php
require_once '../../../../main.inc.php';
require_once '../class/myobject.class.php';
llxHeader();
$object = new MyObject($db);
$sql = "SELECT rowid, ref, label FROM ".MAIN_DB_PREFIX."myobject";
$resql = $db->query($sql);
echo '<table class="noborder">';
echo '<tr><th>ID</th><th>Ref</th><th>Label</th></tr>';
while ($obj = $db->fetch_object($resql)) {
echo '<tr><td>'.$obj->rowid.'</td><td>'.$obj->ref.'</td><td>'.$obj->label.'</td></tr>';
}
echo '</table>';
llxFooter();
5 创建语言文件
文件:langs/en_US/my_module.lang
MyModule = My Module myobject_read = Read MyObject myobject_write = Write MyObject
安装与调试
- 注册模块:将文件夹放入
htdocs/custom/,然后以管理员身份进入 DolibarrHome -> Setup -> Modules,找到你的模块并激活。 - 调试日志:在
$conf->global->MAIN_DEBUG为 1 时,启用dol_syslog()输出日志。 - 权限检查:使用
$user->rights->myobject->read控制访问。 - 数据库升级:使用
update()方法对应 SQL 版本号。
高级功能(可选)
- 触发器:监听
COMPANY_CREATE、INVOICE_VALIDATE等事件。 - 工作流钩子:通过
executeHooks()调用自定义逻辑。 - Rest API:创建
api/class/api_myobject.class.php暴露 RESTful 接口。 - 自定义权限矩阵:通过
$this->rights_class和$this->rights数组定义。
注意事项
- 模块ID:必须与现有模块不冲突(建议使用 100000+ 范围的随机数)。
- 编码规范:遵循 Dolibarr PSR-4 风格,类名首字母大写,文件使用 .class.php 后缀。
- 安全性:所有输入通过
$db->escape()或GETPOST()过滤。 - 兼容性:测试在 PHP 7.4+ 和 MySQL 5.7+ 下的运行情况。
推荐工具
- Dolibarr Module Wizard:在线生成模块骨架。https://dolibarr.org/tools/module-wizard
- Git 版本管理:模块放入单独仓库,方便升级和复用。
如果需要更具体的某个步骤(如触发器、REST API、多语言、数据库升级等)的示例代码,可以告诉我,我可以给你更详细的实现。