Table of Contents

  1. Introduction

  2. Understanding Dolibarr’s Modular Architecture

  3. Why Create a Custom Module?

  4. Prerequisites and Development Environment Setup

  5. Structure of a Dolibarr Module

  6. Creating the Module Descriptor File

  7. Building the Main Module Class

  8. Adding Language Support

  9. Creating Database Tables for Your Module

  10. Designing the User Interface

  11. Implementing Permissions and Access Control

  12. Adding Business Logic with Classes

  13. Using Triggers and Hooks

  14. Managing Configuration Parameters

  15. Integrating with Existing Dolibarr Modules

  16. Creating Lists, Filters, and Export Functions

  17. Generating PDFs or Documents

  18. Best Practices for Security and Performance

  19. Testing and Debugging Your Module

  20. Packaging and Distributing the Module

  21. Updating and Maintaining Your Module

  22. Conclusion


1. Introduction

Dolibarr ERP/CRM is a powerful, open-source platform designed to be flexible and extensible. One of its greatest strengths is its modular structure, allowing developers to create standalone components known as modules. These can enhance or completely transform Dolibarr’s functionality. In this article, we’ll walk through the complete process of developing a custom Dolibarr module, from concept to distribution.


2. Understanding Dolibarr’s Modular Architecture

Each feature in Dolibarr is encapsulated as a module. A module can:

  • Introduce new menus

  • Add database tables

  • Extend UI with custom pages or tabs

  • Hook into business processes

Modules can be core (shipped with Dolibarr) or custom (located in /custom/). This separation allows for clean development without touching core files, ensuring easier upgrades and maintenance.


3. Why Create a Custom Module?

Reasons to develop your own module include:

  • Add industry-specific functionality

  • Replace manual processes with automation

  • Integrate external APIs or systems

  • Tailor the UI and business rules to your organization

Custom modules can be shared on Dolistore or kept internal.


4. Prerequisites and Development Environment Setup

To begin development:

  • Install a local Dolibarr instance

  • Enable Developer mode: $dolibarr_main_prod = 0;

  • Install a code editor (VSCode, PhpStorm)

  • Familiarize yourself with PHP, MySQL, HTML/CSS

Ensure PHP extensions (pdo, gd, intl, etc.) are installed.


5. Structure of a Dolibarr Module

A typical module has this layout:

/custom/mymodule/
├── class/
├── core/
├── lang/
├── modulebuilder.txt
├── modMymodule.class.php
├── mymodule.php
  • modMymodule.class.php: the descriptor file

  • class/: business logic classes

  • core/: triggers and hooks

  • lang/: translation files

  • mymodule.php: entry point or controller


6. Creating the Module Descriptor File

This file tells Dolibarr how to register your module:

class modMymodule extends DolibarrModules {
    public function __construct($db) {
        $this->numero = 123456; // Unique ID
        $this->rights_class = 'mymodule';
        $this->family = "custom";
        $this->name = preg_replace('/^mod/', '', get_class($this));
        $this->description = "My custom module";
        $this->version = '1.0.0';
        $this->const_name = 'MAIN_MODULE_MYMODULE';
        $this->config_page_url = array("mymodule_setup.php@mymodule");
        $this->dictionaries = array();
        $this->langfiles = array("mymodule");
        $this->parts = array();
        $this->modules = array();
        $this->rights = array();
    }
}

Enable the module from Setup > Modules/Applications.


7. Building the Main Module Class

Place the main class file in class/mymodule.class.php. Example:

class Mymodule extends CommonObject {
    public $element = 'mymodule';
    public $table_element = 'my_table';
    public $ismultientitymanaged = 1;
    public $fields = array(
        'title' => array('type' => 'varchar', 'label' => 'Title'),
        'amount' => array('type' => 'double', 'label' => 'Amount')
    );
}

Use this to define data structure and interactions.


8. Adding Language Support

Create language files under:

/custom/mymodule/langs/en_US/mymodule.lang

Add strings like:

MyLabel=My Custom Label

Load them using $langs->load('mymodule');


9. Creating Database Tables for Your Module

Use SQL scripts placed in:

/install/mysql/tables/llx_my_table.key.sql

Dolibarr will execute these when the module is enabled. Follow naming conventions (llx_ prefix).


10. Designing the User Interface

Create PHP pages in your module root (e.g., card.php, list.php). Use Dolibarr UI helpers:

llxHeader();
print load_fiche_titre($langs->trans("My Page"));

Tables, forms, and menus should use Dolibarr’s built-in functions for consistency.


11. Implementing Permissions and Access Control

In the descriptor file:

$this->rights[] = array('id'=>1, 'label'=>'Read', 'default'=>1, 'level'=>'read');
$this->rights[] = array('id'=>2, 'label'=>'Write', 'default'=>0, 'level'=>'write');

Check permissions using:

if ($user->rights->mymodule->read) { ... }

12. Adding Business Logic with Classes

Business logic should be centralized in classes:

class MymoduleManager {
    public function calculateSomething($input) {
        return $input * 2;
    }
}

Keep controller logic minimal and clean.


13. Using Triggers and Hooks

Create triggers in:

/core/triggers/interface_99_modmymodule_Mytrigger.class.php

Example:

function run_trigger($action, $object, $user, $langs, $conf) {
    if ($action == 'BILL_CREATE') {
        // custom logic
    }
    return 0;
}

Hooks allow UI or logic injection at specific points.


14. Managing Configuration Parameters

Store custom settings using dolibarr_set_const() and retrieve via $conf->global->MYMODULE_SETTING.

Create a mymodule_setup.php file for the settings page with a form.


15. Integrating with Existing Dolibarr Modules

Use shared classes like Facture, Product, or Societe:

require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
$invoice = new Facture($db);
$invoice->fetch($id);

You can also hook into their interfaces.


16. Creating Lists, Filters, and Export Functions

Use list.php format:

$sql = "SELECT rowid, title FROM llx_my_table";
$table = new Listview($db);
$table->render($sql);

Add export support using Dolibarr’s export framework.


17. Generating PDFs or Documents

Use TCPDF or build on pdf_common.modules.php:

$pdf = new PDF_MyModule($db);
$pdf->write_file($object, $langs);

PDF files are stored in /documents/mymodule/.


18. Best Practices for Security and Performance

  • Sanitize all input with GETPOST()

  • Use tokens for forms

  • Validate permissions before any critical action

  • Minimize DB queries; use caching if needed

Avoid exposing internal logic in URLs or responses.


19. Testing and Debugging Your Module

Enable logging:

$conf->global->MAIN_DISABLE_ALL_LOGS = 0;

Use dol_syslog() to log events. Test UI and logic in various user roles.


20. Packaging and Distributing the Module

  • Zip your module folder

  • Include README.md, CHANGELOG.txt, and license

  • Upload to Dolistore or share privately

  • Use semantic versioning (1.0.1, 1.1.0)


21. Updating and Maintaining Your Module

  • Maintain backward compatibility when possible

  • Use the module’s version field for controlled updates

  • Test against new Dolibarr versions before releasing updates

Consider user feedback when planning changes.


22. Conclusion

Developing a custom module for Dolibarr can seem daunting at first, but with a solid understanding of its architecture and best practices, the process becomes both manageable and rewarding. Whether you’re customizing a workflow or building an extension for public use, following this comprehensive guide ensures you build secure, efficient, and maintainable modules.