Dolibarr模块开发流程

wen PHP项目 2

本文目录导读:

Dolibarr模块开发流程

  1. 前置准备
  2. 模块物理结构(推荐)
  3. 核心开发步骤
  4. 安装与调试
  5. 高级功能(可选)
  6. 注意事项
  7. 推荐工具

前置准备

  • 环境搭建:本地搭建 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

安装与调试

  1. 注册模块:将文件夹放入 htdocs/custom/,然后以管理员身份进入 Dolibarr Home -> Setup -> Modules,找到你的模块并激活。
  2. 调试日志:在 $conf->global->MAIN_DEBUG 为 1 时,启用 dol_syslog() 输出日志。
  3. 权限检查:使用 $user->rights->myobject->read 控制访问。
  4. 数据库升级:使用 update() 方法对应 SQL 版本号。

高级功能(可选)

  • 触发器:监听 COMPANY_CREATEINVOICE_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+ 下的运行情况。

推荐工具

如果需要更具体的某个步骤(如触发器、REST API、多语言、数据库升级等)的示例代码,可以告诉我,我可以给你更详细的实现。

抱歉,评论功能暂时关闭!