Sprachen und Programmierregeln


Nachfolgend einige Regeln zu Sprache, Syntax und Norm, die wir im Dolibarr-Projekt verwenden:

Übersetzung nicht vollständig

      Hinweis zu Änderungen
Diese Seite darf vervollständigt oder überarbeitet werden. Auch fehlende Übersetzungen sind zu ergänzen.
Um in diesem Wiki beizutragen, melden Sie sich an (oben rechts: Anmelden), kehren zu dieser Seite zurück und klicken auf den Tab bearbeiten (d. i. der klein geschriebene Link im Topmenü).

Versionen

  • Dolibarr muss funktionieren mit:
  1. Allen Betriebssystemen (Windows, Linux, MACOS...)
  2. PHP 5.6.0+ (requires functions like DateTimeZone.getOffset, php-intl) (Muss ohne komplementäres PHP-Modul funktionieren, außer Modul zu PHP-Modul, um auf die Datenbank zuzugreifen).
  3. MySQL 5.1+

Urheberrechtsnormen

  • Alle PHP-Dateien müssen mit einem Header beginnen, der folgendermaßen aussieht
<?php
/* Copyright (C) YYYY John Doe  <email@email.com>
 *
 * Licence information
 */
...

Wenn Sie eine vorhandene Projektdatei bearbeiten, müssen Sie eine neue Copyright-Zeile im Header hinzufügen.

PHP-Normen

PHP

  • Dolibarr ist in PHP geschrieben und unterstützt alle Versionen von PHP, welche höher sind, als 5.6.0+ (requires functions like DateTimeZone.getOffset, php-intl). Alle Dateien müssen mit der Erweiterung .php enden.
  • Die Verwendung von PHP superglobalen Variablen muss über die festgelegten Operatoren $_COOKIE, $_SERVER, $_ENV erfolgen.
  • Allerdings muss die Dolibarr-Funktion GETPOST () verwendet werden, um den Inhalt von $_GET oder $_POST abzurufen.
  • Andere Operatoren wie ($HTTP_SERVER_GET, ...) sind veraltet und dürfen daher nicht verwendet werden. Der Code muss funktionieren, wenn die Option register_long_arrays deaktiviert ist. Desweiteren muss der Code funktionieren, wenn die PHP-Option register_globals deaktiviert ist (wird von PHP empfohlen). Allerdings muss er auch funktionieren wenn die Option register_globals aktiviert ist (standardmäßig bei vielen Installationen).
  • Verwenden Sie nicht PHP_SELF. Stattdessen verwenden Sie $_SERVER["PHP_SELF"]. Beachten Sie weiterhin, dass das Dolibarr-Framework den Inhalt der Variablen $_SERVER["PHP_SELF"] bereinigt. (Siehe Datei main.inc.php).
  • Wenn mehrere Variablen mit demselben Wert initialisiert werden sollen, müssen Sie einzelne Deklarationen verwenden (getrennt durch ; ).
$var1=1;
$var2=1;
$var3=1;

Anstelle von

$var1=$var2=$var3=1;

, weil es langsamer ist.


Strings
  • Zeichenfolgen müssen durch einfache oder doppelte Anführungszeichen begrenzt sein. Eine Variable innerhalb der Zeichenfolge muss außerhalb der Anführungszeichen liegen.
print 'My text show my '.$variable.' !';


Kommentare
  • Kommentare müssen die C-Syntax verwenden, das heißt einen doppelten Schrägstrich für einen Kommentar in einer Zeile oder einen Schrägstrich mit Stern, um einen Block für mehrere Zeilen zu öffnen
/* Kommentarblock
 *
 * Blockende
 */

$monobjet = new MonObjet($db);
$result=$monobjet->fetch($idobject);

for ($i = 1 , $i < 2 ; $i++) {
    // Kommentar in einer Linie
    print $i;
}

function myFunction($param1, $param2)
{
    // Code
}
  • Funktionen müssen bei Erfolg einen Wert zurückgeben, der größer/gleich 0 ist und bei Fehlern zwingend kleiner als 0 ist
  • Es darf kein Code im Dolibarr-Kerncode vorhanden sein, welcher nur von Externen Modulen verwendet wird (Toter Code). Code von externen Modulen muss in den externen Modulen enthalten sein.
  • Verwenden Sie "include_once" für alles, was Funktionen oder Klassendefinitionen enthält (wie * .class.php- und * .lib.php-Dateien), und "include" für PHP-Dateien im Vorlagenstil, die HTML- und PHP-Code enthalten (wie * .inc.php und * .tpl.php Dateien).
  • Der zu verwendende Codierungsstil ist PSR-12 (https://www.php-fig.org/psr/psr-12/). Nur die Regeln, welche mit "Muss" gekennzeichnet sind, sind absolut zwingend. Beachten Sie die folgenden Ausnahmen:
    • Length of line: PSR-12 mention we can't go up to 120 characters on same line, this is a soft limit. It is better to have long lines instead of long page with code content that is just data declaration and does not contain any logic. However, we introduced a hard limit of 1000 characters (having line larger than this may return errors on Continuous Integration tests).
    • Tabs are allowed: The other exception is that we don't replace systematically the tabs with spaces. Using tabs is more convenient for most editors/developers. Also using spaces breaks some auto-format features (like Eclipse autoformat feature on some Eclipse version). For the moment, the best setup is "Keep spaces/tabs as it is", however, you can activate the option "Remove spaces at end of lines".
    • We allow elements of an array on same line and we do not always add a new line at end of each element.
    • Note 1: The following rule are very important to follow:
      • Files must be saved with Unix format (LF) and not Windows (CR/LF). Unix format is compatible on all OS such as Unix like, Windows, Mac, but the Windows text file format may not work on some PHP under Unix.
      • Smart tags PHP are not used. PHP code section must start with <?php
    • Note 2: You can use the file dev/setup/codesniffer/ruleset.xml as rule file to control coding style with PHPCodeSniffer.
    • Note 3: You can use the file dev/setup/eclipse/PSR-12 [built-in].xml as rule file to setup Eclipse syntax formater.
    • Note 4: You may note that current code is not yet compliant with the PSR-12. The reason is that we must "now" follow the "MUST" rules of PSR-12, but it wasn't in the past. So feel free to change coding style to match new rules (keep in mind the 2 exceptions) if you find such cases.

Classes and properties structures

Some properties of classes are found in different classes. To avoid having different names, we will use the following PHP properties names:

- entity                         that is id for the multicompany feature
- date_creation:                 date of creation
- date_modification:             date of last modification (often field tms in database)
- date_validation:               date validation
- fk_user_creation:              id of User of creation
- fk_user_modification:          id of User of last modification
- fk_user_validation:            id of User of validation
- import_key                     contains the import code YYYYMMDDHHMMSS, if record was loaded with a mass import.

SQL Standards

Dateiformat DDL

Dateien, die die Definition der Datenbankstruktur enthalten (DDL-Dateien), benötigen 2 pro Tabelle:

  • Die erste Datei definiert die Tabelle und ihre Felder. Der Dateiname enthält den Tabellennamen, z. B. so: llx_mytable.sql

Alle Tabellen sind mit einem Präfix versehen, um Namenskonflikte zu vermeiden. Das Präfix kann bei der Installation geändert werden. Der Standardwert ist llx_.

Zu jedem Feld wird ein Kommentar hinzugefügt, um seine Verwendung zu erläutern. Die zweite Datei definiert alle Fremdschlüssel, Leistungsindizes oder andere Einschränkungen und der Dateiname lautet: llx_mytable.key.sql

Diese Dateien müssen im Verzeichnis install/mysql/tables für alle Standarddateien oder im Verzeichnis mymodule/tables für Tabellen, die von einem externen Modul bereitgestellt werden, gespeichert werden.

Example: file for creating the table llx_mytable will be llx_mytable.sql:

-- ===========================================================================
-- Copyright (C) 2013 Author <email@author.com>
-- 
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
-- ===========================================================================

create table llx_mytable
(
  rowid       integer NOT NULL AUTO_INCREMENT PRIMARY KEY,
  ref	      varchar(30)       NOT NULL,		-- object reference number
  entity      integer DEFAULT 1 NOT NULL,	        -- multi company id
  ref_ext     varchar(255),-- reference into an external system (not used by dolibarr)
  field_one   integer,
  field_two   integer NOT NULL,
  fk_field    integer,
  field_date  datetime,
  datec       timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,,   -- creation datetime
  tms         timestamp,    -- update time stamp
  fk_user_author integer NOT NULL,                     -- Author, foreign key of llx_user
  fk_user_mod    integer NOT NULL,                      -- Last updater, foreign key of llx_user
  import_key	varchar(14)                -- Use by import process
)type=innodb;

Example: file for creating keys/indexes for the table llx_mytable will be llx_mytable.key.sql:

-- ===========================================================================
-- Copyright (C) 2013 Author <email@author.com>
-- 
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
-- ===========================================================================

ALTER TABLE llx_mytable ADD UNIQUE uk_mytable_field (field_one, field_two);

ALTER TABLE llx_mytable ADD CONSTRAINT fk_mytable_fk_field FOREIGN KEY (fk_field) REFERENCES llx_matablepere (rowid);

Tabellen- und Feldstrukturen

  • Structure of tables.

When you create a new table, it is recommended to use the same conventions as other Dolibarr tables. This means the following fields:

- rowid INTEGER AUTO_INCREMENT PRIMARY KEY    that is technical id of record
- entity INTEGER default 1                    that is id for the multicompany feature
- date_creation   datetime                    that is the creation date
- tms             timestamp                   that will contain date of last modification (the database manages this field automatically, no need to manage it by the code, just create the field)
- date_valid      datetime                    that is the validation date (if applicable)
- import_key      varchar(32)                 that will contains the import code YYYYMMDDHHMMSS if you make mass import.
- status          smallint                    to store a status

Eventually

- fk_user_creat integer that is the id of user making creation
- fk_user_modif integer that is the id of user making change
- fk_user_valid integer that is the id of user validating record (if applicable)
- fk_soc integer that is the ID of the Third party (if applicable)

Note field:

- note_private text for private comment of the object
- note_pubic text for public comment of the object

or

- note text if there is no need to have private and public


  • Type of fields:

Well, to be compatible with any accuracy required by any country on amounts, to be compatible with any database syntax and with the Dolibarr upgrade framework, we will use the following types for database fields:

- integer for a primary key, an integer or any of foreign key (bigint may also be accepted for very large tables)
- smallint for a small number (like for a status) or a boolean
- double(24,8) for any amount
- double(6,3) for any vat rate
- real for a quantity
- varchar for a string (also if length is 1, the type char is more and more deprecated)
- timestamp for a field date+time that is automatically updated
- datetime for a field date+time
- date for a field date
- text or medium text for large fields (no index allowed on such fields)

All business rules must be on same place, into PHP code, not into client, neither into database, that's why type enum is also not allowed. Other type are not allowed for compatibility reasons.

  • All tables has a prefix to avoid name conflicts with other projects. In current version this prefix is fixed ans can't be modified. Its value is llx_. In a future version this value should be modified during installation process.

Primary keys

The primary key of a table must be called rowid.

Some old tables does not use this rule and use a primary key called id (ie Table llx_c_actioncomm), but the reason is history and this should not happen anymore.

Foreign keys

Name of a foreign key must start with the prefix fk_ followed by the table name (i.e. name of the referencing table) (this is required to avoid duplicate names in project that are not allowed even if in different tables by some DBMS like Postgresql) then the field name (i.e. name of the referencing field) (this is to allow to have several foreign keys in same table).

Example: fk_facture_fourn_fk_soc is a foreign key in the table llx_facture_fourn for the field fk_soc in this table (that references the rowid field in another table)

Note: If you develop your own external module, it must have no foreign keys that point to Dolibarr standard tables. This will break standard dolibarr upgrades, repair, backup and restore tools and may also break standard features.

Alternative keys

Sometimes, we need another unique keys than primary key. We can add in this case an alternate unique key. When we need this, we can create an alternate unique key. Such an index is called by a name that start by prefix uk_ followed by an underscore, then the the table name (this is required to avoid duplicate names of unique keys that may create problems for some DBMS like Postgresql) and then another string to define the key (this is to allow to have several unique keys on same table).

Example: uk_societe_code_client is a unique key on table llx_societe on field code_client.

Index performance

Some fields are often used as search or order criteria, or for joins. In such case, we need to set a performance index on field to increase performances. Such indexes are named with a prefix idx_ then the table name and then the field name.

Example: idx_societe_user_creat is a performance index on table llx_societe for field user_creat

SQL Coding rules

  • Alias usage/Fields naming

When doing select, we can use alias to simplify writing/reading of requests:

select chp1, chpxxx2 as chp2 from table2 as t1, table2 as t2 where t1.chpx = t2.chpy

However, we must not used alias for update request as they are not compatible with Mysql 3.1.

  • Using SELECT * is forbidden ! When using SELECT you must define complete list of fields to get. This avoids confusion. And above all, this make reengeering of code easier and make impact analysis of change on a field possible. Example:
SELECT field_a, field_b, field_c FROM table_1 WHERE field_d = '$id'
  • Into SQL requests, you must quote fields except the fields that contain amounts which must be stored as double or real type. Quotes on numbers may result in saving as a different value. For example 412.62 in an insert will be saved as value 412.61999512 into database (due to implicit conversion string to numeric) if the target field has type double(24,8). Only PHP see value 412.61999512. Other tools will see 412.62 giving a sense that there is no problem. But it's PHP that has the good vision. There is really a wrong value into database. By removing quotes on numbers, no problem occurs.

Example:

Good:     INSERT INTO table_1 (field_txt, field_num) VALUES ('txt', 412.62)
Bad:      INSERT INTO table_1 (field_txt, field_num) VALUES ('txt', '412.62')

Note, problem of float numbers is same problem on all langauges and not only when inserting data into database. It occurs also with any language when you work on "real" numbers, so numbers must be, as soon as they are affected, cleaned with function price2num with second parameter defined to : 'MU' (for unit prices), 'MT' (for total prices) or 'MS' (otherwise) depending on usage of number. (see function documentation)

  • Functions NOW, SYSDATE or DATEDIFF are forbidden inside SQL requests. If you must use the current date into a field, value must come from the PHP and not from the database engine. This is for better portability of code and correct management of TimeZone.

For example, don't do:

$sql="SELECT rowid FROM table where datefield = NOW()";

but do:

$sql="SELECT rowid FROM table where datefield = '".$this->db->idate(dol_now())."'";

For example, don't do:

$sql="SELECT rowid FROM table where DATEDIFF(table.datefield, NOW()) > 7";

but do:

$sql="SELECT rowid FROM table where datefield < '".$this->db->idate(dol_now() - (7 * 24 * 3600))."'";

An other advantage of this rule, is that request benefits of index because we are making a compare of a field with a fixed value. When using datediff, you make an operation on field before comparison, this means database can't use the index on field, resulting on very bad performance compared to solution without the datediff.

  • Use $db->ifsql for SQL IF

Do not include the IF into your forged SQL request. But use instead $db->ifsql() method to you will make a SQL IF that is compatible with all SQL databases.


Using Database triggers

Using Database triggers is not allowed into the code of Dolibarr, so you should have no troubles with Database triggers. Database triggers are not portable. Compatibility may be broken when upgrading your version of your database, database triggers are often not included into backup tools, database triggers need permissions that you may not have (and should not have) on a common secured database, database triggers means also that you include some "business rules" of your application into the database where most other rules are managed by the code itself creating conflict or code that can't be debugged with a step by step debugger, ... There is tons of reason why we do not recommand to use database triggers in your own development. Using Database triggers can save you time when you make development but is a very bad practice, so is forbidden as it is not compatible with the high level of quality of code expected by Dolibarr team. External modules that uses Database triggers may also be refused on the market place since it won't work for more than 50% of users.

Mysql specificities

  • Tables must be declared with format InnoDB.

This format supports foreign keys and their restrictions, and transactions integrity is also supported. This guarantees that Dolibarr events keep all data with correct values between tables even when transaction modify different tables.

  • Dolibarr MUST work even if Mysql option strict is active.

To activate it (required when developing on Dolibarr), add the following line into the config file of your Mysql server (my.cnf or my.ini)

sql-mode="STRICT_ALL_TABLES,ONLY_FULL_GROUP_BY,NO_ZERO_DATE"

PostgreSQL specificities

Only Mysql SQL files must be maintained. Those files are converted "on the fly" by the database Dolibarr driver.

There is an exception for the SQL "UPDATE FROM":

MySQL Syntax:

UPDATE table_taget as target, table_source as source SET fieldtarget=source.fieldsource
WHERE source.rowid=target.rowid;

PgSQL Syntax:

UPDATE table_taget as target SET fieldtarget=source.fieldsource
FROM table_source as source WHERE source.rowid=target.rowid;

There is no native SQL requests "UPDATE FROM" in all Dolibarr core. But if you use one in your own code of your module, you should do :

if ($this->db->type=='pgsql') {
$sql="UPDATE table_taget as target SET fieldtarget=source.fieldsource
FROM table_source as source WHERE source.rowid=target.rowid";
} else {
$sql= "UPDATE table_taget as target, table_source as source SET fieldtarget=source.fieldsource
WHERE source.rowid=target.rowid";
}

HTML norms

Syntax rules

  • HTML used must be HTML compliant and not XHTML. All attributes of HTML tags must be in lower case and quoted with ".
  • Links href must be absolute and use the function dol_buildpath() to get absolute path from a relative path and img tag must be build using function img_picto().

For example:

print '<a href="'.dol_buildpath('/mydir/mypage.php').'">'.img_picto('Texte alt','namepictopng','').'</a>';
  • HTML tables must have columns with no forced width, except for columns that contains data we know the length. For example, a column with a picto only can be forced to with="20px".

Otherwise, we must avoid forcing the column width. Reason is that, in most cases, the browser make a better works to define column width automatically than forced values, and it works whatever is the resolution.

  • Javascript/ajax code and call to javascript files into php pages must be avoided. However, if you need to include javascript code, you must add a condition on "$conf->use_javascript_ajax"
if ($conf->use_javascript_ajax) {
...  // php code generating javascript here
}
  • Popup windows must not be used, except for tooltips (and must have a condition as explained before).
  • External scripts must be written in Perl if they can't be written in PHP. Usage of another language is not forbidden but must be argued before in the development mailing-list.

External templating framework ?

There is ton of frameworks to provide a templating language of an HTML page. The best and faster is just called "PHP", and because Dolibarr already depends on PHP, there is no need to introduce a dependency on a third language.

All templating frameworks are just preprocessor, BEFORE PHP. It can't be faster than PHP alone. When we say "speed is increased because templating framework use a cache", you must read in fact "the overtime spent by the framework is reduced by cache, not the speed of processing PHP file". We should say "any templating framework has an overload over PHP, the cache of the templating framework just reduces the slowing effect of using this framework", but not "the speed is increased, it is always decreased compared to pure PHP".

Above all, having a templating system is completely possible by doing a ".tpl.php" file that dos not contains any logic code, but only HTML and "echo". We get same result (but faster and easier to develop because it does not need to do all the setXXX before calling each template). All variables (known by code that include the template) are automaticaly known into a PHP template page. No risk to forget a set, and a lot of line of codes reduced, a lot of time and development errors are also saved.

Also, keeping a 100% isolation between code and HTML output is interesting in only 1 situation: When teams building design is complety different than team building logic code, AND if you build not too sophisticated pages, AND with no need of too many Ajax features (this need to know how code works). And this situation is surely not the Dolibarr future (team will often be same, Ajax will be more and more present, event if I hope not too much, and screens are more and more dependent of dynamic or contextual events, difficult to have this with one simple template without transforming the template into a page with high level of code).

There is a ton of other reasons to not use an external templating system and all arguments to use them are also the best argument to use PHP as our templating system.

Dolibarr norms and code skeleton

Skeleton code

To standardize the code, and to speed up the development of new components in Dolibarr, you'll find skeletons of files fully prepared in the directory htdocs/modulebuilder/templates/.

For example:

  • 1 file that serves as an example of the module description: myModule.class.php
  • 1 file that serves as an example of code for creating a new class: skeleton_class.class.php
  • 1 file that serves as an example of code for creating a new page: skeleton_page.php
  • 1 file that serves as an example of code for creating a script for executing command lines: skeleton_script.php

...

Use it as an example. Note that the skeletons are also used by the PHP Code generator (Module ModuleBuilder), which is described in the development chapter of Dolibarr modules, to speed up your development.

Dates and Timezones

Dolibarr is an application that is multi-user and multi-location. It's therefore necessary to store dates in the right format. To avoid problems with conversions, the following rules should be applied:

  • A date into memory must always be stored with Timestamp GMT format.
  • A date stored into database, is the GMT Timestamp of date submitted into the request usng the PHP server timezone. This does not apply to date update automatically by database (fields tms into database).

For exemple le 1st january 1970, 3 hour at Paris (TZ=+1) = 2 hour at Greenwitch (TZ=0) will be stored into memory with value 7200 and will be submitted into a SQL request to database with the string '19700101030000' (PHP convert into its TZ hour and database will unconvert it using its timezone too that is same than PHP).

All select methods should translate date fields, that are with format TZ of database ('19700101030000'), into a timestamp field by calling the method db->jdate. This is to store into memory a GTM Timestamp date. All insert methods must convert, during generation of SQL request, the memory date into the string by using db->idate (you may find examples into skeleton).

  • Dates that are updated automatically (field tms into database) contains a GMT Timestamp GMT of date when change is done. The select will also use the db->jdate (that use PHP server TZ) to convert read data into a GMT Timestamp into memory. So if timezone of database differs from timezone of PHP server (one of them is not correctly set), you may experience differences between creation date and update date.
  • Manipulation date with PHP must be done using the Dolibarr date functions: dol_now(), dol_mktime(), dol_stringtotime(), dol_getdate(), dol_time_plus_duree(). You may also find other functions available into file date.lib.php.

UTF8/ISO encoding

Dolibarr stores data in the following way:

  • In database, data is stored in UTF8 or ISO. It depends on the database's pagecode therefore these options are set at creation time. In any case, Dolibarr's database driver (in lib/database) deals with it to convert from/to UTF8 at insertion and readout.
  • Memory data is stored in UTF8 (PHP object instances).
  • Web pages are returned and rendered into UTF8

Float numbers, amount and calculation

With PHP, like other languages (Java for exemple), non integer data (float, real, double) are not reliable for calculation. Try to make for example

print 239.2 - 229.3 - 9.9;

You wont get zero but a very small decimal number. If you get zero her, you should be able to find other examples that don't work. Problem of float is general, so a variable that is a result of a calculation using decimal numbers must ALWAYS be cleaned using the function price2num() with the econd parameter to: 'MU', 'MT' or 'MS' depending on need (see description of function).

print price2num(239.2 - 229.3 - 9.9, 'MT');

If data manipulated is not an amount, then using MU, MT, MS has no sense, and you must use the function round().

Creation of tables

Do not create tables, on the fly, during execution by a standard user, we mean, during current usage of software. If you create a module that uses its own table, not available in the default Dolibarr code, then take a look at tutorial Module development. It explains how to provide new tables with your module, so that, the tables will be created during module activation and not during module usage.

Comparing version

If your code need to make different things depending on Dolibarr version, you can use the following tip to detect and compare versions

$version=preg_split('/[\.-]/',DOL_VERSION);
if (versioncompare($version,array(5,0,-4)) >= 0) { //mycode for 5.0 only; }	// For dolibarr 5.0.* (the -4 means we include also alpha, beta, rc and rcX)

But this solution need to include the function versioncompare. An alternative solution to test version is to do:

if ((float) DOL_VERSION >= 5.0) { //mycode for 5.0 only; }	// For dolibarr 5.0.*

Logs

Add logs to your code using function

dol_syslog($yourmessage, LOG_INFO|LOG_DEBUG|LOG_WARNING|LOG_ERR);

Working directory

If you need to create a working directory, into your code, refer to it with DOL_DATA_ROOT.'/mymodule'

The directory can be created into your code by the following function:

$mymoduledir=DOL_DATA_ROOT.'/mymodule';
dol_mkdir($mymoduledir);

If you need a directory to store temporary data, this directory must be DOL_DATA_ROOT.'/mymodule/temp'

Design patterns and Object programming

Creation design patterns (GoF)

Design patterns defined by the Gang Of Four (see wikipédia on Design patterns). No usage of such patterns is required. We found some objects next to Singletons or Factory but not completely compliant with syntax, this is to be compatible with PHP 4 that is not a pure object language.

Structure design patterns (GoF)

Design patterns defined by the Gang Of Four (see wikipédia on Design patterns). No usage of such patterns is required.

Behavior design patterns (GoF)

Design patterns defined by the Gang Of Four (see wikipédia on Design patterns). No usage of such patterns is required.

Design patterns of enterprise (Martin Fowler)

Patterns of code organization

Martin Fowler has identified 3 ways to organize code:

  • The Transaction Script (The source code is linear for each user action).

This is the old school used by all procedural languages. Inconvenient: Redundancy of code. Need to know the physical model of data to develop.

  • The Domain Model

This notion is available with object languages. It is business process (to identify before) that are used for objects classes. Inconvenient: Model very complex to maintain.

  • The Table Module

This is a mix between 2 previous where we have only one unique class for each table of database.

-> As shown in code skeletons (see previous chapter), Dolibarr uses concept of Table Module.

Communication between business logic - data (ORM)

There are 3 ways to make links:

  • The Table And Row Data Gateway

This is the most simple. You have one class per table and each class is a link to the table with CRUD methods (Create, Read, Update, Delete). A class instance is a record in the table. The class contains only code to reach lines and fields of table.

Example: This mode is used by some ORM Frameworks, like iBatis (http://ibatis.apache.org/).

  • The Active Record

Same as previous, but we are allowed to add some business functions into the class, if such functions are dedicated to the table or recording into this table.

Example: This mode is used for Dolibarr development and most PHP software that includes their own framework and best practices.

  • The Data Mapper

Classes represent entities of the problem and not the data. So you have to double, triple ... these classes with Mapper classes to access the data. More "purist" on paper (closer of business), this method also has the disadvantage of being more complex in practice.

Example: This is the choice if you use the ORM Framework Propel (https://propelorm.org/). We find this model in heavier applications, based on this ORM among others.

-> For Dolibarr development, it is recommended to use the connection mode Active Record, which offers the advantages of a model close to the business without having the complexity, without obfuscating technical architecture. It is by this way that the development, understanding of code and technical maintenance and / or business behavior seems the more productive (this is however an ongoing debate between the purists and the pragmatists, debate in which nobody can really be right, because it depends on the objectives).