<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.dolibarr.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Quentic</id>
	<title>Dolibarr ERP CRM Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.dolibarr.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Quentic"/>
	<link rel="alternate" type="text/html" href="https://wiki.dolibarr.org/index.php/Special:Contributions/Quentic"/>
	<updated>2026-10-22T05:17:29Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.17</generator>
	<entry>
		<id>https://wiki.dolibarr.org/index.php?title=Ce_que_fait_Dolibarr&amp;diff=52119</id>
		<title>Ce que fait Dolibarr</title>
		<link rel="alternate" type="text/html" href="https://wiki.dolibarr.org/index.php?title=Ce_que_fait_Dolibarr&amp;diff=52119"/>
		<updated>2021-09-30T09:05:24Z</updated>

		<summary type="html">&lt;p&gt;Quentic: Correction d&amp;#039;erreur de frappe&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- BEGIN interlang links --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Do NOT edit this section&lt;br /&gt;
     Links below are automatically managed by PolyglotBot&lt;br /&gt;
     You can edit links on the English source page : O_que_o_Dolibarr_faz --&amp;gt;&lt;br /&gt;
[[en:What_Dolibarr_Does]]&lt;br /&gt;
[[es:Lo_que_hace_Dolibarr]]&lt;br /&gt;
[[zh:Dolibarr是什么？]]&lt;br /&gt;
[[pt:O_que_o_Dolibarr_faz]]&lt;br /&gt;
[[de:Was_macht_Dolibarr]]&lt;br /&gt;
&amp;lt;!-- END interlang links --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{TemplateDocUtil}}&lt;br /&gt;
[[Category:FAQ FR]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dolibarr ERP &amp;amp; CRM&#039;&#039;&#039; est un logiciel modulaire (on n&#039;active que les fonctions que l&#039;on désire) de gestion d&#039;entreprise qui s&#039;adapte à la taille de votre entreprise (&#039;&#039;&#039;TPE/PME, Grand groupe, Indépendants ou association&#039;&#039;&#039;). C&#039;est un projet OpenSource qui s&#039;exécute au sein d&#039;un serveur Web et peut donc être accessible depuis n&#039;importe quel lieu disposant d&#039;une connexion Internet, ou seulement en local : sur une machine sans connexion.&lt;br /&gt;
&lt;br /&gt;
Notez que Dolibarr est également disponible grâce à des &#039;&#039;&#039;auto-installeurs pour les utilisateurs sans connaissances techniques&#039;&#039;&#039; afin d&#039;&#039;&#039;&#039;installer Dolibarr et tous ces pré-requis (Apache, Mysql, PHP)&#039;&#039;&#039; par un simple fichier auto-installable.&lt;br /&gt;
Ces versions s&#039;appellent:&lt;br /&gt;
&lt;br /&gt;
*[[DoliWamp FR|DoliWamp]], un installeur auto-exe pour les utilisateurs Windows.&lt;br /&gt;
*[[Dolibarr pour Ubuntu ou Debian|DoliDeb]], un installeur pour les utilisateurs Linux Debian/Ubuntu.&lt;br /&gt;
*[[Dolibarr pour Redhat ou Fedora (package rpm)|DoliRpm]], un installeur pour les utilisateurs Linux RedHat/Fedora/OpenSuse/Mandriva/Mageia.&lt;br /&gt;
*une installation séparée (Apache, MySQL, PHP) par exemple : permet d&#039;installer l&#039;environnement nécessaire à Dolibarr sous toute machine : ce format demande plus de connaissances, est généralement réservé à la création de serveur, mais est dans le même temps plus paramétrable.&lt;br /&gt;
&lt;br /&gt;
Dans &#039;&#039;&#039;tous les cas&#039;&#039;&#039; : le paramétrage d&#039;une box ou d&#039;un routeur permet d’accéder à la partie serveur depuis n&#039;importe quel endroit via internet (référez vous à la section [[Informations sécurité]] pour plus d&#039;information)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dolibarr se démarque des autres suites de gestion d&#039;entreprise par sa plus grande simplicité (règle des 3 S):&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Simple pour l&#039;installation&#039;&#039;&#039; (avec au choix des installeurs clé en main pour ceux qui ignorent comment installer un serveur Web, ou une installation manuelle)&lt;br /&gt;
*&#039;&#039;&#039;Simple pour l&#039;utilisation&#039;&#039;&#039; (fonctions modulaires pour ne pas surcharger les menus, informations claires à la saisie)&lt;br /&gt;
*&#039;&#039;&#039;Simple pour le développement&#039;&#039;&#039; (pas de frameworks lourds). Dolibarr intègre en effet sa propre architecture (design patterns) permettant à tout développeur d&#039;être tout de suite opérationnel sans connaissances particulières autre que le PHP.&lt;br /&gt;
&lt;br /&gt;
La version standard est de plus compatible avec tous les systèmes et la plupart des offres Cloud du marché.&lt;br /&gt;
&lt;br /&gt;
Voici une liste des fonctionnalités principales couvertes par Dolibarr...&lt;br /&gt;
&lt;br /&gt;
=[[File:Art.png]] Fonctionnalités / Modules principaux (tous optionnels)=&lt;br /&gt;
&lt;br /&gt;
*Annuaire des prospects et/ou clients et/ou fournisseurs&lt;br /&gt;
*Annuaire des contacts/adresses&lt;br /&gt;
*Catalogue de produits et services&lt;br /&gt;
*Gestion des stocks, inventaires&lt;br /&gt;
*Gestion des comptes bancaires&lt;br /&gt;
*Gestion des commandes&lt;br /&gt;
*Gestion des propositions commerciales&lt;br /&gt;
*Gestion des contrats de services&lt;br /&gt;
*Gestion des factures clients et fournisseurs&lt;br /&gt;
*Gestion des paiements, encaissement en ligne via Paypal, Stripe, ...&lt;br /&gt;
*Gestion des virements bancaires&lt;br /&gt;
*Gestion des expéditions&lt;br /&gt;
*Gestion des adhérents d&#039;association&lt;br /&gt;
*Gestion des congés des employés&lt;br /&gt;
*Gestion des notes de frais&lt;br /&gt;
*Gestion des charges sociales / TVA&lt;br /&gt;
*Enregistrement des paiements des salariés&lt;br /&gt;
*Comptabilité à double entrée, comptabilité générale et auxiliaire : facilement exportable vers d&#039;autres solutions&lt;br /&gt;
*Agenda partagé&lt;br /&gt;
*Point de vente/Caisse enregistreuse&lt;br /&gt;
*Réalisation de sondages&lt;br /&gt;
*EMailing de masses vers les clients, prospect ou utilisateurs Dolibarr&lt;br /&gt;
*Suivi des marges&lt;br /&gt;
*Récolte de dons&lt;br /&gt;
*Rapports et statistiques&lt;br /&gt;
*Export PDF de tous les éléments (factures, propositions commerciales, commandes, bons expéditions, etc...)&lt;br /&gt;
*Imports et exports (CSV ou Excel).&lt;br /&gt;
*Connectivité LDAP&lt;br /&gt;
*De nombreuses autres fonctionnalités issues de modules officiels ou non (Gravatar, Google, ...)&lt;br /&gt;
&lt;br /&gt;
NB : des modules dits &amp;quot;externes&amp;quot; sont commercialisés et maintenus par des développeurs indépendants, ils sont disponibles sur la plateforme Dolistore : https://www.dolistore.com&lt;br /&gt;
&lt;br /&gt;
NB2: de part sa nature &amp;quot;open source&amp;quot; Dolibarr est adaptable à tous besoins. Il est fortement recommandé d&#039;apporter ces modifications sous la forme de modules externes et de ne pas toucher au code source original (un risque important de bug en cascade peut arriver, et compliquera les mises à jour futures)&lt;br /&gt;
&lt;br /&gt;
=[[File:Art.png]] Autres caractéristiques diverses=&lt;br /&gt;
&lt;br /&gt;
*Application multi-utilisateurs avec différents niveaux de permissions par module.&lt;br /&gt;
*Gestion multi-devises.&lt;br /&gt;
*Application simple à utiliser.&lt;br /&gt;
*Facilement personnalisable (activation uniquement des modules désirés, champs personnalisés, choix du thème, options diverses...).&lt;br /&gt;
*Disponibilité d APIs web service ouvertes (SOAP et REST)&lt;br /&gt;
&lt;br /&gt;
*Compatible avec les réglementations de nombreux pays (Gestion de la TVA Non perçue récupérable des DOM-TOM, TICKETBAI du Pays basque, Double tax fédéral/provinçal du Canada/Québec, Timbre fiscal tunisien, Tax GST Inde, ...)&lt;br /&gt;
&lt;br /&gt;
La page suivante décrit les fonctionnalités non couvertes par Dolibarr:&lt;br /&gt;
[[Ce que ne fait pas Dolibarr]]&lt;br /&gt;
&lt;br /&gt;
=[[File:Art.png]] Prérequis=&lt;br /&gt;
*Fonctionne avec PHP {{PHPMinVersion}} et MySQL {{MySqlMinVersion}} ou MariaDB {{MariaDBMinVersion}} ou PostgreSql {{PostgresMinVersion}}.&lt;br /&gt;
*Programme d&#039;auto-installation pour for Windows, Debian/Ubuntu, Fedora/Redhat/OpenSuse ou package pour installation manuelle sur tout serveur dédié/mutualisé. Egalement compatible avec toute solution Cloud respectant les prérequis PHP, MySql ou PostgreSQL (Par exemple chez les fournisseurs Cloud suivant: https://saas.dolibarr.org).&lt;br /&gt;
&lt;br /&gt;
=[[File:Art.png]] Dolibarr Releases=&lt;br /&gt;
&lt;br /&gt;
*La liste des versions de Dolibarr est définie sur la page [[:Category:RoadMap]]&lt;br /&gt;
&lt;br /&gt;
=[[File:Art.png]] Architecture =&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
[[File:Schéma client-serveur.png|none|thumb|927x927px|Présentation client / serveur]]&lt;/div&gt;</summary>
		<author><name>Quentic</name></author>
	</entry>
	<entry>
		<id>https://wiki.dolibarr.org/index.php?title=Langages_et_normes&amp;diff=52118</id>
		<title>Langages et normes</title>
		<link rel="alternate" type="text/html" href="https://wiki.dolibarr.org/index.php?title=Langages_et_normes&amp;diff=52118"/>
		<updated>2021-09-30T08:48:05Z</updated>

		<summary type="html">&lt;p&gt;Quentic: /* Communication Logique métier - Données (ORM) */Correction d&amp;#039;erreur de frappe&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- BEGIN interlang links --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Do NOT edit this section&lt;br /&gt;
     Links below are automatically managed by PolyglotBot&lt;br /&gt;
     You can edit links on the English source page : Language_and_development_rules --&amp;gt;&lt;br /&gt;
[[en:Language_and_development_rules]]&lt;br /&gt;
[[de:Sprachen_und_Programmierregeln]]&lt;br /&gt;
[[es:Lenguaje_y_Normas_de_Desarrollo]]&lt;br /&gt;
[[zh:语言和开发规则]]&lt;br /&gt;
&amp;lt;!-- END interlang links --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{TemplateDocDev}}&lt;br /&gt;
&lt;br /&gt;
Voici les quelques règles sur le langage, la syntaxe et normes de développement en vigueur pour le projet Dolibarr :&lt;br /&gt;
&lt;br /&gt;
=Versions=&lt;br /&gt;
&lt;br /&gt;
*Dolibarr doit fonctionner sur:&lt;br /&gt;
&lt;br /&gt;
#Tous OS (Windows, Linux, MACOS...)&lt;br /&gt;
#PHP {{PHPMinVersion}} (Doit fonctionner sans aucun module PHP complémentaire hors les modules d&#039;accès base de donnée).&lt;br /&gt;
#Mysql {{MySqlMinVersion}}&lt;br /&gt;
&lt;br /&gt;
=Normes Copyright=&lt;br /&gt;
&lt;br /&gt;
*Tout fichier PHP doit avoir un en-tête selon le masque suivant&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
/* Copyright (C) YYYY John Doe  &amp;lt;email@email.com&amp;gt;&lt;br /&gt;
 *&lt;br /&gt;
 * Licence information&lt;br /&gt;
 */&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Quand vous éditez un fichier existant du projet, ajouter une ligne Copyright sous celles existantes.&lt;br /&gt;
&lt;br /&gt;
=Normes PHP=&lt;br /&gt;
&lt;br /&gt;
==PHP==&lt;br /&gt;
&lt;br /&gt;
*Dolibarr est écrit en PHP et supporte toutes versions PHP supérieures à la {{PHPMinVersion}}. Les fichiers doivent tous comporter l&#039;extension .php&lt;br /&gt;
&lt;br /&gt;
*L&#039;appel aux variables superglobales PHP doit passer par les opérateurs dédiés $_COOKIES, $_SERVER, $_ENV. Mais pour récupérer les contenus de $_GET ou $_POST, il faut passer par la fonction dolibarr [[Fonctions utiles Dolibarr|GETPOST()]] .&lt;br /&gt;
&lt;br /&gt;
Les autres opérateurs ($HTTP_SERVER_GET, ...) ayant été passés en deprecated au sein de PHP, ne doivent plus être utilisés. Ainsi le code doit fonctionner y compris quand l&#039;option &#039;&#039;&#039;register_long_arrays&#039;&#039;&#039; est à off.&lt;br /&gt;
De plus, le code doit fonctionner aussi bien quand l&#039;option PHP &#039;&#039;&#039;register_globals&#039;&#039;&#039; est à off (recommandé par PHP)  que quand l&#039;option &#039;&#039;&#039;register_globals&#039;&#039;&#039; est à on (par défaut sur de nombreuses installations).&lt;br /&gt;
&lt;br /&gt;
*Pas d&#039;utilisation de la variable &#039;&#039;&#039;PHP_SELF&#039;&#039;&#039;. Utiliser à la place $_SERVER[&amp;quot;PHP_SELF&amp;quot;]. Notez aussi que le framework Dolibarr passe une routine pour rendre plus sûr le contenu du $_SERVER[&amp;quot;PHP_SELF&amp;quot;] (dans le fichier main.inc.php, donc avant tout traitement métier)&lt;br /&gt;
&lt;br /&gt;
*Quand plusieurs variables doivent être initialisées avec la même valeur, il faut utiliser plusieurs instructions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$var1 = 1; $var2 = 1; $var3 = 1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
plutôt que&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$var1 = $var2 = $var3 = 1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
qui est moins performant.&lt;br /&gt;
&lt;br /&gt;
*Les chaines doivent avoir les variables sorties de la chaine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print &amp;quot;Mon texte affiche ma &amp;quot;.$variable.&amp;quot; !\n&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les commentaires doivent suivre la syntaxe C, ie un double antislash pour un commentaire d&#039;une ligne et utilisation slash-étoile pour ouvrir un bloc de plusieurs lignes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
/* Bloc de commentaire&lt;br /&gt;
 *&lt;br /&gt;
 * Fin du bloc&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
$monobjet = new MonObjet($db);&lt;br /&gt;
$result=$monobjet-&amp;gt;fetch($idobject);&lt;br /&gt;
&lt;br /&gt;
for ($i = 1 , $i &amp;lt; 2 ; $i++)&lt;br /&gt;
{&lt;br /&gt;
  // commentaire sur une ligne&lt;br /&gt;
  print $i;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les fonctions doivent retourner une valeur strictement &amp;gt; à 0 en cas de succès, et un nombre &amp;lt; à 0 en cas d&#039;erreur.&lt;br /&gt;
&lt;br /&gt;
*Pas de code mort (non utilisé) dans le code principal de Dolibarr (le code utilisé uniquement par un module externe doit être inclus dans le module externe).&lt;br /&gt;
&lt;br /&gt;
*Utiliser &amp;quot;include_once&amp;quot; pour l&#039;inclusion de tout fichier contenant des définitions de fonction ou de classes (donc fichiers *.class.php et *.lib.php), utiliser &amp;quot;include&amp;quot; pour tout inclusion de fichier de type template ou contenant un mixte de HTML et PHP (donc fichiers *.inc.php et *.tpl.php).&lt;br /&gt;
&lt;br /&gt;
*Le style de code a utiliser est le PSR-12 (https://www.php-fig.org/psr/psr-12/). Seules les règles &amp;quot;MUST&amp;quot; sont imposées. Notez aussi les points/exceptions suivants:&lt;br /&gt;
**La longueur des lignes: PSR-12 indique que la longueur des lignes a une limite &amp;quot;soft&amp;quot; à 120. Il est en effet préférable d&#039;avoir de longues lignes de données de déclaration plutôt que de longues pages car ce code ne contient aucune logique intéressante ou utile, toutefois une limite &amp;quot;hard&amp;quot; a été instauré à &#039;&#039;&#039;1000&#039;&#039;&#039; caractères. Du code qui ira au delà provoquera des erreurs dans la plateforme d&#039;Intégration Continue.&lt;br /&gt;
**Les tabulations sont acceptées : L&#039;autre exception est qu&#039;on ne remplace pas les tabulations systématiquement par des espaces. L&#039;utilisation des tabulations simplifie la vie de certains développeurs. De plus, l&#039;utilisation d&#039;espaces rend certaines fonctions d&#039;autoformatage défectueuses (comme sur certaines versions d&#039;Eclipse, lors de copier-coller).&lt;br /&gt;
**Note 1: Les règles suivantes sont particulièrement importantes :&lt;br /&gt;
***Les fichiers doivent être sauvés en format Unix (LF) et non Windows (CR/LF). Le format Unix étant compatible sur les OS Unix like, Windows, Mac, alors que le format fichier texte Windows pose problème sous certains PHP sous Unix.&lt;br /&gt;
***Les smart tags PHP ne sont pas utilisés. Les sections de code doivent commencer par &#039;&#039;&#039;&amp;lt;?php&#039;&#039;&#039;&lt;br /&gt;
**Note 2: Vous pouvez utiliser le fichier &#039;&#039;&#039;dev/setup/codesniffer/ruleset.xml&#039;&#039;&#039; comme fichier de contrôle pour vérifier votre style de code avec PHPCodeSniffer.&lt;br /&gt;
**Note 3: Vous pouvez utiliser le fichier &#039;&#039;&#039;dev/setup/eclipse/PSR-12 [built-in].xml&#039;&#039;&#039; comme fichier de règles de syntax pour configurer Eclipse.&lt;br /&gt;
**Note 4: Vous remarquerez que le code actuel ne suit pas forcément tout cela. La raison est historique. La règle fut instaurée en cours de route, aussi, si vous trouvez du code non respectueux de ce standard, n&#039;hésitez pas à le corriger.&lt;br /&gt;
&lt;br /&gt;
==Structures des classes et champs==&lt;br /&gt;
&lt;br /&gt;
Certaines propriétés de classes se retrouvent dans de nombreuses classes. Pour homogénéité, on utilisera les noms suivants:&lt;br /&gt;
{{TemplatePHPFields}}&lt;br /&gt;
&lt;br /&gt;
=Normes SQL=&lt;br /&gt;
&lt;br /&gt;
==Structure des tables et champs==&lt;br /&gt;
&lt;br /&gt;
*Toutes les tables sont préfixées pour éviter les conflits de nommage. Aujourd&#039;hui, le préfixe est modifiable au moment de l&#039;installation. Sa valeur par défaut est &amp;lt;tt&amp;gt;llx_&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*Structure des tables.&lt;br /&gt;
&lt;br /&gt;
Lorsque vous créez une table, il est recommandé de prendre les même conventions de nommages de tables que les autres tables Dolibarr. Avec, à minima les champs suivant:&lt;br /&gt;
 - rowid INTEGER AUTO_INCREMENT PRIMARY KEY    qui est l&#039;id technique&lt;br /&gt;
 - entity INTEGER default 1                    that is id for the multicompany feature&lt;br /&gt;
 - date_creation   datetime                    that is the creation date&lt;br /&gt;
 - tms             timestamp                   qui sera un champ contenant la date de chaque mise à jour (la base de donnée le gère tout seul, pas besoin de le gérer par le code)&lt;br /&gt;
 - import_key      varchar(32)                 qui contiendra le code d&#039;import YYYYMMDDHHMMSS si vous faites des imports en masse dans la table.&lt;br /&gt;
 - status          smallint                    pour stocker le status d&#039;un object&lt;br /&gt;
&lt;br /&gt;
Eventuellement&lt;br /&gt;
 - fk_user_creat  integer qui est l&#039;id du user de création (fk_user_author also found)&lt;br /&gt;
 - fk_user_modif  integer qui est l&#039;id du user de modification&lt;br /&gt;
 - fk_user_valid  integer qui est l&#039;id du user de validation&lt;br /&gt;
 - fk_soc integer qui est l&#039;id du tiers (si applicable)&lt;br /&gt;
&lt;br /&gt;
*Type des champs&lt;br /&gt;
&lt;br /&gt;
Dans la pratique, afin d&#039;être compatible avec toutes les précisions des pays, syntaxes des bases, on utilisera uniquement les types suivants:&lt;br /&gt;
 - integer pour tout nombre entier, id ou clé étrangère (bigint éventuellement accepté pour les id des très grosses tables)&lt;br /&gt;
 - smallint pour tout numérique entier de petite taille (comme pour stocker un code de status)&lt;br /&gt;
 - double(24,8) pour tout montant&lt;br /&gt;
 - double(6,3) pour les taux de tva&lt;br /&gt;
 - real pour une quantité&lt;br /&gt;
 - varchar pour une chaîne (y compris de longueur 1, le type char est de plus en plus déprécié)&lt;br /&gt;
 - timestamp pour un champ date+heure devant être mis a jour automatiquement&lt;br /&gt;
 - datetime pour un champ date+heure&lt;br /&gt;
 - date pour un champ date&lt;br /&gt;
&lt;br /&gt;
==Clé primaire==&lt;br /&gt;
La clé primaire d&#039;une table s&#039;appelle &amp;lt;tt&amp;gt;rowid&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Il y a quelques tables qui échappent à cette règle actuellement (ex [[Table llx_c_actioncomm]]), pour des raisons historiques. Une évolution pourra être étudiée pour une prochaine version.&lt;br /&gt;
&lt;br /&gt;
==Clés étrangères==&lt;br /&gt;
Le nom d&#039;une clé étrangère commence par le préfixe &amp;lt;tt&amp;gt;fk_&amp;lt;/tt&amp;gt; suivi du nom de la table liée (requis pour éviter doublons globales à la base, problématiques sous certains SGBD comme postgresql) puis du champ lié (pour permettre plusieurs clés étrangères différentes sur une même table).&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
fk_facture_fourn_fk_soc&lt;br /&gt;
&lt;br /&gt;
Note: Si vous développez votre propre module externe, il ne doit pas y avoir de clé étrangère depuis vos tables qui pointent sur les tables standards de Dolibarr. Ceci casserait les fonctionnalités de mise à jour, de réparation, de sauvegardes et de restauration.&lt;br /&gt;
&lt;br /&gt;
==Clés alternatives==&lt;br /&gt;
Parfois, il n&#039;y a pas que la clé primaire qui doit être unique. On peut donc ajouter aussi un index clé alternative unique. Un tel index est nommé par un nom qui commence par le préfixe &amp;lt;tt&amp;gt;uk_&amp;lt;/tt&amp;gt; suivi du nom de la table (requis pour éviter doublons d&#039;index globals à la base, problématiques sous certains SGBD comme postgresql) puis d&#039;un suffixe qui caractérise la clé (pour permettre plusieurs index uniques sur une même table).&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
uk_societe_code_client&lt;br /&gt;
&lt;br /&gt;
==Index performance==&lt;br /&gt;
Certains champs sont souvent utilisés comme critère de recherche, de tri ou de jointure. Il convient dans ce cas, d&#039;y mettre un index de performance. De tels indexes seront nommés avec un préfix &amp;lt;tt&amp;gt;idx_&amp;lt;/tt&amp;gt; puis le nom de la table et le nom du champ sur lequel porte l&#039;index.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
idx_societe_user_creat&lt;br /&gt;
&lt;br /&gt;
==Format de fichier DDL==&lt;br /&gt;
Les fichiers qui contiennent la définition de la structure de la base (DDL) doivent être au nombre de 2 par tables:&lt;br /&gt;
Chaque table est définie dans son propre fichier dont le nom est &amp;lt;tt&amp;gt;llx_&#039;&#039;matable&#039;&#039;.sql&amp;lt;/tt&amp;gt;. &lt;br /&gt;
On mettra un commentaire à côté de chaque champ pour en expliquer la signification.&lt;br /&gt;
Les clés étrangères et index de performance ou autres contraintes d&#039;unicité sont définies dans un fichier séparé dont le nom est &amp;lt;tt&amp;gt;llx_&#039;&#039;matable&#039;&#039;.key.sql&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ces fichiers sont placés dans le répertoire &#039;&#039;&#039;install/mysql/tables&#039;&#039;&#039; pour les fichiers standards ou &#039;&#039;&#039;monmodule/tables&#039;&#039;&#039; pour les tables amenées par un module.&lt;br /&gt;
&lt;br /&gt;
Exemple &#039;&#039;&#039;fichier table llx_matable.sql&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
-- Copyright (C) 2008 Author &amp;lt;email@author.com&amp;gt;&lt;br /&gt;
-- &lt;br /&gt;
-- This program is free software; you can redistribute it and/or modify&lt;br /&gt;
-- it under the terms of the GNU General Public License as published by&lt;br /&gt;
-- the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
-- (at your option) any later version.&lt;br /&gt;
--&lt;br /&gt;
-- This program is distributed in the hope that it will be useful,&lt;br /&gt;
-- but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
-- GNU General Public License for more details.&lt;br /&gt;
--&lt;br /&gt;
-- You should have received a copy of the GNU General Public License&lt;br /&gt;
-- along with this program. If not, see &amp;lt;http://www.gnu.org/licenses/&amp;gt;.&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
&lt;br /&gt;
create table llx_matable&lt;br /&gt;
(&lt;br /&gt;
  rowid       integer AUTO_INCREMENT PRIMARY KEY,&lt;br /&gt;
  field_one   integer,&lt;br /&gt;
  field_two   integer NOT NULL,&lt;br /&gt;
  fk_field    integer,&lt;br /&gt;
  field_date  datetime,&lt;br /&gt;
  tms         timestamp&lt;br /&gt;
)ENGINE=innodb;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Exemple &#039;&#039;&#039;fichier clés/index llx_matable.key.sql&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
-- Copyright (C) 2008 Author &amp;lt;email@author.com&amp;gt;&lt;br /&gt;
-- &lt;br /&gt;
-- This program is free software; you can redistribute it and/or modify&lt;br /&gt;
-- it under the terms of the GNU General Public License as published by&lt;br /&gt;
-- the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
-- (at your option) any later version.&lt;br /&gt;
--&lt;br /&gt;
-- This program is distributed in the hope that it will be useful,&lt;br /&gt;
-- but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
-- GNU General Public License for more details.&lt;br /&gt;
--&lt;br /&gt;
-- You should have received a copy of the GNU General Public License&lt;br /&gt;
-- along with this program. If not, see &amp;lt;http://www.gnu.org/licenses/&amp;gt;.&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE llx_matable ADD UNIQUE uk_matable_field(field_one, field_two);&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE llx_matable ADD CONSTRAINT fk_matable_fk_field FOREIGN KEY (fk_field) REFERENCES llx_matablepere (rowid);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Règles de codage SQL==&lt;br /&gt;
&lt;br /&gt;
*Utilisation des alias/nommage de champs&lt;br /&gt;
&lt;br /&gt;
Dans le cas des select on pourra utiliser les alias pour simplifier l&#039;écriture des requêtes:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
select chp1, chpxxx2 as chp2 from table2 as t1, table2 as t2 where t1.chpx = t2.chpy&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Toutefois, il ne faut pas utiliser ces alias sur des requêtes update car non compatible avec mysql 3.1.&lt;br /&gt;
&lt;br /&gt;
*Les SELECT * sont interdits ! Chaque SELECT doit spécifier la liste complète des champs à récupérer. Cela permet d&#039;éviter les confusions. Exemple:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
SELECT field_a, field_b, field_c FROM table_1 WHERE field_d = &#039;$id&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Dans les requêtes SQL, on quote les champs mais pas les numériques qui contiennent des montants destinés à être stockés dans des champs de type double ou real. Les quotes sur les numériques de type float provoquent parfois un stockage d&#039;une valeur différente. Par exemple 412.62 dans le insert sera en fait stocké avec la valeur 412.61999512 en base (suite à des conversions chaines-numériques implicites) si le champ est de type double(24,8). Et seul le PHP voit 412.61999512. Les autres outils verront 412.62 donnant l&#039;impression qu&#039;il n&#039;y a pas de problème. Et c&#039;est le PHP qui a raison, il y a problème en base. En supprimant les quotes sur les numériques, cela va mieux.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
Bon:     INSERT INTO table_1 (field_txt, field_num) VALUES (&#039;txt&#039;, 412.62)&lt;br /&gt;
Mauvais: INSERT INTO table_1 (field_txt, field_num) VALUES (&#039;txt&#039;, &#039;412.62&#039;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remarque, le problème des float est général et pas seulement sur les accès base, il est présent dans tous les languages quand on travaille sur des nombres réels, aussi ils doivent être, dès que affectés, nettoyés par la fonction price2num avec le 2eme paramètre renseigné à:&lt;br /&gt;
&#039;MU&#039; (si il s&#039;agit d&#039;un prix unitaire), &#039;MT&#039; (s&#039;il s&#039;agit d&#039;un prix total) ou &#039;MS&#039; (autres cas) selon le besoin.&lt;br /&gt;
Voir aussi le chapitre &amp;quot;Les nombres réels, montants et calculs&amp;quot; plus bas.&lt;br /&gt;
&lt;br /&gt;
*Les fonctions NOW, SYSDATE ou DATEDIFF sont interdites au sein des ordres SQL. S&#039;il faut saisir la date du moment dans un champ, la valeur doit venir du PHP, par exemple par la fonction dol_now(), et non du moteur de base de données. Ceci afin d&#039;avoir une meilleure portabilité du code mais surtout d&#039;avoir une gestion correcte des TimeZone et ne pas dépendre du TimeZone de la base de donnée.&lt;br /&gt;
&lt;br /&gt;
Par exemple, on ne fera pas:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where datefield = NOW()&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
mais:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where datefield = &#039;&amp;quot;.$this-&amp;gt;db-&amp;gt;idate(dol_now()).&amp;quot;&#039;&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Par exemple, on ne fera pas:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where DATEDIFF(table.datefield, NOW()) &amp;gt; 7&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
mais:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where datefield &amp;lt; &#039;&amp;quot;.$this-&amp;gt;db-&amp;gt;idate(dol_now() - (7 * 24 * 3600)).&amp;quot;&#039;&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un autre avantage de cette règle est que la requête peut bénéficier de l&#039;utilisation de l&#039;index puisqu&#039;on compare datefield à une valeur fixe. Dans le cas du datediff, on applique un traitement sur le champ avant comparaison, rendant impossible l&#039;utilisation de l&#039;index de ce champ. Les conséquences sont des performances très dégradées par rapport à la version sans datediff.&lt;br /&gt;
&lt;br /&gt;
==Règles de migration de base==&lt;br /&gt;
&lt;br /&gt;
*Les scripts de migration de structure sont les fichiers de type &#039;&#039;&#039;install/mysql/migration/a.b.c-x.y.z.sql&#039;&#039;&#039;. Dans un fichier de migration de n vers n+1, on ne détruit une table (DROP TABLE) qui n&#039;est plus utilisée en n+1 que lors de la migration de la version n+1 vers n+2. Ceci afin de toujours conserver les tables deprecated le temps d&#039;une version pour réparer une situation en cas d&#039;erreur de migration.&lt;br /&gt;
&lt;br /&gt;
==Spécificités MySQL==&lt;br /&gt;
&lt;br /&gt;
*Les tables doivent être au format InnoDB.&lt;br /&gt;
&lt;br /&gt;
En effet, ce format gère les clés étrangères, les éventuelles restrictions qui y sont attachées et la notion d&#039;intégrité de transactions requise pour avoir des données en base cohérente entre tables.&lt;br /&gt;
&lt;br /&gt;
*Dolibarr DOIT fonctionner même avec les options &#039;&#039;&#039;strict&#039;&#039;&#039; de Mysql active.&lt;br /&gt;
&lt;br /&gt;
Pour l&#039;activer (fortement recommandé en développement), ajouter la ligne suivante dans le fichier config du serveur Mysql (my.cnf ou my.ini)&lt;br /&gt;
{{MySqlStrictMode}}&lt;br /&gt;
&lt;br /&gt;
==Spécificités PostgreSQL==&lt;br /&gt;
Seuls les fichiers pour Mysql doivent être maintenus.&lt;br /&gt;
Les fichiers pour les autres bases sont convertis &amp;quot;à la volée&amp;quot; par le driver Dolibarr de la base.&lt;br /&gt;
&lt;br /&gt;
Il existe une exception.&lt;br /&gt;
Les requêtes &amp;quot;UPDATE FROM&amp;quot; : &lt;br /&gt;
Syntax MySQL :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
UPDATE table_taget as target, table_source as source SET fieldtarget=source.fieldsource&lt;br /&gt;
WHERE source.rowid=target.rowid;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Syntax PgSQL:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
UPDATE table_taget as target SET fieldtarget=source.fieldsource&lt;br /&gt;
FROM table_source as source WHERE source.rowid=target.rowid;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il n&#039;en existe pas dans Dolibarr, mais pour vos modules Vous devriez faire tel que :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
if ($this-&amp;gt;db-&amp;gt;type==&#039;pgsql&#039;) {&lt;br /&gt;
$sql=&amp;quot;UPDATE table_taget as target SET fieldtarget=source.fieldsource&lt;br /&gt;
FROM table_source as source WHERE source.rowid=target.rowid&amp;quot;;&lt;br /&gt;
} else {&lt;br /&gt;
$sql= &amp;quot;UPDATE table_taget as target, table_source as source SET fieldtarget=source.fieldsource&lt;br /&gt;
WHERE source.rowid=target.rowid&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Normes HTML=&lt;br /&gt;
&lt;br /&gt;
*Tous les attributs dans les balises HTML doivent être *en minuscule* et quotés avec des *doubles quote*.&lt;br /&gt;
&lt;br /&gt;
*Les liens href doivent être absolus en se basant sur la fonction dol_buildpath() pour obtenir un chemin absolu depuis un chemin relatif au répertoire htdocs. Pour les tags img, il faut faire appel à la fonction img_picto().&lt;br /&gt;
&lt;br /&gt;
Par example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print &#039;&amp;lt;a href=&amp;quot;&#039;.dol_buildpath(&#039;/monrep/mapage.php&#039;).&#039;&amp;quot;&amp;gt;&#039;.img_picto(&#039;Texte alt&#039;,&#039;nompictopng&#039;,&#039;&#039;).&#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les tables HTML doivent avoir des colonnes sans valeurs forcées, excepté pour les colonnes qui contiennent une information dont la longueur est non variable. Par exemple, une colonne avec un picto peut être forcée à with=&amp;quot;20px&amp;quot;. Dans les autres cas, il faut éviter de forcer la largeur des colonnes. La raison est que, dans la plupart des cas, le navigateur fait un meilleur travail pour définir automatiquement la bonne largeur des colonnes qu&#039;en forçant manuellement les largeurs. Et ceci marche quelle que soit la résolution de l&#039;écran.&lt;br /&gt;
&lt;br /&gt;
*Le javascript/ajax et l&#039;appel aux scripts java dans les pages php est à proscrire. Si toutefois du code javascript est inclus, il doit être conditionné par le test sur &amp;quot;$conf-&amp;gt;use_javascript_ajax&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
if ($conf-&amp;gt;use_javascript_ajax) {&lt;br /&gt;
...  // Le code php qui génère du javascript est ici&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les popups windows ne doivent pas être utilisées, sauf pour des tooltips (et restent conditionnées par le point ci-dessus).&lt;br /&gt;
&lt;br /&gt;
*Les scripts externes sont écrits en Perl s&#039;ils ne peuvent l&#039;être en php, l&#039;utilisation d&#039;un autre langage n&#039;est pas interdit mais doit être discuté au préalable dans la mailing list des développeurs.&lt;br /&gt;
&lt;br /&gt;
=Normes Dolibarr et squelettes de code=&lt;br /&gt;
&lt;br /&gt;
==Squelettes de code==&lt;br /&gt;
Afin d&#039;uniformiser le code et d&#039;accélérer le développement de nouveaux composants dans Dolibarr, se trouvent dans le répertoire &#039;&#039;&#039;htdocs/modulebuilder/templates&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Par exemple:&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de descripteur de module: &#039;&#039;&#039;myModule.class.php&#039;&#039;&#039;&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de code pour faire une nouvelle classe: &#039;&#039;&#039;skeleton_class.class.php&#039;&#039;&#039;&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de code pour faire une nouvelle page: &#039;&#039;&#039;skeleton_page.php&#039;&#039;&#039;&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de code pour faire un script à exécuter en ligne de commande: &#039;&#039;&#039;skeleton_script.php&#039;&#039;&#039;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
Servez-vous en comme exemple.&lt;br /&gt;
Notons que ces squelettes sont aussi utilisés par le générateur de code PHP ([[Module ModuleBuilder]]) qui est décrit dans la chapitre de développement de module Dolibarr pour accélérer vos développements.&lt;br /&gt;
&lt;br /&gt;
==Les dates et TimeZone==&lt;br /&gt;
Dolibarr se veut une application multi-utilisateur et multi-localisation. Il convient donc de stocker les dates dans le bon format. Pour éviter les problèmes de conversion, les règles suivantes doivent être appliquées:&lt;br /&gt;
&lt;br /&gt;
*Une date en mémoire doit être au format Timestamp GMT.&lt;br /&gt;
*Une date stockée en base de données contient le Timestamp issue de la date soumise dans la requête en heure &amp;lt;b&amp;gt;locale du serveur PHP&amp;lt;/b&amp;gt;. Cela ne concerne pas les dates mises à jour automatiquement par la base (champ &#039;&#039;&#039;tms&#039;&#039;&#039; en base).&lt;br /&gt;
&lt;br /&gt;
Ainsi le 1er janvier 1970, 3 heures à Paris (TZ=+1) = 1er janvier 1970, 2 heures à Greenwich (TZ=0) sera stocké en mémoire par 7200 et sera soumis à la base de données avec la chaine &#039;19700101030000&#039; (PHP convertit en heure de son TZ et la base déconvertit avec son TZ qui est le même que celui de PHP).&lt;br /&gt;
&lt;br /&gt;
Les méthodes select doivent donc traduire les champs dates lus qui sont au format chaine TZ de la base (&#039;19700101030000&#039;) par appel de la méthode db-&amp;gt;jdate afin de récupérer une information en mémoire au format Timestamp GMT. Et les méthodes insert doivent lors de la génération de la requête convertir la date mémoire connue en variable, par la méthode db-&amp;gt;idate (Voir exemples générés par le squelette).&lt;br /&gt;
&lt;br /&gt;
*Les dates mises à jour automatiquement par la base (champ &#039;&#039;&#039;tms&#039;&#039;&#039; en base) contiennent le Timestamp où la modification est faite selon le timezone de la base de donnée. Les méthodes select récupèrent cette donnée en mémoire au format Timestamp GMT en appliquant également le db-&amp;gt;jdate. Si le timezone de la base de donnée diffère de celui du PHP (un des 2 est mal réglé), il peut donc y avoir des écarts entre date de création et modification.&lt;br /&gt;
&lt;br /&gt;
*La manipulation de dates en PHP doit être faite en utilisant les fonctions dates de Dolibarr: &#039;&#039;&#039;dol_now(), dol_mktime(), dol_stringtotime(), dol_getdate(), dol_time_plus_duree()&#039;&#039;&#039;. Vous trouverez également d&#039;autres fonctions prêtes à l&#039;emploi dans le fichier &#039;&#039;&#039;date.lib.php&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==L&#039;encodage UTF8/ISO==&lt;br /&gt;
Dolibarr stocke les informations de manière suivante:&lt;br /&gt;
&lt;br /&gt;
*En base de donnée, les données sont en UTF8 ou ISO. Cela dépend du pagecode de la base, donc des options à la création de cette base. Dans tous les cas le driver d&#039;accès base Dolibarr (dans /lib/database) s&#039;arrange à la lecture et insertion pour convertir vers et depuis de l&#039;UTF8.&lt;br /&gt;
*Les données en mémoires sont donc stockées en UTF8 (instances d&#039;objets PHP).&lt;br /&gt;
*Les pages web affichées à l&#039;écran sont au format UTF8&lt;br /&gt;
&lt;br /&gt;
==Les nombres réels, montants et calculs==&lt;br /&gt;
En PHP comme dans d&#039;autres langages (Java par exemple), les données non entières (float, real, double) ne sont pas fiables.&lt;br /&gt;
Essayer de faire par exemple &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print 239.2 - 229.3 - 9.9;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Vous n&#039;obtiendrez pas zéro mais un nombre très petit en puissance de 10 négative. Si vous obtenez zéro, vous pourrez trouvez d&#039;autres exemples qui ne fonctionnent pas.&lt;br /&gt;
Le problème des float est général, une variable résultante de calcul de nombre réels doit SYSTEMATIQUEMENT être nettoyée par la fonction &#039;&#039;&#039;price2num()&#039;&#039;&#039; avec le 2eme paramètre renseigné à: &#039;MU&#039;, &#039;MT&#039; ou &#039;MS&#039; selon le besoin (voir doc fonction).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print price2num(239.2 - 229.3 - 9.9, &#039;MT&#039;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
S&#039;il ne s&#039;agit pas d&#039;un prix sur lequel s&#039;adapte les paramètres MU, MT ou MS, il faut utiliser la fonction &#039;&#039;&#039;round()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==Création de tables==&lt;br /&gt;
Ne pas créer de table à l&#039;utilisation, c&#039;est-à-dire à la &#039;&#039;&#039;première utilisation&#039;&#039;&#039; du module.&lt;br /&gt;
Si vous créez un module qui utilise des tables qui ne sont pas intégrées en standard dans le code de Dolibarr, veillez à suivre le didacticiel [[Développement module]] qui explique comment joindre des tables qui se créent à l&#039;activation du module et non à son utilisation (voir plus haut).&lt;br /&gt;
&lt;br /&gt;
==Comparer la version==&lt;br /&gt;
&lt;br /&gt;
Si votre code a besoin de faire des choses différentes selon la version de Dolibarr, vous pouvez utiliser le truc suivant pour comparer les versions&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$version=preg_split(&#039;/[\.-]/&#039;,DOL_VERSION);&lt;br /&gt;
if (versioncompare($version,array(5,0,-4)) &amp;gt;= 0) { //mycode for 5.0 only; }	// For dolibarr 5.0.* (the -4 means we include also alpha, beta, rc and rcX)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais cette solution requiert de faire un include avoir la fonction versioncompare. Une alternative est d&#039;utiliser le test suivant:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
if ((float) DOL_VERSION &amp;gt;= 5.0) { //mycode for 5.0 only; }	// For dolibarr 5.0.*&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Logs==&lt;br /&gt;
Ajouter des traces dans votre code avec la fonction&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
dol_syslog($yourmessage, LOG_INFO|LOG_DEBUG|LOG_WARNING|LOG_ERR);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Répertoires de travail==&lt;br /&gt;
Si vous avez besoin de créer un répertoire de travail, dans votre code, faites référence à ce répertoire par&lt;br /&gt;
&#039;&#039;&#039;DOL_DATA_ROOT.&#039;/monmodule&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Le répertoire peut être créé dans votre code à l&#039;exécution par le code suivant:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$mymoduledir=DOL_DATA_ROOT.&#039;/monmodule&#039;;&lt;br /&gt;
dol_mkdir($mymoduledir);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si vous avez besoin d&#039;un répertoire qui contiendra des données temporaires, ce répertoire doit être&#039;&#039;&#039; DOL_DATA_ROOT.&#039;/monmodule/temp&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Design patterns et programmation objet=&lt;br /&gt;
&lt;br /&gt;
==Design patterns de Création (GoF)==&lt;br /&gt;
Design patterns définis par le Gang Of Four (voir la wikipédia sur les [[wikipedia:Patron de conception|Design patterns]]).&lt;br /&gt;
Dans Dolibarr, pas de mise en oeuvre de design patterns de comportement particulier.&lt;br /&gt;
On trouve des objets proches des Singletons et Fabriques conformes à 100% dans l&#039;esprit mais pas dans la syntaxe, ceci afin d’être compatible avec la plus large plage possible de versions de PHP.&lt;br /&gt;
&lt;br /&gt;
==Design patterns d&#039;entreprises (Martin Fowler)==&lt;br /&gt;
&lt;br /&gt;
===Mode d&#039;organisation du code===&lt;br /&gt;
[[wikipedia:Martin_Fowler|Martin Fowler]] a identifié 3 méthodes d&#039;organisation du code appelées &#039;&#039;&#039;patterns&#039;&#039;&#039; (&#039;&#039;&#039;motifs&#039;&#039;&#039;):&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Transaction Script&#039;&#039;&#039; (Le code est linéaire en fonction d&#039;une action utilisateur).&lt;br /&gt;
&lt;br /&gt;
C&#039;est le motif à l&#039;ancienne utilisé dans les langages procéduraux.&lt;br /&gt;
Inconvénient: Redondance du code. Nécessité de connaitre le modèle physique pour développer les parties métiers.&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Domain Model&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
C&#039;est un concept possible depuis les langages objets. Ce sont les procédures métiers (qui doivent être identifiés avant) qui servent de bases pour les classes objets.&lt;br /&gt;
Inconvénient : Motif complexe à maintenir.&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Table Module&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Un intermédiaire entre les 2 précédents où l&#039;on a une instance unique de classe par table de la base de données.&lt;br /&gt;
&lt;br /&gt;
-&amp;gt; Comme le montre les squelettes de code (voir point précédent), Dolibarr se base sur le principe du &#039;&#039;&#039;Table Module&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===Communication Logique métier - Données (ORM)===&lt;br /&gt;
Il existe 3 modes de liaisons:&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Table And Row Data Gateway&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
C&#039;est le plus simple. On crée une classe par table et chaque classe est un pont avec la table correspondante et propose les méthodes CRUD sur cette table (Create, Read, Update, Delete). Une instance de classe étant alors un enregistrement de la table. La classe ne contient que du code d&#039;accès aux lignes ou colonnes de tables. Le code métier doit alors être ajouté dans d&#039;autres classes. Les liens entre ces classes tables et les classes métiers devant être connues ou déduites de la connaissance du développeur.&lt;br /&gt;
&lt;br /&gt;
Exemple: C&#039;est le mode mis en oeuvre quand on utilise certains Frameworks d&#039;ORM comme &#039;&#039;&#039;iBatis&#039;&#039;&#039; (http://ibatis.apache.org/).&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Active Record&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Identique au précédent, mais on se permet d&#039;ajouter quelques fonctions métiers sur la classe, à condition que ces fonctions soient bien  propres à la table ou à la notion métier portée par l&#039;enregistrement. C&#039;est le pattern qui offre le meilleur rapport fonctionnalité/complexité.&lt;br /&gt;
&lt;br /&gt;
Exemple: C&#039;est le mode choisi pour les développements Dolibarr et de nombreuses autres applications PHP qui ont leur propre framework et pratiques de développement.&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Data Mapper&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Les classes représentent les entités du problème et non les données. Il faut donc doubler, tripler... ces classes avec des classes Mapper pour accéder aux données.&lt;br /&gt;
Plus &amp;quot;puriste&amp;quot; sur le papier car plus proche du métier, ce mode a aussi l&#039;inconvénient d&#039;être très complexe et difficile à maintenir dans la réalité (l&#039;expérience pratique constatée ne rejoignant pas les promesses de la théorie).&lt;br /&gt;
&lt;br /&gt;
Exemple: C&#039;est le choix si on utilise le Framework d&#039;ORM &#039;&#039;&#039;Propel&#039;&#039;&#039; (http://propel.phpdb.org/trac/). On le trouve donc sur des applications plus lourdes basées sur cet ORM entre autres.&lt;br /&gt;
&lt;br /&gt;
-&amp;gt; Pour les développements Dolibarr, il est recommandé d&#039;utiliser le mode de liaison &#039;&#039;&#039;Active Record&#039;&#039;&#039; qui offre les avantages d&#039;un modèle proche du métier sans en avoir la complexité et sans trop masquer non plus la technique. C&#039;est dans ce mode que le développement, la compréhension du code et la maintenance technique et/ou fonctionnelle semble la plus productive (ceci est toutefois un éternel débat entre les puristes et les pragmatiques, débat dans lequel personne ne peut vraiment avoir raison, car tout dépend des objectifs à atteindre).&lt;br /&gt;
&lt;br /&gt;
==Design Pattern d&#039;Interface Graphique (MVC)==&lt;br /&gt;
Il existe plusieurs design pattern pour les interfaces utilisateurs (MVC, MVP, MVVM).&lt;br /&gt;
Beaucoup confonde ce design pattern avec celui consistant à utiliser un framework de templates. C&#039;est sans rapport. Un framework de template (voir point précédent) n&#039;est en lien qu&#039;avec la partie &amp;quot;V&amp;quot; de ces modèles.&lt;br /&gt;
&lt;br /&gt;
-&amp;gt; Dolibarr utilise le Design Pattern &#039;&#039;&#039;MVC&#039;&#039;&#039;. La partie M est matérialisée par une classe DAO contenant les méthode CRUD (Create-Read-Update-Delete) d&#039;accès à la table.&lt;br /&gt;
Beaucoup de frameworks ont fait le choix de mettre la partie de code C (Controller) et la partie de code du V (vue) dans des fichiers, voir même répertoires séparés. La maintenance semble plus aisé sur la papier, en pratique, il faut sans arrêt jonglé entre n fichiers, le C étant fortement lié au V. Aussi dans Dolibarr, la séparation est faite par une simple section de commentaire. La partie de code C (Controller) est donc le code qui se trouve sont la balise&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * Actions&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Elle est suivi par la partie de code V (Vue), bien séparé du C par la balise&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * View&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce mode de séparation a eu un effet neutre sur les nouveaux développement mais a permis de réduire de manière si importante le temps requis pour la maintenance et correction de bugs qu&#039;il n&#039;est pas envisagé de basculer vers un autre type de séparation (oui les constats fait dans la vraie vie ne sont pas toujours ceux attendus par la théorie scolaire). L&#039;important reste qu&#039;il y ait toujours séparation entre le C et le V, peut importe comment est matérialisé cette séparation, du moment qu&#039;elle l&#039;est (Rappel: Ne pas confondre la notion de séparation du C et du V avec la notion de séparation du code pour alimenter la données d&#039;une Vue et du code pour formater la Vue, ceci un principe de séparation relevant du Design Pattern de Vue, voir point suivant).&lt;br /&gt;
&lt;br /&gt;
==Design Pattern de Vue - Présentation==&lt;br /&gt;
Il existe des frameworks spécialisés dans le Design Pattern de Vue, la partie qui consiste à formater l&#039;écran vue par l&#039;utilisateur.&lt;br /&gt;
Les vieilles versions de Dolibarr utilisaient Smarty. Ce framework est une surcouche à un Framework, déjà très puissant, de formatage d&#039;écran nommé... PHP. Les bénéfices étant très inférieurs aux inconvénients, il a été abandonné au profit de templates PHP (fichier .tpl.php) qui restent le plus simple, le plus universel, le plus évolutif et le plus performant, des frameworks de présentation. &lt;br /&gt;
&lt;br /&gt;
Son seul défaut est qu&#039;il ne peut garantir à 100% les écarts d&#039;un développeur qui irait intégrer dans la Vue, une logique sans rapport avec la présentation (donc autre que du code à vocation de génération, de formatage, de sortie HTML, de logique de test ou de boucle). Ce point est toutefois contrôlé par le mécanisme de validation du code des chefs de projets.&lt;br /&gt;
&lt;br /&gt;
La encore, c&#039;est l&#039;expérience et le constat &amp;quot;sur le terrain&amp;quot; d&#039;un meilleur rendement de productivité qui a motivé l&#039;abandon des frameworks de Présentation externes au profit du framework PHP.&lt;/div&gt;</summary>
		<author><name>Quentic</name></author>
	</entry>
	<entry>
		<id>https://wiki.dolibarr.org/index.php?title=Langages_et_normes&amp;diff=52117</id>
		<title>Langages et normes</title>
		<link rel="alternate" type="text/html" href="https://wiki.dolibarr.org/index.php?title=Langages_et_normes&amp;diff=52117"/>
		<updated>2021-09-30T08:45:23Z</updated>

		<summary type="html">&lt;p&gt;Quentic: /* Mode d&amp;#039;organisation du code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- BEGIN interlang links --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Do NOT edit this section&lt;br /&gt;
     Links below are automatically managed by PolyglotBot&lt;br /&gt;
     You can edit links on the English source page : Language_and_development_rules --&amp;gt;&lt;br /&gt;
[[en:Language_and_development_rules]]&lt;br /&gt;
[[de:Sprachen_und_Programmierregeln]]&lt;br /&gt;
[[es:Lenguaje_y_Normas_de_Desarrollo]]&lt;br /&gt;
[[zh:语言和开发规则]]&lt;br /&gt;
&amp;lt;!-- END interlang links --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{TemplateDocDev}}&lt;br /&gt;
&lt;br /&gt;
Voici les quelques règles sur le langage, la syntaxe et normes de développement en vigueur pour le projet Dolibarr :&lt;br /&gt;
&lt;br /&gt;
=Versions=&lt;br /&gt;
&lt;br /&gt;
*Dolibarr doit fonctionner sur:&lt;br /&gt;
&lt;br /&gt;
#Tous OS (Windows, Linux, MACOS...)&lt;br /&gt;
#PHP {{PHPMinVersion}} (Doit fonctionner sans aucun module PHP complémentaire hors les modules d&#039;accès base de donnée).&lt;br /&gt;
#Mysql {{MySqlMinVersion}}&lt;br /&gt;
&lt;br /&gt;
=Normes Copyright=&lt;br /&gt;
&lt;br /&gt;
*Tout fichier PHP doit avoir un en-tête selon le masque suivant&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
/* Copyright (C) YYYY John Doe  &amp;lt;email@email.com&amp;gt;&lt;br /&gt;
 *&lt;br /&gt;
 * Licence information&lt;br /&gt;
 */&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Quand vous éditez un fichier existant du projet, ajouter une ligne Copyright sous celles existantes.&lt;br /&gt;
&lt;br /&gt;
=Normes PHP=&lt;br /&gt;
&lt;br /&gt;
==PHP==&lt;br /&gt;
&lt;br /&gt;
*Dolibarr est écrit en PHP et supporte toutes versions PHP supérieures à la {{PHPMinVersion}}. Les fichiers doivent tous comporter l&#039;extension .php&lt;br /&gt;
&lt;br /&gt;
*L&#039;appel aux variables superglobales PHP doit passer par les opérateurs dédiés $_COOKIES, $_SERVER, $_ENV. Mais pour récupérer les contenus de $_GET ou $_POST, il faut passer par la fonction dolibarr [[Fonctions utiles Dolibarr|GETPOST()]] .&lt;br /&gt;
&lt;br /&gt;
Les autres opérateurs ($HTTP_SERVER_GET, ...) ayant été passés en deprecated au sein de PHP, ne doivent plus être utilisés. Ainsi le code doit fonctionner y compris quand l&#039;option &#039;&#039;&#039;register_long_arrays&#039;&#039;&#039; est à off.&lt;br /&gt;
De plus, le code doit fonctionner aussi bien quand l&#039;option PHP &#039;&#039;&#039;register_globals&#039;&#039;&#039; est à off (recommandé par PHP)  que quand l&#039;option &#039;&#039;&#039;register_globals&#039;&#039;&#039; est à on (par défaut sur de nombreuses installations).&lt;br /&gt;
&lt;br /&gt;
*Pas d&#039;utilisation de la variable &#039;&#039;&#039;PHP_SELF&#039;&#039;&#039;. Utiliser à la place $_SERVER[&amp;quot;PHP_SELF&amp;quot;]. Notez aussi que le framework Dolibarr passe une routine pour rendre plus sûr le contenu du $_SERVER[&amp;quot;PHP_SELF&amp;quot;] (dans le fichier main.inc.php, donc avant tout traitement métier)&lt;br /&gt;
&lt;br /&gt;
*Quand plusieurs variables doivent être initialisées avec la même valeur, il faut utiliser plusieurs instructions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$var1 = 1; $var2 = 1; $var3 = 1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
plutôt que&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$var1 = $var2 = $var3 = 1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
qui est moins performant.&lt;br /&gt;
&lt;br /&gt;
*Les chaines doivent avoir les variables sorties de la chaine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print &amp;quot;Mon texte affiche ma &amp;quot;.$variable.&amp;quot; !\n&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les commentaires doivent suivre la syntaxe C, ie un double antislash pour un commentaire d&#039;une ligne et utilisation slash-étoile pour ouvrir un bloc de plusieurs lignes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
/* Bloc de commentaire&lt;br /&gt;
 *&lt;br /&gt;
 * Fin du bloc&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
$monobjet = new MonObjet($db);&lt;br /&gt;
$result=$monobjet-&amp;gt;fetch($idobject);&lt;br /&gt;
&lt;br /&gt;
for ($i = 1 , $i &amp;lt; 2 ; $i++)&lt;br /&gt;
{&lt;br /&gt;
  // commentaire sur une ligne&lt;br /&gt;
  print $i;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les fonctions doivent retourner une valeur strictement &amp;gt; à 0 en cas de succès, et un nombre &amp;lt; à 0 en cas d&#039;erreur.&lt;br /&gt;
&lt;br /&gt;
*Pas de code mort (non utilisé) dans le code principal de Dolibarr (le code utilisé uniquement par un module externe doit être inclus dans le module externe).&lt;br /&gt;
&lt;br /&gt;
*Utiliser &amp;quot;include_once&amp;quot; pour l&#039;inclusion de tout fichier contenant des définitions de fonction ou de classes (donc fichiers *.class.php et *.lib.php), utiliser &amp;quot;include&amp;quot; pour tout inclusion de fichier de type template ou contenant un mixte de HTML et PHP (donc fichiers *.inc.php et *.tpl.php).&lt;br /&gt;
&lt;br /&gt;
*Le style de code a utiliser est le PSR-12 (https://www.php-fig.org/psr/psr-12/). Seules les règles &amp;quot;MUST&amp;quot; sont imposées. Notez aussi les points/exceptions suivants:&lt;br /&gt;
**La longueur des lignes: PSR-12 indique que la longueur des lignes a une limite &amp;quot;soft&amp;quot; à 120. Il est en effet préférable d&#039;avoir de longues lignes de données de déclaration plutôt que de longues pages car ce code ne contient aucune logique intéressante ou utile, toutefois une limite &amp;quot;hard&amp;quot; a été instauré à &#039;&#039;&#039;1000&#039;&#039;&#039; caractères. Du code qui ira au delà provoquera des erreurs dans la plateforme d&#039;Intégration Continue.&lt;br /&gt;
**Les tabulations sont acceptées : L&#039;autre exception est qu&#039;on ne remplace pas les tabulations systématiquement par des espaces. L&#039;utilisation des tabulations simplifie la vie de certains développeurs. De plus, l&#039;utilisation d&#039;espaces rend certaines fonctions d&#039;autoformatage défectueuses (comme sur certaines versions d&#039;Eclipse, lors de copier-coller).&lt;br /&gt;
**Note 1: Les règles suivantes sont particulièrement importantes :&lt;br /&gt;
***Les fichiers doivent être sauvés en format Unix (LF) et non Windows (CR/LF). Le format Unix étant compatible sur les OS Unix like, Windows, Mac, alors que le format fichier texte Windows pose problème sous certains PHP sous Unix.&lt;br /&gt;
***Les smart tags PHP ne sont pas utilisés. Les sections de code doivent commencer par &#039;&#039;&#039;&amp;lt;?php&#039;&#039;&#039;&lt;br /&gt;
**Note 2: Vous pouvez utiliser le fichier &#039;&#039;&#039;dev/setup/codesniffer/ruleset.xml&#039;&#039;&#039; comme fichier de contrôle pour vérifier votre style de code avec PHPCodeSniffer.&lt;br /&gt;
**Note 3: Vous pouvez utiliser le fichier &#039;&#039;&#039;dev/setup/eclipse/PSR-12 [built-in].xml&#039;&#039;&#039; comme fichier de règles de syntax pour configurer Eclipse.&lt;br /&gt;
**Note 4: Vous remarquerez que le code actuel ne suit pas forcément tout cela. La raison est historique. La règle fut instaurée en cours de route, aussi, si vous trouvez du code non respectueux de ce standard, n&#039;hésitez pas à le corriger.&lt;br /&gt;
&lt;br /&gt;
==Structures des classes et champs==&lt;br /&gt;
&lt;br /&gt;
Certaines propriétés de classes se retrouvent dans de nombreuses classes. Pour homogénéité, on utilisera les noms suivants:&lt;br /&gt;
{{TemplatePHPFields}}&lt;br /&gt;
&lt;br /&gt;
=Normes SQL=&lt;br /&gt;
&lt;br /&gt;
==Structure des tables et champs==&lt;br /&gt;
&lt;br /&gt;
*Toutes les tables sont préfixées pour éviter les conflits de nommage. Aujourd&#039;hui, le préfixe est modifiable au moment de l&#039;installation. Sa valeur par défaut est &amp;lt;tt&amp;gt;llx_&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*Structure des tables.&lt;br /&gt;
&lt;br /&gt;
Lorsque vous créez une table, il est recommandé de prendre les même conventions de nommages de tables que les autres tables Dolibarr. Avec, à minima les champs suivant:&lt;br /&gt;
 - rowid INTEGER AUTO_INCREMENT PRIMARY KEY    qui est l&#039;id technique&lt;br /&gt;
 - entity INTEGER default 1                    that is id for the multicompany feature&lt;br /&gt;
 - date_creation   datetime                    that is the creation date&lt;br /&gt;
 - tms             timestamp                   qui sera un champ contenant la date de chaque mise à jour (la base de donnée le gère tout seul, pas besoin de le gérer par le code)&lt;br /&gt;
 - import_key      varchar(32)                 qui contiendra le code d&#039;import YYYYMMDDHHMMSS si vous faites des imports en masse dans la table.&lt;br /&gt;
 - status          smallint                    pour stocker le status d&#039;un object&lt;br /&gt;
&lt;br /&gt;
Eventuellement&lt;br /&gt;
 - fk_user_creat  integer qui est l&#039;id du user de création (fk_user_author also found)&lt;br /&gt;
 - fk_user_modif  integer qui est l&#039;id du user de modification&lt;br /&gt;
 - fk_user_valid  integer qui est l&#039;id du user de validation&lt;br /&gt;
 - fk_soc integer qui est l&#039;id du tiers (si applicable)&lt;br /&gt;
&lt;br /&gt;
*Type des champs&lt;br /&gt;
&lt;br /&gt;
Dans la pratique, afin d&#039;être compatible avec toutes les précisions des pays, syntaxes des bases, on utilisera uniquement les types suivants:&lt;br /&gt;
 - integer pour tout nombre entier, id ou clé étrangère (bigint éventuellement accepté pour les id des très grosses tables)&lt;br /&gt;
 - smallint pour tout numérique entier de petite taille (comme pour stocker un code de status)&lt;br /&gt;
 - double(24,8) pour tout montant&lt;br /&gt;
 - double(6,3) pour les taux de tva&lt;br /&gt;
 - real pour une quantité&lt;br /&gt;
 - varchar pour une chaîne (y compris de longueur 1, le type char est de plus en plus déprécié)&lt;br /&gt;
 - timestamp pour un champ date+heure devant être mis a jour automatiquement&lt;br /&gt;
 - datetime pour un champ date+heure&lt;br /&gt;
 - date pour un champ date&lt;br /&gt;
&lt;br /&gt;
==Clé primaire==&lt;br /&gt;
La clé primaire d&#039;une table s&#039;appelle &amp;lt;tt&amp;gt;rowid&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Il y a quelques tables qui échappent à cette règle actuellement (ex [[Table llx_c_actioncomm]]), pour des raisons historiques. Une évolution pourra être étudiée pour une prochaine version.&lt;br /&gt;
&lt;br /&gt;
==Clés étrangères==&lt;br /&gt;
Le nom d&#039;une clé étrangère commence par le préfixe &amp;lt;tt&amp;gt;fk_&amp;lt;/tt&amp;gt; suivi du nom de la table liée (requis pour éviter doublons globales à la base, problématiques sous certains SGBD comme postgresql) puis du champ lié (pour permettre plusieurs clés étrangères différentes sur une même table).&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
fk_facture_fourn_fk_soc&lt;br /&gt;
&lt;br /&gt;
Note: Si vous développez votre propre module externe, il ne doit pas y avoir de clé étrangère depuis vos tables qui pointent sur les tables standards de Dolibarr. Ceci casserait les fonctionnalités de mise à jour, de réparation, de sauvegardes et de restauration.&lt;br /&gt;
&lt;br /&gt;
==Clés alternatives==&lt;br /&gt;
Parfois, il n&#039;y a pas que la clé primaire qui doit être unique. On peut donc ajouter aussi un index clé alternative unique. Un tel index est nommé par un nom qui commence par le préfixe &amp;lt;tt&amp;gt;uk_&amp;lt;/tt&amp;gt; suivi du nom de la table (requis pour éviter doublons d&#039;index globals à la base, problématiques sous certains SGBD comme postgresql) puis d&#039;un suffixe qui caractérise la clé (pour permettre plusieurs index uniques sur une même table).&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
uk_societe_code_client&lt;br /&gt;
&lt;br /&gt;
==Index performance==&lt;br /&gt;
Certains champs sont souvent utilisés comme critère de recherche, de tri ou de jointure. Il convient dans ce cas, d&#039;y mettre un index de performance. De tels indexes seront nommés avec un préfix &amp;lt;tt&amp;gt;idx_&amp;lt;/tt&amp;gt; puis le nom de la table et le nom du champ sur lequel porte l&#039;index.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
idx_societe_user_creat&lt;br /&gt;
&lt;br /&gt;
==Format de fichier DDL==&lt;br /&gt;
Les fichiers qui contiennent la définition de la structure de la base (DDL) doivent être au nombre de 2 par tables:&lt;br /&gt;
Chaque table est définie dans son propre fichier dont le nom est &amp;lt;tt&amp;gt;llx_&#039;&#039;matable&#039;&#039;.sql&amp;lt;/tt&amp;gt;. &lt;br /&gt;
On mettra un commentaire à côté de chaque champ pour en expliquer la signification.&lt;br /&gt;
Les clés étrangères et index de performance ou autres contraintes d&#039;unicité sont définies dans un fichier séparé dont le nom est &amp;lt;tt&amp;gt;llx_&#039;&#039;matable&#039;&#039;.key.sql&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ces fichiers sont placés dans le répertoire &#039;&#039;&#039;install/mysql/tables&#039;&#039;&#039; pour les fichiers standards ou &#039;&#039;&#039;monmodule/tables&#039;&#039;&#039; pour les tables amenées par un module.&lt;br /&gt;
&lt;br /&gt;
Exemple &#039;&#039;&#039;fichier table llx_matable.sql&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
-- Copyright (C) 2008 Author &amp;lt;email@author.com&amp;gt;&lt;br /&gt;
-- &lt;br /&gt;
-- This program is free software; you can redistribute it and/or modify&lt;br /&gt;
-- it under the terms of the GNU General Public License as published by&lt;br /&gt;
-- the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
-- (at your option) any later version.&lt;br /&gt;
--&lt;br /&gt;
-- This program is distributed in the hope that it will be useful,&lt;br /&gt;
-- but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
-- GNU General Public License for more details.&lt;br /&gt;
--&lt;br /&gt;
-- You should have received a copy of the GNU General Public License&lt;br /&gt;
-- along with this program. If not, see &amp;lt;http://www.gnu.org/licenses/&amp;gt;.&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
&lt;br /&gt;
create table llx_matable&lt;br /&gt;
(&lt;br /&gt;
  rowid       integer AUTO_INCREMENT PRIMARY KEY,&lt;br /&gt;
  field_one   integer,&lt;br /&gt;
  field_two   integer NOT NULL,&lt;br /&gt;
  fk_field    integer,&lt;br /&gt;
  field_date  datetime,&lt;br /&gt;
  tms         timestamp&lt;br /&gt;
)ENGINE=innodb;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Exemple &#039;&#039;&#039;fichier clés/index llx_matable.key.sql&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
-- Copyright (C) 2008 Author &amp;lt;email@author.com&amp;gt;&lt;br /&gt;
-- &lt;br /&gt;
-- This program is free software; you can redistribute it and/or modify&lt;br /&gt;
-- it under the terms of the GNU General Public License as published by&lt;br /&gt;
-- the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
-- (at your option) any later version.&lt;br /&gt;
--&lt;br /&gt;
-- This program is distributed in the hope that it will be useful,&lt;br /&gt;
-- but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
-- GNU General Public License for more details.&lt;br /&gt;
--&lt;br /&gt;
-- You should have received a copy of the GNU General Public License&lt;br /&gt;
-- along with this program. If not, see &amp;lt;http://www.gnu.org/licenses/&amp;gt;.&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE llx_matable ADD UNIQUE uk_matable_field(field_one, field_two);&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE llx_matable ADD CONSTRAINT fk_matable_fk_field FOREIGN KEY (fk_field) REFERENCES llx_matablepere (rowid);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Règles de codage SQL==&lt;br /&gt;
&lt;br /&gt;
*Utilisation des alias/nommage de champs&lt;br /&gt;
&lt;br /&gt;
Dans le cas des select on pourra utiliser les alias pour simplifier l&#039;écriture des requêtes:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
select chp1, chpxxx2 as chp2 from table2 as t1, table2 as t2 where t1.chpx = t2.chpy&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Toutefois, il ne faut pas utiliser ces alias sur des requêtes update car non compatible avec mysql 3.1.&lt;br /&gt;
&lt;br /&gt;
*Les SELECT * sont interdits ! Chaque SELECT doit spécifier la liste complète des champs à récupérer. Cela permet d&#039;éviter les confusions. Exemple:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
SELECT field_a, field_b, field_c FROM table_1 WHERE field_d = &#039;$id&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Dans les requêtes SQL, on quote les champs mais pas les numériques qui contiennent des montants destinés à être stockés dans des champs de type double ou real. Les quotes sur les numériques de type float provoquent parfois un stockage d&#039;une valeur différente. Par exemple 412.62 dans le insert sera en fait stocké avec la valeur 412.61999512 en base (suite à des conversions chaines-numériques implicites) si le champ est de type double(24,8). Et seul le PHP voit 412.61999512. Les autres outils verront 412.62 donnant l&#039;impression qu&#039;il n&#039;y a pas de problème. Et c&#039;est le PHP qui a raison, il y a problème en base. En supprimant les quotes sur les numériques, cela va mieux.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
Bon:     INSERT INTO table_1 (field_txt, field_num) VALUES (&#039;txt&#039;, 412.62)&lt;br /&gt;
Mauvais: INSERT INTO table_1 (field_txt, field_num) VALUES (&#039;txt&#039;, &#039;412.62&#039;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remarque, le problème des float est général et pas seulement sur les accès base, il est présent dans tous les languages quand on travaille sur des nombres réels, aussi ils doivent être, dès que affectés, nettoyés par la fonction price2num avec le 2eme paramètre renseigné à:&lt;br /&gt;
&#039;MU&#039; (si il s&#039;agit d&#039;un prix unitaire), &#039;MT&#039; (s&#039;il s&#039;agit d&#039;un prix total) ou &#039;MS&#039; (autres cas) selon le besoin.&lt;br /&gt;
Voir aussi le chapitre &amp;quot;Les nombres réels, montants et calculs&amp;quot; plus bas.&lt;br /&gt;
&lt;br /&gt;
*Les fonctions NOW, SYSDATE ou DATEDIFF sont interdites au sein des ordres SQL. S&#039;il faut saisir la date du moment dans un champ, la valeur doit venir du PHP, par exemple par la fonction dol_now(), et non du moteur de base de données. Ceci afin d&#039;avoir une meilleure portabilité du code mais surtout d&#039;avoir une gestion correcte des TimeZone et ne pas dépendre du TimeZone de la base de donnée.&lt;br /&gt;
&lt;br /&gt;
Par exemple, on ne fera pas:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where datefield = NOW()&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
mais:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where datefield = &#039;&amp;quot;.$this-&amp;gt;db-&amp;gt;idate(dol_now()).&amp;quot;&#039;&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Par exemple, on ne fera pas:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where DATEDIFF(table.datefield, NOW()) &amp;gt; 7&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
mais:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where datefield &amp;lt; &#039;&amp;quot;.$this-&amp;gt;db-&amp;gt;idate(dol_now() - (7 * 24 * 3600)).&amp;quot;&#039;&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un autre avantage de cette règle est que la requête peut bénéficier de l&#039;utilisation de l&#039;index puisqu&#039;on compare datefield à une valeur fixe. Dans le cas du datediff, on applique un traitement sur le champ avant comparaison, rendant impossible l&#039;utilisation de l&#039;index de ce champ. Les conséquences sont des performances très dégradées par rapport à la version sans datediff.&lt;br /&gt;
&lt;br /&gt;
==Règles de migration de base==&lt;br /&gt;
&lt;br /&gt;
*Les scripts de migration de structure sont les fichiers de type &#039;&#039;&#039;install/mysql/migration/a.b.c-x.y.z.sql&#039;&#039;&#039;. Dans un fichier de migration de n vers n+1, on ne détruit une table (DROP TABLE) qui n&#039;est plus utilisée en n+1 que lors de la migration de la version n+1 vers n+2. Ceci afin de toujours conserver les tables deprecated le temps d&#039;une version pour réparer une situation en cas d&#039;erreur de migration.&lt;br /&gt;
&lt;br /&gt;
==Spécificités MySQL==&lt;br /&gt;
&lt;br /&gt;
*Les tables doivent être au format InnoDB.&lt;br /&gt;
&lt;br /&gt;
En effet, ce format gère les clés étrangères, les éventuelles restrictions qui y sont attachées et la notion d&#039;intégrité de transactions requise pour avoir des données en base cohérente entre tables.&lt;br /&gt;
&lt;br /&gt;
*Dolibarr DOIT fonctionner même avec les options &#039;&#039;&#039;strict&#039;&#039;&#039; de Mysql active.&lt;br /&gt;
&lt;br /&gt;
Pour l&#039;activer (fortement recommandé en développement), ajouter la ligne suivante dans le fichier config du serveur Mysql (my.cnf ou my.ini)&lt;br /&gt;
{{MySqlStrictMode}}&lt;br /&gt;
&lt;br /&gt;
==Spécificités PostgreSQL==&lt;br /&gt;
Seuls les fichiers pour Mysql doivent être maintenus.&lt;br /&gt;
Les fichiers pour les autres bases sont convertis &amp;quot;à la volée&amp;quot; par le driver Dolibarr de la base.&lt;br /&gt;
&lt;br /&gt;
Il existe une exception.&lt;br /&gt;
Les requêtes &amp;quot;UPDATE FROM&amp;quot; : &lt;br /&gt;
Syntax MySQL :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
UPDATE table_taget as target, table_source as source SET fieldtarget=source.fieldsource&lt;br /&gt;
WHERE source.rowid=target.rowid;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Syntax PgSQL:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
UPDATE table_taget as target SET fieldtarget=source.fieldsource&lt;br /&gt;
FROM table_source as source WHERE source.rowid=target.rowid;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il n&#039;en existe pas dans Dolibarr, mais pour vos modules Vous devriez faire tel que :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
if ($this-&amp;gt;db-&amp;gt;type==&#039;pgsql&#039;) {&lt;br /&gt;
$sql=&amp;quot;UPDATE table_taget as target SET fieldtarget=source.fieldsource&lt;br /&gt;
FROM table_source as source WHERE source.rowid=target.rowid&amp;quot;;&lt;br /&gt;
} else {&lt;br /&gt;
$sql= &amp;quot;UPDATE table_taget as target, table_source as source SET fieldtarget=source.fieldsource&lt;br /&gt;
WHERE source.rowid=target.rowid&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Normes HTML=&lt;br /&gt;
&lt;br /&gt;
*Tous les attributs dans les balises HTML doivent être *en minuscule* et quotés avec des *doubles quote*.&lt;br /&gt;
&lt;br /&gt;
*Les liens href doivent être absolus en se basant sur la fonction dol_buildpath() pour obtenir un chemin absolu depuis un chemin relatif au répertoire htdocs. Pour les tags img, il faut faire appel à la fonction img_picto().&lt;br /&gt;
&lt;br /&gt;
Par example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print &#039;&amp;lt;a href=&amp;quot;&#039;.dol_buildpath(&#039;/monrep/mapage.php&#039;).&#039;&amp;quot;&amp;gt;&#039;.img_picto(&#039;Texte alt&#039;,&#039;nompictopng&#039;,&#039;&#039;).&#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les tables HTML doivent avoir des colonnes sans valeurs forcées, excepté pour les colonnes qui contiennent une information dont la longueur est non variable. Par exemple, une colonne avec un picto peut être forcée à with=&amp;quot;20px&amp;quot;. Dans les autres cas, il faut éviter de forcer la largeur des colonnes. La raison est que, dans la plupart des cas, le navigateur fait un meilleur travail pour définir automatiquement la bonne largeur des colonnes qu&#039;en forçant manuellement les largeurs. Et ceci marche quelle que soit la résolution de l&#039;écran.&lt;br /&gt;
&lt;br /&gt;
*Le javascript/ajax et l&#039;appel aux scripts java dans les pages php est à proscrire. Si toutefois du code javascript est inclus, il doit être conditionné par le test sur &amp;quot;$conf-&amp;gt;use_javascript_ajax&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
if ($conf-&amp;gt;use_javascript_ajax) {&lt;br /&gt;
...  // Le code php qui génère du javascript est ici&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les popups windows ne doivent pas être utilisées, sauf pour des tooltips (et restent conditionnées par le point ci-dessus).&lt;br /&gt;
&lt;br /&gt;
*Les scripts externes sont écrits en Perl s&#039;ils ne peuvent l&#039;être en php, l&#039;utilisation d&#039;un autre langage n&#039;est pas interdit mais doit être discuté au préalable dans la mailing list des développeurs.&lt;br /&gt;
&lt;br /&gt;
=Normes Dolibarr et squelettes de code=&lt;br /&gt;
&lt;br /&gt;
==Squelettes de code==&lt;br /&gt;
Afin d&#039;uniformiser le code et d&#039;accélérer le développement de nouveaux composants dans Dolibarr, se trouvent dans le répertoire &#039;&#039;&#039;htdocs/modulebuilder/templates&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Par exemple:&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de descripteur de module: &#039;&#039;&#039;myModule.class.php&#039;&#039;&#039;&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de code pour faire une nouvelle classe: &#039;&#039;&#039;skeleton_class.class.php&#039;&#039;&#039;&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de code pour faire une nouvelle page: &#039;&#039;&#039;skeleton_page.php&#039;&#039;&#039;&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de code pour faire un script à exécuter en ligne de commande: &#039;&#039;&#039;skeleton_script.php&#039;&#039;&#039;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
Servez-vous en comme exemple.&lt;br /&gt;
Notons que ces squelettes sont aussi utilisés par le générateur de code PHP ([[Module ModuleBuilder]]) qui est décrit dans la chapitre de développement de module Dolibarr pour accélérer vos développements.&lt;br /&gt;
&lt;br /&gt;
==Les dates et TimeZone==&lt;br /&gt;
Dolibarr se veut une application multi-utilisateur et multi-localisation. Il convient donc de stocker les dates dans le bon format. Pour éviter les problèmes de conversion, les règles suivantes doivent être appliquées:&lt;br /&gt;
&lt;br /&gt;
*Une date en mémoire doit être au format Timestamp GMT.&lt;br /&gt;
*Une date stockée en base de données contient le Timestamp issue de la date soumise dans la requête en heure &amp;lt;b&amp;gt;locale du serveur PHP&amp;lt;/b&amp;gt;. Cela ne concerne pas les dates mises à jour automatiquement par la base (champ &#039;&#039;&#039;tms&#039;&#039;&#039; en base).&lt;br /&gt;
&lt;br /&gt;
Ainsi le 1er janvier 1970, 3 heures à Paris (TZ=+1) = 1er janvier 1970, 2 heures à Greenwich (TZ=0) sera stocké en mémoire par 7200 et sera soumis à la base de données avec la chaine &#039;19700101030000&#039; (PHP convertit en heure de son TZ et la base déconvertit avec son TZ qui est le même que celui de PHP).&lt;br /&gt;
&lt;br /&gt;
Les méthodes select doivent donc traduire les champs dates lus qui sont au format chaine TZ de la base (&#039;19700101030000&#039;) par appel de la méthode db-&amp;gt;jdate afin de récupérer une information en mémoire au format Timestamp GMT. Et les méthodes insert doivent lors de la génération de la requête convertir la date mémoire connue en variable, par la méthode db-&amp;gt;idate (Voir exemples générés par le squelette).&lt;br /&gt;
&lt;br /&gt;
*Les dates mises à jour automatiquement par la base (champ &#039;&#039;&#039;tms&#039;&#039;&#039; en base) contiennent le Timestamp où la modification est faite selon le timezone de la base de donnée. Les méthodes select récupèrent cette donnée en mémoire au format Timestamp GMT en appliquant également le db-&amp;gt;jdate. Si le timezone de la base de donnée diffère de celui du PHP (un des 2 est mal réglé), il peut donc y avoir des écarts entre date de création et modification.&lt;br /&gt;
&lt;br /&gt;
*La manipulation de dates en PHP doit être faite en utilisant les fonctions dates de Dolibarr: &#039;&#039;&#039;dol_now(), dol_mktime(), dol_stringtotime(), dol_getdate(), dol_time_plus_duree()&#039;&#039;&#039;. Vous trouverez également d&#039;autres fonctions prêtes à l&#039;emploi dans le fichier &#039;&#039;&#039;date.lib.php&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==L&#039;encodage UTF8/ISO==&lt;br /&gt;
Dolibarr stocke les informations de manière suivante:&lt;br /&gt;
&lt;br /&gt;
*En base de donnée, les données sont en UTF8 ou ISO. Cela dépend du pagecode de la base, donc des options à la création de cette base. Dans tous les cas le driver d&#039;accès base Dolibarr (dans /lib/database) s&#039;arrange à la lecture et insertion pour convertir vers et depuis de l&#039;UTF8.&lt;br /&gt;
*Les données en mémoires sont donc stockées en UTF8 (instances d&#039;objets PHP).&lt;br /&gt;
*Les pages web affichées à l&#039;écran sont au format UTF8&lt;br /&gt;
&lt;br /&gt;
==Les nombres réels, montants et calculs==&lt;br /&gt;
En PHP comme dans d&#039;autres langages (Java par exemple), les données non entières (float, real, double) ne sont pas fiables.&lt;br /&gt;
Essayer de faire par exemple &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print 239.2 - 229.3 - 9.9;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Vous n&#039;obtiendrez pas zéro mais un nombre très petit en puissance de 10 négative. Si vous obtenez zéro, vous pourrez trouvez d&#039;autres exemples qui ne fonctionnent pas.&lt;br /&gt;
Le problème des float est général, une variable résultante de calcul de nombre réels doit SYSTEMATIQUEMENT être nettoyée par la fonction &#039;&#039;&#039;price2num()&#039;&#039;&#039; avec le 2eme paramètre renseigné à: &#039;MU&#039;, &#039;MT&#039; ou &#039;MS&#039; selon le besoin (voir doc fonction).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print price2num(239.2 - 229.3 - 9.9, &#039;MT&#039;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
S&#039;il ne s&#039;agit pas d&#039;un prix sur lequel s&#039;adapte les paramètres MU, MT ou MS, il faut utiliser la fonction &#039;&#039;&#039;round()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==Création de tables==&lt;br /&gt;
Ne pas créer de table à l&#039;utilisation, c&#039;est-à-dire à la &#039;&#039;&#039;première utilisation&#039;&#039;&#039; du module.&lt;br /&gt;
Si vous créez un module qui utilise des tables qui ne sont pas intégrées en standard dans le code de Dolibarr, veillez à suivre le didacticiel [[Développement module]] qui explique comment joindre des tables qui se créent à l&#039;activation du module et non à son utilisation (voir plus haut).&lt;br /&gt;
&lt;br /&gt;
==Comparer la version==&lt;br /&gt;
&lt;br /&gt;
Si votre code a besoin de faire des choses différentes selon la version de Dolibarr, vous pouvez utiliser le truc suivant pour comparer les versions&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$version=preg_split(&#039;/[\.-]/&#039;,DOL_VERSION);&lt;br /&gt;
if (versioncompare($version,array(5,0,-4)) &amp;gt;= 0) { //mycode for 5.0 only; }	// For dolibarr 5.0.* (the -4 means we include also alpha, beta, rc and rcX)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais cette solution requiert de faire un include avoir la fonction versioncompare. Une alternative est d&#039;utiliser le test suivant:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
if ((float) DOL_VERSION &amp;gt;= 5.0) { //mycode for 5.0 only; }	// For dolibarr 5.0.*&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Logs==&lt;br /&gt;
Ajouter des traces dans votre code avec la fonction&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
dol_syslog($yourmessage, LOG_INFO|LOG_DEBUG|LOG_WARNING|LOG_ERR);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Répertoires de travail==&lt;br /&gt;
Si vous avez besoin de créer un répertoire de travail, dans votre code, faites référence à ce répertoire par&lt;br /&gt;
&#039;&#039;&#039;DOL_DATA_ROOT.&#039;/monmodule&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Le répertoire peut être créé dans votre code à l&#039;exécution par le code suivant:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$mymoduledir=DOL_DATA_ROOT.&#039;/monmodule&#039;;&lt;br /&gt;
dol_mkdir($mymoduledir);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si vous avez besoin d&#039;un répertoire qui contiendra des données temporaires, ce répertoire doit être&#039;&#039;&#039; DOL_DATA_ROOT.&#039;/monmodule/temp&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Design patterns et programmation objet=&lt;br /&gt;
&lt;br /&gt;
==Design patterns de Création (GoF)==&lt;br /&gt;
Design patterns définis par le Gang Of Four (voir la wikipédia sur les [[wikipedia:Patron de conception|Design patterns]]).&lt;br /&gt;
Dans Dolibarr, pas de mise en oeuvre de design patterns de comportement particulier.&lt;br /&gt;
On trouve des objets proches des Singletons et Fabriques conformes à 100% dans l&#039;esprit mais pas dans la syntaxe, ceci afin d’être compatible avec la plus large plage possible de versions de PHP.&lt;br /&gt;
&lt;br /&gt;
==Design patterns d&#039;entreprises (Martin Fowler)==&lt;br /&gt;
&lt;br /&gt;
===Mode d&#039;organisation du code===&lt;br /&gt;
[[wikipedia:Martin_Fowler|Martin Fowler]] a identifié 3 méthodes d&#039;organisation du code appelées &#039;&#039;&#039;patterns&#039;&#039;&#039; (&#039;&#039;&#039;motifs&#039;&#039;&#039;):&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Transaction Script&#039;&#039;&#039; (Le code est linéaire en fonction d&#039;une action utilisateur).&lt;br /&gt;
&lt;br /&gt;
C&#039;est le motif à l&#039;ancienne utilisé dans les langages procéduraux.&lt;br /&gt;
Inconvénient: Redondance du code. Nécessité de connaitre le modèle physique pour développer les parties métiers.&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Domain Model&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
C&#039;est un concept possible depuis les langages objets. Ce sont les procédures métiers (qui doivent être identifiés avant) qui servent de bases pour les classes objets.&lt;br /&gt;
Inconvénient : Motif complexe à maintenir.&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Table Module&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Un intermédiaire entre les 2 précédents où l&#039;on a une instance unique de classe par table de la base de données.&lt;br /&gt;
&lt;br /&gt;
-&amp;gt; Comme le montre les squelettes de code (voir point précédent), Dolibarr se base sur le principe du &#039;&#039;&#039;Table Module&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===Communication Logique métier - Données (ORM)===&lt;br /&gt;
Il existe 3 modes de liaisons:&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Table And Row Data Gateway&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
C&#039;est le plus simple. On crée une classe par table et chaque classe est un pont avec la table correspondante et propose les méthodes CRUD sur cette table (Create, Read, Update, Delete). Une instance de classe étant alors un enregistrement de la table. La classe ne contient que du code d&#039;accès aux lignes ou colonnes de tables. Le code métier doit alors être ajouté dans d&#039;autres classes. Les liens entre ces classes tables et les classes métiers devant être connues ou déduite de la connaissance du développeur.&lt;br /&gt;
&lt;br /&gt;
Exemple: C&#039;est le mode mis en oeuvre quand on utilise certains Frameworks d&#039;ORM comme &#039;&#039;&#039;iBatis&#039;&#039;&#039; (http://ibatis.apache.org/).&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Active Record&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Identique au précédent, mais on se permet d&#039;ajouter quelques fonctions métiers sur la classe, à conditions que ces fonctions soient bien  propres à la table ou à la notion métier porté par l&#039;enregistrement. C&#039;est le pattern qui offre le meilleur rapport fonctionnalité/complexité.&lt;br /&gt;
&lt;br /&gt;
Exemple: C&#039;est le mode choisi pour les développements Dolibarr et de nombreuses autres applications PHP qui ont leur propre framework et pratiques de développements.&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Data Mapper&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Les classes représentent les entités du problème et non les données. Il faut donc doubler, tripler... ces classes avec des classes Mapper pour accéder aux données.&lt;br /&gt;
Plus &amp;quot;puriste&amp;quot; sur le papier car plus proche du métier, ce mode a aussi l&#039;inconvénient d&#039;être très complexe et difficile à maintenir dans la réalité (l&#039;expérience pratique constaté ne rejoignant pas les promesses de la théorie).&lt;br /&gt;
&lt;br /&gt;
Exemple: C&#039;est le choix si on utilise le Framework d&#039;ORM &#039;&#039;&#039;Propel&#039;&#039;&#039; (http://propel.phpdb.org/trac/). On le trouve donc sur des applications plus lourdes basées sur cet ORM entre autres.&lt;br /&gt;
&lt;br /&gt;
-&amp;gt; Pour les développements Dolibarr, il est recommandé d&#039;utiliser le mode de liaison &#039;&#039;&#039;Active Record&#039;&#039;&#039; qui offre les avantages d&#039;un modèle proche du métier sans en avoir la complexité et sans trop masquer non plus la technique. C&#039;est dans ce mode que le développement, la compréhension du code et la maintenance technique et/ou fonctionnelle semble la plus productive (ceci est toutefois un éternel débat entre les puristes et les pragmatiques, débat dans lequel personne ne peut vraiment avoir raison, car tout dépend des objectifs à atteindre).&lt;br /&gt;
&lt;br /&gt;
==Design Pattern d&#039;Interface Graphique (MVC)==&lt;br /&gt;
Il existe plusieurs design pattern pour les interfaces utilisateurs (MVC, MVP, MVVM).&lt;br /&gt;
Beaucoup confonde ce design pattern avec celui consistant à utiliser un framework de templates. C&#039;est sans rapport. Un framework de template (voir point précédent) n&#039;est en lien qu&#039;avec la partie &amp;quot;V&amp;quot; de ces modèles.&lt;br /&gt;
&lt;br /&gt;
-&amp;gt; Dolibarr utilise le Design Pattern &#039;&#039;&#039;MVC&#039;&#039;&#039;. La partie M est matérialisée par une classe DAO contenant les méthode CRUD (Create-Read-Update-Delete) d&#039;accès à la table.&lt;br /&gt;
Beaucoup de frameworks ont fait le choix de mettre la partie de code C (Controller) et la partie de code du V (vue) dans des fichiers, voir même répertoires séparés. La maintenance semble plus aisé sur la papier, en pratique, il faut sans arrêt jonglé entre n fichiers, le C étant fortement lié au V. Aussi dans Dolibarr, la séparation est faite par une simple section de commentaire. La partie de code C (Controller) est donc le code qui se trouve sont la balise&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * Actions&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Elle est suivi par la partie de code V (Vue), bien séparé du C par la balise&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * View&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce mode de séparation a eu un effet neutre sur les nouveaux développement mais a permis de réduire de manière si importante le temps requis pour la maintenance et correction de bugs qu&#039;il n&#039;est pas envisagé de basculer vers un autre type de séparation (oui les constats fait dans la vraie vie ne sont pas toujours ceux attendus par la théorie scolaire). L&#039;important reste qu&#039;il y ait toujours séparation entre le C et le V, peut importe comment est matérialisé cette séparation, du moment qu&#039;elle l&#039;est (Rappel: Ne pas confondre la notion de séparation du C et du V avec la notion de séparation du code pour alimenter la données d&#039;une Vue et du code pour formater la Vue, ceci un principe de séparation relevant du Design Pattern de Vue, voir point suivant).&lt;br /&gt;
&lt;br /&gt;
==Design Pattern de Vue - Présentation==&lt;br /&gt;
Il existe des frameworks spécialisés dans le Design Pattern de Vue, la partie qui consiste à formater l&#039;écran vue par l&#039;utilisateur.&lt;br /&gt;
Les vieilles versions de Dolibarr utilisaient Smarty. Ce framework est une surcouche à un Framework, déjà très puissant, de formatage d&#039;écran nommé... PHP. Les bénéfices étant très inférieurs aux inconvénients, il a été abandonné au profit de templates PHP (fichier .tpl.php) qui restent le plus simple, le plus universel, le plus évolutif et le plus performant, des frameworks de présentation. &lt;br /&gt;
&lt;br /&gt;
Son seul défaut est qu&#039;il ne peut garantir à 100% les écarts d&#039;un développeur qui irait intégrer dans la Vue, une logique sans rapport avec la présentation (donc autre que du code à vocation de génération, de formatage, de sortie HTML, de logique de test ou de boucle). Ce point est toutefois contrôlé par le mécanisme de validation du code des chefs de projets.&lt;br /&gt;
&lt;br /&gt;
La encore, c&#039;est l&#039;expérience et le constat &amp;quot;sur le terrain&amp;quot; d&#039;un meilleur rendement de productivité qui a motivé l&#039;abandon des frameworks de Présentation externes au profit du framework PHP.&lt;/div&gt;</summary>
		<author><name>Quentic</name></author>
	</entry>
	<entry>
		<id>https://wiki.dolibarr.org/index.php?title=Langages_et_normes&amp;diff=52116</id>
		<title>Langages et normes</title>
		<link rel="alternate" type="text/html" href="https://wiki.dolibarr.org/index.php?title=Langages_et_normes&amp;diff=52116"/>
		<updated>2021-09-30T08:44:10Z</updated>

		<summary type="html">&lt;p&gt;Quentic: /* Design patterns de Création (GoF) */Correction d&amp;#039;erreur de frappe&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- BEGIN interlang links --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Do NOT edit this section&lt;br /&gt;
     Links below are automatically managed by PolyglotBot&lt;br /&gt;
     You can edit links on the English source page : Language_and_development_rules --&amp;gt;&lt;br /&gt;
[[en:Language_and_development_rules]]&lt;br /&gt;
[[de:Sprachen_und_Programmierregeln]]&lt;br /&gt;
[[es:Lenguaje_y_Normas_de_Desarrollo]]&lt;br /&gt;
[[zh:语言和开发规则]]&lt;br /&gt;
&amp;lt;!-- END interlang links --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{TemplateDocDev}}&lt;br /&gt;
&lt;br /&gt;
Voici les quelques règles sur le langage, la syntaxe et normes de développement en vigueur pour le projet Dolibarr :&lt;br /&gt;
&lt;br /&gt;
=Versions=&lt;br /&gt;
&lt;br /&gt;
*Dolibarr doit fonctionner sur:&lt;br /&gt;
&lt;br /&gt;
#Tous OS (Windows, Linux, MACOS...)&lt;br /&gt;
#PHP {{PHPMinVersion}} (Doit fonctionner sans aucun module PHP complémentaire hors les modules d&#039;accès base de donnée).&lt;br /&gt;
#Mysql {{MySqlMinVersion}}&lt;br /&gt;
&lt;br /&gt;
=Normes Copyright=&lt;br /&gt;
&lt;br /&gt;
*Tout fichier PHP doit avoir un en-tête selon le masque suivant&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
/* Copyright (C) YYYY John Doe  &amp;lt;email@email.com&amp;gt;&lt;br /&gt;
 *&lt;br /&gt;
 * Licence information&lt;br /&gt;
 */&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Quand vous éditez un fichier existant du projet, ajouter une ligne Copyright sous celles existantes.&lt;br /&gt;
&lt;br /&gt;
=Normes PHP=&lt;br /&gt;
&lt;br /&gt;
==PHP==&lt;br /&gt;
&lt;br /&gt;
*Dolibarr est écrit en PHP et supporte toutes versions PHP supérieures à la {{PHPMinVersion}}. Les fichiers doivent tous comporter l&#039;extension .php&lt;br /&gt;
&lt;br /&gt;
*L&#039;appel aux variables superglobales PHP doit passer par les opérateurs dédiés $_COOKIES, $_SERVER, $_ENV. Mais pour récupérer les contenus de $_GET ou $_POST, il faut passer par la fonction dolibarr [[Fonctions utiles Dolibarr|GETPOST()]] .&lt;br /&gt;
&lt;br /&gt;
Les autres opérateurs ($HTTP_SERVER_GET, ...) ayant été passés en deprecated au sein de PHP, ne doivent plus être utilisés. Ainsi le code doit fonctionner y compris quand l&#039;option &#039;&#039;&#039;register_long_arrays&#039;&#039;&#039; est à off.&lt;br /&gt;
De plus, le code doit fonctionner aussi bien quand l&#039;option PHP &#039;&#039;&#039;register_globals&#039;&#039;&#039; est à off (recommandé par PHP)  que quand l&#039;option &#039;&#039;&#039;register_globals&#039;&#039;&#039; est à on (par défaut sur de nombreuses installations).&lt;br /&gt;
&lt;br /&gt;
*Pas d&#039;utilisation de la variable &#039;&#039;&#039;PHP_SELF&#039;&#039;&#039;. Utiliser à la place $_SERVER[&amp;quot;PHP_SELF&amp;quot;]. Notez aussi que le framework Dolibarr passe une routine pour rendre plus sûr le contenu du $_SERVER[&amp;quot;PHP_SELF&amp;quot;] (dans le fichier main.inc.php, donc avant tout traitement métier)&lt;br /&gt;
&lt;br /&gt;
*Quand plusieurs variables doivent être initialisées avec la même valeur, il faut utiliser plusieurs instructions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$var1 = 1; $var2 = 1; $var3 = 1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
plutôt que&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$var1 = $var2 = $var3 = 1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
qui est moins performant.&lt;br /&gt;
&lt;br /&gt;
*Les chaines doivent avoir les variables sorties de la chaine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print &amp;quot;Mon texte affiche ma &amp;quot;.$variable.&amp;quot; !\n&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les commentaires doivent suivre la syntaxe C, ie un double antislash pour un commentaire d&#039;une ligne et utilisation slash-étoile pour ouvrir un bloc de plusieurs lignes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
/* Bloc de commentaire&lt;br /&gt;
 *&lt;br /&gt;
 * Fin du bloc&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
$monobjet = new MonObjet($db);&lt;br /&gt;
$result=$monobjet-&amp;gt;fetch($idobject);&lt;br /&gt;
&lt;br /&gt;
for ($i = 1 , $i &amp;lt; 2 ; $i++)&lt;br /&gt;
{&lt;br /&gt;
  // commentaire sur une ligne&lt;br /&gt;
  print $i;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les fonctions doivent retourner une valeur strictement &amp;gt; à 0 en cas de succès, et un nombre &amp;lt; à 0 en cas d&#039;erreur.&lt;br /&gt;
&lt;br /&gt;
*Pas de code mort (non utilisé) dans le code principal de Dolibarr (le code utilisé uniquement par un module externe doit être inclus dans le module externe).&lt;br /&gt;
&lt;br /&gt;
*Utiliser &amp;quot;include_once&amp;quot; pour l&#039;inclusion de tout fichier contenant des définitions de fonction ou de classes (donc fichiers *.class.php et *.lib.php), utiliser &amp;quot;include&amp;quot; pour tout inclusion de fichier de type template ou contenant un mixte de HTML et PHP (donc fichiers *.inc.php et *.tpl.php).&lt;br /&gt;
&lt;br /&gt;
*Le style de code a utiliser est le PSR-12 (https://www.php-fig.org/psr/psr-12/). Seules les règles &amp;quot;MUST&amp;quot; sont imposées. Notez aussi les points/exceptions suivants:&lt;br /&gt;
**La longueur des lignes: PSR-12 indique que la longueur des lignes a une limite &amp;quot;soft&amp;quot; à 120. Il est en effet préférable d&#039;avoir de longues lignes de données de déclaration plutôt que de longues pages car ce code ne contient aucune logique intéressante ou utile, toutefois une limite &amp;quot;hard&amp;quot; a été instauré à &#039;&#039;&#039;1000&#039;&#039;&#039; caractères. Du code qui ira au delà provoquera des erreurs dans la plateforme d&#039;Intégration Continue.&lt;br /&gt;
**Les tabulations sont acceptées : L&#039;autre exception est qu&#039;on ne remplace pas les tabulations systématiquement par des espaces. L&#039;utilisation des tabulations simplifie la vie de certains développeurs. De plus, l&#039;utilisation d&#039;espaces rend certaines fonctions d&#039;autoformatage défectueuses (comme sur certaines versions d&#039;Eclipse, lors de copier-coller).&lt;br /&gt;
**Note 1: Les règles suivantes sont particulièrement importantes :&lt;br /&gt;
***Les fichiers doivent être sauvés en format Unix (LF) et non Windows (CR/LF). Le format Unix étant compatible sur les OS Unix like, Windows, Mac, alors que le format fichier texte Windows pose problème sous certains PHP sous Unix.&lt;br /&gt;
***Les smart tags PHP ne sont pas utilisés. Les sections de code doivent commencer par &#039;&#039;&#039;&amp;lt;?php&#039;&#039;&#039;&lt;br /&gt;
**Note 2: Vous pouvez utiliser le fichier &#039;&#039;&#039;dev/setup/codesniffer/ruleset.xml&#039;&#039;&#039; comme fichier de contrôle pour vérifier votre style de code avec PHPCodeSniffer.&lt;br /&gt;
**Note 3: Vous pouvez utiliser le fichier &#039;&#039;&#039;dev/setup/eclipse/PSR-12 [built-in].xml&#039;&#039;&#039; comme fichier de règles de syntax pour configurer Eclipse.&lt;br /&gt;
**Note 4: Vous remarquerez que le code actuel ne suit pas forcément tout cela. La raison est historique. La règle fut instaurée en cours de route, aussi, si vous trouvez du code non respectueux de ce standard, n&#039;hésitez pas à le corriger.&lt;br /&gt;
&lt;br /&gt;
==Structures des classes et champs==&lt;br /&gt;
&lt;br /&gt;
Certaines propriétés de classes se retrouvent dans de nombreuses classes. Pour homogénéité, on utilisera les noms suivants:&lt;br /&gt;
{{TemplatePHPFields}}&lt;br /&gt;
&lt;br /&gt;
=Normes SQL=&lt;br /&gt;
&lt;br /&gt;
==Structure des tables et champs==&lt;br /&gt;
&lt;br /&gt;
*Toutes les tables sont préfixées pour éviter les conflits de nommage. Aujourd&#039;hui, le préfixe est modifiable au moment de l&#039;installation. Sa valeur par défaut est &amp;lt;tt&amp;gt;llx_&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*Structure des tables.&lt;br /&gt;
&lt;br /&gt;
Lorsque vous créez une table, il est recommandé de prendre les même conventions de nommages de tables que les autres tables Dolibarr. Avec, à minima les champs suivant:&lt;br /&gt;
 - rowid INTEGER AUTO_INCREMENT PRIMARY KEY    qui est l&#039;id technique&lt;br /&gt;
 - entity INTEGER default 1                    that is id for the multicompany feature&lt;br /&gt;
 - date_creation   datetime                    that is the creation date&lt;br /&gt;
 - tms             timestamp                   qui sera un champ contenant la date de chaque mise à jour (la base de donnée le gère tout seul, pas besoin de le gérer par le code)&lt;br /&gt;
 - import_key      varchar(32)                 qui contiendra le code d&#039;import YYYYMMDDHHMMSS si vous faites des imports en masse dans la table.&lt;br /&gt;
 - status          smallint                    pour stocker le status d&#039;un object&lt;br /&gt;
&lt;br /&gt;
Eventuellement&lt;br /&gt;
 - fk_user_creat  integer qui est l&#039;id du user de création (fk_user_author also found)&lt;br /&gt;
 - fk_user_modif  integer qui est l&#039;id du user de modification&lt;br /&gt;
 - fk_user_valid  integer qui est l&#039;id du user de validation&lt;br /&gt;
 - fk_soc integer qui est l&#039;id du tiers (si applicable)&lt;br /&gt;
&lt;br /&gt;
*Type des champs&lt;br /&gt;
&lt;br /&gt;
Dans la pratique, afin d&#039;être compatible avec toutes les précisions des pays, syntaxes des bases, on utilisera uniquement les types suivants:&lt;br /&gt;
 - integer pour tout nombre entier, id ou clé étrangère (bigint éventuellement accepté pour les id des très grosses tables)&lt;br /&gt;
 - smallint pour tout numérique entier de petite taille (comme pour stocker un code de status)&lt;br /&gt;
 - double(24,8) pour tout montant&lt;br /&gt;
 - double(6,3) pour les taux de tva&lt;br /&gt;
 - real pour une quantité&lt;br /&gt;
 - varchar pour une chaîne (y compris de longueur 1, le type char est de plus en plus déprécié)&lt;br /&gt;
 - timestamp pour un champ date+heure devant être mis a jour automatiquement&lt;br /&gt;
 - datetime pour un champ date+heure&lt;br /&gt;
 - date pour un champ date&lt;br /&gt;
&lt;br /&gt;
==Clé primaire==&lt;br /&gt;
La clé primaire d&#039;une table s&#039;appelle &amp;lt;tt&amp;gt;rowid&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Il y a quelques tables qui échappent à cette règle actuellement (ex [[Table llx_c_actioncomm]]), pour des raisons historiques. Une évolution pourra être étudiée pour une prochaine version.&lt;br /&gt;
&lt;br /&gt;
==Clés étrangères==&lt;br /&gt;
Le nom d&#039;une clé étrangère commence par le préfixe &amp;lt;tt&amp;gt;fk_&amp;lt;/tt&amp;gt; suivi du nom de la table liée (requis pour éviter doublons globales à la base, problématiques sous certains SGBD comme postgresql) puis du champ lié (pour permettre plusieurs clés étrangères différentes sur une même table).&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
fk_facture_fourn_fk_soc&lt;br /&gt;
&lt;br /&gt;
Note: Si vous développez votre propre module externe, il ne doit pas y avoir de clé étrangère depuis vos tables qui pointent sur les tables standards de Dolibarr. Ceci casserait les fonctionnalités de mise à jour, de réparation, de sauvegardes et de restauration.&lt;br /&gt;
&lt;br /&gt;
==Clés alternatives==&lt;br /&gt;
Parfois, il n&#039;y a pas que la clé primaire qui doit être unique. On peut donc ajouter aussi un index clé alternative unique. Un tel index est nommé par un nom qui commence par le préfixe &amp;lt;tt&amp;gt;uk_&amp;lt;/tt&amp;gt; suivi du nom de la table (requis pour éviter doublons d&#039;index globals à la base, problématiques sous certains SGBD comme postgresql) puis d&#039;un suffixe qui caractérise la clé (pour permettre plusieurs index uniques sur une même table).&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
uk_societe_code_client&lt;br /&gt;
&lt;br /&gt;
==Index performance==&lt;br /&gt;
Certains champs sont souvent utilisés comme critère de recherche, de tri ou de jointure. Il convient dans ce cas, d&#039;y mettre un index de performance. De tels indexes seront nommés avec un préfix &amp;lt;tt&amp;gt;idx_&amp;lt;/tt&amp;gt; puis le nom de la table et le nom du champ sur lequel porte l&#039;index.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
idx_societe_user_creat&lt;br /&gt;
&lt;br /&gt;
==Format de fichier DDL==&lt;br /&gt;
Les fichiers qui contiennent la définition de la structure de la base (DDL) doivent être au nombre de 2 par tables:&lt;br /&gt;
Chaque table est définie dans son propre fichier dont le nom est &amp;lt;tt&amp;gt;llx_&#039;&#039;matable&#039;&#039;.sql&amp;lt;/tt&amp;gt;. &lt;br /&gt;
On mettra un commentaire à côté de chaque champ pour en expliquer la signification.&lt;br /&gt;
Les clés étrangères et index de performance ou autres contraintes d&#039;unicité sont définies dans un fichier séparé dont le nom est &amp;lt;tt&amp;gt;llx_&#039;&#039;matable&#039;&#039;.key.sql&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ces fichiers sont placés dans le répertoire &#039;&#039;&#039;install/mysql/tables&#039;&#039;&#039; pour les fichiers standards ou &#039;&#039;&#039;monmodule/tables&#039;&#039;&#039; pour les tables amenées par un module.&lt;br /&gt;
&lt;br /&gt;
Exemple &#039;&#039;&#039;fichier table llx_matable.sql&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
-- Copyright (C) 2008 Author &amp;lt;email@author.com&amp;gt;&lt;br /&gt;
-- &lt;br /&gt;
-- This program is free software; you can redistribute it and/or modify&lt;br /&gt;
-- it under the terms of the GNU General Public License as published by&lt;br /&gt;
-- the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
-- (at your option) any later version.&lt;br /&gt;
--&lt;br /&gt;
-- This program is distributed in the hope that it will be useful,&lt;br /&gt;
-- but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
-- GNU General Public License for more details.&lt;br /&gt;
--&lt;br /&gt;
-- You should have received a copy of the GNU General Public License&lt;br /&gt;
-- along with this program. If not, see &amp;lt;http://www.gnu.org/licenses/&amp;gt;.&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
&lt;br /&gt;
create table llx_matable&lt;br /&gt;
(&lt;br /&gt;
  rowid       integer AUTO_INCREMENT PRIMARY KEY,&lt;br /&gt;
  field_one   integer,&lt;br /&gt;
  field_two   integer NOT NULL,&lt;br /&gt;
  fk_field    integer,&lt;br /&gt;
  field_date  datetime,&lt;br /&gt;
  tms         timestamp&lt;br /&gt;
)ENGINE=innodb;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Exemple &#039;&#039;&#039;fichier clés/index llx_matable.key.sql&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
-- Copyright (C) 2008 Author &amp;lt;email@author.com&amp;gt;&lt;br /&gt;
-- &lt;br /&gt;
-- This program is free software; you can redistribute it and/or modify&lt;br /&gt;
-- it under the terms of the GNU General Public License as published by&lt;br /&gt;
-- the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
-- (at your option) any later version.&lt;br /&gt;
--&lt;br /&gt;
-- This program is distributed in the hope that it will be useful,&lt;br /&gt;
-- but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
-- GNU General Public License for more details.&lt;br /&gt;
--&lt;br /&gt;
-- You should have received a copy of the GNU General Public License&lt;br /&gt;
-- along with this program. If not, see &amp;lt;http://www.gnu.org/licenses/&amp;gt;.&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE llx_matable ADD UNIQUE uk_matable_field(field_one, field_two);&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE llx_matable ADD CONSTRAINT fk_matable_fk_field FOREIGN KEY (fk_field) REFERENCES llx_matablepere (rowid);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Règles de codage SQL==&lt;br /&gt;
&lt;br /&gt;
*Utilisation des alias/nommage de champs&lt;br /&gt;
&lt;br /&gt;
Dans le cas des select on pourra utiliser les alias pour simplifier l&#039;écriture des requêtes:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
select chp1, chpxxx2 as chp2 from table2 as t1, table2 as t2 where t1.chpx = t2.chpy&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Toutefois, il ne faut pas utiliser ces alias sur des requêtes update car non compatible avec mysql 3.1.&lt;br /&gt;
&lt;br /&gt;
*Les SELECT * sont interdits ! Chaque SELECT doit spécifier la liste complète des champs à récupérer. Cela permet d&#039;éviter les confusions. Exemple:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
SELECT field_a, field_b, field_c FROM table_1 WHERE field_d = &#039;$id&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Dans les requêtes SQL, on quote les champs mais pas les numériques qui contiennent des montants destinés à être stockés dans des champs de type double ou real. Les quotes sur les numériques de type float provoquent parfois un stockage d&#039;une valeur différente. Par exemple 412.62 dans le insert sera en fait stocké avec la valeur 412.61999512 en base (suite à des conversions chaines-numériques implicites) si le champ est de type double(24,8). Et seul le PHP voit 412.61999512. Les autres outils verront 412.62 donnant l&#039;impression qu&#039;il n&#039;y a pas de problème. Et c&#039;est le PHP qui a raison, il y a problème en base. En supprimant les quotes sur les numériques, cela va mieux.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
Bon:     INSERT INTO table_1 (field_txt, field_num) VALUES (&#039;txt&#039;, 412.62)&lt;br /&gt;
Mauvais: INSERT INTO table_1 (field_txt, field_num) VALUES (&#039;txt&#039;, &#039;412.62&#039;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remarque, le problème des float est général et pas seulement sur les accès base, il est présent dans tous les languages quand on travaille sur des nombres réels, aussi ils doivent être, dès que affectés, nettoyés par la fonction price2num avec le 2eme paramètre renseigné à:&lt;br /&gt;
&#039;MU&#039; (si il s&#039;agit d&#039;un prix unitaire), &#039;MT&#039; (s&#039;il s&#039;agit d&#039;un prix total) ou &#039;MS&#039; (autres cas) selon le besoin.&lt;br /&gt;
Voir aussi le chapitre &amp;quot;Les nombres réels, montants et calculs&amp;quot; plus bas.&lt;br /&gt;
&lt;br /&gt;
*Les fonctions NOW, SYSDATE ou DATEDIFF sont interdites au sein des ordres SQL. S&#039;il faut saisir la date du moment dans un champ, la valeur doit venir du PHP, par exemple par la fonction dol_now(), et non du moteur de base de données. Ceci afin d&#039;avoir une meilleure portabilité du code mais surtout d&#039;avoir une gestion correcte des TimeZone et ne pas dépendre du TimeZone de la base de donnée.&lt;br /&gt;
&lt;br /&gt;
Par exemple, on ne fera pas:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where datefield = NOW()&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
mais:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where datefield = &#039;&amp;quot;.$this-&amp;gt;db-&amp;gt;idate(dol_now()).&amp;quot;&#039;&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Par exemple, on ne fera pas:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where DATEDIFF(table.datefield, NOW()) &amp;gt; 7&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
mais:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where datefield &amp;lt; &#039;&amp;quot;.$this-&amp;gt;db-&amp;gt;idate(dol_now() - (7 * 24 * 3600)).&amp;quot;&#039;&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un autre avantage de cette règle est que la requête peut bénéficier de l&#039;utilisation de l&#039;index puisqu&#039;on compare datefield à une valeur fixe. Dans le cas du datediff, on applique un traitement sur le champ avant comparaison, rendant impossible l&#039;utilisation de l&#039;index de ce champ. Les conséquences sont des performances très dégradées par rapport à la version sans datediff.&lt;br /&gt;
&lt;br /&gt;
==Règles de migration de base==&lt;br /&gt;
&lt;br /&gt;
*Les scripts de migration de structure sont les fichiers de type &#039;&#039;&#039;install/mysql/migration/a.b.c-x.y.z.sql&#039;&#039;&#039;. Dans un fichier de migration de n vers n+1, on ne détruit une table (DROP TABLE) qui n&#039;est plus utilisée en n+1 que lors de la migration de la version n+1 vers n+2. Ceci afin de toujours conserver les tables deprecated le temps d&#039;une version pour réparer une situation en cas d&#039;erreur de migration.&lt;br /&gt;
&lt;br /&gt;
==Spécificités MySQL==&lt;br /&gt;
&lt;br /&gt;
*Les tables doivent être au format InnoDB.&lt;br /&gt;
&lt;br /&gt;
En effet, ce format gère les clés étrangères, les éventuelles restrictions qui y sont attachées et la notion d&#039;intégrité de transactions requise pour avoir des données en base cohérente entre tables.&lt;br /&gt;
&lt;br /&gt;
*Dolibarr DOIT fonctionner même avec les options &#039;&#039;&#039;strict&#039;&#039;&#039; de Mysql active.&lt;br /&gt;
&lt;br /&gt;
Pour l&#039;activer (fortement recommandé en développement), ajouter la ligne suivante dans le fichier config du serveur Mysql (my.cnf ou my.ini)&lt;br /&gt;
{{MySqlStrictMode}}&lt;br /&gt;
&lt;br /&gt;
==Spécificités PostgreSQL==&lt;br /&gt;
Seuls les fichiers pour Mysql doivent être maintenus.&lt;br /&gt;
Les fichiers pour les autres bases sont convertis &amp;quot;à la volée&amp;quot; par le driver Dolibarr de la base.&lt;br /&gt;
&lt;br /&gt;
Il existe une exception.&lt;br /&gt;
Les requêtes &amp;quot;UPDATE FROM&amp;quot; : &lt;br /&gt;
Syntax MySQL :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
UPDATE table_taget as target, table_source as source SET fieldtarget=source.fieldsource&lt;br /&gt;
WHERE source.rowid=target.rowid;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Syntax PgSQL:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
UPDATE table_taget as target SET fieldtarget=source.fieldsource&lt;br /&gt;
FROM table_source as source WHERE source.rowid=target.rowid;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il n&#039;en existe pas dans Dolibarr, mais pour vos modules Vous devriez faire tel que :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
if ($this-&amp;gt;db-&amp;gt;type==&#039;pgsql&#039;) {&lt;br /&gt;
$sql=&amp;quot;UPDATE table_taget as target SET fieldtarget=source.fieldsource&lt;br /&gt;
FROM table_source as source WHERE source.rowid=target.rowid&amp;quot;;&lt;br /&gt;
} else {&lt;br /&gt;
$sql= &amp;quot;UPDATE table_taget as target, table_source as source SET fieldtarget=source.fieldsource&lt;br /&gt;
WHERE source.rowid=target.rowid&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Normes HTML=&lt;br /&gt;
&lt;br /&gt;
*Tous les attributs dans les balises HTML doivent être *en minuscule* et quotés avec des *doubles quote*.&lt;br /&gt;
&lt;br /&gt;
*Les liens href doivent être absolus en se basant sur la fonction dol_buildpath() pour obtenir un chemin absolu depuis un chemin relatif au répertoire htdocs. Pour les tags img, il faut faire appel à la fonction img_picto().&lt;br /&gt;
&lt;br /&gt;
Par example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print &#039;&amp;lt;a href=&amp;quot;&#039;.dol_buildpath(&#039;/monrep/mapage.php&#039;).&#039;&amp;quot;&amp;gt;&#039;.img_picto(&#039;Texte alt&#039;,&#039;nompictopng&#039;,&#039;&#039;).&#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les tables HTML doivent avoir des colonnes sans valeurs forcées, excepté pour les colonnes qui contiennent une information dont la longueur est non variable. Par exemple, une colonne avec un picto peut être forcée à with=&amp;quot;20px&amp;quot;. Dans les autres cas, il faut éviter de forcer la largeur des colonnes. La raison est que, dans la plupart des cas, le navigateur fait un meilleur travail pour définir automatiquement la bonne largeur des colonnes qu&#039;en forçant manuellement les largeurs. Et ceci marche quelle que soit la résolution de l&#039;écran.&lt;br /&gt;
&lt;br /&gt;
*Le javascript/ajax et l&#039;appel aux scripts java dans les pages php est à proscrire. Si toutefois du code javascript est inclus, il doit être conditionné par le test sur &amp;quot;$conf-&amp;gt;use_javascript_ajax&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
if ($conf-&amp;gt;use_javascript_ajax) {&lt;br /&gt;
...  // Le code php qui génère du javascript est ici&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les popups windows ne doivent pas être utilisées, sauf pour des tooltips (et restent conditionnées par le point ci-dessus).&lt;br /&gt;
&lt;br /&gt;
*Les scripts externes sont écrits en Perl s&#039;ils ne peuvent l&#039;être en php, l&#039;utilisation d&#039;un autre langage n&#039;est pas interdit mais doit être discuté au préalable dans la mailing list des développeurs.&lt;br /&gt;
&lt;br /&gt;
=Normes Dolibarr et squelettes de code=&lt;br /&gt;
&lt;br /&gt;
==Squelettes de code==&lt;br /&gt;
Afin d&#039;uniformiser le code et d&#039;accélérer le développement de nouveaux composants dans Dolibarr, se trouvent dans le répertoire &#039;&#039;&#039;htdocs/modulebuilder/templates&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Par exemple:&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de descripteur de module: &#039;&#039;&#039;myModule.class.php&#039;&#039;&#039;&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de code pour faire une nouvelle classe: &#039;&#039;&#039;skeleton_class.class.php&#039;&#039;&#039;&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de code pour faire une nouvelle page: &#039;&#039;&#039;skeleton_page.php&#039;&#039;&#039;&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de code pour faire un script à exécuter en ligne de commande: &#039;&#039;&#039;skeleton_script.php&#039;&#039;&#039;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
Servez-vous en comme exemple.&lt;br /&gt;
Notons que ces squelettes sont aussi utilisés par le générateur de code PHP ([[Module ModuleBuilder]]) qui est décrit dans la chapitre de développement de module Dolibarr pour accélérer vos développements.&lt;br /&gt;
&lt;br /&gt;
==Les dates et TimeZone==&lt;br /&gt;
Dolibarr se veut une application multi-utilisateur et multi-localisation. Il convient donc de stocker les dates dans le bon format. Pour éviter les problèmes de conversion, les règles suivantes doivent être appliquées:&lt;br /&gt;
&lt;br /&gt;
*Une date en mémoire doit être au format Timestamp GMT.&lt;br /&gt;
*Une date stockée en base de données contient le Timestamp issue de la date soumise dans la requête en heure &amp;lt;b&amp;gt;locale du serveur PHP&amp;lt;/b&amp;gt;. Cela ne concerne pas les dates mises à jour automatiquement par la base (champ &#039;&#039;&#039;tms&#039;&#039;&#039; en base).&lt;br /&gt;
&lt;br /&gt;
Ainsi le 1er janvier 1970, 3 heures à Paris (TZ=+1) = 1er janvier 1970, 2 heures à Greenwich (TZ=0) sera stocké en mémoire par 7200 et sera soumis à la base de données avec la chaine &#039;19700101030000&#039; (PHP convertit en heure de son TZ et la base déconvertit avec son TZ qui est le même que celui de PHP).&lt;br /&gt;
&lt;br /&gt;
Les méthodes select doivent donc traduire les champs dates lus qui sont au format chaine TZ de la base (&#039;19700101030000&#039;) par appel de la méthode db-&amp;gt;jdate afin de récupérer une information en mémoire au format Timestamp GMT. Et les méthodes insert doivent lors de la génération de la requête convertir la date mémoire connue en variable, par la méthode db-&amp;gt;idate (Voir exemples générés par le squelette).&lt;br /&gt;
&lt;br /&gt;
*Les dates mises à jour automatiquement par la base (champ &#039;&#039;&#039;tms&#039;&#039;&#039; en base) contiennent le Timestamp où la modification est faite selon le timezone de la base de donnée. Les méthodes select récupèrent cette donnée en mémoire au format Timestamp GMT en appliquant également le db-&amp;gt;jdate. Si le timezone de la base de donnée diffère de celui du PHP (un des 2 est mal réglé), il peut donc y avoir des écarts entre date de création et modification.&lt;br /&gt;
&lt;br /&gt;
*La manipulation de dates en PHP doit être faite en utilisant les fonctions dates de Dolibarr: &#039;&#039;&#039;dol_now(), dol_mktime(), dol_stringtotime(), dol_getdate(), dol_time_plus_duree()&#039;&#039;&#039;. Vous trouverez également d&#039;autres fonctions prêtes à l&#039;emploi dans le fichier &#039;&#039;&#039;date.lib.php&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==L&#039;encodage UTF8/ISO==&lt;br /&gt;
Dolibarr stocke les informations de manière suivante:&lt;br /&gt;
&lt;br /&gt;
*En base de donnée, les données sont en UTF8 ou ISO. Cela dépend du pagecode de la base, donc des options à la création de cette base. Dans tous les cas le driver d&#039;accès base Dolibarr (dans /lib/database) s&#039;arrange à la lecture et insertion pour convertir vers et depuis de l&#039;UTF8.&lt;br /&gt;
*Les données en mémoires sont donc stockées en UTF8 (instances d&#039;objets PHP).&lt;br /&gt;
*Les pages web affichées à l&#039;écran sont au format UTF8&lt;br /&gt;
&lt;br /&gt;
==Les nombres réels, montants et calculs==&lt;br /&gt;
En PHP comme dans d&#039;autres langages (Java par exemple), les données non entières (float, real, double) ne sont pas fiables.&lt;br /&gt;
Essayer de faire par exemple &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print 239.2 - 229.3 - 9.9;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Vous n&#039;obtiendrez pas zéro mais un nombre très petit en puissance de 10 négative. Si vous obtenez zéro, vous pourrez trouvez d&#039;autres exemples qui ne fonctionnent pas.&lt;br /&gt;
Le problème des float est général, une variable résultante de calcul de nombre réels doit SYSTEMATIQUEMENT être nettoyée par la fonction &#039;&#039;&#039;price2num()&#039;&#039;&#039; avec le 2eme paramètre renseigné à: &#039;MU&#039;, &#039;MT&#039; ou &#039;MS&#039; selon le besoin (voir doc fonction).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print price2num(239.2 - 229.3 - 9.9, &#039;MT&#039;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
S&#039;il ne s&#039;agit pas d&#039;un prix sur lequel s&#039;adapte les paramètres MU, MT ou MS, il faut utiliser la fonction &#039;&#039;&#039;round()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==Création de tables==&lt;br /&gt;
Ne pas créer de table à l&#039;utilisation, c&#039;est-à-dire à la &#039;&#039;&#039;première utilisation&#039;&#039;&#039; du module.&lt;br /&gt;
Si vous créez un module qui utilise des tables qui ne sont pas intégrées en standard dans le code de Dolibarr, veillez à suivre le didacticiel [[Développement module]] qui explique comment joindre des tables qui se créent à l&#039;activation du module et non à son utilisation (voir plus haut).&lt;br /&gt;
&lt;br /&gt;
==Comparer la version==&lt;br /&gt;
&lt;br /&gt;
Si votre code a besoin de faire des choses différentes selon la version de Dolibarr, vous pouvez utiliser le truc suivant pour comparer les versions&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$version=preg_split(&#039;/[\.-]/&#039;,DOL_VERSION);&lt;br /&gt;
if (versioncompare($version,array(5,0,-4)) &amp;gt;= 0) { //mycode for 5.0 only; }	// For dolibarr 5.0.* (the -4 means we include also alpha, beta, rc and rcX)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais cette solution requiert de faire un include avoir la fonction versioncompare. Une alternative est d&#039;utiliser le test suivant:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
if ((float) DOL_VERSION &amp;gt;= 5.0) { //mycode for 5.0 only; }	// For dolibarr 5.0.*&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Logs==&lt;br /&gt;
Ajouter des traces dans votre code avec la fonction&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
dol_syslog($yourmessage, LOG_INFO|LOG_DEBUG|LOG_WARNING|LOG_ERR);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Répertoires de travail==&lt;br /&gt;
Si vous avez besoin de créer un répertoire de travail, dans votre code, faites référence à ce répertoire par&lt;br /&gt;
&#039;&#039;&#039;DOL_DATA_ROOT.&#039;/monmodule&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Le répertoire peut être créé dans votre code à l&#039;exécution par le code suivant:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$mymoduledir=DOL_DATA_ROOT.&#039;/monmodule&#039;;&lt;br /&gt;
dol_mkdir($mymoduledir);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si vous avez besoin d&#039;un répertoire qui contiendra des données temporaires, ce répertoire doit être&#039;&#039;&#039; DOL_DATA_ROOT.&#039;/monmodule/temp&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Design patterns et programmation objet=&lt;br /&gt;
&lt;br /&gt;
==Design patterns de Création (GoF)==&lt;br /&gt;
Design patterns définis par le Gang Of Four (voir la wikipédia sur les [[wikipedia:Patron de conception|Design patterns]]).&lt;br /&gt;
Dans Dolibarr, pas de mise en oeuvre de design patterns de comportement particulier.&lt;br /&gt;
On trouve des objets proches des Singletons et Fabriques conformes à 100% dans l&#039;esprit mais pas dans la syntaxe, ceci afin d’être compatible avec la plus large plage possible de versions de PHP.&lt;br /&gt;
&lt;br /&gt;
==Design patterns d&#039;entreprises (Martin Fowler)==&lt;br /&gt;
&lt;br /&gt;
===Mode d&#039;organisation du code===&lt;br /&gt;
[[wikipedia:Martin_Fowler|Martin Fowler]] a identifié 3 méthodes d&#039;organisation du code appelées &#039;&#039;&#039;patterns&#039;&#039;&#039; (&#039;&#039;&#039;motifs&#039;&#039;&#039;):&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Transaction Script&#039;&#039;&#039; (Le code est linéaire en fonction d&#039;une action utilisateur).&lt;br /&gt;
&lt;br /&gt;
C&#039;est le motif à l&#039;ancienne utilisé dans les langages procéduraux.&lt;br /&gt;
Inconvénient: Redondance du code. Nécessité de connaitre le modèle physique pour développer les parties métiers.&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Domain Model&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
C&#039;est un concept possible depuis les langages objets. Ce sont les procédures métiers (qui doivent être identifiés avant) qui servent de bases pour les classes objets.&lt;br /&gt;
Inconvénient: Motif complexe à maintenir.&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Table Module&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Un intermédiaire entre les 2 précédents où l&#039;on a une instance unique de classe par table de la base de données.&lt;br /&gt;
&lt;br /&gt;
-&amp;gt; Comme le montre les squelettes de code (voir point précédent), Dolibarr se base sur le principe du &#039;&#039;&#039;Table Module&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===Communication Logique métier - Données (ORM)===&lt;br /&gt;
Il existe 3 modes de liaisons:&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Table And Row Data Gateway&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
C&#039;est le plus simple. On crée une classe par table et chaque classe est un pont avec la table correspondante et propose les méthodes CRUD sur cette table (Create, Read, Update, Delete). Une instance de classe étant alors un enregistrement de la table. La classe ne contient que du code d&#039;accès aux lignes ou colonnes de tables. Le code métier doit alors être ajouté dans d&#039;autres classes. Les liens entre ces classes tables et les classes métiers devant être connues ou déduite de la connaissance du développeur.&lt;br /&gt;
&lt;br /&gt;
Exemple: C&#039;est le mode mis en oeuvre quand on utilise certains Frameworks d&#039;ORM comme &#039;&#039;&#039;iBatis&#039;&#039;&#039; (http://ibatis.apache.org/).&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Active Record&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Identique au précédent, mais on se permet d&#039;ajouter quelques fonctions métiers sur la classe, à conditions que ces fonctions soient bien  propres à la table ou à la notion métier porté par l&#039;enregistrement. C&#039;est le pattern qui offre le meilleur rapport fonctionnalité/complexité.&lt;br /&gt;
&lt;br /&gt;
Exemple: C&#039;est le mode choisi pour les développements Dolibarr et de nombreuses autres applications PHP qui ont leur propre framework et pratiques de développements.&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Data Mapper&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Les classes représentent les entités du problème et non les données. Il faut donc doubler, tripler... ces classes avec des classes Mapper pour accéder aux données.&lt;br /&gt;
Plus &amp;quot;puriste&amp;quot; sur le papier car plus proche du métier, ce mode a aussi l&#039;inconvénient d&#039;être très complexe et difficile à maintenir dans la réalité (l&#039;expérience pratique constaté ne rejoignant pas les promesses de la théorie).&lt;br /&gt;
&lt;br /&gt;
Exemple: C&#039;est le choix si on utilise le Framework d&#039;ORM &#039;&#039;&#039;Propel&#039;&#039;&#039; (http://propel.phpdb.org/trac/). On le trouve donc sur des applications plus lourdes basées sur cet ORM entre autres.&lt;br /&gt;
&lt;br /&gt;
-&amp;gt; Pour les développements Dolibarr, il est recommandé d&#039;utiliser le mode de liaison &#039;&#039;&#039;Active Record&#039;&#039;&#039; qui offre les avantages d&#039;un modèle proche du métier sans en avoir la complexité et sans trop masquer non plus la technique. C&#039;est dans ce mode que le développement, la compréhension du code et la maintenance technique et/ou fonctionnelle semble la plus productive (ceci est toutefois un éternel débat entre les puristes et les pragmatiques, débat dans lequel personne ne peut vraiment avoir raison, car tout dépend des objectifs à atteindre).&lt;br /&gt;
&lt;br /&gt;
==Design Pattern d&#039;Interface Graphique (MVC)==&lt;br /&gt;
Il existe plusieurs design pattern pour les interfaces utilisateurs (MVC, MVP, MVVM).&lt;br /&gt;
Beaucoup confonde ce design pattern avec celui consistant à utiliser un framework de templates. C&#039;est sans rapport. Un framework de template (voir point précédent) n&#039;est en lien qu&#039;avec la partie &amp;quot;V&amp;quot; de ces modèles.&lt;br /&gt;
&lt;br /&gt;
-&amp;gt; Dolibarr utilise le Design Pattern &#039;&#039;&#039;MVC&#039;&#039;&#039;. La partie M est matérialisée par une classe DAO contenant les méthode CRUD (Create-Read-Update-Delete) d&#039;accès à la table.&lt;br /&gt;
Beaucoup de frameworks ont fait le choix de mettre la partie de code C (Controller) et la partie de code du V (vue) dans des fichiers, voir même répertoires séparés. La maintenance semble plus aisé sur la papier, en pratique, il faut sans arrêt jonglé entre n fichiers, le C étant fortement lié au V. Aussi dans Dolibarr, la séparation est faite par une simple section de commentaire. La partie de code C (Controller) est donc le code qui se trouve sont la balise&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * Actions&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Elle est suivi par la partie de code V (Vue), bien séparé du C par la balise&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * View&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce mode de séparation a eu un effet neutre sur les nouveaux développement mais a permis de réduire de manière si importante le temps requis pour la maintenance et correction de bugs qu&#039;il n&#039;est pas envisagé de basculer vers un autre type de séparation (oui les constats fait dans la vraie vie ne sont pas toujours ceux attendus par la théorie scolaire). L&#039;important reste qu&#039;il y ait toujours séparation entre le C et le V, peut importe comment est matérialisé cette séparation, du moment qu&#039;elle l&#039;est (Rappel: Ne pas confondre la notion de séparation du C et du V avec la notion de séparation du code pour alimenter la données d&#039;une Vue et du code pour formater la Vue, ceci un principe de séparation relevant du Design Pattern de Vue, voir point suivant).&lt;br /&gt;
&lt;br /&gt;
==Design Pattern de Vue - Présentation==&lt;br /&gt;
Il existe des frameworks spécialisés dans le Design Pattern de Vue, la partie qui consiste à formater l&#039;écran vue par l&#039;utilisateur.&lt;br /&gt;
Les vieilles versions de Dolibarr utilisaient Smarty. Ce framework est une surcouche à un Framework, déjà très puissant, de formatage d&#039;écran nommé... PHP. Les bénéfices étant très inférieurs aux inconvénients, il a été abandonné au profit de templates PHP (fichier .tpl.php) qui restent le plus simple, le plus universel, le plus évolutif et le plus performant, des frameworks de présentation. &lt;br /&gt;
&lt;br /&gt;
Son seul défaut est qu&#039;il ne peut garantir à 100% les écarts d&#039;un développeur qui irait intégrer dans la Vue, une logique sans rapport avec la présentation (donc autre que du code à vocation de génération, de formatage, de sortie HTML, de logique de test ou de boucle). Ce point est toutefois contrôlé par le mécanisme de validation du code des chefs de projets.&lt;br /&gt;
&lt;br /&gt;
La encore, c&#039;est l&#039;expérience et le constat &amp;quot;sur le terrain&amp;quot; d&#039;un meilleur rendement de productivité qui a motivé l&#039;abandon des frameworks de Présentation externes au profit du framework PHP.&lt;/div&gt;</summary>
		<author><name>Quentic</name></author>
	</entry>
	<entry>
		<id>https://wiki.dolibarr.org/index.php?title=Langages_et_normes&amp;diff=52115</id>
		<title>Langages et normes</title>
		<link rel="alternate" type="text/html" href="https://wiki.dolibarr.org/index.php?title=Langages_et_normes&amp;diff=52115"/>
		<updated>2021-09-30T08:40:23Z</updated>

		<summary type="html">&lt;p&gt;Quentic: Correction d&amp;#039;erreur de frappe&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- BEGIN interlang links --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Do NOT edit this section&lt;br /&gt;
     Links below are automatically managed by PolyglotBot&lt;br /&gt;
     You can edit links on the English source page : Language_and_development_rules --&amp;gt;&lt;br /&gt;
[[en:Language_and_development_rules]]&lt;br /&gt;
[[de:Sprachen_und_Programmierregeln]]&lt;br /&gt;
[[es:Lenguaje_y_Normas_de_Desarrollo]]&lt;br /&gt;
[[zh:语言和开发规则]]&lt;br /&gt;
&amp;lt;!-- END interlang links --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{TemplateDocDev}}&lt;br /&gt;
&lt;br /&gt;
Voici les quelques règles sur le langage, la syntaxe et normes de développement en vigueur pour le projet Dolibarr :&lt;br /&gt;
&lt;br /&gt;
=Versions=&lt;br /&gt;
&lt;br /&gt;
*Dolibarr doit fonctionner sur:&lt;br /&gt;
&lt;br /&gt;
#Tous OS (Windows, Linux, MACOS...)&lt;br /&gt;
#PHP {{PHPMinVersion}} (Doit fonctionner sans aucun module PHP complémentaire hors les modules d&#039;accès base de donnée).&lt;br /&gt;
#Mysql {{MySqlMinVersion}}&lt;br /&gt;
&lt;br /&gt;
=Normes Copyright=&lt;br /&gt;
&lt;br /&gt;
*Tout fichier PHP doit avoir un en-tête selon le masque suivant&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
/* Copyright (C) YYYY John Doe  &amp;lt;email@email.com&amp;gt;&lt;br /&gt;
 *&lt;br /&gt;
 * Licence information&lt;br /&gt;
 */&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Quand vous éditez un fichier existant du projet, ajouter une ligne Copyright sous celles existantes.&lt;br /&gt;
&lt;br /&gt;
=Normes PHP=&lt;br /&gt;
&lt;br /&gt;
==PHP==&lt;br /&gt;
&lt;br /&gt;
*Dolibarr est écrit en PHP et supporte toutes versions PHP supérieures à la {{PHPMinVersion}}. Les fichiers doivent tous comporter l&#039;extension .php&lt;br /&gt;
&lt;br /&gt;
*L&#039;appel aux variables superglobales PHP doit passer par les opérateurs dédiés $_COOKIES, $_SERVER, $_ENV. Mais pour récupérer les contenus de $_GET ou $_POST, il faut passer par la fonction dolibarr [[Fonctions utiles Dolibarr|GETPOST()]] .&lt;br /&gt;
&lt;br /&gt;
Les autres opérateurs ($HTTP_SERVER_GET, ...) ayant été passés en deprecated au sein de PHP, ne doivent plus être utilisés. Ainsi le code doit fonctionner y compris quand l&#039;option &#039;&#039;&#039;register_long_arrays&#039;&#039;&#039; est à off.&lt;br /&gt;
De plus, le code doit fonctionner aussi bien quand l&#039;option PHP &#039;&#039;&#039;register_globals&#039;&#039;&#039; est à off (recommandé par PHP)  que quand l&#039;option &#039;&#039;&#039;register_globals&#039;&#039;&#039; est à on (par défaut sur de nombreuses installations).&lt;br /&gt;
&lt;br /&gt;
*Pas d&#039;utilisation de la variable &#039;&#039;&#039;PHP_SELF&#039;&#039;&#039;. Utiliser à la place $_SERVER[&amp;quot;PHP_SELF&amp;quot;]. Notez aussi que le framework Dolibarr passe une routine pour rendre plus sûr le contenu du $_SERVER[&amp;quot;PHP_SELF&amp;quot;] (dans le fichier main.inc.php, donc avant tout traitement métier)&lt;br /&gt;
&lt;br /&gt;
*Quand plusieurs variables doivent être initialisées avec la même valeur, il faut utiliser plusieurs instructions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$var1 = 1; $var2 = 1; $var3 = 1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
plutôt que&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$var1 = $var2 = $var3 = 1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
qui est moins performant.&lt;br /&gt;
&lt;br /&gt;
*Les chaines doivent avoir les variables sorties de la chaine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print &amp;quot;Mon texte affiche ma &amp;quot;.$variable.&amp;quot; !\n&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les commentaires doivent suivre la syntaxe C, ie un double antislash pour un commentaire d&#039;une ligne et utilisation slash-étoile pour ouvrir un bloc de plusieurs lignes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
/* Bloc de commentaire&lt;br /&gt;
 *&lt;br /&gt;
 * Fin du bloc&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
$monobjet = new MonObjet($db);&lt;br /&gt;
$result=$monobjet-&amp;gt;fetch($idobject);&lt;br /&gt;
&lt;br /&gt;
for ($i = 1 , $i &amp;lt; 2 ; $i++)&lt;br /&gt;
{&lt;br /&gt;
  // commentaire sur une ligne&lt;br /&gt;
  print $i;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les fonctions doivent retourner une valeur strictement &amp;gt; à 0 en cas de succès, et un nombre &amp;lt; à 0 en cas d&#039;erreur.&lt;br /&gt;
&lt;br /&gt;
*Pas de code mort (non utilisé) dans le code principal de Dolibarr (le code utilisé uniquement par un module externe doit être inclus dans le module externe).&lt;br /&gt;
&lt;br /&gt;
*Utiliser &amp;quot;include_once&amp;quot; pour l&#039;inclusion de tout fichier contenant des définitions de fonction ou de classes (donc fichiers *.class.php et *.lib.php), utiliser &amp;quot;include&amp;quot; pour tout inclusion de fichier de type template ou contenant un mixte de HTML et PHP (donc fichiers *.inc.php et *.tpl.php).&lt;br /&gt;
&lt;br /&gt;
*Le style de code a utiliser est le PSR-12 (https://www.php-fig.org/psr/psr-12/). Seules les règles &amp;quot;MUST&amp;quot; sont imposées. Notez aussi les points/exceptions suivants:&lt;br /&gt;
**La longueur des lignes: PSR-12 indique que la longueur des lignes a une limite &amp;quot;soft&amp;quot; à 120. Il est en effet préférable d&#039;avoir de longues lignes de données de déclaration plutôt que de longues pages car ce code ne contient aucune logique intéressante ou utile, toutefois une limite &amp;quot;hard&amp;quot; a été instauré à &#039;&#039;&#039;1000&#039;&#039;&#039; caractères. Du code qui ira au delà provoquera des erreurs dans la plateforme d&#039;Intégration Continue.&lt;br /&gt;
**Les tabulations sont acceptées : L&#039;autre exception est qu&#039;on ne remplace pas les tabulations systématiquement par des espaces. L&#039;utilisation des tabulations simplifie la vie de certains développeurs. De plus, l&#039;utilisation d&#039;espaces rend certaines fonctions d&#039;autoformatage défectueuses (comme sur certaines versions d&#039;Eclipse, lors de copier-coller).&lt;br /&gt;
**Note 1: Les règles suivantes sont particulièrement importantes :&lt;br /&gt;
***Les fichiers doivent être sauvés en format Unix (LF) et non Windows (CR/LF). Le format Unix étant compatible sur les OS Unix like, Windows, Mac, alors que le format fichier texte Windows pose problème sous certains PHP sous Unix.&lt;br /&gt;
***Les smart tags PHP ne sont pas utilisés. Les sections de code doivent commencer par &#039;&#039;&#039;&amp;lt;?php&#039;&#039;&#039;&lt;br /&gt;
**Note 2: Vous pouvez utiliser le fichier &#039;&#039;&#039;dev/setup/codesniffer/ruleset.xml&#039;&#039;&#039; comme fichier de contrôle pour vérifier votre style de code avec PHPCodeSniffer.&lt;br /&gt;
**Note 3: Vous pouvez utiliser le fichier &#039;&#039;&#039;dev/setup/eclipse/PSR-12 [built-in].xml&#039;&#039;&#039; comme fichier de règles de syntax pour configurer Eclipse.&lt;br /&gt;
**Note 4: Vous remarquerez que le code actuel ne suit pas forcément tout cela. La raison est historique. La règle fut instaurée en cours de route, aussi, si vous trouvez du code non respectueux de ce standard, n&#039;hésitez pas à le corriger.&lt;br /&gt;
&lt;br /&gt;
==Structures des classes et champs==&lt;br /&gt;
&lt;br /&gt;
Certaines propriétés de classes se retrouvent dans de nombreuses classes. Pour homogénéité, on utilisera les noms suivants:&lt;br /&gt;
{{TemplatePHPFields}}&lt;br /&gt;
&lt;br /&gt;
=Normes SQL=&lt;br /&gt;
&lt;br /&gt;
==Structure des tables et champs==&lt;br /&gt;
&lt;br /&gt;
*Toutes les tables sont préfixées pour éviter les conflits de nommage. Aujourd&#039;hui, le préfixe est modifiable au moment de l&#039;installation. Sa valeur par défaut est &amp;lt;tt&amp;gt;llx_&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*Structure des tables.&lt;br /&gt;
&lt;br /&gt;
Lorsque vous créez une table, il est recommandé de prendre les même conventions de nommages de tables que les autres tables Dolibarr. Avec, à minima les champs suivant:&lt;br /&gt;
 - rowid INTEGER AUTO_INCREMENT PRIMARY KEY    qui est l&#039;id technique&lt;br /&gt;
 - entity INTEGER default 1                    that is id for the multicompany feature&lt;br /&gt;
 - date_creation   datetime                    that is the creation date&lt;br /&gt;
 - tms             timestamp                   qui sera un champ contenant la date de chaque mise à jour (la base de donnée le gère tout seul, pas besoin de le gérer par le code)&lt;br /&gt;
 - import_key      varchar(32)                 qui contiendra le code d&#039;import YYYYMMDDHHMMSS si vous faites des imports en masse dans la table.&lt;br /&gt;
 - status          smallint                    pour stocker le status d&#039;un object&lt;br /&gt;
&lt;br /&gt;
Eventuellement&lt;br /&gt;
 - fk_user_creat  integer qui est l&#039;id du user de création (fk_user_author also found)&lt;br /&gt;
 - fk_user_modif  integer qui est l&#039;id du user de modification&lt;br /&gt;
 - fk_user_valid  integer qui est l&#039;id du user de validation&lt;br /&gt;
 - fk_soc integer qui est l&#039;id du tiers (si applicable)&lt;br /&gt;
&lt;br /&gt;
*Type des champs&lt;br /&gt;
&lt;br /&gt;
Dans la pratique, afin d&#039;être compatible avec toutes les précisions des pays, syntaxes des bases, on utilisera uniquement les types suivants:&lt;br /&gt;
 - integer pour tout nombre entier, id ou clé étrangère (bigint éventuellement accepté pour les id des très grosses tables)&lt;br /&gt;
 - smallint pour tout numérique entier de petite taille (comme pour stocker un code de status)&lt;br /&gt;
 - double(24,8) pour tout montant&lt;br /&gt;
 - double(6,3) pour les taux de tva&lt;br /&gt;
 - real pour une quantité&lt;br /&gt;
 - varchar pour une chaîne (y compris de longueur 1, le type char est de plus en plus déprécié)&lt;br /&gt;
 - timestamp pour un champ date+heure devant être mis a jour automatiquement&lt;br /&gt;
 - datetime pour un champ date+heure&lt;br /&gt;
 - date pour un champ date&lt;br /&gt;
&lt;br /&gt;
==Clé primaire==&lt;br /&gt;
La clé primaire d&#039;une table s&#039;appelle &amp;lt;tt&amp;gt;rowid&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Il y a quelques tables qui échappent à cette règle actuellement (ex [[Table llx_c_actioncomm]]), pour des raisons historiques. Une évolution pourra être étudiée pour une prochaine version.&lt;br /&gt;
&lt;br /&gt;
==Clés étrangères==&lt;br /&gt;
Le nom d&#039;une clé étrangère commence par le préfixe &amp;lt;tt&amp;gt;fk_&amp;lt;/tt&amp;gt; suivi du nom de la table liée (requis pour éviter doublons globales à la base, problématiques sous certains SGBD comme postgresql) puis du champ lié (pour permettre plusieurs clés étrangères différentes sur une même table).&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
fk_facture_fourn_fk_soc&lt;br /&gt;
&lt;br /&gt;
Note: Si vous développez votre propre module externe, il ne doit pas y avoir de clé étrangère depuis vos tables qui pointent sur les tables standards de Dolibarr. Ceci casserait les fonctionnalités de mise à jour, de réparation, de sauvegardes et de restauration.&lt;br /&gt;
&lt;br /&gt;
==Clés alternatives==&lt;br /&gt;
Parfois, il n&#039;y a pas que la clé primaire qui doit être unique. On peut donc ajouter aussi un index clé alternative unique. Un tel index est nommé par un nom qui commence par le préfixe &amp;lt;tt&amp;gt;uk_&amp;lt;/tt&amp;gt; suivi du nom de la table (requis pour éviter doublons d&#039;index globals à la base, problématiques sous certains SGBD comme postgresql) puis d&#039;un suffixe qui caractérise la clé (pour permettre plusieurs index uniques sur une même table).&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
uk_societe_code_client&lt;br /&gt;
&lt;br /&gt;
==Index performance==&lt;br /&gt;
Certains champs sont souvent utilisés comme critère de recherche, de tri ou de jointure. Il convient dans ce cas, d&#039;y mettre un index de performance. De tels indexes seront nommés avec un préfix &amp;lt;tt&amp;gt;idx_&amp;lt;/tt&amp;gt; puis le nom de la table et le nom du champ sur lequel porte l&#039;index.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
idx_societe_user_creat&lt;br /&gt;
&lt;br /&gt;
==Format de fichier DDL==&lt;br /&gt;
Les fichiers qui contiennent la définition de la structure de la base (DDL) doivent être au nombre de 2 par tables:&lt;br /&gt;
Chaque table est définie dans son propre fichier dont le nom est &amp;lt;tt&amp;gt;llx_&#039;&#039;matable&#039;&#039;.sql&amp;lt;/tt&amp;gt;. &lt;br /&gt;
On mettra un commentaire à côté de chaque champ pour en expliquer la signification.&lt;br /&gt;
Les clés étrangères et index de performance ou autres contraintes d&#039;unicité sont définies dans un fichier séparé dont le nom est &amp;lt;tt&amp;gt;llx_&#039;&#039;matable&#039;&#039;.key.sql&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ces fichiers sont placés dans le répertoire &#039;&#039;&#039;install/mysql/tables&#039;&#039;&#039; pour les fichiers standards ou &#039;&#039;&#039;monmodule/tables&#039;&#039;&#039; pour les tables amenées par un module.&lt;br /&gt;
&lt;br /&gt;
Exemple &#039;&#039;&#039;fichier table llx_matable.sql&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
-- Copyright (C) 2008 Author &amp;lt;email@author.com&amp;gt;&lt;br /&gt;
-- &lt;br /&gt;
-- This program is free software; you can redistribute it and/or modify&lt;br /&gt;
-- it under the terms of the GNU General Public License as published by&lt;br /&gt;
-- the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
-- (at your option) any later version.&lt;br /&gt;
--&lt;br /&gt;
-- This program is distributed in the hope that it will be useful,&lt;br /&gt;
-- but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
-- GNU General Public License for more details.&lt;br /&gt;
--&lt;br /&gt;
-- You should have received a copy of the GNU General Public License&lt;br /&gt;
-- along with this program. If not, see &amp;lt;http://www.gnu.org/licenses/&amp;gt;.&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
&lt;br /&gt;
create table llx_matable&lt;br /&gt;
(&lt;br /&gt;
  rowid       integer AUTO_INCREMENT PRIMARY KEY,&lt;br /&gt;
  field_one   integer,&lt;br /&gt;
  field_two   integer NOT NULL,&lt;br /&gt;
  fk_field    integer,&lt;br /&gt;
  field_date  datetime,&lt;br /&gt;
  tms         timestamp&lt;br /&gt;
)ENGINE=innodb;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Exemple &#039;&#039;&#039;fichier clés/index llx_matable.key.sql&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
-- Copyright (C) 2008 Author &amp;lt;email@author.com&amp;gt;&lt;br /&gt;
-- &lt;br /&gt;
-- This program is free software; you can redistribute it and/or modify&lt;br /&gt;
-- it under the terms of the GNU General Public License as published by&lt;br /&gt;
-- the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
-- (at your option) any later version.&lt;br /&gt;
--&lt;br /&gt;
-- This program is distributed in the hope that it will be useful,&lt;br /&gt;
-- but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
-- GNU General Public License for more details.&lt;br /&gt;
--&lt;br /&gt;
-- You should have received a copy of the GNU General Public License&lt;br /&gt;
-- along with this program. If not, see &amp;lt;http://www.gnu.org/licenses/&amp;gt;.&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE llx_matable ADD UNIQUE uk_matable_field(field_one, field_two);&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE llx_matable ADD CONSTRAINT fk_matable_fk_field FOREIGN KEY (fk_field) REFERENCES llx_matablepere (rowid);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Règles de codage SQL==&lt;br /&gt;
&lt;br /&gt;
*Utilisation des alias/nommage de champs&lt;br /&gt;
&lt;br /&gt;
Dans le cas des select on pourra utiliser les alias pour simplifier l&#039;écriture des requêtes:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
select chp1, chpxxx2 as chp2 from table2 as t1, table2 as t2 where t1.chpx = t2.chpy&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Toutefois, il ne faut pas utiliser ces alias sur des requêtes update car non compatible avec mysql 3.1.&lt;br /&gt;
&lt;br /&gt;
*Les SELECT * sont interdits ! Chaque SELECT doit spécifier la liste complète des champs à récupérer. Cela permet d&#039;éviter les confusions. Exemple:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
SELECT field_a, field_b, field_c FROM table_1 WHERE field_d = &#039;$id&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Dans les requêtes SQL, on quote les champs mais pas les numériques qui contiennent des montants destinés à être stockés dans des champs de type double ou real. Les quotes sur les numériques de type float provoquent parfois un stockage d&#039;une valeur différente. Par exemple 412.62 dans le insert sera en fait stocké avec la valeur 412.61999512 en base (suite à des conversions chaines-numériques implicites) si le champ est de type double(24,8). Et seul le PHP voit 412.61999512. Les autres outils verront 412.62 donnant l&#039;impression qu&#039;il n&#039;y a pas de problème. Et c&#039;est le PHP qui a raison, il y a problème en base. En supprimant les quotes sur les numériques, cela va mieux.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
Bon:     INSERT INTO table_1 (field_txt, field_num) VALUES (&#039;txt&#039;, 412.62)&lt;br /&gt;
Mauvais: INSERT INTO table_1 (field_txt, field_num) VALUES (&#039;txt&#039;, &#039;412.62&#039;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remarque, le problème des float est général et pas seulement sur les accès base, il est présent dans tous les languages quand on travaille sur des nombres réels, aussi ils doivent être, dès que affectés, nettoyés par la fonction price2num avec le 2eme paramètre renseigné à:&lt;br /&gt;
&#039;MU&#039; (si il s&#039;agit d&#039;un prix unitaire), &#039;MT&#039; (s&#039;il s&#039;agit d&#039;un prix total) ou &#039;MS&#039; (autres cas) selon le besoin.&lt;br /&gt;
Voir aussi le chapitre &amp;quot;Les nombres réels, montants et calculs&amp;quot; plus bas.&lt;br /&gt;
&lt;br /&gt;
*Les fonctions NOW, SYSDATE ou DATEDIFF sont interdites au sein des ordres SQL. S&#039;il faut saisir la date du moment dans un champ, la valeur doit venir du PHP, par exemple par la fonction dol_now(), et non du moteur de base de données. Ceci afin d&#039;avoir une meilleure portabilité du code mais surtout d&#039;avoir une gestion correcte des TimeZone et ne pas dépendre du TimeZone de la base de donnée.&lt;br /&gt;
&lt;br /&gt;
Par exemple, on ne fera pas:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where datefield = NOW()&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
mais:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where datefield = &#039;&amp;quot;.$this-&amp;gt;db-&amp;gt;idate(dol_now()).&amp;quot;&#039;&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Par exemple, on ne fera pas:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where DATEDIFF(table.datefield, NOW()) &amp;gt; 7&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
mais:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where datefield &amp;lt; &#039;&amp;quot;.$this-&amp;gt;db-&amp;gt;idate(dol_now() - (7 * 24 * 3600)).&amp;quot;&#039;&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un autre avantage de cette règle est que la requête peut bénéficier de l&#039;utilisation de l&#039;index puisqu&#039;on compare datefield à une valeur fixe. Dans le cas du datediff, on applique un traitement sur le champ avant comparaison, rendant impossible l&#039;utilisation de l&#039;index de ce champ. Les conséquences sont des performances très dégradées par rapport à la version sans datediff.&lt;br /&gt;
&lt;br /&gt;
==Règles de migration de base==&lt;br /&gt;
&lt;br /&gt;
*Les scripts de migration de structure sont les fichiers de type &#039;&#039;&#039;install/mysql/migration/a.b.c-x.y.z.sql&#039;&#039;&#039;. Dans un fichier de migration de n vers n+1, on ne détruit une table (DROP TABLE) qui n&#039;est plus utilisée en n+1 que lors de la migration de la version n+1 vers n+2. Ceci afin de toujours conserver les tables deprecated le temps d&#039;une version pour réparer une situation en cas d&#039;erreur de migration.&lt;br /&gt;
&lt;br /&gt;
==Spécificités MySQL==&lt;br /&gt;
&lt;br /&gt;
*Les tables doivent être au format InnoDB.&lt;br /&gt;
&lt;br /&gt;
En effet, ce format gère les clés étrangères, les éventuelles restrictions qui y sont attachées et la notion d&#039;intégrité de transactions requise pour avoir des données en base cohérente entre tables.&lt;br /&gt;
&lt;br /&gt;
*Dolibarr DOIT fonctionner même avec les options &#039;&#039;&#039;strict&#039;&#039;&#039; de Mysql active.&lt;br /&gt;
&lt;br /&gt;
Pour l&#039;activer (fortement recommandé en développement), ajouter la ligne suivante dans le fichier config du serveur Mysql (my.cnf ou my.ini)&lt;br /&gt;
{{MySqlStrictMode}}&lt;br /&gt;
&lt;br /&gt;
==Spécificités PostgreSQL==&lt;br /&gt;
Seuls les fichiers pour Mysql doivent être maintenus.&lt;br /&gt;
Les fichiers pour les autres bases sont convertis &amp;quot;à la volée&amp;quot; par le driver Dolibarr de la base.&lt;br /&gt;
&lt;br /&gt;
Il existe une exception.&lt;br /&gt;
Les requêtes &amp;quot;UPDATE FROM&amp;quot; : &lt;br /&gt;
Syntax MySQL :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
UPDATE table_taget as target, table_source as source SET fieldtarget=source.fieldsource&lt;br /&gt;
WHERE source.rowid=target.rowid;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Syntax PgSQL:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
UPDATE table_taget as target SET fieldtarget=source.fieldsource&lt;br /&gt;
FROM table_source as source WHERE source.rowid=target.rowid;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il n&#039;en existe pas dans Dolibarr, mais pour vos modules Vous devriez faire tel que :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
if ($this-&amp;gt;db-&amp;gt;type==&#039;pgsql&#039;) {&lt;br /&gt;
$sql=&amp;quot;UPDATE table_taget as target SET fieldtarget=source.fieldsource&lt;br /&gt;
FROM table_source as source WHERE source.rowid=target.rowid&amp;quot;;&lt;br /&gt;
} else {&lt;br /&gt;
$sql= &amp;quot;UPDATE table_taget as target, table_source as source SET fieldtarget=source.fieldsource&lt;br /&gt;
WHERE source.rowid=target.rowid&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Normes HTML=&lt;br /&gt;
&lt;br /&gt;
*Tous les attributs dans les balises HTML doivent être *en minuscule* et quotés avec des *doubles quote*.&lt;br /&gt;
&lt;br /&gt;
*Les liens href doivent être absolus en se basant sur la fonction dol_buildpath() pour obtenir un chemin absolu depuis un chemin relatif au répertoire htdocs. Pour les tags img, il faut faire appel à la fonction img_picto().&lt;br /&gt;
&lt;br /&gt;
Par example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print &#039;&amp;lt;a href=&amp;quot;&#039;.dol_buildpath(&#039;/monrep/mapage.php&#039;).&#039;&amp;quot;&amp;gt;&#039;.img_picto(&#039;Texte alt&#039;,&#039;nompictopng&#039;,&#039;&#039;).&#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les tables HTML doivent avoir des colonnes sans valeurs forcées, excepté pour les colonnes qui contiennent une information dont la longueur est non variable. Par exemple, une colonne avec un picto peut être forcée à with=&amp;quot;20px&amp;quot;. Dans les autres cas, il faut éviter de forcer la largeur des colonnes. La raison est que, dans la plupart des cas, le navigateur fait un meilleur travail pour définir automatiquement la bonne largeur des colonnes qu&#039;en forçant manuellement les largeurs. Et ceci marche quelle que soit la résolution de l&#039;écran.&lt;br /&gt;
&lt;br /&gt;
*Le javascript/ajax et l&#039;appel aux scripts java dans les pages php est à proscrire. Si toutefois du code javascript est inclus, il doit être conditionné par le test sur &amp;quot;$conf-&amp;gt;use_javascript_ajax&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
if ($conf-&amp;gt;use_javascript_ajax) {&lt;br /&gt;
...  // Le code php qui génère du javascript est ici&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les popups windows ne doivent pas être utilisées, sauf pour des tooltips (et restent conditionnées par le point ci-dessus).&lt;br /&gt;
&lt;br /&gt;
*Les scripts externes sont écrits en Perl s&#039;ils ne peuvent l&#039;être en php, l&#039;utilisation d&#039;un autre langage n&#039;est pas interdit mais doit être discuté au préalable dans la mailing list des développeurs.&lt;br /&gt;
&lt;br /&gt;
=Normes Dolibarr et squelettes de code=&lt;br /&gt;
&lt;br /&gt;
==Squelettes de code==&lt;br /&gt;
Afin d&#039;uniformiser le code et d&#039;accélérer le développement de nouveaux composants dans Dolibarr, se trouvent dans le répertoire &#039;&#039;&#039;htdocs/modulebuilder/templates&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Par exemple:&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de descripteur de module: &#039;&#039;&#039;myModule.class.php&#039;&#039;&#039;&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de code pour faire une nouvelle classe: &#039;&#039;&#039;skeleton_class.class.php&#039;&#039;&#039;&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de code pour faire une nouvelle page: &#039;&#039;&#039;skeleton_page.php&#039;&#039;&#039;&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de code pour faire un script à exécuter en ligne de commande: &#039;&#039;&#039;skeleton_script.php&#039;&#039;&#039;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
Servez-vous en comme exemple.&lt;br /&gt;
Notons que ces squelettes sont aussi utilisés par le générateur de code PHP ([[Module ModuleBuilder]]) qui est décrit dans la chapitre de développement de module Dolibarr pour accélérer vos développements.&lt;br /&gt;
&lt;br /&gt;
==Les dates et TimeZone==&lt;br /&gt;
Dolibarr se veut une application multi-utilisateur et multi-localisation. Il convient donc de stocker les dates dans le bon format. Pour éviter les problèmes de conversion, les règles suivantes doivent être appliquées:&lt;br /&gt;
&lt;br /&gt;
*Une date en mémoire doit être au format Timestamp GMT.&lt;br /&gt;
*Une date stockée en base de données contient le Timestamp issue de la date soumise dans la requête en heure &amp;lt;b&amp;gt;locale du serveur PHP&amp;lt;/b&amp;gt;. Cela ne concerne pas les dates mises à jour automatiquement par la base (champ &#039;&#039;&#039;tms&#039;&#039;&#039; en base).&lt;br /&gt;
&lt;br /&gt;
Ainsi le 1er janvier 1970, 3 heures à Paris (TZ=+1) = 1er janvier 1970, 2 heures à Greenwich (TZ=0) sera stocké en mémoire par 7200 et sera soumis à la base de données avec la chaine &#039;19700101030000&#039; (PHP convertit en heure de son TZ et la base déconvertit avec son TZ qui est le même que celui de PHP).&lt;br /&gt;
&lt;br /&gt;
Les méthodes select doivent donc traduire les champs dates lus qui sont au format chaine TZ de la base (&#039;19700101030000&#039;) par appel de la méthode db-&amp;gt;jdate afin de récupérer une information en mémoire au format Timestamp GMT. Et les méthodes insert doivent lors de la génération de la requête convertir la date mémoire connue en variable, par la méthode db-&amp;gt;idate (Voir exemples générés par le squelette).&lt;br /&gt;
&lt;br /&gt;
*Les dates mises à jour automatiquement par la base (champ &#039;&#039;&#039;tms&#039;&#039;&#039; en base) contiennent le Timestamp où la modification est faite selon le timezone de la base de donnée. Les méthodes select récupèrent cette donnée en mémoire au format Timestamp GMT en appliquant également le db-&amp;gt;jdate. Si le timezone de la base de donnée diffère de celui du PHP (un des 2 est mal réglé), il peut donc y avoir des écarts entre date de création et modification.&lt;br /&gt;
&lt;br /&gt;
*La manipulation de dates en PHP doit être faite en utilisant les fonctions dates de Dolibarr: &#039;&#039;&#039;dol_now(), dol_mktime(), dol_stringtotime(), dol_getdate(), dol_time_plus_duree()&#039;&#039;&#039;. Vous trouverez également d&#039;autres fonctions prêtes à l&#039;emploi dans le fichier &#039;&#039;&#039;date.lib.php&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==L&#039;encodage UTF8/ISO==&lt;br /&gt;
Dolibarr stocke les informations de manière suivante:&lt;br /&gt;
&lt;br /&gt;
*En base de donnée, les données sont en UTF8 ou ISO. Cela dépend du pagecode de la base, donc des options à la création de cette base. Dans tous les cas le driver d&#039;accès base Dolibarr (dans /lib/database) s&#039;arrange à la lecture et insertion pour convertir vers et depuis de l&#039;UTF8.&lt;br /&gt;
*Les données en mémoires sont donc stockées en UTF8 (instances d&#039;objets PHP).&lt;br /&gt;
*Les pages web affichées à l&#039;écran sont au format UTF8&lt;br /&gt;
&lt;br /&gt;
==Les nombres réels, montants et calculs==&lt;br /&gt;
En PHP comme dans d&#039;autres langages (Java par exemple), les données non entières (float, real, double) ne sont pas fiables.&lt;br /&gt;
Essayer de faire par exemple &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print 239.2 - 229.3 - 9.9;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Vous n&#039;obtiendrez pas zéro mais un nombre très petit en puissance de 10 négative. Si vous obtenez zéro, vous pourrez trouvez d&#039;autres exemples qui ne fonctionnent pas.&lt;br /&gt;
Le problème des float est général, une variable résultante de calcul de nombre réels doit SYSTEMATIQUEMENT être nettoyée par la fonction &#039;&#039;&#039;price2num()&#039;&#039;&#039; avec le 2eme paramètre renseigné à: &#039;MU&#039;, &#039;MT&#039; ou &#039;MS&#039; selon le besoin (voir doc fonction).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print price2num(239.2 - 229.3 - 9.9, &#039;MT&#039;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
S&#039;il ne s&#039;agit pas d&#039;un prix sur lequel s&#039;adapte les paramètres MU, MT ou MS, il faut utiliser la fonction &#039;&#039;&#039;round()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==Création de tables==&lt;br /&gt;
Ne pas créer de table à l&#039;utilisation, c&#039;est-à-dire à la &#039;&#039;&#039;première utilisation&#039;&#039;&#039; du module.&lt;br /&gt;
Si vous créez un module qui utilise des tables qui ne sont pas intégrées en standard dans le code de Dolibarr, veillez à suivre le didacticiel [[Développement module]] qui explique comment joindre des tables qui se créent à l&#039;activation du module et non à son utilisation (voir plus haut).&lt;br /&gt;
&lt;br /&gt;
==Comparer la version==&lt;br /&gt;
&lt;br /&gt;
Si votre code a besoin de faire des choses différentes selon la version de Dolibarr, vous pouvez utiliser le truc suivant pour comparer les versions&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$version=preg_split(&#039;/[\.-]/&#039;,DOL_VERSION);&lt;br /&gt;
if (versioncompare($version,array(5,0,-4)) &amp;gt;= 0) { //mycode for 5.0 only; }	// For dolibarr 5.0.* (the -4 means we include also alpha, beta, rc and rcX)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais cette solution requiert de faire un include avoir la fonction versioncompare. Une alternative est d&#039;utiliser le test suivant:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
if ((float) DOL_VERSION &amp;gt;= 5.0) { //mycode for 5.0 only; }	// For dolibarr 5.0.*&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Logs==&lt;br /&gt;
Ajouter des traces dans votre code avec la fonction&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
dol_syslog($yourmessage, LOG_INFO|LOG_DEBUG|LOG_WARNING|LOG_ERR);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Répertoires de travail==&lt;br /&gt;
Si vous avez besoin de créer un répertoire de travail, dans votre code, faites référence à ce répertoire par&lt;br /&gt;
&#039;&#039;&#039;DOL_DATA_ROOT.&#039;/monmodule&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Le répertoire peut être créé dans votre code à l&#039;exécution par le code suivant:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$mymoduledir=DOL_DATA_ROOT.&#039;/monmodule&#039;;&lt;br /&gt;
dol_mkdir($mymoduledir);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si vous avez besoin d&#039;un répertoire qui contiendra des données temporaires, ce répertoire doit être&#039;&#039;&#039; DOL_DATA_ROOT.&#039;/monmodule/temp&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Design patterns et programmation objet=&lt;br /&gt;
&lt;br /&gt;
==Design patterns de Création (GoF)==&lt;br /&gt;
Design patterns définis par le Gang Of Four (voir la wikipédia sur les [[wikipedia:Patron de conception|Design patterns]]).&lt;br /&gt;
Dans Dolibarr, pas de mise en oeuvre de design patterns de comportement particulier.&lt;br /&gt;
On trouve des objets proches des Singletons et Fabriques conforme à 100% dans l&#039;esprit mais pas dans la syntaxe, ceci afin d’être compatible avec la plus large plage possible de versions de PHP.&lt;br /&gt;
&lt;br /&gt;
==Design patterns d&#039;entreprises (Martin Fowler)==&lt;br /&gt;
&lt;br /&gt;
===Mode d&#039;organisation du code===&lt;br /&gt;
[[wikipedia:Martin_Fowler|Martin Fowler]] a identifié 3 méthodes d&#039;organisation du code appelées &#039;&#039;&#039;patterns&#039;&#039;&#039; (&#039;&#039;&#039;motifs&#039;&#039;&#039;):&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Transaction Script&#039;&#039;&#039; (Le code est linéaire en fonction d&#039;une action utilisateur).&lt;br /&gt;
&lt;br /&gt;
C&#039;est le motif à l&#039;ancienne utilisé dans les langages procéduraux.&lt;br /&gt;
Inconvénient: Redondance du code. Nécessité de connaitre le modèle physique pour développer les parties métiers.&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Domain Model&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
C&#039;est un concept possible depuis les langages objets. Ce sont les procédures métiers (qui doivent être identifiés avant) qui servent de bases pour les classes objets.&lt;br /&gt;
Inconvénient: Motif complexe à maintenir.&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Table Module&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Un intermédiaire entre les 2 précédents où l&#039;on a une instance unique de classe par table de la base de données.&lt;br /&gt;
&lt;br /&gt;
-&amp;gt; Comme le montre les squelettes de code (voir point précédent), Dolibarr se base sur le principe du &#039;&#039;&#039;Table Module&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===Communication Logique métier - Données (ORM)===&lt;br /&gt;
Il existe 3 modes de liaisons:&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Table And Row Data Gateway&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
C&#039;est le plus simple. On crée une classe par table et chaque classe est un pont avec la table correspondante et propose les méthodes CRUD sur cette table (Create, Read, Update, Delete). Une instance de classe étant alors un enregistrement de la table. La classe ne contient que du code d&#039;accès aux lignes ou colonnes de tables. Le code métier doit alors être ajouté dans d&#039;autres classes. Les liens entre ces classes tables et les classes métiers devant être connues ou déduite de la connaissance du développeur.&lt;br /&gt;
&lt;br /&gt;
Exemple: C&#039;est le mode mis en oeuvre quand on utilise certains Frameworks d&#039;ORM comme &#039;&#039;&#039;iBatis&#039;&#039;&#039; (http://ibatis.apache.org/).&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Active Record&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Identique au précédent, mais on se permet d&#039;ajouter quelques fonctions métiers sur la classe, à conditions que ces fonctions soient bien  propres à la table ou à la notion métier porté par l&#039;enregistrement. C&#039;est le pattern qui offre le meilleur rapport fonctionnalité/complexité.&lt;br /&gt;
&lt;br /&gt;
Exemple: C&#039;est le mode choisi pour les développements Dolibarr et de nombreuses autres applications PHP qui ont leur propre framework et pratiques de développements.&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Data Mapper&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Les classes représentent les entités du problème et non les données. Il faut donc doubler, tripler... ces classes avec des classes Mapper pour accéder aux données.&lt;br /&gt;
Plus &amp;quot;puriste&amp;quot; sur le papier car plus proche du métier, ce mode a aussi l&#039;inconvénient d&#039;être très complexe et difficile à maintenir dans la réalité (l&#039;expérience pratique constaté ne rejoignant pas les promesses de la théorie).&lt;br /&gt;
&lt;br /&gt;
Exemple: C&#039;est le choix si on utilise le Framework d&#039;ORM &#039;&#039;&#039;Propel&#039;&#039;&#039; (http://propel.phpdb.org/trac/). On le trouve donc sur des applications plus lourdes basées sur cet ORM entre autres.&lt;br /&gt;
&lt;br /&gt;
-&amp;gt; Pour les développements Dolibarr, il est recommandé d&#039;utiliser le mode de liaison &#039;&#039;&#039;Active Record&#039;&#039;&#039; qui offre les avantages d&#039;un modèle proche du métier sans en avoir la complexité et sans trop masquer non plus la technique. C&#039;est dans ce mode que le développement, la compréhension du code et la maintenance technique et/ou fonctionnelle semble la plus productive (ceci est toutefois un éternel débat entre les puristes et les pragmatiques, débat dans lequel personne ne peut vraiment avoir raison, car tout dépend des objectifs à atteindre).&lt;br /&gt;
&lt;br /&gt;
==Design Pattern d&#039;Interface Graphique (MVC)==&lt;br /&gt;
Il existe plusieurs design pattern pour les interfaces utilisateurs (MVC, MVP, MVVM).&lt;br /&gt;
Beaucoup confonde ce design pattern avec celui consistant à utiliser un framework de templates. C&#039;est sans rapport. Un framework de template (voir point précédent) n&#039;est en lien qu&#039;avec la partie &amp;quot;V&amp;quot; de ces modèles.&lt;br /&gt;
&lt;br /&gt;
-&amp;gt; Dolibarr utilise le Design Pattern &#039;&#039;&#039;MVC&#039;&#039;&#039;. La partie M est matérialisée par une classe DAO contenant les méthode CRUD (Create-Read-Update-Delete) d&#039;accès à la table.&lt;br /&gt;
Beaucoup de frameworks ont fait le choix de mettre la partie de code C (Controller) et la partie de code du V (vue) dans des fichiers, voir même répertoires séparés. La maintenance semble plus aisé sur la papier, en pratique, il faut sans arrêt jonglé entre n fichiers, le C étant fortement lié au V. Aussi dans Dolibarr, la séparation est faite par une simple section de commentaire. La partie de code C (Controller) est donc le code qui se trouve sont la balise&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * Actions&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Elle est suivi par la partie de code V (Vue), bien séparé du C par la balise&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * View&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce mode de séparation a eu un effet neutre sur les nouveaux développement mais a permis de réduire de manière si importante le temps requis pour la maintenance et correction de bugs qu&#039;il n&#039;est pas envisagé de basculer vers un autre type de séparation (oui les constats fait dans la vraie vie ne sont pas toujours ceux attendus par la théorie scolaire). L&#039;important reste qu&#039;il y ait toujours séparation entre le C et le V, peut importe comment est matérialisé cette séparation, du moment qu&#039;elle l&#039;est (Rappel: Ne pas confondre la notion de séparation du C et du V avec la notion de séparation du code pour alimenter la données d&#039;une Vue et du code pour formater la Vue, ceci un principe de séparation relevant du Design Pattern de Vue, voir point suivant).&lt;br /&gt;
&lt;br /&gt;
==Design Pattern de Vue - Présentation==&lt;br /&gt;
Il existe des frameworks spécialisés dans le Design Pattern de Vue, la partie qui consiste à formater l&#039;écran vue par l&#039;utilisateur.&lt;br /&gt;
Les vieilles versions de Dolibarr utilisaient Smarty. Ce framework est une surcouche à un Framework, déjà très puissant, de formatage d&#039;écran nommé... PHP. Les bénéfices étant très inférieurs aux inconvénients, il a été abandonné au profit de templates PHP (fichier .tpl.php) qui restent le plus simple, le plus universel, le plus évolutif et le plus performant, des frameworks de présentation. &lt;br /&gt;
&lt;br /&gt;
Son seul défaut est qu&#039;il ne peut garantir à 100% les écarts d&#039;un développeur qui irait intégrer dans la Vue, une logique sans rapport avec la présentation (donc autre que du code à vocation de génération, de formatage, de sortie HTML, de logique de test ou de boucle). Ce point est toutefois contrôlé par le mécanisme de validation du code des chefs de projets.&lt;br /&gt;
&lt;br /&gt;
La encore, c&#039;est l&#039;expérience et le constat &amp;quot;sur le terrain&amp;quot; d&#039;un meilleur rendement de productivité qui a motivé l&#039;abandon des frameworks de Présentation externes au profit du framework PHP.&lt;/div&gt;</summary>
		<author><name>Quentic</name></author>
	</entry>
	<entry>
		<id>https://wiki.dolibarr.org/index.php?title=Langages_et_normes&amp;diff=52114</id>
		<title>Langages et normes</title>
		<link rel="alternate" type="text/html" href="https://wiki.dolibarr.org/index.php?title=Langages_et_normes&amp;diff=52114"/>
		<updated>2021-09-30T08:36:05Z</updated>

		<summary type="html">&lt;p&gt;Quentic: /* Normes HTML */Orthographe&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- BEGIN interlang links --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Do NOT edit this section&lt;br /&gt;
     Links below are automatically managed by PolyglotBot&lt;br /&gt;
     You can edit links on the English source page : Language_and_development_rules --&amp;gt;&lt;br /&gt;
[[en:Language_and_development_rules]]&lt;br /&gt;
[[de:Sprachen_und_Programmierregeln]]&lt;br /&gt;
[[es:Lenguaje_y_Normas_de_Desarrollo]]&lt;br /&gt;
[[zh:语言和开发规则]]&lt;br /&gt;
&amp;lt;!-- END interlang links --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{TemplateDocDev}}&lt;br /&gt;
&lt;br /&gt;
Voici les quelques règles sur le langage, la syntaxe et normes de développement en vigueur pour le projet Dolibarr :&lt;br /&gt;
&lt;br /&gt;
=Versions=&lt;br /&gt;
&lt;br /&gt;
*Dolibarr doit fonctionner sur:&lt;br /&gt;
&lt;br /&gt;
#Tous OS (Windows, Linux, MACOS...)&lt;br /&gt;
#PHP {{PHPMinVersion}} (Doit fonctionner sans aucun module PHP complémentaire hors les modules d&#039;accès base de donnée).&lt;br /&gt;
#Mysql {{MySqlMinVersion}}&lt;br /&gt;
&lt;br /&gt;
=Normes Copyright=&lt;br /&gt;
&lt;br /&gt;
*Tout fichier PHP doit avoir un en-tête selon le masque suivant&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
/* Copyright (C) YYYY John Doe  &amp;lt;email@email.com&amp;gt;&lt;br /&gt;
 *&lt;br /&gt;
 * Licence information&lt;br /&gt;
 */&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Quand vous éditez un fichier existant du projet, ajouter une ligne Copyright sous celles existantes.&lt;br /&gt;
&lt;br /&gt;
=Normes PHP=&lt;br /&gt;
&lt;br /&gt;
==PHP==&lt;br /&gt;
&lt;br /&gt;
*Dolibarr est écrit en PHP et supporte toutes versions PHP supérieures à la {{PHPMinVersion}}. Les fichiers doivent tous comporter l&#039;extension .php&lt;br /&gt;
&lt;br /&gt;
*L&#039;appel aux variables superglobales PHP doit passer par les opérateurs dédiés $_COOKIES, $_SERVER, $_ENV. Mais pour récupérer les contenus de $_GET ou $_POST, il faut passer par la fonction dolibarr [[Fonctions utiles Dolibarr|GETPOST()]] .&lt;br /&gt;
&lt;br /&gt;
Les autres opérateurs ($HTTP_SERVER_GET, ...) ayant été passés en deprecated au sein de PHP, ne doivent plus être utilisés. Ainsi le code doit fonctionner y compris quand l&#039;option &#039;&#039;&#039;register_long_arrays&#039;&#039;&#039; est à off.&lt;br /&gt;
De plus, le code doit fonctionner aussi bien quand l&#039;option PHP &#039;&#039;&#039;register_globals&#039;&#039;&#039; est à off (recommandé par PHP)  que quand l&#039;option &#039;&#039;&#039;register_globals&#039;&#039;&#039; est à on (par défaut sur de nombreuses installations).&lt;br /&gt;
&lt;br /&gt;
*Pas d&#039;utilisation de la variable &#039;&#039;&#039;PHP_SELF&#039;&#039;&#039;. Utiliser à la place $_SERVER[&amp;quot;PHP_SELF&amp;quot;]. Notez aussi que le framework Dolibarr passe une routine pour rendre plus sûr le contenu du $_SERVER[&amp;quot;PHP_SELF&amp;quot;] (dans le fichier main.inc.php, donc avant tout traitement métier)&lt;br /&gt;
&lt;br /&gt;
*Quand plusieurs variables doivent être initialisées avec la même valeur, il faut utiliser plusieurs instructions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$var1 = 1; $var2 = 1; $var3 = 1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
plutôt que&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$var1 = $var2 = $var3 = 1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
qui est moins performant.&lt;br /&gt;
&lt;br /&gt;
*Les chaines doivent avoir les variables sorties de la chaine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print &amp;quot;Mon texte affiche ma &amp;quot;.$variable.&amp;quot; !\n&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les commentaires doivent suivre la syntaxe C, ie un double antislash pour un commentaire d&#039;une ligne et utilisation slash-étoile pour ouvrir un bloc de plusieurs lignes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
/* Bloc de commentaire&lt;br /&gt;
 *&lt;br /&gt;
 * Fin du bloc&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
$monobjet = new MonObjet($db);&lt;br /&gt;
$result=$monobjet-&amp;gt;fetch($idobject);&lt;br /&gt;
&lt;br /&gt;
for ($i = 1 , $i &amp;lt; 2 ; $i++)&lt;br /&gt;
{&lt;br /&gt;
  // commentaire sur une ligne&lt;br /&gt;
  print $i;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les fonctions doivent retourner une valeur strictement &amp;gt; à 0 en cas de succès, et un nombre &amp;lt; à 0 en cas d&#039;erreur.&lt;br /&gt;
&lt;br /&gt;
*Pas de code mort (non utilisé) dans le code principal de Dolibarr (le code utilisé uniquement par un module externe doit être inclus dans le module externe).&lt;br /&gt;
&lt;br /&gt;
*Utiliser &amp;quot;include_once&amp;quot; pour l&#039;inclusion de tout fichier contenant des définitions de fonction ou de classes (donc fichiers *.class.php et *.lib.php), utiliser &amp;quot;include&amp;quot; pour tout inclusion de fichier de type template ou contenant un mixte de HTML et PHP (donc fichiers *.inc.php et *.tpl.php).&lt;br /&gt;
&lt;br /&gt;
*Le style de code a utiliser est le PSR-12 (https://www.php-fig.org/psr/psr-12/). Seules les règles &amp;quot;MUST&amp;quot; sont imposées. Notez aussi les points/exceptions suivants:&lt;br /&gt;
**La longueur des lignes: PSR-12 indique que la longueur des lignes a une limite &amp;quot;soft&amp;quot; à 120. Il est en effet préférable d&#039;avoir de longues lignes de données de déclaration plutôt que de longues pages car ce code ne contient aucune logique intéressante ou utile, toutefois une limite &amp;quot;hard&amp;quot; a été instauré à &#039;&#039;&#039;1000&#039;&#039;&#039; caractères. Du code qui ira au delà provoquera des erreurs dans la plateforme d&#039;Intégration Continue.&lt;br /&gt;
**Les tabulations sont acceptées : L&#039;autre exception est qu&#039;on ne remplace pas les tabulations systématiquement par des espaces. L&#039;utilisation des tabulations simplifie la vie de certains développeurs. De plus, l&#039;utilisation d&#039;espaces rend certaines fonctions d&#039;autoformatage défectueuses (comme sur certaines versions d&#039;Eclipse, lors de copier-coller).&lt;br /&gt;
**Note 1: Les règles suivantes sont particulièrement importantes :&lt;br /&gt;
***Les fichiers doivent être sauvés en format Unix (LF) et non Windows (CR/LF). Le format Unix étant compatible sur les OS Unix like, Windows, Mac, alors que le format fichier texte Windows pose problème sous certains PHP sous Unix.&lt;br /&gt;
***Les smart tags PHP ne sont pas utilisés. Les sections de code doivent commencer par &#039;&#039;&#039;&amp;lt;?php&#039;&#039;&#039;&lt;br /&gt;
**Note 2: Vous pouvez utiliser le fichier &#039;&#039;&#039;dev/setup/codesniffer/ruleset.xml&#039;&#039;&#039; comme fichier de contrôle pour vérifier votre style de code avec PHPCodeSniffer.&lt;br /&gt;
**Note 3: Vous pouvez utiliser le fichier &#039;&#039;&#039;dev/setup/eclipse/PSR-12 [built-in].xml&#039;&#039;&#039; comme fichier de règles de syntax pour configurer Eclipse.&lt;br /&gt;
**Note 4: Vous remarquerez que le code actuel ne suit pas forcément tout cela. La raison est historique. La règle fut instaurée en cours de route, aussi, si vous trouvez du code non respectueux de ce standard, n&#039;hésitez pas à le corriger.&lt;br /&gt;
&lt;br /&gt;
==Structures des classes et champs==&lt;br /&gt;
&lt;br /&gt;
Certaines propriétés de classes se retrouvent dans de nombreuses classes. Pour homogénéité, on utilisera les noms suivants:&lt;br /&gt;
{{TemplatePHPFields}}&lt;br /&gt;
&lt;br /&gt;
=Normes SQL=&lt;br /&gt;
&lt;br /&gt;
==Structure des tables et champs==&lt;br /&gt;
&lt;br /&gt;
*Toutes les tables sont préfixées pour éviter les conflits de nommage. Aujourd&#039;hui, le préfixe est modifiable au moment de l&#039;installation. Sa valeur par défaut est &amp;lt;tt&amp;gt;llx_&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*Structure des tables.&lt;br /&gt;
&lt;br /&gt;
Lorsque vous créez une table, il est recommandé de prendre les même conventions de nommages de tables que les autres tables Dolibarr. Avec, à minima les champs suivant:&lt;br /&gt;
 - rowid INTEGER AUTO_INCREMENT PRIMARY KEY    qui est l&#039;id technique&lt;br /&gt;
 - entity INTEGER default 1                    that is id for the multicompany feature&lt;br /&gt;
 - date_creation   datetime                    that is the creation date&lt;br /&gt;
 - tms             timestamp                   qui sera un champ contenant la date de chaque mise à jour (la base de donnée le gère tout seul, pas besoin de le gérer par le code)&lt;br /&gt;
 - import_key      varchar(32)                 qui contiendra le code d&#039;import YYYYMMDDHHMMSS si vous faites des imports en masse dans la table.&lt;br /&gt;
 - status          smallint                    pour stocker le status d&#039;un object&lt;br /&gt;
&lt;br /&gt;
Eventuellement&lt;br /&gt;
 - fk_user_creat  integer qui est l&#039;id du user de création (fk_user_author also found)&lt;br /&gt;
 - fk_user_modif  integer qui est l&#039;id du user de modification&lt;br /&gt;
 - fk_user_valid  integer qui est l&#039;id du user de validation&lt;br /&gt;
 - fk_soc integer qui est l&#039;id du tiers (si applicable)&lt;br /&gt;
&lt;br /&gt;
*Type des champs&lt;br /&gt;
&lt;br /&gt;
Dans la pratique, afin d&#039;être compatible avec toutes les précisions des pays, syntaxes des bases, on utilisera uniquement les types suivants:&lt;br /&gt;
 - integer pour tout nombre entier, id ou clé étrangère (bigint éventuellement accepté pour les id des très grosses tables)&lt;br /&gt;
 - smallint pour tout numérique entier de petite taille (comme pour stocker un code de status)&lt;br /&gt;
 - double(24,8) pour tout montant&lt;br /&gt;
 - double(6,3) pour les taux de tva&lt;br /&gt;
 - real pour une quantité&lt;br /&gt;
 - varchar pour une chaîne (y compris de longueur 1, le type char est de plus en plus déprécié)&lt;br /&gt;
 - timestamp pour un champ date+heure devant être mis a jour automatiquement&lt;br /&gt;
 - datetime pour un champ date+heure&lt;br /&gt;
 - date pour un champ date&lt;br /&gt;
&lt;br /&gt;
==Clé primaire==&lt;br /&gt;
La clé primaire d&#039;une table s&#039;appelle &amp;lt;tt&amp;gt;rowid&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Il y a quelques tables qui échappent à cette règle actuellement (ex [[Table llx_c_actioncomm]]), pour des raisons historiques. Une évolution pourra être étudiée pour une prochaine version.&lt;br /&gt;
&lt;br /&gt;
==Clés étrangères==&lt;br /&gt;
Le nom d&#039;une clé étrangère commence par le préfixe &amp;lt;tt&amp;gt;fk_&amp;lt;/tt&amp;gt; suivi du nom de la table liée (requis pour éviter doublons globales à la base, problématiques sous certains SGBD comme postgresql) puis du champ lié (pour permettre plusieurs clés étrangères différentes sur une même table).&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
fk_facture_fourn_fk_soc&lt;br /&gt;
&lt;br /&gt;
Note: Si vous développez votre propre module externe, il ne doit pas y avoir de clé étrangère depuis vos tables qui pointent sur les tables standards de Dolibarr. Ceci casserait les fonctionnalités de mise à jour, de réparation, de sauvegardes et de restauration.&lt;br /&gt;
&lt;br /&gt;
==Clés alternatives==&lt;br /&gt;
Parfois, il n&#039;y a pas que la clé primaire qui doit être unique. On peut donc ajouter aussi un index clé alternative unique. Un tel index est nommé par un nom qui commence par le préfixe &amp;lt;tt&amp;gt;uk_&amp;lt;/tt&amp;gt; suivi du nom de la table (requis pour éviter doublons d&#039;index globals à la base, problématiques sous certains SGBD comme postgresql) puis d&#039;un suffixe qui caractérise la clé (pour permettre plusieurs index uniques sur une même table).&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
uk_societe_code_client&lt;br /&gt;
&lt;br /&gt;
==Index performance==&lt;br /&gt;
Certains champs sont souvent utilisés comme critère de recherche, de tri ou de jointure. Il convient dans ce cas, d&#039;y mettre un index de performance. De tels indexes seront nommés avec un préfix &amp;lt;tt&amp;gt;idx_&amp;lt;/tt&amp;gt; puis le nom de la table et le nom du champ sur lequel porte l&#039;index.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
idx_societe_user_creat&lt;br /&gt;
&lt;br /&gt;
==Format de fichier DDL==&lt;br /&gt;
Les fichiers qui contiennent la définition de la structure de la base (DDL) doivent être au nombre de 2 par tables:&lt;br /&gt;
Chaque table est définie dans son propre fichier dont le nom est &amp;lt;tt&amp;gt;llx_&#039;&#039;matable&#039;&#039;.sql&amp;lt;/tt&amp;gt;. &lt;br /&gt;
On mettra un commentaire à côté de chaque champ pour en expliquer la signification.&lt;br /&gt;
Les clés étrangères et index de performance ou autres contraintes d&#039;unicité sont définies dans un fichier séparé dont le nom est &amp;lt;tt&amp;gt;llx_&#039;&#039;matable&#039;&#039;.key.sql&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ces fichiers sont placés dans le répertoire &#039;&#039;&#039;install/mysql/tables&#039;&#039;&#039; pour les fichiers standards ou &#039;&#039;&#039;monmodule/tables&#039;&#039;&#039; pour les tables amenées par un module.&lt;br /&gt;
&lt;br /&gt;
Exemple &#039;&#039;&#039;fichier table llx_matable.sql&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
-- Copyright (C) 2008 Author &amp;lt;email@author.com&amp;gt;&lt;br /&gt;
-- &lt;br /&gt;
-- This program is free software; you can redistribute it and/or modify&lt;br /&gt;
-- it under the terms of the GNU General Public License as published by&lt;br /&gt;
-- the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
-- (at your option) any later version.&lt;br /&gt;
--&lt;br /&gt;
-- This program is distributed in the hope that it will be useful,&lt;br /&gt;
-- but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
-- GNU General Public License for more details.&lt;br /&gt;
--&lt;br /&gt;
-- You should have received a copy of the GNU General Public License&lt;br /&gt;
-- along with this program. If not, see &amp;lt;http://www.gnu.org/licenses/&amp;gt;.&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
&lt;br /&gt;
create table llx_matable&lt;br /&gt;
(&lt;br /&gt;
  rowid       integer AUTO_INCREMENT PRIMARY KEY,&lt;br /&gt;
  field_one   integer,&lt;br /&gt;
  field_two   integer NOT NULL,&lt;br /&gt;
  fk_field    integer,&lt;br /&gt;
  field_date  datetime,&lt;br /&gt;
  tms         timestamp&lt;br /&gt;
)ENGINE=innodb;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Exemple &#039;&#039;&#039;fichier clés/index llx_matable.key.sql&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
-- Copyright (C) 2008 Author &amp;lt;email@author.com&amp;gt;&lt;br /&gt;
-- &lt;br /&gt;
-- This program is free software; you can redistribute it and/or modify&lt;br /&gt;
-- it under the terms of the GNU General Public License as published by&lt;br /&gt;
-- the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
-- (at your option) any later version.&lt;br /&gt;
--&lt;br /&gt;
-- This program is distributed in the hope that it will be useful,&lt;br /&gt;
-- but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
-- GNU General Public License for more details.&lt;br /&gt;
--&lt;br /&gt;
-- You should have received a copy of the GNU General Public License&lt;br /&gt;
-- along with this program. If not, see &amp;lt;http://www.gnu.org/licenses/&amp;gt;.&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE llx_matable ADD UNIQUE uk_matable_field(field_one, field_two);&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE llx_matable ADD CONSTRAINT fk_matable_fk_field FOREIGN KEY (fk_field) REFERENCES llx_matablepere (rowid);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Règles de codage SQL==&lt;br /&gt;
&lt;br /&gt;
*Utilisation des alias/nommage de champs&lt;br /&gt;
&lt;br /&gt;
Dans le cas des select on pourra utiliser les alias pour simplifier l&#039;écriture des requêtes:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
select chp1, chpxxx2 as chp2 from table2 as t1, table2 as t2 where t1.chpx = t2.chpy&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Toutefois, il ne faut pas utiliser ces alias sur des requêtes update car non compatible avec mysql 3.1.&lt;br /&gt;
&lt;br /&gt;
*Les SELECT * sont interdits ! Chaque SELECT doit spécifier la liste complète des champs à récupérer. Cela permet d&#039;éviter les confusions. Exemple:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
SELECT field_a, field_b, field_c FROM table_1 WHERE field_d = &#039;$id&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Dans les requêtes SQL, on quote les champs mais pas les numériques qui contiennent des montants destinés à être stockés dans des champs de type double ou real. Les quotes sur les numériques de type float provoquent parfois un stockage d&#039;une valeur différente. Par exemple 412.62 dans le insert sera en fait stocké avec la valeur 412.61999512 en base (suite à des conversions chaines-numériques implicites) si le champ est de type double(24,8). Et seul le PHP voit 412.61999512. Les autres outils verront 412.62 donnant l&#039;impression qu&#039;il n&#039;y a pas de problème. Et c&#039;est le PHP qui a raison, il y a problème en base. En supprimant les quotes sur les numériques, cela va mieux.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
Bon:     INSERT INTO table_1 (field_txt, field_num) VALUES (&#039;txt&#039;, 412.62)&lt;br /&gt;
Mauvais: INSERT INTO table_1 (field_txt, field_num) VALUES (&#039;txt&#039;, &#039;412.62&#039;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remarque, le problème des float est général et pas seulement sur les accès base, il est présent dans tous les languages quand on travaille sur des nombres réels, aussi ils doivent être, dès que affectés, nettoyés par la fonction price2num avec le 2eme paramètre renseigné à:&lt;br /&gt;
&#039;MU&#039; (si il s&#039;agit d&#039;un prix unitaire), &#039;MT&#039; (s&#039;il s&#039;agit d&#039;un prix total) ou &#039;MS&#039; (autres cas) selon le besoin.&lt;br /&gt;
Voir aussi le chapitre &amp;quot;Les nombres réels, montants et calculs&amp;quot; plus bas.&lt;br /&gt;
&lt;br /&gt;
*Les fonctions NOW, SYSDATE ou DATEDIFF sont interdites au sein des ordres SQL. S&#039;il faut saisir la date du moment dans un champ, la valeur doit venir du PHP, par exemple par la fonction dol_now(), et non du moteur de base de données. Ceci afin d&#039;avoir une meilleure portabilité du code mais surtout d&#039;avoir une gestion correcte des TimeZone et ne pas dépendre du TimeZone de la base de donnée.&lt;br /&gt;
&lt;br /&gt;
Par exemple, on ne fera pas:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where datefield = NOW()&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
mais:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where datefield = &#039;&amp;quot;.$this-&amp;gt;db-&amp;gt;idate(dol_now()).&amp;quot;&#039;&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Par exemple, on ne fera pas:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where DATEDIFF(table.datefield, NOW()) &amp;gt; 7&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
mais:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where datefield &amp;lt; &#039;&amp;quot;.$this-&amp;gt;db-&amp;gt;idate(dol_now() - (7 * 24 * 3600)).&amp;quot;&#039;&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un autre avantage de cette règle est que la requête peut bénéficier de l&#039;utilisation de l&#039;index puisqu&#039;on compare datefield à une valeur fixe. Dans le cas du datediff, on applique un traitement sur le champ avant comparaison, rendant impossible l&#039;utilisation de l&#039;index de ce champ. Les conséquences sont des performances très dégradées par rapport à la version sans datediff.&lt;br /&gt;
&lt;br /&gt;
==Règles de migration de base==&lt;br /&gt;
&lt;br /&gt;
*Les scripts de migration de structure sont les fichiers de type &#039;&#039;&#039;install/mysql/migration/a.b.c-x.y.z.sql&#039;&#039;&#039;. Dans un fichier de migration de n vers n+1, on ne détruit une table (DROP TABLE) qui n&#039;est plus utilisée en n+1 que lors de la migration de la version n+1 vers n+2. Ceci afin de toujours conserver les tables deprecated le temps d&#039;une version pour réparer une situation en cas d&#039;erreur de migration.&lt;br /&gt;
&lt;br /&gt;
==Spécificités MySQL==&lt;br /&gt;
&lt;br /&gt;
*Les tables doivent être au format InnoDB.&lt;br /&gt;
&lt;br /&gt;
En effet, ce format gère les clés étrangères, les éventuelles restrictions qui y sont attachées et la notion d&#039;intégrité de transactions requise pour avoir des données en base cohérente entre tables.&lt;br /&gt;
&lt;br /&gt;
*Dolibarr DOIT fonctionner même avec les options &#039;&#039;&#039;strict&#039;&#039;&#039; de Mysql active.&lt;br /&gt;
&lt;br /&gt;
Pour l&#039;activer (fortement recommandé en développement), ajouter la ligne suivante dans le fichier config du serveur Mysql (my.cnf ou my.ini)&lt;br /&gt;
{{MySqlStrictMode}}&lt;br /&gt;
&lt;br /&gt;
==Spécificités PostgreSQL==&lt;br /&gt;
Seuls les fichiers pour Mysql doivent être maintenus.&lt;br /&gt;
Les fichiers pour les autres bases sont convertis &amp;quot;à la volée&amp;quot; par le driver Dolibarr de la base.&lt;br /&gt;
&lt;br /&gt;
Il existe une exception.&lt;br /&gt;
Les requêtes &amp;quot;UPDATE FROM&amp;quot; : &lt;br /&gt;
Syntax MySQL :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
UPDATE table_taget as target, table_source as source SET fieldtarget=source.fieldsource&lt;br /&gt;
WHERE source.rowid=target.rowid;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Syntax PgSQL:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
UPDATE table_taget as target SET fieldtarget=source.fieldsource&lt;br /&gt;
FROM table_source as source WHERE source.rowid=target.rowid;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il n&#039;en existe pas dans Dolibarr, mais pour vos modules Vous devriez faire tel que :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
if ($this-&amp;gt;db-&amp;gt;type==&#039;pgsql&#039;) {&lt;br /&gt;
$sql=&amp;quot;UPDATE table_taget as target SET fieldtarget=source.fieldsource&lt;br /&gt;
FROM table_source as source WHERE source.rowid=target.rowid&amp;quot;;&lt;br /&gt;
} else {&lt;br /&gt;
$sql= &amp;quot;UPDATE table_taget as target, table_source as source SET fieldtarget=source.fieldsource&lt;br /&gt;
WHERE source.rowid=target.rowid&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Normes HTML=&lt;br /&gt;
&lt;br /&gt;
*Tous les attributs dans les balises HTML doivent être *en minuscule* et quotés avec des *doubles quote*.&lt;br /&gt;
&lt;br /&gt;
*Les liens href doivent être absolus en se basant sur la fonction dol_buildpath() pour obtenir un chemin absolu depuis un chemin relatif au répertoire htdocs. Pour les tags img, il faut faire appel à la fonction img_picto().&lt;br /&gt;
&lt;br /&gt;
Par example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print &#039;&amp;lt;a href=&amp;quot;&#039;.dol_buildpath(&#039;/monrep/mapage.php&#039;).&#039;&amp;quot;&amp;gt;&#039;.img_picto(&#039;Texte alt&#039;,&#039;nompictopng&#039;,&#039;&#039;).&#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les tables HTML doivent avoir des colonnes sans valeurs forcées, excepté pour les colonnes qui contiennent une information dont la longueur est non variable. Par exemple, une colonne avec un picto peut être forcée à with=&amp;quot;20px&amp;quot;. Dans les autres cas, il faut éviter de forcer la largeur des colonnes. La raison est que, dans la plupart des cas, le navigateur fait un meilleur travail pour définir automatiquement la bonne largeur des colonnes qu&#039;en forçant manuellement les largeurs. Et ceci marche quelle que soit la résolution de l&#039;écran.&lt;br /&gt;
&lt;br /&gt;
*Le javascript/ajax et l&#039;appel aux scripts java dans les pages php est à proscrire. Si toutefois du code javascript est inclus, il doit être conditionné par le test sur &amp;quot;$conf-&amp;gt;use_javascript_ajax&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
if ($conf-&amp;gt;use_javascript_ajax) {&lt;br /&gt;
...  // Le code php qui génère du javascript est ici&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les popups windows ne doivent pas être utilisées, sauf pour des tooltips (et restent conditionnées par le point ci-dessus).&lt;br /&gt;
&lt;br /&gt;
*Les scripts externes sont écrits en Perl s&#039;ils ne peuvent l&#039;être en php, l&#039;utilisation d&#039;un autre langage n&#039;est pas interdit mais doit être discuté au préalable dans la mailing list des développeurs.&lt;br /&gt;
&lt;br /&gt;
=Normes Dolibarr et squelettes de code=&lt;br /&gt;
&lt;br /&gt;
==Squelettes de code==&lt;br /&gt;
Afin d&#039;uniformiser le code et d&#039;accélérer le développement de nouveaux composants dans Dolibarr, se trouvent dans le répertoire &#039;&#039;&#039;htdocs/modulebuilder/templates&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Pr exemple:&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de descripteur de module: &#039;&#039;&#039;myModule.class.php&#039;&#039;&#039;&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de code pour faire une nouvelle classe: &#039;&#039;&#039;skeleton_class.class.php&#039;&#039;&#039;&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de code pour faire une nouvelle page: &#039;&#039;&#039;skeleton_page.php&#039;&#039;&#039;&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de code pour faire un script à exécuter en ligne de commande: &#039;&#039;&#039;skeleton_script.php&#039;&#039;&#039;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
Servez-vous en comme exemple.&lt;br /&gt;
Notons que ces squelettes sont aussi utilisés par le générateur de code PHP ([[Module ModuleBuilder]]) qui est décrit dans la chapitre de développement de module Dolibarr pour accélérer vos développement.&lt;br /&gt;
&lt;br /&gt;
==Les dates et TimeZone==&lt;br /&gt;
Dolibarr se veut une application multi-utilisateur et multi-localisation. Il convient donc de stocker les dates dans le bon format. Pour éviter les problèmes de conversion, les règles suivantes doivent être appliquées:&lt;br /&gt;
&lt;br /&gt;
*Une date en mémoire doit être au format Timestamp GMT.&lt;br /&gt;
*Une date stockée en base de données contient le Timestamp issue de la date soumise dans la requête en heure &amp;lt;b&amp;gt;locale du serveur PHP&amp;lt;/b&amp;gt;. Cela ne concerne pas les dates mises à jour automatiquement par la base (champ &#039;&#039;&#039;tms&#039;&#039;&#039; en base).&lt;br /&gt;
&lt;br /&gt;
Ainsi le 1er janvier 1970, 3 heures à Paris (TZ=+1) = 1er janvier 1970, 2 heures à Greenwich (TZ=0) sera stocké en mémoire par 7200 et sera soumis à la base de données avec la chaine &#039;19700101030000&#039; (PHP convertit en heure de son TZ et la base déconvertit avec son TZ qui est le même que celui de PHP).&lt;br /&gt;
&lt;br /&gt;
Les méthodes select doivent donc traduire les champs dates lus qui sont au format chaine TZ de la base (&#039;19700101030000&#039;) par appel de la méthode db-&amp;gt;jdate afin de récupérer une information en mémoire au format Timestamp GMT. Et les méthodes insert doivent lors de la génération de la requête convertir la date mémoire connue en variable, par la méthode db-&amp;gt;idate (Voir exemples générés par le squelette).&lt;br /&gt;
&lt;br /&gt;
*Les dates mises à jour automatiquement par la base (champ &#039;&#039;&#039;tms&#039;&#039;&#039; en base) contiennent le Timestamp où la modification est faite selon le timezone de la base de donnée. Les méthodes select récupèrent cette donnée en mémoire au format Timestamp GMT en appliquant également le db-&amp;gt;jdate. Si le timezone de la base de donnée diffère de celui du PHP (un des 2 est mal réglé), il peut donc y avoir des écarts entre date de création et modification.&lt;br /&gt;
&lt;br /&gt;
*La manipulation de dates en PHP doit être faite en utilisant les fonctions dates de Dolibarr: &#039;&#039;&#039;dol_now(), dol_mktime(), dol_stringtotime(), dol_getdate(), dol_time_plus_duree()&#039;&#039;&#039;. Vous trouverez également d&#039;autres fonctions prêtes à l&#039;emploi dans le fichier &#039;&#039;&#039;date.lib.php&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==L&#039;encodage UTF8/ISO==&lt;br /&gt;
Dolibarr stocke les informations de manière suivante:&lt;br /&gt;
&lt;br /&gt;
*En base de donnée, les données sont en UTF8 ou ISO. Cela dépend du pagecode de la base, donc des options à la création de cette base. Dans tous les cas le driver d&#039;accès base Dolibarr (dans /lib/database) s&#039;arrange à la lecture et insertion pour convertir vers et depuis de l&#039;UTF8.&lt;br /&gt;
*Les données en mémoires sont donc stockées en UTF8 (instances d&#039;objets PHP).&lt;br /&gt;
*Les pages web affichées à l&#039;écran sont au format UTF8&lt;br /&gt;
&lt;br /&gt;
==Les nombres réels, montants et calculs==&lt;br /&gt;
En PHP comme dans d&#039;autres langages (Java par exemple), les données non entières (float, real, double) ne sont pas fiables.&lt;br /&gt;
Essayer de faire par exemple &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print 239.2 - 229.3 - 9.9;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Vous n&#039;obtiendrez pas zéro mais un nombre très petit en puissance de 10 négative. Si vous obtenez zéro, vous pourrez trouvez d&#039;autres exemples qui ne fonctionnent pas.&lt;br /&gt;
Le problème des float est général, une variable résultante de calcul de nombre réels doit SYSTEMATIQUEMENT être nettoyée par la fonction &#039;&#039;&#039;price2num()&#039;&#039;&#039; avec le 2eme paramètre renseigné à: &#039;MU&#039;, &#039;MT&#039; ou &#039;MS&#039; selon le besoin (voir doc fonction).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print price2num(239.2 - 229.3 - 9.9, &#039;MT&#039;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
S&#039;il ne s&#039;agit pas d&#039;un prix sur lequel s&#039;adapte les paramètres MU, MT ou MS, il faut utiliser la fonction &#039;&#039;&#039;round()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==Création de tables==&lt;br /&gt;
Ne pas créer de table à l&#039;utilisation, c&#039;est-à-dire à la &#039;&#039;&#039;première utilisation&#039;&#039;&#039; du module.&lt;br /&gt;
Si vous créez un module qui utilise des tables qui ne sont pas intégrées en standard dans le code de Dolibarr, veillez à suivre le didacticiel [[Développement module]] qui explique comment joindre des tables qui se créent à l&#039;activation du module et non à son utilisation (voir plus haut).&lt;br /&gt;
&lt;br /&gt;
==Comparer la version==&lt;br /&gt;
&lt;br /&gt;
Si votre code a besoin de faire des choses différentes selon la version de Dolibarr, vous pouvez utiliser le truc suivant pour comparer les versions&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$version=preg_split(&#039;/[\.-]/&#039;,DOL_VERSION);&lt;br /&gt;
if (versioncompare($version,array(5,0,-4)) &amp;gt;= 0) { //mycode for 5.0 only; }	// For dolibarr 5.0.* (the -4 means we include also alpha, beta, rc and rcX)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais cette solution requiert de faire un include avoir la fonction versioncompare. Une alternative est d&#039;utiliser le test suivant:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
if ((float) DOL_VERSION &amp;gt;= 5.0) { //mycode for 5.0 only; }	// For dolibarr 5.0.*&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Logs==&lt;br /&gt;
Ajouter des traces dans votre code avec la fonction&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
dol_syslog($yourmessage, LOG_INFO|LOG_DEBUG|LOG_WARNING|LOG_ERR);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Répertoires de travail==&lt;br /&gt;
Si vous avez besoin de créer un répertoire de travail, dans votre code, faites référence à ce répertoire par&lt;br /&gt;
&#039;&#039;&#039;DOL_DATA_ROOT.&#039;/monmodule&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Le répertoire peut être créé dans votre code à l&#039;exécution par le code suivant:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$mymoduledir=DOL_DATA_ROOT.&#039;/monmodule&#039;;&lt;br /&gt;
dol_mkdir($mymoduledir);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si vous avez besoin d&#039;un répertoire qui contiendra des données temporaires, ce répertoire doit être&#039;&#039;&#039; DOL_DATA_ROOT.&#039;/monmodule/temp&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Design patterns et programmation objet=&lt;br /&gt;
&lt;br /&gt;
==Design patterns de Création (GoF)==&lt;br /&gt;
Design patterns définis par le Gang Of Four (voir la wikipédia sur les [[wikipedia:Patron de conception|Design patterns]]).&lt;br /&gt;
Dans Dolibarr, pas de mise en oeuvre de design patterns de comportement particulier.&lt;br /&gt;
On trouve des objets proches des Singletons et Fabriques conforme à 100% dans l&#039;esprit mais pas dans la syntaxe, ceci afin d’être compatible avec la plus large plage possible de versions de PHP.&lt;br /&gt;
&lt;br /&gt;
==Design patterns d&#039;entreprises (Martin Fowler)==&lt;br /&gt;
&lt;br /&gt;
===Mode d&#039;organisation du code===&lt;br /&gt;
[[wikipedia:Martin_Fowler|Martin Fowler]] a identifié 3 méthodes d&#039;organisation du code appelées &#039;&#039;&#039;patterns&#039;&#039;&#039; (&#039;&#039;&#039;motifs&#039;&#039;&#039;):&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Transaction Script&#039;&#039;&#039; (Le code est linéaire en fonction d&#039;une action utilisateur).&lt;br /&gt;
&lt;br /&gt;
C&#039;est le motif à l&#039;ancienne utilisé dans les langages procéduraux.&lt;br /&gt;
Inconvénient: Redondance du code. Nécessité de connaitre le modèle physique pour développer les parties métiers.&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Domain Model&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
C&#039;est un concept possible depuis les langages objets. Ce sont les procédures métiers (qui doivent être identifiés avant) qui servent de bases pour les classes objets.&lt;br /&gt;
Inconvénient: Motif complexe à maintenir.&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Table Module&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Un intermédiaire entre les 2 précédents où l&#039;on a une instance unique de classe par table de la base de données.&lt;br /&gt;
&lt;br /&gt;
-&amp;gt; Comme le montre les squelettes de code (voir point précédent), Dolibarr se base sur le principe du &#039;&#039;&#039;Table Module&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===Communication Logique métier - Données (ORM)===&lt;br /&gt;
Il existe 3 modes de liaisons:&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Table And Row Data Gateway&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
C&#039;est le plus simple. On crée une classe par table et chaque classe est un pont avec la table correspondante et propose les méthodes CRUD sur cette table (Create, Read, Update, Delete). Une instance de classe étant alors un enregistrement de la table. La classe ne contient que du code d&#039;accès aux lignes ou colonnes de tables. Le code métier doit alors être ajouté dans d&#039;autres classes. Les liens entre ces classes tables et les classes métiers devant être connues ou déduite de la connaissance du développeur.&lt;br /&gt;
&lt;br /&gt;
Exemple: C&#039;est le mode mis en oeuvre quand on utilise certains Frameworks d&#039;ORM comme &#039;&#039;&#039;iBatis&#039;&#039;&#039; (http://ibatis.apache.org/).&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Active Record&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Identique au précédent, mais on se permet d&#039;ajouter quelques fonctions métiers sur la classe, à conditions que ces fonctions soient bien  propres à la table ou à la notion métier porté par l&#039;enregistrement. C&#039;est le pattern qui offre le meilleur rapport fonctionnalité/complexité.&lt;br /&gt;
&lt;br /&gt;
Exemple: C&#039;est le mode choisi pour les développements Dolibarr et de nombreuses autres applications PHP qui ont leur propre framework et pratiques de développements.&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Data Mapper&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Les classes représentent les entités du problème et non les données. Il faut donc doubler, tripler... ces classes avec des classes Mapper pour accéder aux données.&lt;br /&gt;
Plus &amp;quot;puriste&amp;quot; sur le papier car plus proche du métier, ce mode a aussi l&#039;inconvénient d&#039;être très complexe et difficile à maintenir dans la réalité (l&#039;expérience pratique constaté ne rejoignant pas les promesses de la théorie).&lt;br /&gt;
&lt;br /&gt;
Exemple: C&#039;est le choix si on utilise le Framework d&#039;ORM &#039;&#039;&#039;Propel&#039;&#039;&#039; (http://propel.phpdb.org/trac/). On le trouve donc sur des applications plus lourdes basées sur cet ORM entre autres.&lt;br /&gt;
&lt;br /&gt;
-&amp;gt; Pour les développements Dolibarr, il est recommandé d&#039;utiliser le mode de liaison &#039;&#039;&#039;Active Record&#039;&#039;&#039; qui offre les avantages d&#039;un modèle proche du métier sans en avoir la complexité et sans trop masquer non plus la technique. C&#039;est dans ce mode que le développement, la compréhension du code et la maintenance technique et/ou fonctionnelle semble la plus productive (ceci est toutefois un éternel débat entre les puristes et les pragmatiques, débat dans lequel personne ne peut vraiment avoir raison, car tout dépend des objectifs à atteindre).&lt;br /&gt;
&lt;br /&gt;
==Design Pattern d&#039;Interface Graphique (MVC)==&lt;br /&gt;
Il existe plusieurs design pattern pour les interfaces utilisateurs (MVC, MVP, MVVM).&lt;br /&gt;
Beaucoup confonde ce design pattern avec celui consistant à utiliser un framework de templates. C&#039;est sans rapport. Un framework de template (voir point précédent) n&#039;est en lien qu&#039;avec la partie &amp;quot;V&amp;quot; de ces modèles.&lt;br /&gt;
&lt;br /&gt;
-&amp;gt; Dolibarr utilise le Design Pattern &#039;&#039;&#039;MVC&#039;&#039;&#039;. La partie M est matérialisée par une classe DAO contenant les méthode CRUD (Create-Read-Update-Delete) d&#039;accès à la table.&lt;br /&gt;
Beaucoup de frameworks ont fait le choix de mettre la partie de code C (Controller) et la partie de code du V (vue) dans des fichiers, voir même répertoires séparés. La maintenance semble plus aisé sur la papier, en pratique, il faut sans arrêt jonglé entre n fichiers, le C étant fortement lié au V. Aussi dans Dolibarr, la séparation est faite par une simple section de commentaire. La partie de code C (Controller) est donc le code qui se trouve sont la balise&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * Actions&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Elle est suivi par la partie de code V (Vue), bien séparé du C par la balise&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * View&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce mode de séparation a eu un effet neutre sur les nouveaux développement mais a permis de réduire de manière si importante le temps requis pour la maintenance et correction de bugs qu&#039;il n&#039;est pas envisagé de basculer vers un autre type de séparation (oui les constats fait dans la vraie vie ne sont pas toujours ceux attendus par la théorie scolaire). L&#039;important reste qu&#039;il y ait toujours séparation entre le C et le V, peut importe comment est matérialisé cette séparation, du moment qu&#039;elle l&#039;est (Rappel: Ne pas confondre la notion de séparation du C et du V avec la notion de séparation du code pour alimenter la données d&#039;une Vue et du code pour formater la Vue, ceci un principe de séparation relevant du Design Pattern de Vue, voir point suivant).&lt;br /&gt;
&lt;br /&gt;
==Design Pattern de Vue - Présentation==&lt;br /&gt;
Il existe des frameworks spécialisés dans le Design Pattern de Vue, la partie qui consiste à formater l&#039;écran vue par l&#039;utilisateur.&lt;br /&gt;
Les vieilles versions de Dolibarr utilisaient Smarty. Ce framework est une surcouche à un Framework, déjà très puissant, de formatage d&#039;écran nommé... PHP. Les bénéfices étant très inférieurs aux inconvénients, il a été abandonné au profit de templates PHP (fichier .tpl.php) qui restent le plus simple, le plus universel, le plus évolutif et le plus performant, des frameworks de présentation. &lt;br /&gt;
&lt;br /&gt;
Son seul défaut est qu&#039;il ne peut garantir à 100% les écarts d&#039;un développeur qui irait intégrer dans la Vue, une logique sans rapport avec la présentation (donc autre que du code à vocation de génération, de formatage, de sortie HTML, de logique de test ou de boucle). Ce point est toutefois contrôlé par le mécanisme de validation du code des chefs de projets.&lt;br /&gt;
&lt;br /&gt;
La encore, c&#039;est l&#039;expérience et le constat &amp;quot;sur le terrain&amp;quot; d&#039;un meilleur rendement de productivité qui a motivé l&#039;abandon des frameworks de Présentation externes au profit du framework PHP.&lt;/div&gt;</summary>
		<author><name>Quentic</name></author>
	</entry>
	<entry>
		<id>https://wiki.dolibarr.org/index.php?title=Langages_et_normes&amp;diff=52113</id>
		<title>Langages et normes</title>
		<link rel="alternate" type="text/html" href="https://wiki.dolibarr.org/index.php?title=Langages_et_normes&amp;diff=52113"/>
		<updated>2021-09-30T08:33:58Z</updated>

		<summary type="html">&lt;p&gt;Quentic: /* Structure des tables et champs */Correction d&amp;#039;erreur de frappe&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- BEGIN interlang links --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Do NOT edit this section&lt;br /&gt;
     Links below are automatically managed by PolyglotBot&lt;br /&gt;
     You can edit links on the English source page : Language_and_development_rules --&amp;gt;&lt;br /&gt;
[[en:Language_and_development_rules]]&lt;br /&gt;
[[de:Sprachen_und_Programmierregeln]]&lt;br /&gt;
[[es:Lenguaje_y_Normas_de_Desarrollo]]&lt;br /&gt;
[[zh:语言和开发规则]]&lt;br /&gt;
&amp;lt;!-- END interlang links --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{TemplateDocDev}}&lt;br /&gt;
&lt;br /&gt;
Voici les quelques règles sur le langage, la syntaxe et normes de développement en vigueur pour le projet Dolibarr :&lt;br /&gt;
&lt;br /&gt;
=Versions=&lt;br /&gt;
&lt;br /&gt;
*Dolibarr doit fonctionner sur:&lt;br /&gt;
&lt;br /&gt;
#Tous OS (Windows, Linux, MACOS...)&lt;br /&gt;
#PHP {{PHPMinVersion}} (Doit fonctionner sans aucun module PHP complémentaire hors les modules d&#039;accès base de donnée).&lt;br /&gt;
#Mysql {{MySqlMinVersion}}&lt;br /&gt;
&lt;br /&gt;
=Normes Copyright=&lt;br /&gt;
&lt;br /&gt;
*Tout fichier PHP doit avoir un en-tête selon le masque suivant&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
/* Copyright (C) YYYY John Doe  &amp;lt;email@email.com&amp;gt;&lt;br /&gt;
 *&lt;br /&gt;
 * Licence information&lt;br /&gt;
 */&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Quand vous éditez un fichier existant du projet, ajouter une ligne Copyright sous celles existantes.&lt;br /&gt;
&lt;br /&gt;
=Normes PHP=&lt;br /&gt;
&lt;br /&gt;
==PHP==&lt;br /&gt;
&lt;br /&gt;
*Dolibarr est écrit en PHP et supporte toutes versions PHP supérieures à la {{PHPMinVersion}}. Les fichiers doivent tous comporter l&#039;extension .php&lt;br /&gt;
&lt;br /&gt;
*L&#039;appel aux variables superglobales PHP doit passer par les opérateurs dédiés $_COOKIES, $_SERVER, $_ENV. Mais pour récupérer les contenus de $_GET ou $_POST, il faut passer par la fonction dolibarr [[Fonctions utiles Dolibarr|GETPOST()]] .&lt;br /&gt;
&lt;br /&gt;
Les autres opérateurs ($HTTP_SERVER_GET, ...) ayant été passés en deprecated au sein de PHP, ne doivent plus être utilisés. Ainsi le code doit fonctionner y compris quand l&#039;option &#039;&#039;&#039;register_long_arrays&#039;&#039;&#039; est à off.&lt;br /&gt;
De plus, le code doit fonctionner aussi bien quand l&#039;option PHP &#039;&#039;&#039;register_globals&#039;&#039;&#039; est à off (recommandé par PHP)  que quand l&#039;option &#039;&#039;&#039;register_globals&#039;&#039;&#039; est à on (par défaut sur de nombreuses installations).&lt;br /&gt;
&lt;br /&gt;
*Pas d&#039;utilisation de la variable &#039;&#039;&#039;PHP_SELF&#039;&#039;&#039;. Utiliser à la place $_SERVER[&amp;quot;PHP_SELF&amp;quot;]. Notez aussi que le framework Dolibarr passe une routine pour rendre plus sûr le contenu du $_SERVER[&amp;quot;PHP_SELF&amp;quot;] (dans le fichier main.inc.php, donc avant tout traitement métier)&lt;br /&gt;
&lt;br /&gt;
*Quand plusieurs variables doivent être initialisées avec la même valeur, il faut utiliser plusieurs instructions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$var1 = 1; $var2 = 1; $var3 = 1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
plutôt que&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$var1 = $var2 = $var3 = 1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
qui est moins performant.&lt;br /&gt;
&lt;br /&gt;
*Les chaines doivent avoir les variables sorties de la chaine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print &amp;quot;Mon texte affiche ma &amp;quot;.$variable.&amp;quot; !\n&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les commentaires doivent suivre la syntaxe C, ie un double antislash pour un commentaire d&#039;une ligne et utilisation slash-étoile pour ouvrir un bloc de plusieurs lignes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
/* Bloc de commentaire&lt;br /&gt;
 *&lt;br /&gt;
 * Fin du bloc&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
$monobjet = new MonObjet($db);&lt;br /&gt;
$result=$monobjet-&amp;gt;fetch($idobject);&lt;br /&gt;
&lt;br /&gt;
for ($i = 1 , $i &amp;lt; 2 ; $i++)&lt;br /&gt;
{&lt;br /&gt;
  // commentaire sur une ligne&lt;br /&gt;
  print $i;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les fonctions doivent retourner une valeur strictement &amp;gt; à 0 en cas de succès, et un nombre &amp;lt; à 0 en cas d&#039;erreur.&lt;br /&gt;
&lt;br /&gt;
*Pas de code mort (non utilisé) dans le code principal de Dolibarr (le code utilisé uniquement par un module externe doit être inclus dans le module externe).&lt;br /&gt;
&lt;br /&gt;
*Utiliser &amp;quot;include_once&amp;quot; pour l&#039;inclusion de tout fichier contenant des définitions de fonction ou de classes (donc fichiers *.class.php et *.lib.php), utiliser &amp;quot;include&amp;quot; pour tout inclusion de fichier de type template ou contenant un mixte de HTML et PHP (donc fichiers *.inc.php et *.tpl.php).&lt;br /&gt;
&lt;br /&gt;
*Le style de code a utiliser est le PSR-12 (https://www.php-fig.org/psr/psr-12/). Seules les règles &amp;quot;MUST&amp;quot; sont imposées. Notez aussi les points/exceptions suivants:&lt;br /&gt;
**La longueur des lignes: PSR-12 indique que la longueur des lignes a une limite &amp;quot;soft&amp;quot; à 120. Il est en effet préférable d&#039;avoir de longues lignes de données de déclaration plutôt que de longues pages car ce code ne contient aucune logique intéressante ou utile, toutefois une limite &amp;quot;hard&amp;quot; a été instauré à &#039;&#039;&#039;1000&#039;&#039;&#039; caractères. Du code qui ira au delà provoquera des erreurs dans la plateforme d&#039;Intégration Continue.&lt;br /&gt;
**Les tabulations sont acceptées : L&#039;autre exception est qu&#039;on ne remplace pas les tabulations systématiquement par des espaces. L&#039;utilisation des tabulations simplifie la vie de certains développeurs. De plus, l&#039;utilisation d&#039;espaces rend certaines fonctions d&#039;autoformatage défectueuses (comme sur certaines versions d&#039;Eclipse, lors de copier-coller).&lt;br /&gt;
**Note 1: Les règles suivantes sont particulièrement importantes :&lt;br /&gt;
***Les fichiers doivent être sauvés en format Unix (LF) et non Windows (CR/LF). Le format Unix étant compatible sur les OS Unix like, Windows, Mac, alors que le format fichier texte Windows pose problème sous certains PHP sous Unix.&lt;br /&gt;
***Les smart tags PHP ne sont pas utilisés. Les sections de code doivent commencer par &#039;&#039;&#039;&amp;lt;?php&#039;&#039;&#039;&lt;br /&gt;
**Note 2: Vous pouvez utiliser le fichier &#039;&#039;&#039;dev/setup/codesniffer/ruleset.xml&#039;&#039;&#039; comme fichier de contrôle pour vérifier votre style de code avec PHPCodeSniffer.&lt;br /&gt;
**Note 3: Vous pouvez utiliser le fichier &#039;&#039;&#039;dev/setup/eclipse/PSR-12 [built-in].xml&#039;&#039;&#039; comme fichier de règles de syntax pour configurer Eclipse.&lt;br /&gt;
**Note 4: Vous remarquerez que le code actuel ne suit pas forcément tout cela. La raison est historique. La règle fut instaurée en cours de route, aussi, si vous trouvez du code non respectueux de ce standard, n&#039;hésitez pas à le corriger.&lt;br /&gt;
&lt;br /&gt;
==Structures des classes et champs==&lt;br /&gt;
&lt;br /&gt;
Certaines propriétés de classes se retrouvent dans de nombreuses classes. Pour homogénéité, on utilisera les noms suivants:&lt;br /&gt;
{{TemplatePHPFields}}&lt;br /&gt;
&lt;br /&gt;
=Normes SQL=&lt;br /&gt;
&lt;br /&gt;
==Structure des tables et champs==&lt;br /&gt;
&lt;br /&gt;
*Toutes les tables sont préfixées pour éviter les conflits de nommage. Aujourd&#039;hui, le préfixe est modifiable au moment de l&#039;installation. Sa valeur par défaut est &amp;lt;tt&amp;gt;llx_&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*Structure des tables.&lt;br /&gt;
&lt;br /&gt;
Lorsque vous créez une table, il est recommandé de prendre les même conventions de nommages de tables que les autres tables Dolibarr. Avec, à minima les champs suivant:&lt;br /&gt;
 - rowid INTEGER AUTO_INCREMENT PRIMARY KEY    qui est l&#039;id technique&lt;br /&gt;
 - entity INTEGER default 1                    that is id for the multicompany feature&lt;br /&gt;
 - date_creation   datetime                    that is the creation date&lt;br /&gt;
 - tms             timestamp                   qui sera un champ contenant la date de chaque mise à jour (la base de donnée le gère tout seul, pas besoin de le gérer par le code)&lt;br /&gt;
 - import_key      varchar(32)                 qui contiendra le code d&#039;import YYYYMMDDHHMMSS si vous faites des imports en masse dans la table.&lt;br /&gt;
 - status          smallint                    pour stocker le status d&#039;un object&lt;br /&gt;
&lt;br /&gt;
Eventuellement&lt;br /&gt;
 - fk_user_creat  integer qui est l&#039;id du user de création (fk_user_author also found)&lt;br /&gt;
 - fk_user_modif  integer qui est l&#039;id du user de modification&lt;br /&gt;
 - fk_user_valid  integer qui est l&#039;id du user de validation&lt;br /&gt;
 - fk_soc integer qui est l&#039;id du tiers (si applicable)&lt;br /&gt;
&lt;br /&gt;
*Type des champs&lt;br /&gt;
&lt;br /&gt;
Dans la pratique, afin d&#039;être compatible avec toutes les précisions des pays, syntaxes des bases, on utilisera uniquement les types suivants:&lt;br /&gt;
 - integer pour tout nombre entier, id ou clé étrangère (bigint éventuellement accepté pour les id des très grosses tables)&lt;br /&gt;
 - smallint pour tout numérique entier de petite taille (comme pour stocker un code de status)&lt;br /&gt;
 - double(24,8) pour tout montant&lt;br /&gt;
 - double(6,3) pour les taux de tva&lt;br /&gt;
 - real pour une quantité&lt;br /&gt;
 - varchar pour une chaîne (y compris de longueur 1, le type char est de plus en plus déprécié)&lt;br /&gt;
 - timestamp pour un champ date+heure devant être mis a jour automatiquement&lt;br /&gt;
 - datetime pour un champ date+heure&lt;br /&gt;
 - date pour un champ date&lt;br /&gt;
&lt;br /&gt;
==Clé primaire==&lt;br /&gt;
La clé primaire d&#039;une table s&#039;appelle &amp;lt;tt&amp;gt;rowid&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Il y a quelques tables qui échappent à cette règle actuellement (ex [[Table llx_c_actioncomm]]), pour des raisons historiques. Une évolution pourra être étudiée pour une prochaine version.&lt;br /&gt;
&lt;br /&gt;
==Clés étrangères==&lt;br /&gt;
Le nom d&#039;une clé étrangère commence par le préfixe &amp;lt;tt&amp;gt;fk_&amp;lt;/tt&amp;gt; suivi du nom de la table liée (requis pour éviter doublons globales à la base, problématiques sous certains SGBD comme postgresql) puis du champ lié (pour permettre plusieurs clés étrangères différentes sur une même table).&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
fk_facture_fourn_fk_soc&lt;br /&gt;
&lt;br /&gt;
Note: Si vous développez votre propre module externe, il ne doit pas y avoir de clé étrangère depuis vos tables qui pointent sur les tables standards de Dolibarr. Ceci casserait les fonctionnalités de mise à jour, de réparation, de sauvegardes et de restauration.&lt;br /&gt;
&lt;br /&gt;
==Clés alternatives==&lt;br /&gt;
Parfois, il n&#039;y a pas que la clé primaire qui doit être unique. On peut donc ajouter aussi un index clé alternative unique. Un tel index est nommé par un nom qui commence par le préfixe &amp;lt;tt&amp;gt;uk_&amp;lt;/tt&amp;gt; suivi du nom de la table (requis pour éviter doublons d&#039;index globals à la base, problématiques sous certains SGBD comme postgresql) puis d&#039;un suffixe qui caractérise la clé (pour permettre plusieurs index uniques sur une même table).&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
uk_societe_code_client&lt;br /&gt;
&lt;br /&gt;
==Index performance==&lt;br /&gt;
Certains champs sont souvent utilisés comme critère de recherche, de tri ou de jointure. Il convient dans ce cas, d&#039;y mettre un index de performance. De tels indexes seront nommés avec un préfix &amp;lt;tt&amp;gt;idx_&amp;lt;/tt&amp;gt; puis le nom de la table et le nom du champ sur lequel porte l&#039;index.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
idx_societe_user_creat&lt;br /&gt;
&lt;br /&gt;
==Format de fichier DDL==&lt;br /&gt;
Les fichiers qui contiennent la définition de la structure de la base (DDL) doivent être au nombre de 2 par tables:&lt;br /&gt;
Chaque table est définie dans son propre fichier dont le nom est &amp;lt;tt&amp;gt;llx_&#039;&#039;matable&#039;&#039;.sql&amp;lt;/tt&amp;gt;. &lt;br /&gt;
On mettra un commentaire à côté de chaque champ pour en expliquer la signification.&lt;br /&gt;
Les clés étrangères et index de performance ou autres contraintes d&#039;unicité sont définies dans un fichier séparé dont le nom est &amp;lt;tt&amp;gt;llx_&#039;&#039;matable&#039;&#039;.key.sql&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ces fichiers sont placés dans le répertoire &#039;&#039;&#039;install/mysql/tables&#039;&#039;&#039; pour les fichiers standards ou &#039;&#039;&#039;monmodule/tables&#039;&#039;&#039; pour les tables amenées par un module.&lt;br /&gt;
&lt;br /&gt;
Exemple &#039;&#039;&#039;fichier table llx_matable.sql&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
-- Copyright (C) 2008 Author &amp;lt;email@author.com&amp;gt;&lt;br /&gt;
-- &lt;br /&gt;
-- This program is free software; you can redistribute it and/or modify&lt;br /&gt;
-- it under the terms of the GNU General Public License as published by&lt;br /&gt;
-- the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
-- (at your option) any later version.&lt;br /&gt;
--&lt;br /&gt;
-- This program is distributed in the hope that it will be useful,&lt;br /&gt;
-- but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
-- GNU General Public License for more details.&lt;br /&gt;
--&lt;br /&gt;
-- You should have received a copy of the GNU General Public License&lt;br /&gt;
-- along with this program. If not, see &amp;lt;http://www.gnu.org/licenses/&amp;gt;.&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
&lt;br /&gt;
create table llx_matable&lt;br /&gt;
(&lt;br /&gt;
  rowid       integer AUTO_INCREMENT PRIMARY KEY,&lt;br /&gt;
  field_one   integer,&lt;br /&gt;
  field_two   integer NOT NULL,&lt;br /&gt;
  fk_field    integer,&lt;br /&gt;
  field_date  datetime,&lt;br /&gt;
  tms         timestamp&lt;br /&gt;
)ENGINE=innodb;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Exemple &#039;&#039;&#039;fichier clés/index llx_matable.key.sql&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
-- Copyright (C) 2008 Author &amp;lt;email@author.com&amp;gt;&lt;br /&gt;
-- &lt;br /&gt;
-- This program is free software; you can redistribute it and/or modify&lt;br /&gt;
-- it under the terms of the GNU General Public License as published by&lt;br /&gt;
-- the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
-- (at your option) any later version.&lt;br /&gt;
--&lt;br /&gt;
-- This program is distributed in the hope that it will be useful,&lt;br /&gt;
-- but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
-- GNU General Public License for more details.&lt;br /&gt;
--&lt;br /&gt;
-- You should have received a copy of the GNU General Public License&lt;br /&gt;
-- along with this program. If not, see &amp;lt;http://www.gnu.org/licenses/&amp;gt;.&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE llx_matable ADD UNIQUE uk_matable_field(field_one, field_two);&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE llx_matable ADD CONSTRAINT fk_matable_fk_field FOREIGN KEY (fk_field) REFERENCES llx_matablepere (rowid);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Règles de codage SQL==&lt;br /&gt;
&lt;br /&gt;
*Utilisation des alias/nommage de champs&lt;br /&gt;
&lt;br /&gt;
Dans le cas des select on pourra utiliser les alias pour simplifier l&#039;écriture des requêtes:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
select chp1, chpxxx2 as chp2 from table2 as t1, table2 as t2 where t1.chpx = t2.chpy&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Toutefois, il ne faut pas utiliser ces alias sur des requêtes update car non compatible avec mysql 3.1.&lt;br /&gt;
&lt;br /&gt;
*Les SELECT * sont interdits ! Chaque SELECT doit spécifier la liste complète des champs à récupérer. Cela permet d&#039;éviter les confusions. Exemple:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
SELECT field_a, field_b, field_c FROM table_1 WHERE field_d = &#039;$id&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Dans les requêtes SQL, on quote les champs mais pas les numériques qui contiennent des montants destinés à être stockés dans des champs de type double ou real. Les quotes sur les numériques de type float provoquent parfois un stockage d&#039;une valeur différente. Par exemple 412.62 dans le insert sera en fait stocké avec la valeur 412.61999512 en base (suite à des conversions chaines-numériques implicites) si le champ est de type double(24,8). Et seul le PHP voit 412.61999512. Les autres outils verront 412.62 donnant l&#039;impression qu&#039;il n&#039;y a pas de problème. Et c&#039;est le PHP qui a raison, il y a problème en base. En supprimant les quotes sur les numériques, cela va mieux.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
Bon:     INSERT INTO table_1 (field_txt, field_num) VALUES (&#039;txt&#039;, 412.62)&lt;br /&gt;
Mauvais: INSERT INTO table_1 (field_txt, field_num) VALUES (&#039;txt&#039;, &#039;412.62&#039;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remarque, le problème des float est général et pas seulement sur les accès base, il est présent dans tous les languages quand on travaille sur des nombres réels, aussi ils doivent être, dès que affectés, nettoyés par la fonction price2num avec le 2eme paramètre renseigné à:&lt;br /&gt;
&#039;MU&#039; (si il s&#039;agit d&#039;un prix unitaire), &#039;MT&#039; (s&#039;il s&#039;agit d&#039;un prix total) ou &#039;MS&#039; (autres cas) selon le besoin.&lt;br /&gt;
Voir aussi le chapitre &amp;quot;Les nombres réels, montants et calculs&amp;quot; plus bas.&lt;br /&gt;
&lt;br /&gt;
*Les fonctions NOW, SYSDATE ou DATEDIFF sont interdites au sein des ordres SQL. S&#039;il faut saisir la date du moment dans un champ, la valeur doit venir du PHP, par exemple par la fonction dol_now(), et non du moteur de base de données. Ceci afin d&#039;avoir une meilleure portabilité du code mais surtout d&#039;avoir une gestion correcte des TimeZone et ne pas dépendre du TimeZone de la base de donnée.&lt;br /&gt;
&lt;br /&gt;
Par exemple, on ne fera pas:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where datefield = NOW()&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
mais:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where datefield = &#039;&amp;quot;.$this-&amp;gt;db-&amp;gt;idate(dol_now()).&amp;quot;&#039;&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Par exemple, on ne fera pas:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where DATEDIFF(table.datefield, NOW()) &amp;gt; 7&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
mais:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where datefield &amp;lt; &#039;&amp;quot;.$this-&amp;gt;db-&amp;gt;idate(dol_now() - (7 * 24 * 3600)).&amp;quot;&#039;&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un autre avantage de cette règle est que la requête peut bénéficier de l&#039;utilisation de l&#039;index puisqu&#039;on compare datefield à une valeur fixe. Dans le cas du datediff, on applique un traitement sur le champ avant comparaison, rendant impossible l&#039;utilisation de l&#039;index de ce champ. Les conséquences sont des performances très dégradées par rapport à la version sans datediff.&lt;br /&gt;
&lt;br /&gt;
==Règles de migration de base==&lt;br /&gt;
&lt;br /&gt;
*Les scripts de migration de structure sont les fichiers de type &#039;&#039;&#039;install/mysql/migration/a.b.c-x.y.z.sql&#039;&#039;&#039;. Dans un fichier de migration de n vers n+1, on ne détruit une table (DROP TABLE) qui n&#039;est plus utilisée en n+1 que lors de la migration de la version n+1 vers n+2. Ceci afin de toujours conserver les tables deprecated le temps d&#039;une version pour réparer une situation en cas d&#039;erreur de migration.&lt;br /&gt;
&lt;br /&gt;
==Spécificités MySQL==&lt;br /&gt;
&lt;br /&gt;
*Les tables doivent être au format InnoDB.&lt;br /&gt;
&lt;br /&gt;
En effet, ce format gère les clés étrangères, les éventuelles restrictions qui y sont attachées et la notion d&#039;intégrité de transactions requise pour avoir des données en base cohérente entre tables.&lt;br /&gt;
&lt;br /&gt;
*Dolibarr DOIT fonctionner même avec les options &#039;&#039;&#039;strict&#039;&#039;&#039; de Mysql active.&lt;br /&gt;
&lt;br /&gt;
Pour l&#039;activer (fortement recommandé en développement), ajouter la ligne suivante dans le fichier config du serveur Mysql (my.cnf ou my.ini)&lt;br /&gt;
{{MySqlStrictMode}}&lt;br /&gt;
&lt;br /&gt;
==Spécificités PostgreSQL==&lt;br /&gt;
Seuls les fichiers pour Mysql doivent être maintenus.&lt;br /&gt;
Les fichiers pour les autres bases sont convertis &amp;quot;à la volée&amp;quot; par le driver Dolibarr de la base.&lt;br /&gt;
&lt;br /&gt;
Il existe une exception.&lt;br /&gt;
Les requêtes &amp;quot;UPDATE FROM&amp;quot; : &lt;br /&gt;
Syntax MySQL :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
UPDATE table_taget as target, table_source as source SET fieldtarget=source.fieldsource&lt;br /&gt;
WHERE source.rowid=target.rowid;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Syntax PgSQL:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
UPDATE table_taget as target SET fieldtarget=source.fieldsource&lt;br /&gt;
FROM table_source as source WHERE source.rowid=target.rowid;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il n&#039;en existe pas dans Dolibarr, mais pour vos modules Vous devriez faire tel que :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
if ($this-&amp;gt;db-&amp;gt;type==&#039;pgsql&#039;) {&lt;br /&gt;
$sql=&amp;quot;UPDATE table_taget as target SET fieldtarget=source.fieldsource&lt;br /&gt;
FROM table_source as source WHERE source.rowid=target.rowid&amp;quot;;&lt;br /&gt;
} else {&lt;br /&gt;
$sql= &amp;quot;UPDATE table_taget as target, table_source as source SET fieldtarget=source.fieldsource&lt;br /&gt;
WHERE source.rowid=target.rowid&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Normes HTML=&lt;br /&gt;
&lt;br /&gt;
*Tous les attributs dans les balises HTML doivent être *en minuscule* et quotés avec des *doubles quote*.&lt;br /&gt;
&lt;br /&gt;
*Les liens href doivent être absolus en se basant sur la fonction dol_buildpath() pour obtenir un chemin absolu depuis un chemin relatif au répertoire htdocs. Pour les tags img, il faut faire appel à la fonction img_picto().&lt;br /&gt;
&lt;br /&gt;
Par example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print &#039;&amp;lt;a href=&amp;quot;&#039;.dol_buildpath(&#039;/monrep/mapage.php&#039;).&#039;&amp;quot;&amp;gt;&#039;.img_picto(&#039;Texte alt&#039;,&#039;nompictopng&#039;,&#039;&#039;).&#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les tables HTML doivent avoir des colonnes sans valeurs forcées, excepté pour les colonnes qui contiennent une information dont la longueur est non variable. Par exemple, une colonne avec un picto peut être forcée à with=&amp;quot;20px&amp;quot;. Dans les autres cas, il faut éviter de forcer la largeur des colonnes. La raison est que, dans la plupart des cas, le navigateur fait un meilleur travail pour définir automatiquement la bonne largeur des colonnes qu&#039;en forçant manuellement les largeurs. Et ceci marche quelque soit la résolution de l&#039;écran.&lt;br /&gt;
&lt;br /&gt;
*Le javascript/ajax et l&#039;appel aux scripts java dans les pages php est à proscrire. Si toutefois du code javascript est inclus, il doit être conditionné par le test sur &amp;quot;$conf-&amp;gt;use_javascript_ajax&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
if ($conf-&amp;gt;use_javascript_ajax) {&lt;br /&gt;
...  // Le code php qui génère du javascript est ici&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les popups windows ne doivent pas être utilisées, sauf pour des tooltips (et restent conditionnées par le point ci-dessus).&lt;br /&gt;
&lt;br /&gt;
*Les scripts externes sont écrits en Perl s&#039;ils ne peuvent l&#039;être en php, l&#039;utilisation d&#039;un autre langage n&#039;est pas interdit mais doit être discuté au préalable dans la mailing list des développeurs.&lt;br /&gt;
&lt;br /&gt;
=Normes Dolibarr et squelettes de code=&lt;br /&gt;
&lt;br /&gt;
==Squelettes de code==&lt;br /&gt;
Afin d&#039;uniformiser le code et d&#039;accélérer le développement de nouveaux composants dans Dolibarr, se trouvent dans le répertoire &#039;&#039;&#039;htdocs/modulebuilder/templates&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Pr exemple:&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de descripteur de module: &#039;&#039;&#039;myModule.class.php&#039;&#039;&#039;&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de code pour faire une nouvelle classe: &#039;&#039;&#039;skeleton_class.class.php&#039;&#039;&#039;&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de code pour faire une nouvelle page: &#039;&#039;&#039;skeleton_page.php&#039;&#039;&#039;&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de code pour faire un script à exécuter en ligne de commande: &#039;&#039;&#039;skeleton_script.php&#039;&#039;&#039;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
Servez-vous en comme exemple.&lt;br /&gt;
Notons que ces squelettes sont aussi utilisés par le générateur de code PHP ([[Module ModuleBuilder]]) qui est décrit dans la chapitre de développement de module Dolibarr pour accélérer vos développement.&lt;br /&gt;
&lt;br /&gt;
==Les dates et TimeZone==&lt;br /&gt;
Dolibarr se veut une application multi-utilisateur et multi-localisation. Il convient donc de stocker les dates dans le bon format. Pour éviter les problèmes de conversion, les règles suivantes doivent être appliquées:&lt;br /&gt;
&lt;br /&gt;
*Une date en mémoire doit être au format Timestamp GMT.&lt;br /&gt;
*Une date stockée en base de données contient le Timestamp issue de la date soumise dans la requête en heure &amp;lt;b&amp;gt;locale du serveur PHP&amp;lt;/b&amp;gt;. Cela ne concerne pas les dates mises à jour automatiquement par la base (champ &#039;&#039;&#039;tms&#039;&#039;&#039; en base).&lt;br /&gt;
&lt;br /&gt;
Ainsi le 1er janvier 1970, 3 heures à Paris (TZ=+1) = 1er janvier 1970, 2 heures à Greenwich (TZ=0) sera stocké en mémoire par 7200 et sera soumis à la base de données avec la chaine &#039;19700101030000&#039; (PHP convertit en heure de son TZ et la base déconvertit avec son TZ qui est le même que celui de PHP).&lt;br /&gt;
&lt;br /&gt;
Les méthodes select doivent donc traduire les champs dates lus qui sont au format chaine TZ de la base (&#039;19700101030000&#039;) par appel de la méthode db-&amp;gt;jdate afin de récupérer une information en mémoire au format Timestamp GMT. Et les méthodes insert doivent lors de la génération de la requête convertir la date mémoire connue en variable, par la méthode db-&amp;gt;idate (Voir exemples générés par le squelette).&lt;br /&gt;
&lt;br /&gt;
*Les dates mises à jour automatiquement par la base (champ &#039;&#039;&#039;tms&#039;&#039;&#039; en base) contiennent le Timestamp où la modification est faite selon le timezone de la base de donnée. Les méthodes select récupèrent cette donnée en mémoire au format Timestamp GMT en appliquant également le db-&amp;gt;jdate. Si le timezone de la base de donnée diffère de celui du PHP (un des 2 est mal réglé), il peut donc y avoir des écarts entre date de création et modification.&lt;br /&gt;
&lt;br /&gt;
*La manipulation de dates en PHP doit être faite en utilisant les fonctions dates de Dolibarr: &#039;&#039;&#039;dol_now(), dol_mktime(), dol_stringtotime(), dol_getdate(), dol_time_plus_duree()&#039;&#039;&#039;. Vous trouverez également d&#039;autres fonctions prêtes à l&#039;emploi dans le fichier &#039;&#039;&#039;date.lib.php&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==L&#039;encodage UTF8/ISO==&lt;br /&gt;
Dolibarr stocke les informations de manière suivante:&lt;br /&gt;
&lt;br /&gt;
*En base de donnée, les données sont en UTF8 ou ISO. Cela dépend du pagecode de la base, donc des options à la création de cette base. Dans tous les cas le driver d&#039;accès base Dolibarr (dans /lib/database) s&#039;arrange à la lecture et insertion pour convertir vers et depuis de l&#039;UTF8.&lt;br /&gt;
*Les données en mémoires sont donc stockées en UTF8 (instances d&#039;objets PHP).&lt;br /&gt;
*Les pages web affichées à l&#039;écran sont au format UTF8&lt;br /&gt;
&lt;br /&gt;
==Les nombres réels, montants et calculs==&lt;br /&gt;
En PHP comme dans d&#039;autres langages (Java par exemple), les données non entières (float, real, double) ne sont pas fiables.&lt;br /&gt;
Essayer de faire par exemple &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print 239.2 - 229.3 - 9.9;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Vous n&#039;obtiendrez pas zéro mais un nombre très petit en puissance de 10 négative. Si vous obtenez zéro, vous pourrez trouvez d&#039;autres exemples qui ne fonctionnent pas.&lt;br /&gt;
Le problème des float est général, une variable résultante de calcul de nombre réels doit SYSTEMATIQUEMENT être nettoyée par la fonction &#039;&#039;&#039;price2num()&#039;&#039;&#039; avec le 2eme paramètre renseigné à: &#039;MU&#039;, &#039;MT&#039; ou &#039;MS&#039; selon le besoin (voir doc fonction).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print price2num(239.2 - 229.3 - 9.9, &#039;MT&#039;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
S&#039;il ne s&#039;agit pas d&#039;un prix sur lequel s&#039;adapte les paramètres MU, MT ou MS, il faut utiliser la fonction &#039;&#039;&#039;round()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==Création de tables==&lt;br /&gt;
Ne pas créer de table à l&#039;utilisation, c&#039;est-à-dire à la &#039;&#039;&#039;première utilisation&#039;&#039;&#039; du module.&lt;br /&gt;
Si vous créez un module qui utilise des tables qui ne sont pas intégrées en standard dans le code de Dolibarr, veillez à suivre le didacticiel [[Développement module]] qui explique comment joindre des tables qui se créent à l&#039;activation du module et non à son utilisation (voir plus haut).&lt;br /&gt;
&lt;br /&gt;
==Comparer la version==&lt;br /&gt;
&lt;br /&gt;
Si votre code a besoin de faire des choses différentes selon la version de Dolibarr, vous pouvez utiliser le truc suivant pour comparer les versions&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$version=preg_split(&#039;/[\.-]/&#039;,DOL_VERSION);&lt;br /&gt;
if (versioncompare($version,array(5,0,-4)) &amp;gt;= 0) { //mycode for 5.0 only; }	// For dolibarr 5.0.* (the -4 means we include also alpha, beta, rc and rcX)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais cette solution requiert de faire un include avoir la fonction versioncompare. Une alternative est d&#039;utiliser le test suivant:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
if ((float) DOL_VERSION &amp;gt;= 5.0) { //mycode for 5.0 only; }	// For dolibarr 5.0.*&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Logs==&lt;br /&gt;
Ajouter des traces dans votre code avec la fonction&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
dol_syslog($yourmessage, LOG_INFO|LOG_DEBUG|LOG_WARNING|LOG_ERR);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Répertoires de travail==&lt;br /&gt;
Si vous avez besoin de créer un répertoire de travail, dans votre code, faites référence à ce répertoire par&lt;br /&gt;
&#039;&#039;&#039;DOL_DATA_ROOT.&#039;/monmodule&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Le répertoire peut être créé dans votre code à l&#039;exécution par le code suivant:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$mymoduledir=DOL_DATA_ROOT.&#039;/monmodule&#039;;&lt;br /&gt;
dol_mkdir($mymoduledir);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si vous avez besoin d&#039;un répertoire qui contiendra des données temporaires, ce répertoire doit être&#039;&#039;&#039; DOL_DATA_ROOT.&#039;/monmodule/temp&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Design patterns et programmation objet=&lt;br /&gt;
&lt;br /&gt;
==Design patterns de Création (GoF)==&lt;br /&gt;
Design patterns définis par le Gang Of Four (voir la wikipédia sur les [[wikipedia:Patron de conception|Design patterns]]).&lt;br /&gt;
Dans Dolibarr, pas de mise en oeuvre de design patterns de comportement particulier.&lt;br /&gt;
On trouve des objets proches des Singletons et Fabriques conforme à 100% dans l&#039;esprit mais pas dans la syntaxe, ceci afin d’être compatible avec la plus large plage possible de versions de PHP.&lt;br /&gt;
&lt;br /&gt;
==Design patterns d&#039;entreprises (Martin Fowler)==&lt;br /&gt;
&lt;br /&gt;
===Mode d&#039;organisation du code===&lt;br /&gt;
[[wikipedia:Martin_Fowler|Martin Fowler]] a identifié 3 méthodes d&#039;organisation du code appelées &#039;&#039;&#039;patterns&#039;&#039;&#039; (&#039;&#039;&#039;motifs&#039;&#039;&#039;):&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Transaction Script&#039;&#039;&#039; (Le code est linéaire en fonction d&#039;une action utilisateur).&lt;br /&gt;
&lt;br /&gt;
C&#039;est le motif à l&#039;ancienne utilisé dans les langages procéduraux.&lt;br /&gt;
Inconvénient: Redondance du code. Nécessité de connaitre le modèle physique pour développer les parties métiers.&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Domain Model&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
C&#039;est un concept possible depuis les langages objets. Ce sont les procédures métiers (qui doivent être identifiés avant) qui servent de bases pour les classes objets.&lt;br /&gt;
Inconvénient: Motif complexe à maintenir.&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Table Module&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Un intermédiaire entre les 2 précédents où l&#039;on a une instance unique de classe par table de la base de données.&lt;br /&gt;
&lt;br /&gt;
-&amp;gt; Comme le montre les squelettes de code (voir point précédent), Dolibarr se base sur le principe du &#039;&#039;&#039;Table Module&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===Communication Logique métier - Données (ORM)===&lt;br /&gt;
Il existe 3 modes de liaisons:&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Table And Row Data Gateway&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
C&#039;est le plus simple. On crée une classe par table et chaque classe est un pont avec la table correspondante et propose les méthodes CRUD sur cette table (Create, Read, Update, Delete). Une instance de classe étant alors un enregistrement de la table. La classe ne contient que du code d&#039;accès aux lignes ou colonnes de tables. Le code métier doit alors être ajouté dans d&#039;autres classes. Les liens entre ces classes tables et les classes métiers devant être connues ou déduite de la connaissance du développeur.&lt;br /&gt;
&lt;br /&gt;
Exemple: C&#039;est le mode mis en oeuvre quand on utilise certains Frameworks d&#039;ORM comme &#039;&#039;&#039;iBatis&#039;&#039;&#039; (http://ibatis.apache.org/).&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Active Record&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Identique au précédent, mais on se permet d&#039;ajouter quelques fonctions métiers sur la classe, à conditions que ces fonctions soient bien  propres à la table ou à la notion métier porté par l&#039;enregistrement. C&#039;est le pattern qui offre le meilleur rapport fonctionnalité/complexité.&lt;br /&gt;
&lt;br /&gt;
Exemple: C&#039;est le mode choisi pour les développements Dolibarr et de nombreuses autres applications PHP qui ont leur propre framework et pratiques de développements.&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Data Mapper&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Les classes représentent les entités du problème et non les données. Il faut donc doubler, tripler... ces classes avec des classes Mapper pour accéder aux données.&lt;br /&gt;
Plus &amp;quot;puriste&amp;quot; sur le papier car plus proche du métier, ce mode a aussi l&#039;inconvénient d&#039;être très complexe et difficile à maintenir dans la réalité (l&#039;expérience pratique constaté ne rejoignant pas les promesses de la théorie).&lt;br /&gt;
&lt;br /&gt;
Exemple: C&#039;est le choix si on utilise le Framework d&#039;ORM &#039;&#039;&#039;Propel&#039;&#039;&#039; (http://propel.phpdb.org/trac/). On le trouve donc sur des applications plus lourdes basées sur cet ORM entre autres.&lt;br /&gt;
&lt;br /&gt;
-&amp;gt; Pour les développements Dolibarr, il est recommandé d&#039;utiliser le mode de liaison &#039;&#039;&#039;Active Record&#039;&#039;&#039; qui offre les avantages d&#039;un modèle proche du métier sans en avoir la complexité et sans trop masquer non plus la technique. C&#039;est dans ce mode que le développement, la compréhension du code et la maintenance technique et/ou fonctionnelle semble la plus productive (ceci est toutefois un éternel débat entre les puristes et les pragmatiques, débat dans lequel personne ne peut vraiment avoir raison, car tout dépend des objectifs à atteindre).&lt;br /&gt;
&lt;br /&gt;
==Design Pattern d&#039;Interface Graphique (MVC)==&lt;br /&gt;
Il existe plusieurs design pattern pour les interfaces utilisateurs (MVC, MVP, MVVM).&lt;br /&gt;
Beaucoup confonde ce design pattern avec celui consistant à utiliser un framework de templates. C&#039;est sans rapport. Un framework de template (voir point précédent) n&#039;est en lien qu&#039;avec la partie &amp;quot;V&amp;quot; de ces modèles.&lt;br /&gt;
&lt;br /&gt;
-&amp;gt; Dolibarr utilise le Design Pattern &#039;&#039;&#039;MVC&#039;&#039;&#039;. La partie M est matérialisée par une classe DAO contenant les méthode CRUD (Create-Read-Update-Delete) d&#039;accès à la table.&lt;br /&gt;
Beaucoup de frameworks ont fait le choix de mettre la partie de code C (Controller) et la partie de code du V (vue) dans des fichiers, voir même répertoires séparés. La maintenance semble plus aisé sur la papier, en pratique, il faut sans arrêt jonglé entre n fichiers, le C étant fortement lié au V. Aussi dans Dolibarr, la séparation est faite par une simple section de commentaire. La partie de code C (Controller) est donc le code qui se trouve sont la balise&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * Actions&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Elle est suivi par la partie de code V (Vue), bien séparé du C par la balise&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * View&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce mode de séparation a eu un effet neutre sur les nouveaux développement mais a permis de réduire de manière si importante le temps requis pour la maintenance et correction de bugs qu&#039;il n&#039;est pas envisagé de basculer vers un autre type de séparation (oui les constats fait dans la vraie vie ne sont pas toujours ceux attendus par la théorie scolaire). L&#039;important reste qu&#039;il y ait toujours séparation entre le C et le V, peut importe comment est matérialisé cette séparation, du moment qu&#039;elle l&#039;est (Rappel: Ne pas confondre la notion de séparation du C et du V avec la notion de séparation du code pour alimenter la données d&#039;une Vue et du code pour formater la Vue, ceci un principe de séparation relevant du Design Pattern de Vue, voir point suivant).&lt;br /&gt;
&lt;br /&gt;
==Design Pattern de Vue - Présentation==&lt;br /&gt;
Il existe des frameworks spécialisés dans le Design Pattern de Vue, la partie qui consiste à formater l&#039;écran vue par l&#039;utilisateur.&lt;br /&gt;
Les vieilles versions de Dolibarr utilisaient Smarty. Ce framework est une surcouche à un Framework, déjà très puissant, de formatage d&#039;écran nommé... PHP. Les bénéfices étant très inférieurs aux inconvénients, il a été abandonné au profit de templates PHP (fichier .tpl.php) qui restent le plus simple, le plus universel, le plus évolutif et le plus performant, des frameworks de présentation. &lt;br /&gt;
&lt;br /&gt;
Son seul défaut est qu&#039;il ne peut garantir à 100% les écarts d&#039;un développeur qui irait intégrer dans la Vue, une logique sans rapport avec la présentation (donc autre que du code à vocation de génération, de formatage, de sortie HTML, de logique de test ou de boucle). Ce point est toutefois contrôlé par le mécanisme de validation du code des chefs de projets.&lt;br /&gt;
&lt;br /&gt;
La encore, c&#039;est l&#039;expérience et le constat &amp;quot;sur le terrain&amp;quot; d&#039;un meilleur rendement de productivité qui a motivé l&#039;abandon des frameworks de Présentation externes au profit du framework PHP.&lt;/div&gt;</summary>
		<author><name>Quentic</name></author>
	</entry>
	<entry>
		<id>https://wiki.dolibarr.org/index.php?title=Langages_et_normes&amp;diff=52112</id>
		<title>Langages et normes</title>
		<link rel="alternate" type="text/html" href="https://wiki.dolibarr.org/index.php?title=Langages_et_normes&amp;diff=52112"/>
		<updated>2021-09-30T08:32:30Z</updated>

		<summary type="html">&lt;p&gt;Quentic: /* PHP */Correction d&amp;#039;erreur de frappe&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- BEGIN interlang links --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Do NOT edit this section&lt;br /&gt;
     Links below are automatically managed by PolyglotBot&lt;br /&gt;
     You can edit links on the English source page : Language_and_development_rules --&amp;gt;&lt;br /&gt;
[[en:Language_and_development_rules]]&lt;br /&gt;
[[de:Sprachen_und_Programmierregeln]]&lt;br /&gt;
[[es:Lenguaje_y_Normas_de_Desarrollo]]&lt;br /&gt;
[[zh:语言和开发规则]]&lt;br /&gt;
&amp;lt;!-- END interlang links --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{TemplateDocDev}}&lt;br /&gt;
&lt;br /&gt;
Voici les quelques règles sur le langage, la syntaxe et normes de développement en vigueur pour le projet Dolibarr :&lt;br /&gt;
&lt;br /&gt;
=Versions=&lt;br /&gt;
&lt;br /&gt;
*Dolibarr doit fonctionner sur:&lt;br /&gt;
&lt;br /&gt;
#Tous OS (Windows, Linux, MACOS...)&lt;br /&gt;
#PHP {{PHPMinVersion}} (Doit fonctionner sans aucun module PHP complémentaire hors les modules d&#039;accès base de donnée).&lt;br /&gt;
#Mysql {{MySqlMinVersion}}&lt;br /&gt;
&lt;br /&gt;
=Normes Copyright=&lt;br /&gt;
&lt;br /&gt;
*Tout fichier PHP doit avoir un en-tête selon le masque suivant&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
/* Copyright (C) YYYY John Doe  &amp;lt;email@email.com&amp;gt;&lt;br /&gt;
 *&lt;br /&gt;
 * Licence information&lt;br /&gt;
 */&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Quand vous éditez un fichier existant du projet, ajouter une ligne Copyright sous celles existantes.&lt;br /&gt;
&lt;br /&gt;
=Normes PHP=&lt;br /&gt;
&lt;br /&gt;
==PHP==&lt;br /&gt;
&lt;br /&gt;
*Dolibarr est écrit en PHP et supporte toutes versions PHP supérieures à la {{PHPMinVersion}}. Les fichiers doivent tous comporter l&#039;extension .php&lt;br /&gt;
&lt;br /&gt;
*L&#039;appel aux variables superglobales PHP doit passer par les opérateurs dédiés $_COOKIES, $_SERVER, $_ENV. Mais pour récupérer les contenus de $_GET ou $_POST, il faut passer par la fonction dolibarr [[Fonctions utiles Dolibarr|GETPOST()]] .&lt;br /&gt;
&lt;br /&gt;
Les autres opérateurs ($HTTP_SERVER_GET, ...) ayant été passés en deprecated au sein de PHP, ne doivent plus être utilisés. Ainsi le code doit fonctionner y compris quand l&#039;option &#039;&#039;&#039;register_long_arrays&#039;&#039;&#039; est à off.&lt;br /&gt;
De plus, le code doit fonctionner aussi bien quand l&#039;option PHP &#039;&#039;&#039;register_globals&#039;&#039;&#039; est à off (recommandé par PHP)  que quand l&#039;option &#039;&#039;&#039;register_globals&#039;&#039;&#039; est à on (par défaut sur de nombreuses installations).&lt;br /&gt;
&lt;br /&gt;
*Pas d&#039;utilisation de la variable &#039;&#039;&#039;PHP_SELF&#039;&#039;&#039;. Utiliser à la place $_SERVER[&amp;quot;PHP_SELF&amp;quot;]. Notez aussi que le framework Dolibarr passe une routine pour rendre plus sûr le contenu du $_SERVER[&amp;quot;PHP_SELF&amp;quot;] (dans le fichier main.inc.php, donc avant tout traitement métier)&lt;br /&gt;
&lt;br /&gt;
*Quand plusieurs variables doivent être initialisées avec la même valeur, il faut utiliser plusieurs instructions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$var1 = 1; $var2 = 1; $var3 = 1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
plutôt que&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$var1 = $var2 = $var3 = 1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
qui est moins performant.&lt;br /&gt;
&lt;br /&gt;
*Les chaines doivent avoir les variables sorties de la chaine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print &amp;quot;Mon texte affiche ma &amp;quot;.$variable.&amp;quot; !\n&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les commentaires doivent suivre la syntaxe C, ie un double antislash pour un commentaire d&#039;une ligne et utilisation slash-étoile pour ouvrir un bloc de plusieurs lignes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
/* Bloc de commentaire&lt;br /&gt;
 *&lt;br /&gt;
 * Fin du bloc&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
$monobjet = new MonObjet($db);&lt;br /&gt;
$result=$monobjet-&amp;gt;fetch($idobject);&lt;br /&gt;
&lt;br /&gt;
for ($i = 1 , $i &amp;lt; 2 ; $i++)&lt;br /&gt;
{&lt;br /&gt;
  // commentaire sur une ligne&lt;br /&gt;
  print $i;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les fonctions doivent retourner une valeur strictement &amp;gt; à 0 en cas de succès, et un nombre &amp;lt; à 0 en cas d&#039;erreur.&lt;br /&gt;
&lt;br /&gt;
*Pas de code mort (non utilisé) dans le code principal de Dolibarr (le code utilisé uniquement par un module externe doit être inclus dans le module externe).&lt;br /&gt;
&lt;br /&gt;
*Utiliser &amp;quot;include_once&amp;quot; pour l&#039;inclusion de tout fichier contenant des définitions de fonction ou de classes (donc fichiers *.class.php et *.lib.php), utiliser &amp;quot;include&amp;quot; pour tout inclusion de fichier de type template ou contenant un mixte de HTML et PHP (donc fichiers *.inc.php et *.tpl.php).&lt;br /&gt;
&lt;br /&gt;
*Le style de code a utiliser est le PSR-12 (https://www.php-fig.org/psr/psr-12/). Seules les règles &amp;quot;MUST&amp;quot; sont imposées. Notez aussi les points/exceptions suivants:&lt;br /&gt;
**La longueur des lignes: PSR-12 indique que la longueur des lignes a une limite &amp;quot;soft&amp;quot; à 120. Il est en effet préférable d&#039;avoir de longues lignes de données de déclaration plutôt que de longues pages car ce code ne contient aucune logique intéressante ou utile, toutefois une limite &amp;quot;hard&amp;quot; a été instauré à &#039;&#039;&#039;1000&#039;&#039;&#039; caractères. Du code qui ira au delà provoquera des erreurs dans la plateforme d&#039;Intégration Continue.&lt;br /&gt;
**Les tabulations sont acceptées : L&#039;autre exception est qu&#039;on ne remplace pas les tabulations systématiquement par des espaces. L&#039;utilisation des tabulations simplifie la vie de certains développeurs. De plus, l&#039;utilisation d&#039;espaces rend certaines fonctions d&#039;autoformatage défectueuses (comme sur certaines versions d&#039;Eclipse, lors de copier-coller).&lt;br /&gt;
**Note 1: Les règles suivantes sont particulièrement importantes :&lt;br /&gt;
***Les fichiers doivent être sauvés en format Unix (LF) et non Windows (CR/LF). Le format Unix étant compatible sur les OS Unix like, Windows, Mac, alors que le format fichier texte Windows pose problème sous certains PHP sous Unix.&lt;br /&gt;
***Les smart tags PHP ne sont pas utilisés. Les sections de code doivent commencer par &#039;&#039;&#039;&amp;lt;?php&#039;&#039;&#039;&lt;br /&gt;
**Note 2: Vous pouvez utiliser le fichier &#039;&#039;&#039;dev/setup/codesniffer/ruleset.xml&#039;&#039;&#039; comme fichier de contrôle pour vérifier votre style de code avec PHPCodeSniffer.&lt;br /&gt;
**Note 3: Vous pouvez utiliser le fichier &#039;&#039;&#039;dev/setup/eclipse/PSR-12 [built-in].xml&#039;&#039;&#039; comme fichier de règles de syntax pour configurer Eclipse.&lt;br /&gt;
**Note 4: Vous remarquerez que le code actuel ne suit pas forcément tout cela. La raison est historique. La règle fut instaurée en cours de route, aussi, si vous trouvez du code non respectueux de ce standard, n&#039;hésitez pas à le corriger.&lt;br /&gt;
&lt;br /&gt;
==Structures des classes et champs==&lt;br /&gt;
&lt;br /&gt;
Certaines propriétés de classes se retrouvent dans de nombreuses classes. Pour homogénéité, on utilisera les noms suivants:&lt;br /&gt;
{{TemplatePHPFields}}&lt;br /&gt;
&lt;br /&gt;
=Normes SQL=&lt;br /&gt;
&lt;br /&gt;
==Structure des tables et champs==&lt;br /&gt;
&lt;br /&gt;
*Toutes les tables sont préfixées pour éviter les conflits de nommage. Aujourd&#039;hui, le préfixe est modifiable au moment de l&#039;installation. Sa valeur par défaut est &amp;lt;tt&amp;gt;llx_&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*Structure des tables.&lt;br /&gt;
&lt;br /&gt;
Lorsque vous créez une table, il est recommandé de prendre les même conventions de nommages de tables que les autres tables Dolibarr. Avec, à minima les champs suivant:&lt;br /&gt;
 - rowid INTEGER AUTO_INCREMENT PRIMARY KEY    qui est l&#039;id technique&lt;br /&gt;
 - entity INTEGER default 1                    that is id for the multicompany feature&lt;br /&gt;
 - date_creation   datetime                    that is the creation date&lt;br /&gt;
 - tms             timestamp                   qui sera un champ contenant la date de chaque mise à jour (la base de donnée le gère tout seul, pas besoin de le gérer par le code)&lt;br /&gt;
 - import_key      varchar(32)                 qui contiendra le code d&#039;import YYYYMMDDHHMMSS si vous faites des imports en masse dans la table.&lt;br /&gt;
 - status          smallint                    pour stocker le status d&#039;un object&lt;br /&gt;
&lt;br /&gt;
Eventuellement&lt;br /&gt;
 - fk_user_creat  integer qui est l&#039;id du user de création (fk_user_author also found)&lt;br /&gt;
 - fk_user_modif  integer qui est l&#039;id du user de modification&lt;br /&gt;
 - fk_user_valid  integer qui est l&#039;id du user de validation&lt;br /&gt;
 - fk_soc integer qui est l&#039;id du tiers (si applicable)&lt;br /&gt;
&lt;br /&gt;
*Type des champs&lt;br /&gt;
&lt;br /&gt;
Dans la pratique, afin d&#039;etre compatible avec toutes les précisions des pays, syntaxes des bases, on utilisera uniquement les types suivants:&lt;br /&gt;
 - integer pour tout nombre entier, id ou clé étrangère (bigint éventuellement accepté pour les id des très grosses tables)&lt;br /&gt;
 - smallint pour tout numérique entier de petite taille (comme pour stocker un code de status)&lt;br /&gt;
 - double(24,8) pour tout montant&lt;br /&gt;
 - double(6,3) pour les taux de tva&lt;br /&gt;
 - real pour une quantité&lt;br /&gt;
 - varchar pour une chaine (y compris de longueur 1, le type char est de plus en plus déprécié)&lt;br /&gt;
 - timestamp pour un champ date+heure devant être mis a jour automatiquement&lt;br /&gt;
 - datetime pour un champ date+heure&lt;br /&gt;
 - date pour un champ date&lt;br /&gt;
&lt;br /&gt;
==Clé primaire==&lt;br /&gt;
La clé primaire d&#039;une table s&#039;appelle &amp;lt;tt&amp;gt;rowid&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Il y a quelques tables qui échappent à cette règle actuellement (ex [[Table llx_c_actioncomm]]), pour des raisons historiques. Une évolution pourra être étudiée pour une prochaine version.&lt;br /&gt;
&lt;br /&gt;
==Clés étrangères==&lt;br /&gt;
Le nom d&#039;une clé étrangère commence par le préfixe &amp;lt;tt&amp;gt;fk_&amp;lt;/tt&amp;gt; suivi du nom de la table liée (requis pour éviter doublons globales à la base, problématiques sous certains SGBD comme postgresql) puis du champ lié (pour permettre plusieurs clés étrangères différentes sur une même table).&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
fk_facture_fourn_fk_soc&lt;br /&gt;
&lt;br /&gt;
Note: Si vous développez votre propre module externe, il ne doit pas y avoir de clé étrangère depuis vos tables qui pointent sur les tables standards de Dolibarr. Ceci casserait les fonctionnalités de mise à jour, de réparation, de sauvegardes et de restauration.&lt;br /&gt;
&lt;br /&gt;
==Clés alternatives==&lt;br /&gt;
Parfois, il n&#039;y a pas que la clé primaire qui doit être unique. On peut donc ajouter aussi un index clé alternative unique. Un tel index est nommé par un nom qui commence par le préfixe &amp;lt;tt&amp;gt;uk_&amp;lt;/tt&amp;gt; suivi du nom de la table (requis pour éviter doublons d&#039;index globals à la base, problématiques sous certains SGBD comme postgresql) puis d&#039;un suffixe qui caractérise la clé (pour permettre plusieurs index uniques sur une même table).&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
uk_societe_code_client&lt;br /&gt;
&lt;br /&gt;
==Index performance==&lt;br /&gt;
Certains champs sont souvent utilisés comme critère de recherche, de tri ou de jointure. Il convient dans ce cas, d&#039;y mettre un index de performance. De tels indexes seront nommés avec un préfix &amp;lt;tt&amp;gt;idx_&amp;lt;/tt&amp;gt; puis le nom de la table et le nom du champ sur lequel porte l&#039;index.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
idx_societe_user_creat&lt;br /&gt;
&lt;br /&gt;
==Format de fichier DDL==&lt;br /&gt;
Les fichiers qui contiennent la définition de la structure de la base (DDL) doivent être au nombre de 2 par tables:&lt;br /&gt;
Chaque table est définie dans son propre fichier dont le nom est &amp;lt;tt&amp;gt;llx_&#039;&#039;matable&#039;&#039;.sql&amp;lt;/tt&amp;gt;. &lt;br /&gt;
On mettra un commentaire à côté de chaque champ pour en expliquer la signification.&lt;br /&gt;
Les clés étrangères et index de performance ou autres contraintes d&#039;unicité sont définies dans un fichier séparé dont le nom est &amp;lt;tt&amp;gt;llx_&#039;&#039;matable&#039;&#039;.key.sql&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ces fichiers sont placés dans le répertoire &#039;&#039;&#039;install/mysql/tables&#039;&#039;&#039; pour les fichiers standards ou &#039;&#039;&#039;monmodule/tables&#039;&#039;&#039; pour les tables amenées par un module.&lt;br /&gt;
&lt;br /&gt;
Exemple &#039;&#039;&#039;fichier table llx_matable.sql&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
-- Copyright (C) 2008 Author &amp;lt;email@author.com&amp;gt;&lt;br /&gt;
-- &lt;br /&gt;
-- This program is free software; you can redistribute it and/or modify&lt;br /&gt;
-- it under the terms of the GNU General Public License as published by&lt;br /&gt;
-- the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
-- (at your option) any later version.&lt;br /&gt;
--&lt;br /&gt;
-- This program is distributed in the hope that it will be useful,&lt;br /&gt;
-- but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
-- GNU General Public License for more details.&lt;br /&gt;
--&lt;br /&gt;
-- You should have received a copy of the GNU General Public License&lt;br /&gt;
-- along with this program. If not, see &amp;lt;http://www.gnu.org/licenses/&amp;gt;.&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
&lt;br /&gt;
create table llx_matable&lt;br /&gt;
(&lt;br /&gt;
  rowid       integer AUTO_INCREMENT PRIMARY KEY,&lt;br /&gt;
  field_one   integer,&lt;br /&gt;
  field_two   integer NOT NULL,&lt;br /&gt;
  fk_field    integer,&lt;br /&gt;
  field_date  datetime,&lt;br /&gt;
  tms         timestamp&lt;br /&gt;
)ENGINE=innodb;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Exemple &#039;&#039;&#039;fichier clés/index llx_matable.key.sql&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
-- Copyright (C) 2008 Author &amp;lt;email@author.com&amp;gt;&lt;br /&gt;
-- &lt;br /&gt;
-- This program is free software; you can redistribute it and/or modify&lt;br /&gt;
-- it under the terms of the GNU General Public License as published by&lt;br /&gt;
-- the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
-- (at your option) any later version.&lt;br /&gt;
--&lt;br /&gt;
-- This program is distributed in the hope that it will be useful,&lt;br /&gt;
-- but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
-- GNU General Public License for more details.&lt;br /&gt;
--&lt;br /&gt;
-- You should have received a copy of the GNU General Public License&lt;br /&gt;
-- along with this program. If not, see &amp;lt;http://www.gnu.org/licenses/&amp;gt;.&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE llx_matable ADD UNIQUE uk_matable_field(field_one, field_two);&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE llx_matable ADD CONSTRAINT fk_matable_fk_field FOREIGN KEY (fk_field) REFERENCES llx_matablepere (rowid);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Règles de codage SQL==&lt;br /&gt;
&lt;br /&gt;
*Utilisation des alias/nommage de champs&lt;br /&gt;
&lt;br /&gt;
Dans le cas des select on pourra utiliser les alias pour simplifier l&#039;écriture des requêtes:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
select chp1, chpxxx2 as chp2 from table2 as t1, table2 as t2 where t1.chpx = t2.chpy&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Toutefois, il ne faut pas utiliser ces alias sur des requêtes update car non compatible avec mysql 3.1.&lt;br /&gt;
&lt;br /&gt;
*Les SELECT * sont interdits ! Chaque SELECT doit spécifier la liste complète des champs à récupérer. Cela permet d&#039;éviter les confusions. Exemple:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
SELECT field_a, field_b, field_c FROM table_1 WHERE field_d = &#039;$id&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Dans les requêtes SQL, on quote les champs mais pas les numériques qui contiennent des montants destinés à être stockés dans des champs de type double ou real. Les quotes sur les numériques de type float provoquent parfois un stockage d&#039;une valeur différente. Par exemple 412.62 dans le insert sera en fait stocké avec la valeur 412.61999512 en base (suite à des conversions chaines-numériques implicites) si le champ est de type double(24,8). Et seul le PHP voit 412.61999512. Les autres outils verront 412.62 donnant l&#039;impression qu&#039;il n&#039;y a pas de problème. Et c&#039;est le PHP qui a raison, il y a problème en base. En supprimant les quotes sur les numériques, cela va mieux.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
Bon:     INSERT INTO table_1 (field_txt, field_num) VALUES (&#039;txt&#039;, 412.62)&lt;br /&gt;
Mauvais: INSERT INTO table_1 (field_txt, field_num) VALUES (&#039;txt&#039;, &#039;412.62&#039;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remarque, le problème des float est général et pas seulement sur les accès base, il est présent dans tous les languages quand on travaille sur des nombres réels, aussi ils doivent être, dès que affectés, nettoyés par la fonction price2num avec le 2eme paramètre renseigné à:&lt;br /&gt;
&#039;MU&#039; (si il s&#039;agit d&#039;un prix unitaire), &#039;MT&#039; (s&#039;il s&#039;agit d&#039;un prix total) ou &#039;MS&#039; (autres cas) selon le besoin.&lt;br /&gt;
Voir aussi le chapitre &amp;quot;Les nombres réels, montants et calculs&amp;quot; plus bas.&lt;br /&gt;
&lt;br /&gt;
*Les fonctions NOW, SYSDATE ou DATEDIFF sont interdites au sein des ordres SQL. S&#039;il faut saisir la date du moment dans un champ, la valeur doit venir du PHP, par exemple par la fonction dol_now(), et non du moteur de base de données. Ceci afin d&#039;avoir une meilleure portabilité du code mais surtout d&#039;avoir une gestion correcte des TimeZone et ne pas dépendre du TimeZone de la base de donnée.&lt;br /&gt;
&lt;br /&gt;
Par exemple, on ne fera pas:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where datefield = NOW()&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
mais:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where datefield = &#039;&amp;quot;.$this-&amp;gt;db-&amp;gt;idate(dol_now()).&amp;quot;&#039;&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Par exemple, on ne fera pas:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where DATEDIFF(table.datefield, NOW()) &amp;gt; 7&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
mais:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where datefield &amp;lt; &#039;&amp;quot;.$this-&amp;gt;db-&amp;gt;idate(dol_now() - (7 * 24 * 3600)).&amp;quot;&#039;&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un autre avantage de cette règle est que la requête peut bénéficier de l&#039;utilisation de l&#039;index puisqu&#039;on compare datefield à une valeur fixe. Dans le cas du datediff, on applique un traitement sur le champ avant comparaison, rendant impossible l&#039;utilisation de l&#039;index de ce champ. Les conséquences sont des performances très dégradées par rapport à la version sans datediff.&lt;br /&gt;
&lt;br /&gt;
==Règles de migration de base==&lt;br /&gt;
&lt;br /&gt;
*Les scripts de migration de structure sont les fichiers de type &#039;&#039;&#039;install/mysql/migration/a.b.c-x.y.z.sql&#039;&#039;&#039;. Dans un fichier de migration de n vers n+1, on ne détruit une table (DROP TABLE) qui n&#039;est plus utilisée en n+1 que lors de la migration de la version n+1 vers n+2. Ceci afin de toujours conserver les tables deprecated le temps d&#039;une version pour réparer une situation en cas d&#039;erreur de migration.&lt;br /&gt;
&lt;br /&gt;
==Spécificités MySQL==&lt;br /&gt;
&lt;br /&gt;
*Les tables doivent être au format InnoDB.&lt;br /&gt;
&lt;br /&gt;
En effet, ce format gère les clés étrangères, les éventuelles restrictions qui y sont attachées et la notion d&#039;intégrité de transactions requise pour avoir des données en base cohérente entre tables.&lt;br /&gt;
&lt;br /&gt;
*Dolibarr DOIT fonctionner même avec les options &#039;&#039;&#039;strict&#039;&#039;&#039; de Mysql active.&lt;br /&gt;
&lt;br /&gt;
Pour l&#039;activer (fortement recommandé en développement), ajouter la ligne suivante dans le fichier config du serveur Mysql (my.cnf ou my.ini)&lt;br /&gt;
{{MySqlStrictMode}}&lt;br /&gt;
&lt;br /&gt;
==Spécificités PostgreSQL==&lt;br /&gt;
Seuls les fichiers pour Mysql doivent être maintenus.&lt;br /&gt;
Les fichiers pour les autres bases sont convertis &amp;quot;à la volée&amp;quot; par le driver Dolibarr de la base.&lt;br /&gt;
&lt;br /&gt;
Il existe une exception.&lt;br /&gt;
Les requêtes &amp;quot;UPDATE FROM&amp;quot; : &lt;br /&gt;
Syntax MySQL :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
UPDATE table_taget as target, table_source as source SET fieldtarget=source.fieldsource&lt;br /&gt;
WHERE source.rowid=target.rowid;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Syntax PgSQL:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
UPDATE table_taget as target SET fieldtarget=source.fieldsource&lt;br /&gt;
FROM table_source as source WHERE source.rowid=target.rowid;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il n&#039;en existe pas dans Dolibarr, mais pour vos modules Vous devriez faire tel que :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
if ($this-&amp;gt;db-&amp;gt;type==&#039;pgsql&#039;) {&lt;br /&gt;
$sql=&amp;quot;UPDATE table_taget as target SET fieldtarget=source.fieldsource&lt;br /&gt;
FROM table_source as source WHERE source.rowid=target.rowid&amp;quot;;&lt;br /&gt;
} else {&lt;br /&gt;
$sql= &amp;quot;UPDATE table_taget as target, table_source as source SET fieldtarget=source.fieldsource&lt;br /&gt;
WHERE source.rowid=target.rowid&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Normes HTML=&lt;br /&gt;
&lt;br /&gt;
*Tous les attributs dans les balises HTML doivent être *en minuscule* et quotés avec des *doubles quote*.&lt;br /&gt;
&lt;br /&gt;
*Les liens href doivent être absolus en se basant sur la fonction dol_buildpath() pour obtenir un chemin absolu depuis un chemin relatif au répertoire htdocs. Pour les tags img, il faut faire appel à la fonction img_picto().&lt;br /&gt;
&lt;br /&gt;
Par example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print &#039;&amp;lt;a href=&amp;quot;&#039;.dol_buildpath(&#039;/monrep/mapage.php&#039;).&#039;&amp;quot;&amp;gt;&#039;.img_picto(&#039;Texte alt&#039;,&#039;nompictopng&#039;,&#039;&#039;).&#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les tables HTML doivent avoir des colonnes sans valeurs forcées, excepté pour les colonnes qui contiennent une information dont la longueur est non variable. Par exemple, une colonne avec un picto peut être forcée à with=&amp;quot;20px&amp;quot;. Dans les autres cas, il faut éviter de forcer la largeur des colonnes. La raison est que, dans la plupart des cas, le navigateur fait un meilleur travail pour définir automatiquement la bonne largeur des colonnes qu&#039;en forçant manuellement les largeurs. Et ceci marche quelque soit la résolution de l&#039;écran.&lt;br /&gt;
&lt;br /&gt;
*Le javascript/ajax et l&#039;appel aux scripts java dans les pages php est à proscrire. Si toutefois du code javascript est inclus, il doit être conditionné par le test sur &amp;quot;$conf-&amp;gt;use_javascript_ajax&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
if ($conf-&amp;gt;use_javascript_ajax) {&lt;br /&gt;
...  // Le code php qui génère du javascript est ici&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les popups windows ne doivent pas être utilisées, sauf pour des tooltips (et restent conditionnées par le point ci-dessus).&lt;br /&gt;
&lt;br /&gt;
*Les scripts externes sont écrits en Perl s&#039;ils ne peuvent l&#039;être en php, l&#039;utilisation d&#039;un autre langage n&#039;est pas interdit mais doit être discuté au préalable dans la mailing list des développeurs.&lt;br /&gt;
&lt;br /&gt;
=Normes Dolibarr et squelettes de code=&lt;br /&gt;
&lt;br /&gt;
==Squelettes de code==&lt;br /&gt;
Afin d&#039;uniformiser le code et d&#039;accélérer le développement de nouveaux composants dans Dolibarr, se trouvent dans le répertoire &#039;&#039;&#039;htdocs/modulebuilder/templates&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Pr exemple:&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de descripteur de module: &#039;&#039;&#039;myModule.class.php&#039;&#039;&#039;&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de code pour faire une nouvelle classe: &#039;&#039;&#039;skeleton_class.class.php&#039;&#039;&#039;&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de code pour faire une nouvelle page: &#039;&#039;&#039;skeleton_page.php&#039;&#039;&#039;&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de code pour faire un script à exécuter en ligne de commande: &#039;&#039;&#039;skeleton_script.php&#039;&#039;&#039;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
Servez-vous en comme exemple.&lt;br /&gt;
Notons que ces squelettes sont aussi utilisés par le générateur de code PHP ([[Module ModuleBuilder]]) qui est décrit dans la chapitre de développement de module Dolibarr pour accélérer vos développement.&lt;br /&gt;
&lt;br /&gt;
==Les dates et TimeZone==&lt;br /&gt;
Dolibarr se veut une application multi-utilisateur et multi-localisation. Il convient donc de stocker les dates dans le bon format. Pour éviter les problèmes de conversion, les règles suivantes doivent être appliquées:&lt;br /&gt;
&lt;br /&gt;
*Une date en mémoire doit être au format Timestamp GMT.&lt;br /&gt;
*Une date stockée en base de données contient le Timestamp issue de la date soumise dans la requête en heure &amp;lt;b&amp;gt;locale du serveur PHP&amp;lt;/b&amp;gt;. Cela ne concerne pas les dates mises à jour automatiquement par la base (champ &#039;&#039;&#039;tms&#039;&#039;&#039; en base).&lt;br /&gt;
&lt;br /&gt;
Ainsi le 1er janvier 1970, 3 heures à Paris (TZ=+1) = 1er janvier 1970, 2 heures à Greenwich (TZ=0) sera stocké en mémoire par 7200 et sera soumis à la base de données avec la chaine &#039;19700101030000&#039; (PHP convertit en heure de son TZ et la base déconvertit avec son TZ qui est le même que celui de PHP).&lt;br /&gt;
&lt;br /&gt;
Les méthodes select doivent donc traduire les champs dates lus qui sont au format chaine TZ de la base (&#039;19700101030000&#039;) par appel de la méthode db-&amp;gt;jdate afin de récupérer une information en mémoire au format Timestamp GMT. Et les méthodes insert doivent lors de la génération de la requête convertir la date mémoire connue en variable, par la méthode db-&amp;gt;idate (Voir exemples générés par le squelette).&lt;br /&gt;
&lt;br /&gt;
*Les dates mises à jour automatiquement par la base (champ &#039;&#039;&#039;tms&#039;&#039;&#039; en base) contiennent le Timestamp où la modification est faite selon le timezone de la base de donnée. Les méthodes select récupèrent cette donnée en mémoire au format Timestamp GMT en appliquant également le db-&amp;gt;jdate. Si le timezone de la base de donnée diffère de celui du PHP (un des 2 est mal réglé), il peut donc y avoir des écarts entre date de création et modification.&lt;br /&gt;
&lt;br /&gt;
*La manipulation de dates en PHP doit être faite en utilisant les fonctions dates de Dolibarr: &#039;&#039;&#039;dol_now(), dol_mktime(), dol_stringtotime(), dol_getdate(), dol_time_plus_duree()&#039;&#039;&#039;. Vous trouverez également d&#039;autres fonctions prêtes à l&#039;emploi dans le fichier &#039;&#039;&#039;date.lib.php&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==L&#039;encodage UTF8/ISO==&lt;br /&gt;
Dolibarr stocke les informations de manière suivante:&lt;br /&gt;
&lt;br /&gt;
*En base de donnée, les données sont en UTF8 ou ISO. Cela dépend du pagecode de la base, donc des options à la création de cette base. Dans tous les cas le driver d&#039;accès base Dolibarr (dans /lib/database) s&#039;arrange à la lecture et insertion pour convertir vers et depuis de l&#039;UTF8.&lt;br /&gt;
*Les données en mémoires sont donc stockées en UTF8 (instances d&#039;objets PHP).&lt;br /&gt;
*Les pages web affichées à l&#039;écran sont au format UTF8&lt;br /&gt;
&lt;br /&gt;
==Les nombres réels, montants et calculs==&lt;br /&gt;
En PHP comme dans d&#039;autres langages (Java par exemple), les données non entières (float, real, double) ne sont pas fiables.&lt;br /&gt;
Essayer de faire par exemple &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print 239.2 - 229.3 - 9.9;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Vous n&#039;obtiendrez pas zéro mais un nombre très petit en puissance de 10 négative. Si vous obtenez zéro, vous pourrez trouvez d&#039;autres exemples qui ne fonctionnent pas.&lt;br /&gt;
Le problème des float est général, une variable résultante de calcul de nombre réels doit SYSTEMATIQUEMENT être nettoyée par la fonction &#039;&#039;&#039;price2num()&#039;&#039;&#039; avec le 2eme paramètre renseigné à: &#039;MU&#039;, &#039;MT&#039; ou &#039;MS&#039; selon le besoin (voir doc fonction).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print price2num(239.2 - 229.3 - 9.9, &#039;MT&#039;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
S&#039;il ne s&#039;agit pas d&#039;un prix sur lequel s&#039;adapte les paramètres MU, MT ou MS, il faut utiliser la fonction &#039;&#039;&#039;round()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==Création de tables==&lt;br /&gt;
Ne pas créer de table à l&#039;utilisation, c&#039;est-à-dire à la &#039;&#039;&#039;première utilisation&#039;&#039;&#039; du module.&lt;br /&gt;
Si vous créez un module qui utilise des tables qui ne sont pas intégrées en standard dans le code de Dolibarr, veillez à suivre le didacticiel [[Développement module]] qui explique comment joindre des tables qui se créent à l&#039;activation du module et non à son utilisation (voir plus haut).&lt;br /&gt;
&lt;br /&gt;
==Comparer la version==&lt;br /&gt;
&lt;br /&gt;
Si votre code a besoin de faire des choses différentes selon la version de Dolibarr, vous pouvez utiliser le truc suivant pour comparer les versions&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$version=preg_split(&#039;/[\.-]/&#039;,DOL_VERSION);&lt;br /&gt;
if (versioncompare($version,array(5,0,-4)) &amp;gt;= 0) { //mycode for 5.0 only; }	// For dolibarr 5.0.* (the -4 means we include also alpha, beta, rc and rcX)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais cette solution requiert de faire un include avoir la fonction versioncompare. Une alternative est d&#039;utiliser le test suivant:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
if ((float) DOL_VERSION &amp;gt;= 5.0) { //mycode for 5.0 only; }	// For dolibarr 5.0.*&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Logs==&lt;br /&gt;
Ajouter des traces dans votre code avec la fonction&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
dol_syslog($yourmessage, LOG_INFO|LOG_DEBUG|LOG_WARNING|LOG_ERR);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Répertoires de travail==&lt;br /&gt;
Si vous avez besoin de créer un répertoire de travail, dans votre code, faites référence à ce répertoire par&lt;br /&gt;
&#039;&#039;&#039;DOL_DATA_ROOT.&#039;/monmodule&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Le répertoire peut être créé dans votre code à l&#039;exécution par le code suivant:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$mymoduledir=DOL_DATA_ROOT.&#039;/monmodule&#039;;&lt;br /&gt;
dol_mkdir($mymoduledir);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si vous avez besoin d&#039;un répertoire qui contiendra des données temporaires, ce répertoire doit être&#039;&#039;&#039; DOL_DATA_ROOT.&#039;/monmodule/temp&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Design patterns et programmation objet=&lt;br /&gt;
&lt;br /&gt;
==Design patterns de Création (GoF)==&lt;br /&gt;
Design patterns définis par le Gang Of Four (voir la wikipédia sur les [[wikipedia:Patron de conception|Design patterns]]).&lt;br /&gt;
Dans Dolibarr, pas de mise en oeuvre de design patterns de comportement particulier.&lt;br /&gt;
On trouve des objets proches des Singletons et Fabriques conforme à 100% dans l&#039;esprit mais pas dans la syntaxe, ceci afin d’être compatible avec la plus large plage possible de versions de PHP.&lt;br /&gt;
&lt;br /&gt;
==Design patterns d&#039;entreprises (Martin Fowler)==&lt;br /&gt;
&lt;br /&gt;
===Mode d&#039;organisation du code===&lt;br /&gt;
[[wikipedia:Martin_Fowler|Martin Fowler]] a identifié 3 méthodes d&#039;organisation du code appelées &#039;&#039;&#039;patterns&#039;&#039;&#039; (&#039;&#039;&#039;motifs&#039;&#039;&#039;):&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Transaction Script&#039;&#039;&#039; (Le code est linéaire en fonction d&#039;une action utilisateur).&lt;br /&gt;
&lt;br /&gt;
C&#039;est le motif à l&#039;ancienne utilisé dans les langages procéduraux.&lt;br /&gt;
Inconvénient: Redondance du code. Nécessité de connaitre le modèle physique pour développer les parties métiers.&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Domain Model&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
C&#039;est un concept possible depuis les langages objets. Ce sont les procédures métiers (qui doivent être identifiés avant) qui servent de bases pour les classes objets.&lt;br /&gt;
Inconvénient: Motif complexe à maintenir.&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Table Module&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Un intermédiaire entre les 2 précédents où l&#039;on a une instance unique de classe par table de la base de données.&lt;br /&gt;
&lt;br /&gt;
-&amp;gt; Comme le montre les squelettes de code (voir point précédent), Dolibarr se base sur le principe du &#039;&#039;&#039;Table Module&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===Communication Logique métier - Données (ORM)===&lt;br /&gt;
Il existe 3 modes de liaisons:&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Table And Row Data Gateway&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
C&#039;est le plus simple. On crée une classe par table et chaque classe est un pont avec la table correspondante et propose les méthodes CRUD sur cette table (Create, Read, Update, Delete). Une instance de classe étant alors un enregistrement de la table. La classe ne contient que du code d&#039;accès aux lignes ou colonnes de tables. Le code métier doit alors être ajouté dans d&#039;autres classes. Les liens entre ces classes tables et les classes métiers devant être connues ou déduite de la connaissance du développeur.&lt;br /&gt;
&lt;br /&gt;
Exemple: C&#039;est le mode mis en oeuvre quand on utilise certains Frameworks d&#039;ORM comme &#039;&#039;&#039;iBatis&#039;&#039;&#039; (http://ibatis.apache.org/).&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Active Record&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Identique au précédent, mais on se permet d&#039;ajouter quelques fonctions métiers sur la classe, à conditions que ces fonctions soient bien  propres à la table ou à la notion métier porté par l&#039;enregistrement. C&#039;est le pattern qui offre le meilleur rapport fonctionnalité/complexité.&lt;br /&gt;
&lt;br /&gt;
Exemple: C&#039;est le mode choisi pour les développements Dolibarr et de nombreuses autres applications PHP qui ont leur propre framework et pratiques de développements.&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Data Mapper&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Les classes représentent les entités du problème et non les données. Il faut donc doubler, tripler... ces classes avec des classes Mapper pour accéder aux données.&lt;br /&gt;
Plus &amp;quot;puriste&amp;quot; sur le papier car plus proche du métier, ce mode a aussi l&#039;inconvénient d&#039;être très complexe et difficile à maintenir dans la réalité (l&#039;expérience pratique constaté ne rejoignant pas les promesses de la théorie).&lt;br /&gt;
&lt;br /&gt;
Exemple: C&#039;est le choix si on utilise le Framework d&#039;ORM &#039;&#039;&#039;Propel&#039;&#039;&#039; (http://propel.phpdb.org/trac/). On le trouve donc sur des applications plus lourdes basées sur cet ORM entre autres.&lt;br /&gt;
&lt;br /&gt;
-&amp;gt; Pour les développements Dolibarr, il est recommandé d&#039;utiliser le mode de liaison &#039;&#039;&#039;Active Record&#039;&#039;&#039; qui offre les avantages d&#039;un modèle proche du métier sans en avoir la complexité et sans trop masquer non plus la technique. C&#039;est dans ce mode que le développement, la compréhension du code et la maintenance technique et/ou fonctionnelle semble la plus productive (ceci est toutefois un éternel débat entre les puristes et les pragmatiques, débat dans lequel personne ne peut vraiment avoir raison, car tout dépend des objectifs à atteindre).&lt;br /&gt;
&lt;br /&gt;
==Design Pattern d&#039;Interface Graphique (MVC)==&lt;br /&gt;
Il existe plusieurs design pattern pour les interfaces utilisateurs (MVC, MVP, MVVM).&lt;br /&gt;
Beaucoup confonde ce design pattern avec celui consistant à utiliser un framework de templates. C&#039;est sans rapport. Un framework de template (voir point précédent) n&#039;est en lien qu&#039;avec la partie &amp;quot;V&amp;quot; de ces modèles.&lt;br /&gt;
&lt;br /&gt;
-&amp;gt; Dolibarr utilise le Design Pattern &#039;&#039;&#039;MVC&#039;&#039;&#039;. La partie M est matérialisée par une classe DAO contenant les méthode CRUD (Create-Read-Update-Delete) d&#039;accès à la table.&lt;br /&gt;
Beaucoup de frameworks ont fait le choix de mettre la partie de code C (Controller) et la partie de code du V (vue) dans des fichiers, voir même répertoires séparés. La maintenance semble plus aisé sur la papier, en pratique, il faut sans arrêt jonglé entre n fichiers, le C étant fortement lié au V. Aussi dans Dolibarr, la séparation est faite par une simple section de commentaire. La partie de code C (Controller) est donc le code qui se trouve sont la balise&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * Actions&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Elle est suivi par la partie de code V (Vue), bien séparé du C par la balise&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * View&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce mode de séparation a eu un effet neutre sur les nouveaux développement mais a permis de réduire de manière si importante le temps requis pour la maintenance et correction de bugs qu&#039;il n&#039;est pas envisagé de basculer vers un autre type de séparation (oui les constats fait dans la vraie vie ne sont pas toujours ceux attendus par la théorie scolaire). L&#039;important reste qu&#039;il y ait toujours séparation entre le C et le V, peut importe comment est matérialisé cette séparation, du moment qu&#039;elle l&#039;est (Rappel: Ne pas confondre la notion de séparation du C et du V avec la notion de séparation du code pour alimenter la données d&#039;une Vue et du code pour formater la Vue, ceci un principe de séparation relevant du Design Pattern de Vue, voir point suivant).&lt;br /&gt;
&lt;br /&gt;
==Design Pattern de Vue - Présentation==&lt;br /&gt;
Il existe des frameworks spécialisés dans le Design Pattern de Vue, la partie qui consiste à formater l&#039;écran vue par l&#039;utilisateur.&lt;br /&gt;
Les vieilles versions de Dolibarr utilisaient Smarty. Ce framework est une surcouche à un Framework, déjà très puissant, de formatage d&#039;écran nommé... PHP. Les bénéfices étant très inférieurs aux inconvénients, il a été abandonné au profit de templates PHP (fichier .tpl.php) qui restent le plus simple, le plus universel, le plus évolutif et le plus performant, des frameworks de présentation. &lt;br /&gt;
&lt;br /&gt;
Son seul défaut est qu&#039;il ne peut garantir à 100% les écarts d&#039;un développeur qui irait intégrer dans la Vue, une logique sans rapport avec la présentation (donc autre que du code à vocation de génération, de formatage, de sortie HTML, de logique de test ou de boucle). Ce point est toutefois contrôlé par le mécanisme de validation du code des chefs de projets.&lt;br /&gt;
&lt;br /&gt;
La encore, c&#039;est l&#039;expérience et le constat &amp;quot;sur le terrain&amp;quot; d&#039;un meilleur rendement de productivité qui a motivé l&#039;abandon des frameworks de Présentation externes au profit du framework PHP.&lt;/div&gt;</summary>
		<author><name>Quentic</name></author>
	</entry>
	<entry>
		<id>https://wiki.dolibarr.org/index.php?title=Langages_et_normes&amp;diff=52111</id>
		<title>Langages et normes</title>
		<link rel="alternate" type="text/html" href="https://wiki.dolibarr.org/index.php?title=Langages_et_normes&amp;diff=52111"/>
		<updated>2021-09-30T08:27:13Z</updated>

		<summary type="html">&lt;p&gt;Quentic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- BEGIN interlang links --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Do NOT edit this section&lt;br /&gt;
     Links below are automatically managed by PolyglotBot&lt;br /&gt;
     You can edit links on the English source page : Language_and_development_rules --&amp;gt;&lt;br /&gt;
[[en:Language_and_development_rules]]&lt;br /&gt;
[[de:Sprachen_und_Programmierregeln]]&lt;br /&gt;
[[es:Lenguaje_y_Normas_de_Desarrollo]]&lt;br /&gt;
[[zh:语言和开发规则]]&lt;br /&gt;
&amp;lt;!-- END interlang links --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{TemplateDocDev}}&lt;br /&gt;
&lt;br /&gt;
Voici les quelques règles sur le langage, la syntaxe et normes de développement en vigueur pour le projet Dolibarr :&lt;br /&gt;
&lt;br /&gt;
=Versions=&lt;br /&gt;
&lt;br /&gt;
*Dolibarr doit fonctionner sur:&lt;br /&gt;
&lt;br /&gt;
#Tous OS (Windows, Linux, MACOS...)&lt;br /&gt;
#PHP {{PHPMinVersion}} (Doit fonctionner sans aucun module PHP complémentaire hors les modules d&#039;accès base de donnée).&lt;br /&gt;
#Mysql {{MySqlMinVersion}}&lt;br /&gt;
&lt;br /&gt;
=Normes Copyright=&lt;br /&gt;
&lt;br /&gt;
*Tout fichier PHP doit avoir un en-tête selon le masque suivant&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
/* Copyright (C) YYYY John Doe  &amp;lt;email@email.com&amp;gt;&lt;br /&gt;
 *&lt;br /&gt;
 * Licence information&lt;br /&gt;
 */&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Quand vous éditez un fichier existant du projet, ajouter une ligne Copyright sous celles existantes.&lt;br /&gt;
&lt;br /&gt;
=Normes PHP=&lt;br /&gt;
&lt;br /&gt;
==PHP==&lt;br /&gt;
&lt;br /&gt;
*Dolibarr est écrit en PHP et supporte toutes versions PHP supérieures à la {{PHPMinVersion}}. Les fichiers doivent tous comporter l&#039;extension .php&lt;br /&gt;
&lt;br /&gt;
*L&#039;appel aux variables superglobales PHP doit passer par les opérateurs dédiés $_COOKIES, $_SERVER, $_ENV. Mais pour récupérer les contenus de $_GET ou $_POST, il faut passer par la fonction dolibarr [[Fonctions utiles Dolibarr|GETPOST()]] .&lt;br /&gt;
&lt;br /&gt;
Les autres opérateurs ($HTTP_SERVER_GET, ...) ayant été passés en deprecated au sein de PHP, ne doivent plus être utilisés. Ainsi le code doit fonctionner y compris quand l&#039;option &#039;&#039;&#039;register_long_arrays&#039;&#039;&#039; est à off.&lt;br /&gt;
De plus, le code doit fonctionner aussi bien quand l&#039;option PHP &#039;&#039;&#039;register_globals&#039;&#039;&#039; est à off (recommandé par PHP)  que quand l&#039;option &#039;&#039;&#039;register_globals&#039;&#039;&#039; est à on (par défaut sur de nombreuses installations).&lt;br /&gt;
&lt;br /&gt;
*Pas d&#039;utilisation de la variable &#039;&#039;&#039;PHP_SELF&#039;&#039;&#039;. Utiliser à la place $_SERVER[&amp;quot;PHP_SELF&amp;quot;]. Notez aussi que le framework Dolibarr passe une routine pour rendre plus sûr le contenu du $_SERVER[&amp;quot;PHP_SELF&amp;quot;] (dans le fichier main.inc.php, donc avant tout traitement métier)&lt;br /&gt;
&lt;br /&gt;
*Quand plusieurs variables doivent être initialisées avec la même valeur, il faut utiliser plusieurs instructions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$var1 = 1; $var2 = 1; $var3 = 1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
plutôt que&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$var1 = $var2 = $var3 = 1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
qui est moins performant.&lt;br /&gt;
&lt;br /&gt;
*Les chaines doivent avoir les variables sorties de la chaine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print &amp;quot;Mon texte affiche ma &amp;quot;.$variable.&amp;quot; !\n&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les commentaires doivent suivre la syntaxe C, ie un double antislash pour un commentaire d&#039;une ligne et utilisation slash-étoile pour ouvrir un bloc de plusieurs lignes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
/* Bloc de commentaire&lt;br /&gt;
 *&lt;br /&gt;
 * Fin du bloc&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
$monobjet = new MonObjet($db);&lt;br /&gt;
$result=$monobjet-&amp;gt;fetch($idobject);&lt;br /&gt;
&lt;br /&gt;
for ($i = 1 , $i &amp;lt; 2 ; $i++)&lt;br /&gt;
{&lt;br /&gt;
  // commentaire sur une ligne&lt;br /&gt;
  print $i;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les fonctions doivent retourner une valeur strictement &amp;gt; à 0 en cas de succès, et un nombre &amp;lt; à 0 en cas d&#039;erreur.&lt;br /&gt;
&lt;br /&gt;
*Pas de code mort (non utilisé) dans le code principal de Dolibarr (le code utilisé uniquement par un module externe doit être inclus dans le module externe).&lt;br /&gt;
&lt;br /&gt;
*Utiliser &amp;quot;include_once&amp;quot; pour l&#039;inclusion de tout fichier contenant des définitions de fonction ou de classes (donc fichiers *.class.php et *.lib.php), utiliser &amp;quot;include&amp;quot; pour tout inclusion de fichier de type template ou contenant un mixte de HTML et PHP (donc fichiers *.inc.php et *.tpl.php).&lt;br /&gt;
&lt;br /&gt;
*Le style de code a utiliser est le PSR-12 (https://www.php-fig.org/psr/psr-12/). Seules les règles &amp;quot;MUST&amp;quot; sont imposées. Notez aussi les points/exceptions suivants:&lt;br /&gt;
**La longueur des lignes: PSR-12 indique que la longueur des lignes a une limite &amp;quot;soft&amp;quot; à 120. Il est en effet préférable d&#039;avoir de longues lignes de données de déclaration plutôt que de longues pages car ce code ne contient aucune logique intéressante ou utile, toutefois une limite &amp;quot;hard&amp;quot; a été instauré à &#039;&#039;&#039;1000&#039;&#039;&#039; caractères. Du code qui ira au delà provoquera des erreurs dans la plateforme d&#039;Intégration Continue.&lt;br /&gt;
**Les tabulations sont acceptées: L&#039;autre exception est qu&#039;on ne remplace pas les tabulations systématiquement par des espaces. L&#039;utilisation des tabulations simplifie la vie de certains développeurs. De plus, l&#039;utilisation d&#039;espaces rend certaines fonctions d&#039;autoformatage défectueuses (comme sur certaines versions d&#039;Eclipse, lors de copié-collé).&lt;br /&gt;
**Note 1: Les règles suivantes sont particulièrement importantes:&lt;br /&gt;
***Les fichiers doivent être sauvés en format Unix (LF) et non Windows (CR/LF). Le format Unix étant compatible sur les OS Unix like, Windows, Mac, alors que le format fichier texte Windows pose problème sous certains PHP sous Unix.&lt;br /&gt;
***Les smart tags PHP ne sont pas utilisés. Les sections de code doivent commencer par &#039;&#039;&#039;&amp;lt;?php&#039;&#039;&#039;&lt;br /&gt;
**Note 2: Vous pouvez utiliser le fichier &#039;&#039;&#039;dev/setup/codesniffer/ruleset.xml&#039;&#039;&#039; comme fichier de contrôle pour vérifier votre style de code avec PHPCodeSniffer.&lt;br /&gt;
**Note 3: Vous pouvez utiliser le fichier &#039;&#039;&#039;dev/setup/eclipse/PSR-12 [built-in].xml&#039;&#039;&#039; comme fichier de règles de syntax pour configurer Eclipse.&lt;br /&gt;
**Note 4: Vous remarquerez que le code actuel ne suit pas forcément tout cela. La raison est historique. La règle fut instaurée en cours de route, aussi, si vous trouvez du code non respectueux de ce standard, n&#039;hésitez pas à le corriger.&lt;br /&gt;
&lt;br /&gt;
==Structures des classes et champs==&lt;br /&gt;
&lt;br /&gt;
Certaines propriétés de classes se retrouvent dans de nombreuses classes. Pour homogénéité, on utilisera les noms suivants:&lt;br /&gt;
{{TemplatePHPFields}}&lt;br /&gt;
&lt;br /&gt;
=Normes SQL=&lt;br /&gt;
&lt;br /&gt;
==Structure des tables et champs==&lt;br /&gt;
&lt;br /&gt;
*Toutes les tables sont préfixées pour éviter les conflits de nommage. Aujourd&#039;hui, le préfixe est modifiable au moment de l&#039;installation. Sa valeur par défaut est &amp;lt;tt&amp;gt;llx_&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*Structure des tables.&lt;br /&gt;
&lt;br /&gt;
Lorsque vous créez une table, il est recommandé de prendre les même conventions de nommages de tables que les autres tables Dolibarr. Avec, à minima les champs suivant:&lt;br /&gt;
 - rowid INTEGER AUTO_INCREMENT PRIMARY KEY    qui est l&#039;id technique&lt;br /&gt;
 - entity INTEGER default 1                    that is id for the multicompany feature&lt;br /&gt;
 - date_creation   datetime                    that is the creation date&lt;br /&gt;
 - tms             timestamp                   qui sera un champ contenant la date de chaque mise à jour (la base de donnée le gère tout seul, pas besoin de le gérer par le code)&lt;br /&gt;
 - import_key      varchar(32)                 qui contiendra le code d&#039;import YYYYMMDDHHMMSS si vous faites des imports en masse dans la table.&lt;br /&gt;
 - status          smallint                    pour stocker le status d&#039;un object&lt;br /&gt;
&lt;br /&gt;
Eventuellement&lt;br /&gt;
 - fk_user_creat  integer qui est l&#039;id du user de création (fk_user_author also found)&lt;br /&gt;
 - fk_user_modif  integer qui est l&#039;id du user de modification&lt;br /&gt;
 - fk_user_valid  integer qui est l&#039;id du user de validation&lt;br /&gt;
 - fk_soc integer qui est l&#039;id du tiers (si applicable)&lt;br /&gt;
&lt;br /&gt;
*Type des champs&lt;br /&gt;
&lt;br /&gt;
Dans la pratique, afin d&#039;etre compatible avec toutes les précisions des pays, syntaxes des bases, on utilisera uniquement les types suivants:&lt;br /&gt;
 - integer pour tout nombre entier, id ou clé étrangère (bigint éventuellement accepté pour les id des très grosses tables)&lt;br /&gt;
 - smallint pour tout numérique entier de petite taille (comme pour stocker un code de status)&lt;br /&gt;
 - double(24,8) pour tout montant&lt;br /&gt;
 - double(6,3) pour les taux de tva&lt;br /&gt;
 - real pour une quantité&lt;br /&gt;
 - varchar pour une chaine (y compris de longueur 1, le type char est de plus en plus déprécié)&lt;br /&gt;
 - timestamp pour un champ date+heure devant être mis a jour automatiquement&lt;br /&gt;
 - datetime pour un champ date+heure&lt;br /&gt;
 - date pour un champ date&lt;br /&gt;
&lt;br /&gt;
==Clé primaire==&lt;br /&gt;
La clé primaire d&#039;une table s&#039;appelle &amp;lt;tt&amp;gt;rowid&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Il y a quelques tables qui échappent à cette règle actuellement (ex [[Table llx_c_actioncomm]]), pour des raisons historiques. Une évolution pourra être étudiée pour une prochaine version.&lt;br /&gt;
&lt;br /&gt;
==Clés étrangères==&lt;br /&gt;
Le nom d&#039;une clé étrangère commence par le préfixe &amp;lt;tt&amp;gt;fk_&amp;lt;/tt&amp;gt; suivi du nom de la table liée (requis pour éviter doublons globales à la base, problématiques sous certains SGBD comme postgresql) puis du champ lié (pour permettre plusieurs clés étrangères différentes sur une même table).&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
fk_facture_fourn_fk_soc&lt;br /&gt;
&lt;br /&gt;
Note: Si vous développez votre propre module externe, il ne doit pas y avoir de clé étrangère depuis vos tables qui pointent sur les tables standards de Dolibarr. Ceci casserait les fonctionnalités de mise à jour, de réparation, de sauvegardes et de restauration.&lt;br /&gt;
&lt;br /&gt;
==Clés alternatives==&lt;br /&gt;
Parfois, il n&#039;y a pas que la clé primaire qui doit être unique. On peut donc ajouter aussi un index clé alternative unique. Un tel index est nommé par un nom qui commence par le préfixe &amp;lt;tt&amp;gt;uk_&amp;lt;/tt&amp;gt; suivi du nom de la table (requis pour éviter doublons d&#039;index globals à la base, problématiques sous certains SGBD comme postgresql) puis d&#039;un suffixe qui caractérise la clé (pour permettre plusieurs index uniques sur une même table).&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
uk_societe_code_client&lt;br /&gt;
&lt;br /&gt;
==Index performance==&lt;br /&gt;
Certains champs sont souvent utilisés comme critère de recherche, de tri ou de jointure. Il convient dans ce cas, d&#039;y mettre un index de performance. De tels indexes seront nommés avec un préfix &amp;lt;tt&amp;gt;idx_&amp;lt;/tt&amp;gt; puis le nom de la table et le nom du champ sur lequel porte l&#039;index.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
idx_societe_user_creat&lt;br /&gt;
&lt;br /&gt;
==Format de fichier DDL==&lt;br /&gt;
Les fichiers qui contiennent la définition de la structure de la base (DDL) doivent être au nombre de 2 par tables:&lt;br /&gt;
Chaque table est définie dans son propre fichier dont le nom est &amp;lt;tt&amp;gt;llx_&#039;&#039;matable&#039;&#039;.sql&amp;lt;/tt&amp;gt;. &lt;br /&gt;
On mettra un commentaire à côté de chaque champ pour en expliquer la signification.&lt;br /&gt;
Les clés étrangères et index de performance ou autres contraintes d&#039;unicité sont définies dans un fichier séparé dont le nom est &amp;lt;tt&amp;gt;llx_&#039;&#039;matable&#039;&#039;.key.sql&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ces fichiers sont placés dans le répertoire &#039;&#039;&#039;install/mysql/tables&#039;&#039;&#039; pour les fichiers standards ou &#039;&#039;&#039;monmodule/tables&#039;&#039;&#039; pour les tables amenées par un module.&lt;br /&gt;
&lt;br /&gt;
Exemple &#039;&#039;&#039;fichier table llx_matable.sql&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
-- Copyright (C) 2008 Author &amp;lt;email@author.com&amp;gt;&lt;br /&gt;
-- &lt;br /&gt;
-- This program is free software; you can redistribute it and/or modify&lt;br /&gt;
-- it under the terms of the GNU General Public License as published by&lt;br /&gt;
-- the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
-- (at your option) any later version.&lt;br /&gt;
--&lt;br /&gt;
-- This program is distributed in the hope that it will be useful,&lt;br /&gt;
-- but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
-- GNU General Public License for more details.&lt;br /&gt;
--&lt;br /&gt;
-- You should have received a copy of the GNU General Public License&lt;br /&gt;
-- along with this program. If not, see &amp;lt;http://www.gnu.org/licenses/&amp;gt;.&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
&lt;br /&gt;
create table llx_matable&lt;br /&gt;
(&lt;br /&gt;
  rowid       integer AUTO_INCREMENT PRIMARY KEY,&lt;br /&gt;
  field_one   integer,&lt;br /&gt;
  field_two   integer NOT NULL,&lt;br /&gt;
  fk_field    integer,&lt;br /&gt;
  field_date  datetime,&lt;br /&gt;
  tms         timestamp&lt;br /&gt;
)ENGINE=innodb;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Exemple &#039;&#039;&#039;fichier clés/index llx_matable.key.sql&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
-- Copyright (C) 2008 Author &amp;lt;email@author.com&amp;gt;&lt;br /&gt;
-- &lt;br /&gt;
-- This program is free software; you can redistribute it and/or modify&lt;br /&gt;
-- it under the terms of the GNU General Public License as published by&lt;br /&gt;
-- the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
-- (at your option) any later version.&lt;br /&gt;
--&lt;br /&gt;
-- This program is distributed in the hope that it will be useful,&lt;br /&gt;
-- but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
-- GNU General Public License for more details.&lt;br /&gt;
--&lt;br /&gt;
-- You should have received a copy of the GNU General Public License&lt;br /&gt;
-- along with this program. If not, see &amp;lt;http://www.gnu.org/licenses/&amp;gt;.&lt;br /&gt;
-- ===========================================================================&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE llx_matable ADD UNIQUE uk_matable_field(field_one, field_two);&lt;br /&gt;
&lt;br /&gt;
ALTER TABLE llx_matable ADD CONSTRAINT fk_matable_fk_field FOREIGN KEY (fk_field) REFERENCES llx_matablepere (rowid);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Règles de codage SQL==&lt;br /&gt;
&lt;br /&gt;
*Utilisation des alias/nommage de champs&lt;br /&gt;
&lt;br /&gt;
Dans le cas des select on pourra utiliser les alias pour simplifier l&#039;écriture des requêtes:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
select chp1, chpxxx2 as chp2 from table2 as t1, table2 as t2 where t1.chpx = t2.chpy&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Toutefois, il ne faut pas utiliser ces alias sur des requêtes update car non compatible avec mysql 3.1.&lt;br /&gt;
&lt;br /&gt;
*Les SELECT * sont interdits ! Chaque SELECT doit spécifier la liste complète des champs à récupérer. Cela permet d&#039;éviter les confusions. Exemple:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
SELECT field_a, field_b, field_c FROM table_1 WHERE field_d = &#039;$id&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Dans les requêtes SQL, on quote les champs mais pas les numériques qui contiennent des montants destinés à être stockés dans des champs de type double ou real. Les quotes sur les numériques de type float provoquent parfois un stockage d&#039;une valeur différente. Par exemple 412.62 dans le insert sera en fait stocké avec la valeur 412.61999512 en base (suite à des conversions chaines-numériques implicites) si le champ est de type double(24,8). Et seul le PHP voit 412.61999512. Les autres outils verront 412.62 donnant l&#039;impression qu&#039;il n&#039;y a pas de problème. Et c&#039;est le PHP qui a raison, il y a problème en base. En supprimant les quotes sur les numériques, cela va mieux.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
Bon:     INSERT INTO table_1 (field_txt, field_num) VALUES (&#039;txt&#039;, 412.62)&lt;br /&gt;
Mauvais: INSERT INTO table_1 (field_txt, field_num) VALUES (&#039;txt&#039;, &#039;412.62&#039;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remarque, le problème des float est général et pas seulement sur les accès base, il est présent dans tous les languages quand on travaille sur des nombres réels, aussi ils doivent être, dès que affectés, nettoyés par la fonction price2num avec le 2eme paramètre renseigné à:&lt;br /&gt;
&#039;MU&#039; (si il s&#039;agit d&#039;un prix unitaire), &#039;MT&#039; (s&#039;il s&#039;agit d&#039;un prix total) ou &#039;MS&#039; (autres cas) selon le besoin.&lt;br /&gt;
Voir aussi le chapitre &amp;quot;Les nombres réels, montants et calculs&amp;quot; plus bas.&lt;br /&gt;
&lt;br /&gt;
*Les fonctions NOW, SYSDATE ou DATEDIFF sont interdites au sein des ordres SQL. S&#039;il faut saisir la date du moment dans un champ, la valeur doit venir du PHP, par exemple par la fonction dol_now(), et non du moteur de base de données. Ceci afin d&#039;avoir une meilleure portabilité du code mais surtout d&#039;avoir une gestion correcte des TimeZone et ne pas dépendre du TimeZone de la base de donnée.&lt;br /&gt;
&lt;br /&gt;
Par exemple, on ne fera pas:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where datefield = NOW()&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
mais:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where datefield = &#039;&amp;quot;.$this-&amp;gt;db-&amp;gt;idate(dol_now()).&amp;quot;&#039;&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Par exemple, on ne fera pas:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where DATEDIFF(table.datefield, NOW()) &amp;gt; 7&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
mais:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$sql=&amp;quot;SELECT rowid FROM table where datefield &amp;lt; &#039;&amp;quot;.$this-&amp;gt;db-&amp;gt;idate(dol_now() - (7 * 24 * 3600)).&amp;quot;&#039;&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un autre avantage de cette règle est que la requête peut bénéficier de l&#039;utilisation de l&#039;index puisqu&#039;on compare datefield à une valeur fixe. Dans le cas du datediff, on applique un traitement sur le champ avant comparaison, rendant impossible l&#039;utilisation de l&#039;index de ce champ. Les conséquences sont des performances très dégradées par rapport à la version sans datediff.&lt;br /&gt;
&lt;br /&gt;
==Règles de migration de base==&lt;br /&gt;
&lt;br /&gt;
*Les scripts de migration de structure sont les fichiers de type &#039;&#039;&#039;install/mysql/migration/a.b.c-x.y.z.sql&#039;&#039;&#039;. Dans un fichier de migration de n vers n+1, on ne détruit une table (DROP TABLE) qui n&#039;est plus utilisée en n+1 que lors de la migration de la version n+1 vers n+2. Ceci afin de toujours conserver les tables deprecated le temps d&#039;une version pour réparer une situation en cas d&#039;erreur de migration.&lt;br /&gt;
&lt;br /&gt;
==Spécificités MySQL==&lt;br /&gt;
&lt;br /&gt;
*Les tables doivent être au format InnoDB.&lt;br /&gt;
&lt;br /&gt;
En effet, ce format gère les clés étrangères, les éventuelles restrictions qui y sont attachées et la notion d&#039;intégrité de transactions requise pour avoir des données en base cohérente entre tables.&lt;br /&gt;
&lt;br /&gt;
*Dolibarr DOIT fonctionner même avec les options &#039;&#039;&#039;strict&#039;&#039;&#039; de Mysql active.&lt;br /&gt;
&lt;br /&gt;
Pour l&#039;activer (fortement recommandé en développement), ajouter la ligne suivante dans le fichier config du serveur Mysql (my.cnf ou my.ini)&lt;br /&gt;
{{MySqlStrictMode}}&lt;br /&gt;
&lt;br /&gt;
==Spécificités PostgreSQL==&lt;br /&gt;
Seuls les fichiers pour Mysql doivent être maintenus.&lt;br /&gt;
Les fichiers pour les autres bases sont convertis &amp;quot;à la volée&amp;quot; par le driver Dolibarr de la base.&lt;br /&gt;
&lt;br /&gt;
Il existe une exception.&lt;br /&gt;
Les requêtes &amp;quot;UPDATE FROM&amp;quot; : &lt;br /&gt;
Syntax MySQL :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
UPDATE table_taget as target, table_source as source SET fieldtarget=source.fieldsource&lt;br /&gt;
WHERE source.rowid=target.rowid;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Syntax PgSQL:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
UPDATE table_taget as target SET fieldtarget=source.fieldsource&lt;br /&gt;
FROM table_source as source WHERE source.rowid=target.rowid;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il n&#039;en existe pas dans Dolibarr, mais pour vos modules Vous devriez faire tel que :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
if ($this-&amp;gt;db-&amp;gt;type==&#039;pgsql&#039;) {&lt;br /&gt;
$sql=&amp;quot;UPDATE table_taget as target SET fieldtarget=source.fieldsource&lt;br /&gt;
FROM table_source as source WHERE source.rowid=target.rowid&amp;quot;;&lt;br /&gt;
} else {&lt;br /&gt;
$sql= &amp;quot;UPDATE table_taget as target, table_source as source SET fieldtarget=source.fieldsource&lt;br /&gt;
WHERE source.rowid=target.rowid&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Normes HTML=&lt;br /&gt;
&lt;br /&gt;
*Tous les attributs dans les balises HTML doivent être *en minuscule* et quotés avec des *doubles quote*.&lt;br /&gt;
&lt;br /&gt;
*Les liens href doivent être absolus en se basant sur la fonction dol_buildpath() pour obtenir un chemin absolu depuis un chemin relatif au répertoire htdocs. Pour les tags img, il faut faire appel à la fonction img_picto().&lt;br /&gt;
&lt;br /&gt;
Par example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print &#039;&amp;lt;a href=&amp;quot;&#039;.dol_buildpath(&#039;/monrep/mapage.php&#039;).&#039;&amp;quot;&amp;gt;&#039;.img_picto(&#039;Texte alt&#039;,&#039;nompictopng&#039;,&#039;&#039;).&#039;&amp;lt;/a&amp;gt;&#039;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les tables HTML doivent avoir des colonnes sans valeurs forcées, excepté pour les colonnes qui contiennent une information dont la longueur est non variable. Par exemple, une colonne avec un picto peut être forcée à with=&amp;quot;20px&amp;quot;. Dans les autres cas, il faut éviter de forcer la largeur des colonnes. La raison est que, dans la plupart des cas, le navigateur fait un meilleur travail pour définir automatiquement la bonne largeur des colonnes qu&#039;en forçant manuellement les largeurs. Et ceci marche quelque soit la résolution de l&#039;écran.&lt;br /&gt;
&lt;br /&gt;
*Le javascript/ajax et l&#039;appel aux scripts java dans les pages php est à proscrire. Si toutefois du code javascript est inclus, il doit être conditionné par le test sur &amp;quot;$conf-&amp;gt;use_javascript_ajax&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
if ($conf-&amp;gt;use_javascript_ajax) {&lt;br /&gt;
...  // Le code php qui génère du javascript est ici&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Les popups windows ne doivent pas être utilisées, sauf pour des tooltips (et restent conditionnées par le point ci-dessus).&lt;br /&gt;
&lt;br /&gt;
*Les scripts externes sont écrits en Perl s&#039;ils ne peuvent l&#039;être en php, l&#039;utilisation d&#039;un autre langage n&#039;est pas interdit mais doit être discuté au préalable dans la mailing list des développeurs.&lt;br /&gt;
&lt;br /&gt;
=Normes Dolibarr et squelettes de code=&lt;br /&gt;
&lt;br /&gt;
==Squelettes de code==&lt;br /&gt;
Afin d&#039;uniformiser le code et d&#039;accélérer le développement de nouveaux composants dans Dolibarr, se trouvent dans le répertoire &#039;&#039;&#039;htdocs/modulebuilder/templates&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Pr exemple:&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de descripteur de module: &#039;&#039;&#039;myModule.class.php&#039;&#039;&#039;&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de code pour faire une nouvelle classe: &#039;&#039;&#039;skeleton_class.class.php&#039;&#039;&#039;&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de code pour faire une nouvelle page: &#039;&#039;&#039;skeleton_page.php&#039;&#039;&#039;&lt;br /&gt;
*1 fichier qui sert d&#039;exemple de code pour faire un script à exécuter en ligne de commande: &#039;&#039;&#039;skeleton_script.php&#039;&#039;&#039;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
Servez-vous en comme exemple.&lt;br /&gt;
Notons que ces squelettes sont aussi utilisés par le générateur de code PHP ([[Module ModuleBuilder]]) qui est décrit dans la chapitre de développement de module Dolibarr pour accélérer vos développement.&lt;br /&gt;
&lt;br /&gt;
==Les dates et TimeZone==&lt;br /&gt;
Dolibarr se veut une application multi-utilisateur et multi-localisation. Il convient donc de stocker les dates dans le bon format. Pour éviter les problèmes de conversion, les règles suivantes doivent être appliquées:&lt;br /&gt;
&lt;br /&gt;
*Une date en mémoire doit être au format Timestamp GMT.&lt;br /&gt;
*Une date stockée en base de données contient le Timestamp issue de la date soumise dans la requête en heure &amp;lt;b&amp;gt;locale du serveur PHP&amp;lt;/b&amp;gt;. Cela ne concerne pas les dates mises à jour automatiquement par la base (champ &#039;&#039;&#039;tms&#039;&#039;&#039; en base).&lt;br /&gt;
&lt;br /&gt;
Ainsi le 1er janvier 1970, 3 heures à Paris (TZ=+1) = 1er janvier 1970, 2 heures à Greenwich (TZ=0) sera stocké en mémoire par 7200 et sera soumis à la base de données avec la chaine &#039;19700101030000&#039; (PHP convertit en heure de son TZ et la base déconvertit avec son TZ qui est le même que celui de PHP).&lt;br /&gt;
&lt;br /&gt;
Les méthodes select doivent donc traduire les champs dates lus qui sont au format chaine TZ de la base (&#039;19700101030000&#039;) par appel de la méthode db-&amp;gt;jdate afin de récupérer une information en mémoire au format Timestamp GMT. Et les méthodes insert doivent lors de la génération de la requête convertir la date mémoire connue en variable, par la méthode db-&amp;gt;idate (Voir exemples générés par le squelette).&lt;br /&gt;
&lt;br /&gt;
*Les dates mises à jour automatiquement par la base (champ &#039;&#039;&#039;tms&#039;&#039;&#039; en base) contiennent le Timestamp où la modification est faite selon le timezone de la base de donnée. Les méthodes select récupèrent cette donnée en mémoire au format Timestamp GMT en appliquant également le db-&amp;gt;jdate. Si le timezone de la base de donnée diffère de celui du PHP (un des 2 est mal réglé), il peut donc y avoir des écarts entre date de création et modification.&lt;br /&gt;
&lt;br /&gt;
*La manipulation de dates en PHP doit être faite en utilisant les fonctions dates de Dolibarr: &#039;&#039;&#039;dol_now(), dol_mktime(), dol_stringtotime(), dol_getdate(), dol_time_plus_duree()&#039;&#039;&#039;. Vous trouverez également d&#039;autres fonctions prêtes à l&#039;emploi dans le fichier &#039;&#039;&#039;date.lib.php&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==L&#039;encodage UTF8/ISO==&lt;br /&gt;
Dolibarr stocke les informations de manière suivante:&lt;br /&gt;
&lt;br /&gt;
*En base de donnée, les données sont en UTF8 ou ISO. Cela dépend du pagecode de la base, donc des options à la création de cette base. Dans tous les cas le driver d&#039;accès base Dolibarr (dans /lib/database) s&#039;arrange à la lecture et insertion pour convertir vers et depuis de l&#039;UTF8.&lt;br /&gt;
*Les données en mémoires sont donc stockées en UTF8 (instances d&#039;objets PHP).&lt;br /&gt;
*Les pages web affichées à l&#039;écran sont au format UTF8&lt;br /&gt;
&lt;br /&gt;
==Les nombres réels, montants et calculs==&lt;br /&gt;
En PHP comme dans d&#039;autres langages (Java par exemple), les données non entières (float, real, double) ne sont pas fiables.&lt;br /&gt;
Essayer de faire par exemple &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print 239.2 - 229.3 - 9.9;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Vous n&#039;obtiendrez pas zéro mais un nombre très petit en puissance de 10 négative. Si vous obtenez zéro, vous pourrez trouvez d&#039;autres exemples qui ne fonctionnent pas.&lt;br /&gt;
Le problème des float est général, une variable résultante de calcul de nombre réels doit SYSTEMATIQUEMENT être nettoyée par la fonction &#039;&#039;&#039;price2num()&#039;&#039;&#039; avec le 2eme paramètre renseigné à: &#039;MU&#039;, &#039;MT&#039; ou &#039;MS&#039; selon le besoin (voir doc fonction).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
print price2num(239.2 - 229.3 - 9.9, &#039;MT&#039;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
S&#039;il ne s&#039;agit pas d&#039;un prix sur lequel s&#039;adapte les paramètres MU, MT ou MS, il faut utiliser la fonction &#039;&#039;&#039;round()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==Création de tables==&lt;br /&gt;
Ne pas créer de table à l&#039;utilisation, c&#039;est-à-dire à la &#039;&#039;&#039;première utilisation&#039;&#039;&#039; du module.&lt;br /&gt;
Si vous créez un module qui utilise des tables qui ne sont pas intégrées en standard dans le code de Dolibarr, veillez à suivre le didacticiel [[Développement module]] qui explique comment joindre des tables qui se créent à l&#039;activation du module et non à son utilisation (voir plus haut).&lt;br /&gt;
&lt;br /&gt;
==Comparer la version==&lt;br /&gt;
&lt;br /&gt;
Si votre code a besoin de faire des choses différentes selon la version de Dolibarr, vous pouvez utiliser le truc suivant pour comparer les versions&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$version=preg_split(&#039;/[\.-]/&#039;,DOL_VERSION);&lt;br /&gt;
if (versioncompare($version,array(5,0,-4)) &amp;gt;= 0) { //mycode for 5.0 only; }	// For dolibarr 5.0.* (the -4 means we include also alpha, beta, rc and rcX)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mais cette solution requiert de faire un include avoir la fonction versioncompare. Une alternative est d&#039;utiliser le test suivant:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
if ((float) DOL_VERSION &amp;gt;= 5.0) { //mycode for 5.0 only; }	// For dolibarr 5.0.*&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Logs==&lt;br /&gt;
Ajouter des traces dans votre code avec la fonction&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
dol_syslog($yourmessage, LOG_INFO|LOG_DEBUG|LOG_WARNING|LOG_ERR);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Répertoires de travail==&lt;br /&gt;
Si vous avez besoin de créer un répertoire de travail, dans votre code, faites référence à ce répertoire par&lt;br /&gt;
&#039;&#039;&#039;DOL_DATA_ROOT.&#039;/monmodule&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Le répertoire peut être créé dans votre code à l&#039;exécution par le code suivant:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;PHP&amp;quot;&amp;gt;&lt;br /&gt;
$mymoduledir=DOL_DATA_ROOT.&#039;/monmodule&#039;;&lt;br /&gt;
dol_mkdir($mymoduledir);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si vous avez besoin d&#039;un répertoire qui contiendra des données temporaires, ce répertoire doit être&#039;&#039;&#039; DOL_DATA_ROOT.&#039;/monmodule/temp&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Design patterns et programmation objet=&lt;br /&gt;
&lt;br /&gt;
==Design patterns de Création (GoF)==&lt;br /&gt;
Design patterns définis par le Gang Of Four (voir la wikipédia sur les [[wikipedia:Patron de conception|Design patterns]]).&lt;br /&gt;
Dans Dolibarr, pas de mise en oeuvre de design patterns de comportement particulier.&lt;br /&gt;
On trouve des objets proches des Singletons et Fabriques conforme à 100% dans l&#039;esprit mais pas dans la syntaxe, ceci afin d’être compatible avec la plus large plage possible de versions de PHP.&lt;br /&gt;
&lt;br /&gt;
==Design patterns d&#039;entreprises (Martin Fowler)==&lt;br /&gt;
&lt;br /&gt;
===Mode d&#039;organisation du code===&lt;br /&gt;
[[wikipedia:Martin_Fowler|Martin Fowler]] a identifié 3 méthodes d&#039;organisation du code appelées &#039;&#039;&#039;patterns&#039;&#039;&#039; (&#039;&#039;&#039;motifs&#039;&#039;&#039;):&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Transaction Script&#039;&#039;&#039; (Le code est linéaire en fonction d&#039;une action utilisateur).&lt;br /&gt;
&lt;br /&gt;
C&#039;est le motif à l&#039;ancienne utilisé dans les langages procéduraux.&lt;br /&gt;
Inconvénient: Redondance du code. Nécessité de connaitre le modèle physique pour développer les parties métiers.&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Domain Model&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
C&#039;est un concept possible depuis les langages objets. Ce sont les procédures métiers (qui doivent être identifiés avant) qui servent de bases pour les classes objets.&lt;br /&gt;
Inconvénient: Motif complexe à maintenir.&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Table Module&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Un intermédiaire entre les 2 précédents où l&#039;on a une instance unique de classe par table de la base de données.&lt;br /&gt;
&lt;br /&gt;
-&amp;gt; Comme le montre les squelettes de code (voir point précédent), Dolibarr se base sur le principe du &#039;&#039;&#039;Table Module&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===Communication Logique métier - Données (ORM)===&lt;br /&gt;
Il existe 3 modes de liaisons:&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Table And Row Data Gateway&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
C&#039;est le plus simple. On crée une classe par table et chaque classe est un pont avec la table correspondante et propose les méthodes CRUD sur cette table (Create, Read, Update, Delete). Une instance de classe étant alors un enregistrement de la table. La classe ne contient que du code d&#039;accès aux lignes ou colonnes de tables. Le code métier doit alors être ajouté dans d&#039;autres classes. Les liens entre ces classes tables et les classes métiers devant être connues ou déduite de la connaissance du développeur.&lt;br /&gt;
&lt;br /&gt;
Exemple: C&#039;est le mode mis en oeuvre quand on utilise certains Frameworks d&#039;ORM comme &#039;&#039;&#039;iBatis&#039;&#039;&#039; (http://ibatis.apache.org/).&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Active Record&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Identique au précédent, mais on se permet d&#039;ajouter quelques fonctions métiers sur la classe, à conditions que ces fonctions soient bien  propres à la table ou à la notion métier porté par l&#039;enregistrement. C&#039;est le pattern qui offre le meilleur rapport fonctionnalité/complexité.&lt;br /&gt;
&lt;br /&gt;
Exemple: C&#039;est le mode choisi pour les développements Dolibarr et de nombreuses autres applications PHP qui ont leur propre framework et pratiques de développements.&lt;br /&gt;
&lt;br /&gt;
*Le &#039;&#039;&#039;Data Mapper&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Les classes représentent les entités du problème et non les données. Il faut donc doubler, tripler... ces classes avec des classes Mapper pour accéder aux données.&lt;br /&gt;
Plus &amp;quot;puriste&amp;quot; sur le papier car plus proche du métier, ce mode a aussi l&#039;inconvénient d&#039;être très complexe et difficile à maintenir dans la réalité (l&#039;expérience pratique constaté ne rejoignant pas les promesses de la théorie).&lt;br /&gt;
&lt;br /&gt;
Exemple: C&#039;est le choix si on utilise le Framework d&#039;ORM &#039;&#039;&#039;Propel&#039;&#039;&#039; (http://propel.phpdb.org/trac/). On le trouve donc sur des applications plus lourdes basées sur cet ORM entre autres.&lt;br /&gt;
&lt;br /&gt;
-&amp;gt; Pour les développements Dolibarr, il est recommandé d&#039;utiliser le mode de liaison &#039;&#039;&#039;Active Record&#039;&#039;&#039; qui offre les avantages d&#039;un modèle proche du métier sans en avoir la complexité et sans trop masquer non plus la technique. C&#039;est dans ce mode que le développement, la compréhension du code et la maintenance technique et/ou fonctionnelle semble la plus productive (ceci est toutefois un éternel débat entre les puristes et les pragmatiques, débat dans lequel personne ne peut vraiment avoir raison, car tout dépend des objectifs à atteindre).&lt;br /&gt;
&lt;br /&gt;
==Design Pattern d&#039;Interface Graphique (MVC)==&lt;br /&gt;
Il existe plusieurs design pattern pour les interfaces utilisateurs (MVC, MVP, MVVM).&lt;br /&gt;
Beaucoup confonde ce design pattern avec celui consistant à utiliser un framework de templates. C&#039;est sans rapport. Un framework de template (voir point précédent) n&#039;est en lien qu&#039;avec la partie &amp;quot;V&amp;quot; de ces modèles.&lt;br /&gt;
&lt;br /&gt;
-&amp;gt; Dolibarr utilise le Design Pattern &#039;&#039;&#039;MVC&#039;&#039;&#039;. La partie M est matérialisée par une classe DAO contenant les méthode CRUD (Create-Read-Update-Delete) d&#039;accès à la table.&lt;br /&gt;
Beaucoup de frameworks ont fait le choix de mettre la partie de code C (Controller) et la partie de code du V (vue) dans des fichiers, voir même répertoires séparés. La maintenance semble plus aisé sur la papier, en pratique, il faut sans arrêt jonglé entre n fichiers, le C étant fortement lié au V. Aussi dans Dolibarr, la séparation est faite par une simple section de commentaire. La partie de code C (Controller) est donc le code qui se trouve sont la balise&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * Actions&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Elle est suivi par la partie de code V (Vue), bien séparé du C par la balise&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * View&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce mode de séparation a eu un effet neutre sur les nouveaux développement mais a permis de réduire de manière si importante le temps requis pour la maintenance et correction de bugs qu&#039;il n&#039;est pas envisagé de basculer vers un autre type de séparation (oui les constats fait dans la vraie vie ne sont pas toujours ceux attendus par la théorie scolaire). L&#039;important reste qu&#039;il y ait toujours séparation entre le C et le V, peut importe comment est matérialisé cette séparation, du moment qu&#039;elle l&#039;est (Rappel: Ne pas confondre la notion de séparation du C et du V avec la notion de séparation du code pour alimenter la données d&#039;une Vue et du code pour formater la Vue, ceci un principe de séparation relevant du Design Pattern de Vue, voir point suivant).&lt;br /&gt;
&lt;br /&gt;
==Design Pattern de Vue - Présentation==&lt;br /&gt;
Il existe des frameworks spécialisés dans le Design Pattern de Vue, la partie qui consiste à formater l&#039;écran vue par l&#039;utilisateur.&lt;br /&gt;
Les vieilles versions de Dolibarr utilisaient Smarty. Ce framework est une surcouche à un Framework, déjà très puissant, de formatage d&#039;écran nommé... PHP. Les bénéfices étant très inférieurs aux inconvénients, il a été abandonné au profit de templates PHP (fichier .tpl.php) qui restent le plus simple, le plus universel, le plus évolutif et le plus performant, des frameworks de présentation. &lt;br /&gt;
&lt;br /&gt;
Son seul défaut est qu&#039;il ne peut garantir à 100% les écarts d&#039;un développeur qui irait intégrer dans la Vue, une logique sans rapport avec la présentation (donc autre que du code à vocation de génération, de formatage, de sortie HTML, de logique de test ou de boucle). Ce point est toutefois contrôlé par le mécanisme de validation du code des chefs de projets.&lt;br /&gt;
&lt;br /&gt;
La encore, c&#039;est l&#039;expérience et le constat &amp;quot;sur le terrain&amp;quot; d&#039;un meilleur rendement de productivité qui a motivé l&#039;abandon des frameworks de Présentation externes au profit du framework PHP.&lt;/div&gt;</summary>
		<author><name>Quentic</name></author>
	</entry>
	<entry>
		<id>https://wiki.dolibarr.org/index.php?title=Outils_de_d%C3%A9veloppement_-_Composants_optionnels&amp;diff=52110</id>
		<title>Outils de développement - Composants optionnels</title>
		<link rel="alternate" type="text/html" href="https://wiki.dolibarr.org/index.php?title=Outils_de_d%C3%A9veloppement_-_Composants_optionnels&amp;diff=52110"/>
		<updated>2021-09-30T08:22:12Z</updated>

		<summary type="html">&lt;p&gt;Quentic: Correction d&amp;#039;erreur de frappe&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- BEGIN interlang links --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Do NOT edit this section&lt;br /&gt;
     Links below are automatically managed by PolyglotBot&lt;br /&gt;
     You can edit links on the English source page : Environment_and_development_tools_-_Optional --&amp;gt;&lt;br /&gt;
[[en:Environment_and_development_tools_-_Optional]]&lt;br /&gt;
[[es:Herramientas_de_Desarrollo_-_Opcional]]&lt;br /&gt;
&amp;lt;!-- END interlang links --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{TemplateDocDev}}&lt;br /&gt;
Cette page liste les composants et autres technologies supplémentaires que vous pourriez vouloir installer sur votre environnement de développement. Elles ne sont pas requises pour développer sur Dolibarr, ni pour réaliser des modules mais peuvent être utiles pour des travaux très particuliers.&lt;br /&gt;
&lt;br /&gt;
== Si vous désirez faire des scripts en Perl ==&lt;br /&gt;
* Installation du plugin Eclipse pour Perl: EPIC&lt;br /&gt;
Pour cela, utiliser la procédure &#039;&#039;&#039;Find And Install&#039;&#039;&#039; et ajouter l&#039;URL de mise à jour: http://e-p-i-c.sourceforge.net/updates&lt;br /&gt;
&lt;br /&gt;
== Si vous désirez faire des scripts en Python ==&lt;br /&gt;
* Installation du plugin Eclipse pour PyThon: PyDev&lt;br /&gt;
Pour cela, utiliser la procédure &#039;&#039;&#039;Find And Install&#039;&#039;&#039; et ajouter l&#039;URL de mise à jour: http://pydev.org/updates&lt;br /&gt;
&lt;br /&gt;
== Si vous êtes sous Windows ==&lt;br /&gt;
&lt;br /&gt;
* Notepad++ (pour ceux qui ne supportent pas java ou utilisent un vieux coucou trop faible pour Eclipse).&lt;br /&gt;
&lt;br /&gt;
* WinMerge (pour la comparaison de fichiers ou répertoires)&lt;br /&gt;
&lt;br /&gt;
* CygWin (pour la commande patch si vous préferez les lignes de commandes)&lt;br /&gt;
&lt;br /&gt;
A noter que Netbeans-PHP fonctionne efficacement avec Dolibarr.&lt;br /&gt;
&lt;br /&gt;
== Si vous désirez faire du debuggage pas à pas ou du tunning (XDebug) ==&lt;br /&gt;
&lt;br /&gt;
* Pour ajouter des infos de tuning page dans la console javascript à partir de Dolibarr 3.8, ajouter la variable d&#039;environnement MAIN_SHOW_TUNING_INFO à 1 dans Apache. Pour cela, inclure la ligne suivante dans votre fichier apache.conf:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
SetEnv MAIN_SHOW_TUNING_INFO 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Pour du tuning à la ligne de code près, installer XDebug:&lt;br /&gt;
=== [[File:Logo_windows.png|24px]] In Windows ===&lt;br /&gt;
* Télécharger le fichier dll &#039;&#039;&#039;php_debug_xxx.dll&#039;&#039;&#039; sur http://www.xdebug.org et stocker le dans le répertoire /ext de php. Ensuite activer le plugin.&lt;br /&gt;
&lt;br /&gt;
* Modifier le ficiher php.ini ou xdebug.ini pour ajouter le paramètres suivant:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
 [xdebug]&lt;br /&gt;
 xdebug.remote_enable=on&lt;br /&gt;
 xdebug.remote_handle=dbgp&lt;br /&gt;
 xdebug.remote_host=localhost&lt;br /&gt;
 xdebug.remote_port=9000&lt;br /&gt;
 xdebug.show_local_vars=off&lt;br /&gt;
 xdebug.profiler_output_dir=c:/temp&lt;br /&gt;
 xdebug.profiler_append=0&lt;br /&gt;
 xdebug.profiler_enable=0&lt;br /&gt;
 xdebug.profiler_enable_trigger=1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[File:Logo_ubuntu.png|24px]] In Ubuntu / Linux ===&lt;br /&gt;
* Installer le package &#039;&#039;&#039;php-xdebug&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt-get install php5-xdebug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Modifier xdebug.ini pour ajouter les paramètres suivants après les lignes de type zend_extension=xxx (ou similaire):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
 ; With xdebug 2.1 and more&lt;br /&gt;
 xdebug.remote_enable=on&lt;br /&gt;
 xdebug.remote_handle=dbgp&lt;br /&gt;
 xdebug.remote_host=localhost&lt;br /&gt;
 xdebug.remote_port=9000&lt;br /&gt;
 xdebug.show_local_vars=off&lt;br /&gt;
 xdebug.profiler_output_dir=/tmp&lt;br /&gt;
 xdebug.profiler_append=0&lt;br /&gt;
 xdebug.profiler_enable=0&lt;br /&gt;
 xdebug.profiler_enable_trigger=1&lt;br /&gt;
 ; Add also this for xdebug 2.2 and more&lt;br /&gt;
 xdebug.show_mem_delta=1&lt;br /&gt;
 xdebug.trace_output_dir=/tmp&lt;br /&gt;
 xdebug.auto_trace=0&lt;br /&gt;
 xdebug.trace_enable_trigger=1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[File:Eclipsephp.jpg|24px]] Eclipse configuration ===&lt;br /&gt;
* Ouvrir Eclipse. Dans Window-&amp;gt;Preferences-&amp;gt;General-&amp;gt;Web Browser, sélectionner navigateur externe, et choisir le navigateur par défaut de votre système.&lt;br /&gt;
&lt;br /&gt;
* Aller dans la rubrique Window-&amp;gt;Preferences-&amp;gt;PHP-&amp;gt;Debug, et positionner les options PHP Debugger à XDebug. Remarquer que la case “Stop a la première ligne” sur cette page doit également être active. Vous pourrez la modifier plus tard. &lt;br /&gt;
&lt;br /&gt;
* Après avoir validé les changements, aller dans la vue PHP Debug prespective, puis aller dans le menu Debug Configurations… Ici, vérifier que le Server Debugger est positionné à XDebug, et que votre server PHP pointe sur http://localhost/ ou le chemin approprié au serveur. La zone de localisation des fichiers doit de plus pointer sur le fichier à débugger, relativement à votre workspace. Ce chemin doit être quelquechose comme /dolibarr/htdocs/index.php.&lt;br /&gt;
&lt;br /&gt;
* Vérifiez la section URL pour voir si elle pointe correctement – si non, vérifier que la case “Auto-Generate” est bien décochée, et entrer manuellement le bon chemin. Appliquer les changement et fermer la fenêtre de dialogue.&lt;br /&gt;
&lt;br /&gt;
* Vous devriez maintenant être prêt pour lancer du debug de Dolibarr. Cliquer sur Run-&amp;gt;Debug ou F11 pour activer le debug, Eclipse devrait basculer sur la vue Debug, et la page devrait commencer à se charger dans le navigateur externe. Si la case “Break at First Line” a bien été cochée précédemment, alors le programme aura stoppé à la première ligne. Vous pouvez alors faire du pas à pas sur les lignes de code successives en utilisant les boutons de la barre de Debug d&#039;Eclipse. Eventuellement, vous pouvez placer des point d&#039;arrêts à différents endroits du code pour y stopper l&#039;exécution du code.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ensuite pour analyser les fichiers de profiling générés par XDebug, il faut appeler l&#039;url avec XDEBUG_PROFILE=1 pour générer le fichier profiling puis installer KCacheGrind (Linux) ou WinCacheGrind (Windows) pour l&#039;analyser.&lt;br /&gt;
&lt;br /&gt;
== Pour développer ou utiliser les contrôles Qualité (PHPUnit, PHPCodeSniffer, PHPCpd, PHPDepends) ==&lt;br /&gt;
=== Depuis Eclipse ===&lt;br /&gt;
Le plugin PTI pour utiliser PHPUnit et PHPCodesniffer est maintenant abandonnée.&lt;br /&gt;
&lt;br /&gt;
* Pour utiliser PHPUnit, ceci est disponible en standard dans une installation de base d&#039;Eclipse.&lt;br /&gt;
&lt;br /&gt;
* Pour utiliser PHPCodesniffer, vous pouvez créer une entrée &amp;quot;External Tools&amp;quot; avec une configuration de ce type&lt;br /&gt;
&lt;br /&gt;
[[Image:Setup_phpcs.png]]&lt;br /&gt;
&lt;br /&gt;
=== En ligne de commande manuelle ===&lt;br /&gt;
==== Installer PHPUnit ====&lt;br /&gt;
* Télécharger l&#039;archive de la version sur http://pear.phpunit.de/get/ et dézipper le contenu dans un répertoire inclus dans le paramètre include_path de votre fichier de configuration php.ini.&lt;br /&gt;
* Préparer le script phpunit:&lt;br /&gt;
** Sur Linux: Renommer le script phpunit.php script en phpunit et remplacer la chaine @php_bin@ dans ce fichier avec le chemin complet de la ligne de commande de l&#039;interpréteur PHP (en général /usr/bin/php).&lt;br /&gt;
** Sur Windows: Remplacer la chaine @php_bin@ dans le fichier phpunit.bat avec le chemin complet de la ligne de commande de l&#039;interpréteur PHP et remplacer la chaine @bin_dir@ avec le répertoire de PHPUnit.&lt;br /&gt;
** Modifier votre PATH pour inclure le répertoire contenant phpunit.&lt;br /&gt;
** Donner les permissions de s&#039;exécuter (chmod +x phpunit sur Linux). &lt;br /&gt;
* Préparer le script PHPUnit/Util/PHP.php:&lt;br /&gt;
** Remplacer la chaine @php_bin@ dans ce fichier avec le chemin complet de la ligne de commande de l&#039;interpréteur PHP (en général /usr/bin/php).&lt;br /&gt;
* Le module xdebug est également requis si vous voulez faire du reporting de couverture de tests.&lt;br /&gt;
&lt;br /&gt;
==== Exécuter les tests PHPUnit ====&lt;br /&gt;
* Aller dans le répertoire &#039;&#039;&#039;/test&#039;&#039;&#039; des sources. Reportez vous au fichier &#039;&#039;&#039;README&#039;&#039;&#039; pour connaitre la procédure pour lancer une campagne de tests.&lt;br /&gt;
&lt;br /&gt;
==== Installer les autres outils ====&lt;br /&gt;
* Référez vous à la documentation des différents outils (PHPCodeSniffer, PHPCpd, PHPDepends) pour leur installation et utilisation en ligne de commande. Par exemple, pour installer ou mettre à jour PHPCodeSniffer:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo pear upgrade PHP_CodeSniffer&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Les librairies pear seront installées dans &#039;&#039;&#039;/usr/share/php/PHP&#039;&#039;&#039; mais pour les prendre en compte avec Eclipse PTI, il faut ajouter une entrée &amp;quot;PHP&amp;quot; sur &#039;&#039;&#039;/usr/share/php&#039;&#039;&#039; et configurer PHPCheckstyle pour utiliser cette entrée.&lt;br /&gt;
&lt;br /&gt;
== Pour développer ou utiliser les tests Selenium ==&lt;br /&gt;
=== Depuis Firefox ===&lt;br /&gt;
==== Installer le plugin pour Firefox Selenium IDE ====&lt;br /&gt;
* Télécharger le fichier du plugin Selenium IDE pour Firefox.&lt;br /&gt;
* L&#039;ajouter dans Outils - Modules complémentaires de Firefox.&lt;br /&gt;
&lt;br /&gt;
==== Exécuter les tests Selenium ====&lt;br /&gt;
* Aller dans le menu Outils - Selinum IDE de firefox.&lt;br /&gt;
* Ouvrir le fichier de tests xml&lt;br /&gt;
* Executer le test.&lt;br /&gt;
&lt;br /&gt;
== Pour générer la documentation Doxygen ==&lt;br /&gt;
* Installer Doxygen disponible sur http://www.doxygen.org (ou par le package doxygen sous Ubuntu). &lt;br /&gt;
* Installer le plugin Eclipse en ajoutant l&#039;url source http://download.gna.org/eclox/update/ dans l&#039;outil de mise à jour Eclipse puis configurer Eclipse pour indiquer l&#039;emplacement de Doxygen (Window-Preferences-Doxygen).&lt;br /&gt;
&lt;br /&gt;
== Pour ajouter le support asciidoc à Eclipse ==&lt;br /&gt;
&lt;br /&gt;
Ajouter l&#039;URL http://download.eclipse.org/mylyn/snapshots/nightly/docs/ dans les Install repositories. Puis installer le package &#039;&#039;&#039;Mylyn Docs - Mylyn Wikitext Extras&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Quentic</name></author>
	</entry>
	<entry>
		<id>https://wiki.dolibarr.org/index.php?title=Outils_de_d%C3%A9veloppement&amp;diff=52109</id>
		<title>Outils de développement</title>
		<link rel="alternate" type="text/html" href="https://wiki.dolibarr.org/index.php?title=Outils_de_d%C3%A9veloppement&amp;diff=52109"/>
		<updated>2021-09-30T08:20:08Z</updated>

		<summary type="html">&lt;p&gt;Quentic: /* Optionnel */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- BEGIN interlang links --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Do NOT edit this section&lt;br /&gt;
     Links below are automatically managed by PolyglotBot&lt;br /&gt;
     You can edit links on the English source page : Environment_and_development_tools --&amp;gt;&lt;br /&gt;
[[en:Environment_and_development_tools]]&lt;br /&gt;
[[es:Herramientas_de_Desarrollo]]&lt;br /&gt;
&amp;lt;!-- END interlang links --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{TemplateDocDevFr}}&lt;br /&gt;
&lt;br /&gt;
Tout environnement de développement peut être utilisé.&lt;br /&gt;
Toutefois voici une liste d&#039;outils fortement recommandés pour leur complétude, leur qualité et la productivité du développement qu&#039;ils apportent. Ils sont utilisés par la plupart des développeurs principaux de Dolibarr. Notons que toutes ces solutions sont gratuites et OpenSource.&lt;br /&gt;
&lt;br /&gt;
=[[File:Eclipsephp.jpg]] Pour tout développeur=&lt;br /&gt;
&lt;br /&gt;
Voici le socle de travail recommandé, toutefois tout outil respectant les standards Web, PHP, Mysql peuvent faire l&#039;affaire.&lt;br /&gt;
&lt;br /&gt;
==Un serveur AMP==&lt;br /&gt;
&lt;br /&gt;
*Apache, MariaDB et PHP&lt;br /&gt;
&lt;br /&gt;
Sur Linux: Ces 3 produits sont disponibles dans toutes distributions.&lt;br /&gt;
&lt;br /&gt;
Sur Windows: Installez [http://www.wampserver.com/WampServer] (base MariaDB, Apache et PHP tout clé en main). Ce serveur WAMP offre le trio MariaDB + Apache + PHP, avec possibilité de basculer de version pour n&#039;importe lequel de ces composants d&#039;un simple clic).&lt;br /&gt;
&lt;br /&gt;
==Chrome ou Firefox et plugins==&lt;br /&gt;
&lt;br /&gt;
*Chrome&lt;br /&gt;
&lt;br /&gt;
A télécharger depuis le site http://www.chrome.com&lt;br /&gt;
&lt;br /&gt;
*Firefox avec les plugins: &lt;br /&gt;
**Firebug + Firecookie + FirePHP,&lt;br /&gt;
**HTML Validator,&lt;br /&gt;
**User agent switcher pour simuler des accès depuis un smartphone&lt;br /&gt;
**Selenium IDE&lt;br /&gt;
**Cert Viewer Plus si vous comptez faire des tests en HTTPS,&lt;br /&gt;
**QuickProxy si vous voulez basculer rapidement votre navigateur vers des utilitaires Proxy (WebScarab)...&lt;br /&gt;
&lt;br /&gt;
A télécharger depuis le site http://www.firefox.com&lt;br /&gt;
&lt;br /&gt;
==SquirrelSQL==&lt;br /&gt;
&lt;br /&gt;
*SquirrelSQL pour l&#039;administration de base&lt;br /&gt;
&lt;br /&gt;
A télécharger depuis le site http://squirrel-sql.sf.net&lt;br /&gt;
&lt;br /&gt;
==Eclipse et plugins==&lt;br /&gt;
===Installation d&#039;Eclipse===&lt;br /&gt;
Nous recommandons la version suivante d&#039;Eclipse:&lt;br /&gt;
&lt;br /&gt;
{{DownloadEclipse}}&lt;br /&gt;
&lt;br /&gt;
Sinon toute version disponible sur le site [http://www.eclipse.org Eclipse] fait l&#039;affaire.&lt;br /&gt;
&lt;br /&gt;
Une fois Eclipse installé, il est recommandé de modifier/vérifier les paramètres suivants:&lt;br /&gt;
{{EclipseStandardSetup}}&lt;br /&gt;
&lt;br /&gt;
===Installation du plugin Eclipse pour PHP: PDT.===&lt;br /&gt;
Avec certaines installations d&#039;Eclipse, PDT peut etre installé depuis Help -&amp;gt; Install new software et choisir PDT.&lt;br /&gt;
Si PDT n&#039;est pas présent, si vous avez installé la version Eclipse ci-dessus, il suffit d&#039;utiliser la procédure Help -&amp;gt; Install new software -&amp;gt; Add -&amp;gt; pour installer le package complémentaire:&lt;br /&gt;
&lt;br /&gt;
{{DownloadEclipsePDT}}&lt;br /&gt;
&lt;br /&gt;
Une fois PDT installé, il faut aussi le configurer dans Eclipse comme défini dans le chapitre [[Outils_de_développement_-_Composants_optionnels#Depuis_Eclipse]].&lt;br /&gt;
&lt;br /&gt;
===Configurer Eclipse pour récupérer les sources===&lt;br /&gt;
Une fois qu&#039;Eclipse est installé, vous pouvez vous connecter au repository GIT pour y récupérer les dernières versions de développement.&lt;br /&gt;
&lt;br /&gt;
Pour cela, voir la page [[FAQ Récupérer, mettre à jours les sources GIT du projet]].&lt;br /&gt;
&lt;br /&gt;
==Git Hooks==&lt;br /&gt;
&lt;br /&gt;
===Installer le hook git Pre-commit===&lt;br /&gt;
L&#039;utilisation de ce hook git est essentiel pour vérifier la syntaxe des fichiers qui sont commit et pouvoir annuler celui-ci si la syntaxe est mauvaise. Si phpcs et phpcbf sont installés, la syntaxe peut être modifiée automatiquement. Voici comment faire:&lt;br /&gt;
&lt;br /&gt;
Allez dans &#039;&#039;&#039;/dev/setup/git/hooks&#039;&#039;&#039; de votre dépôt local, copiez le fichier &#039;&#039;&#039;pre-commit&#039;&#039;&#039; dans le dossier &#039;&#039;&#039;.git/hooks&#039;&#039;&#039; se trouvant a la racine de votre dépôt git local et rendez-le exécutable.&lt;br /&gt;
&lt;br /&gt;
Ensuite, il est nécessaire d&#039;éditer le fichier &#039;&#039;&#039;pre-commit&#039;&#039;&#039; présent dans &#039;&#039;&#039;.git/hooks&#039;&#039;&#039; pour modifier la variable DIRPHPCS pour ajouter le chemin des outils phpcs et phpcbf (le laisser vide si les outils sont disponibles dans la variable PATH).&lt;br /&gt;
&lt;br /&gt;
Ce type de hook est utilisé lorsqu&#039;on utilise l&#039;invité de commande mais aussi lorsque qu&#039;un commit est créé avec un IDE commun (exemple Eclipse et Virtual Studio Code). Une fois installé, le hook démarrera lors de votre prochain commit pour reformater votre code, pour que votre code corresponde toujours aux règles de syntaxe de codage. Si tout le monde active ce hook, tout le monde utilisera la même règle de syntaxe de codage, il est donc fortement recommandé de l&#039;activer si vous le pouvez.&lt;br /&gt;
&lt;br /&gt;
=[[File:Computer.png]] Optionnel=&lt;br /&gt;
Vous pouvez aussi installer des composants optionnels pour avoir le support de technologies suplémentaires.&lt;br /&gt;
Voir la page [[Outils de développement - Composants optionnels]].&lt;/div&gt;</summary>
		<author><name>Quentic</name></author>
	</entry>
	<entry>
		<id>https://wiki.dolibarr.org/index.php?title=Outils_de_d%C3%A9veloppement&amp;diff=52108</id>
		<title>Outils de développement</title>
		<link rel="alternate" type="text/html" href="https://wiki.dolibarr.org/index.php?title=Outils_de_d%C3%A9veloppement&amp;diff=52108"/>
		<updated>2021-09-30T08:19:40Z</updated>

		<summary type="html">&lt;p&gt;Quentic: /* Installer le hook git Pre-commit */Correction d&amp;#039;erreur de frappe&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- BEGIN interlang links --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Do NOT edit this section&lt;br /&gt;
     Links below are automatically managed by PolyglotBot&lt;br /&gt;
     You can edit links on the English source page : Environment_and_development_tools --&amp;gt;&lt;br /&gt;
[[en:Environment_and_development_tools]]&lt;br /&gt;
[[es:Herramientas_de_Desarrollo]]&lt;br /&gt;
&amp;lt;!-- END interlang links --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{TemplateDocDevFr}}&lt;br /&gt;
&lt;br /&gt;
Tout environnement de développement peut être utilisé.&lt;br /&gt;
Toutefois voici une liste d&#039;outils fortement recommandés pour leur complétude, leur qualité et la productivité du développement qu&#039;ils apportent. Ils sont utilisés par la plupart des développeurs principaux de Dolibarr. Notons que toutes ces solutions sont gratuites et OpenSource.&lt;br /&gt;
&lt;br /&gt;
=[[File:Eclipsephp.jpg]] Pour tout développeur=&lt;br /&gt;
&lt;br /&gt;
Voici le socle de travail recommandé, toutefois tout outil respectant les standards Web, PHP, Mysql peuvent faire l&#039;affaire.&lt;br /&gt;
&lt;br /&gt;
==Un serveur AMP==&lt;br /&gt;
&lt;br /&gt;
*Apache, MariaDB et PHP&lt;br /&gt;
&lt;br /&gt;
Sur Linux: Ces 3 produits sont disponibles dans toutes distributions.&lt;br /&gt;
&lt;br /&gt;
Sur Windows: Installez [http://www.wampserver.com/WampServer] (base MariaDB, Apache et PHP tout clé en main). Ce serveur WAMP offre le trio MariaDB + Apache + PHP, avec possibilité de basculer de version pour n&#039;importe lequel de ces composants d&#039;un simple clic).&lt;br /&gt;
&lt;br /&gt;
==Chrome ou Firefox et plugins==&lt;br /&gt;
&lt;br /&gt;
*Chrome&lt;br /&gt;
&lt;br /&gt;
A télécharger depuis le site http://www.chrome.com&lt;br /&gt;
&lt;br /&gt;
*Firefox avec les plugins: &lt;br /&gt;
**Firebug + Firecookie + FirePHP,&lt;br /&gt;
**HTML Validator,&lt;br /&gt;
**User agent switcher pour simuler des accès depuis un smartphone&lt;br /&gt;
**Selenium IDE&lt;br /&gt;
**Cert Viewer Plus si vous comptez faire des tests en HTTPS,&lt;br /&gt;
**QuickProxy si vous voulez basculer rapidement votre navigateur vers des utilitaires Proxy (WebScarab)...&lt;br /&gt;
&lt;br /&gt;
A télécharger depuis le site http://www.firefox.com&lt;br /&gt;
&lt;br /&gt;
==SquirrelSQL==&lt;br /&gt;
&lt;br /&gt;
*SquirrelSQL pour l&#039;administration de base&lt;br /&gt;
&lt;br /&gt;
A télécharger depuis le site http://squirrel-sql.sf.net&lt;br /&gt;
&lt;br /&gt;
==Eclipse et plugins==&lt;br /&gt;
===Installation d&#039;Eclipse===&lt;br /&gt;
Nous recommandons la version suivante d&#039;Eclipse:&lt;br /&gt;
&lt;br /&gt;
{{DownloadEclipse}}&lt;br /&gt;
&lt;br /&gt;
Sinon toute version disponible sur le site [http://www.eclipse.org Eclipse] fait l&#039;affaire.&lt;br /&gt;
&lt;br /&gt;
Une fois Eclipse installé, il est recommandé de modifier/vérifier les paramètres suivants:&lt;br /&gt;
{{EclipseStandardSetup}}&lt;br /&gt;
&lt;br /&gt;
===Installation du plugin Eclipse pour PHP: PDT.===&lt;br /&gt;
Avec certaines installations d&#039;Eclipse, PDT peut etre installé depuis Help -&amp;gt; Install new software et choisir PDT.&lt;br /&gt;
Si PDT n&#039;est pas présent, si vous avez installé la version Eclipse ci-dessus, il suffit d&#039;utiliser la procédure Help -&amp;gt; Install new software -&amp;gt; Add -&amp;gt; pour installer le package complémentaire:&lt;br /&gt;
&lt;br /&gt;
{{DownloadEclipsePDT}}&lt;br /&gt;
&lt;br /&gt;
Une fois PDT installé, il faut aussi le configurer dans Eclipse comme défini dans le chapitre [[Outils_de_développement_-_Composants_optionnels#Depuis_Eclipse]].&lt;br /&gt;
&lt;br /&gt;
===Configurer Eclipse pour récupérer les sources===&lt;br /&gt;
Une fois qu&#039;Eclipse est installé, vous pouvez vous connecter au repository GIT pour y récupérer les dernières versions de développement.&lt;br /&gt;
&lt;br /&gt;
Pour cela, voir la page [[FAQ Récupérer, mettre à jours les sources GIT du projet]].&lt;br /&gt;
&lt;br /&gt;
==Git Hooks==&lt;br /&gt;
&lt;br /&gt;
===Installer le hook git Pre-commit===&lt;br /&gt;
L&#039;utilisation de ce hook git est essentiel pour vérifier la syntaxe des fichiers qui sont commit et pouvoir annuler celui-ci si la syntaxe est mauvaise. Si phpcs et phpcbf sont installés, la syntaxe peut être modifiée automatiquement. Voici comment faire:&lt;br /&gt;
&lt;br /&gt;
Allez dans &#039;&#039;&#039;/dev/setup/git/hooks&#039;&#039;&#039; de votre dépôt local, copiez le fichier &#039;&#039;&#039;pre-commit&#039;&#039;&#039; dans le dossier &#039;&#039;&#039;.git/hooks&#039;&#039;&#039; se trouvant a la racine de votre dépôt git local et rendez-le exécutable.&lt;br /&gt;
&lt;br /&gt;
Ensuite, il est nécessaire d&#039;éditer le fichier &#039;&#039;&#039;pre-commit&#039;&#039;&#039; présent dans &#039;&#039;&#039;.git/hooks&#039;&#039;&#039; pour modifier la variable DIRPHPCS pour ajouter le chemin des outils phpcs et phpcbf (le laisser vide si les outils sont disponibles dans la variable PATH).&lt;br /&gt;
&lt;br /&gt;
Ce type de hook est utilisé lorsqu&#039;on utilise l&#039;invité de commande mais aussi lorsque qu&#039;un commit est créé avec un IDE commun (exemple Eclipse et Virtual Studio Code). Une fois installé, le hook démarrera lors de votre prochain commit pour reformater votre code, pour que votre code corresponde toujours aux règles de syntaxe de codage. Si tout le monde active ce hook, tout le monde utilisera la même règle de syntaxe de codage, il est donc fortement recommandé de l&#039;activer si vous le pouvez.&lt;br /&gt;
&lt;br /&gt;
=[[File:Computer.png]] Optionnel=&lt;br /&gt;
Vous pouvez aussi installe des composants optionnels pour avoir le support de technologies suplémentaires.&lt;br /&gt;
Voir la page [[Outils de développement - Composants optionnels]].&lt;/div&gt;</summary>
		<author><name>Quentic</name></author>
	</entry>
	<entry>
		<id>https://wiki.dolibarr.org/index.php?title=Syst%C3%A8me_de_menus&amp;diff=52107</id>
		<title>Système de menus</title>
		<link rel="alternate" type="text/html" href="https://wiki.dolibarr.org/index.php?title=Syst%C3%A8me_de_menus&amp;diff=52107"/>
		<updated>2021-09-30T08:13:04Z</updated>

		<summary type="html">&lt;p&gt;Quentic: /* Ajouter votre entrée menu */Reformulation des actions à la manière  &amp;quot;rédaction technique&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- BEGIN interlang links --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Do NOT edit this section&lt;br /&gt;
     Links below are automatically managed by PolyglotBot&lt;br /&gt;
     You can edit links on the English source page : Menus_system --&amp;gt;&lt;br /&gt;
[[en:Menus_system]]&lt;br /&gt;
[[es:Sistema_de_menús]]&lt;br /&gt;
[[de:Menü_System]]&lt;br /&gt;
[[zh:菜单]]&lt;br /&gt;
&amp;lt;!-- END interlang links --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Noyau]]&lt;br /&gt;
{{TemplateDocDev}}&lt;br /&gt;
&lt;br /&gt;
=Le système de menu Dolibarr=&lt;br /&gt;
&lt;br /&gt;
Il y a 2 systèmes de menu. Un système de menu définit les entrées de menu à afficher, conditions et localisation.&lt;br /&gt;
&lt;br /&gt;
Changer de système de menu est possible via la page &#039;&#039;&#039;Configuration - Menus&#039;&#039;&#039;. Choisir ensuite &#039;&#039;&#039;Editeur de menus&#039;&#039;&#039;. Prendre par exemple les gestionnaires de menu &amp;quot;auguria&amp;quot;, fournis en standard au lieu de &amp;quot;eldy&amp;quot;. Ces gestionnaires de menu (gauche et haut) sont complètement opérationnels et offrent la même vision mais en utilisant une technologie de stockage différente.&lt;br /&gt;
&lt;br /&gt;
Pour personnaliser ces menus par défaut, vous pouvez, soit ajouter votre propre entrée menu, soit développer votre propre gestionnaire de menu qui remplacera complètement le gestionnaire par défaut. Vous décidez alors comment stocker votre menu (en base de données comme avec le gestionnaire de menu &#039;&#039;&#039;auguria&#039;&#039;&#039;, centralisé en dur dans un fichier comme avec le gestionnaire de menu &#039;&#039;&#039;eldy&#039;&#039;&#039;, dans un fichier xml, ...). Voir les chapitres suivants pour cela....&lt;br /&gt;
&lt;br /&gt;
=Ajouter votre entrée menu=&lt;br /&gt;
Imaginez que vous vouliez ajouter une entrée menu. Allez dans &#039;&#039;&#039;Accueil - Configuration - Menus&#039;&#039;&#039;. Choisissez &#039;&#039;&#039;Editeur de menu&#039;&#039;&#039;. Ajoutez l&#039;entrée. &lt;br /&gt;
&lt;br /&gt;
Par exemple, pour ajouter une entrée de menu afin d&#039;arriver sur la page qui liste uniquement les opportunités avec les filtres déjà positionnées, vous ajouterez une entrée qui ressemblera à ceci:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;divforimgcentpercent&amp;quot;&amp;gt;&lt;br /&gt;
[[File:Menu editor.png]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Développer son propre système de menu=&lt;br /&gt;
&lt;br /&gt;
Le but de cet article est de décrire comment créer un nouveau système de menu dans son intégralité (remplacement de l&#039;intégralité des entrées menus, chamboulement complet du concept de navigation).&lt;br /&gt;
&lt;br /&gt;
Cela ne concerne pas le simple ajout d&#039;entrées de menus. Si tel et le cas et que vous désirez juste savoir comment ajouter des entrées menus au sein d&#039;un gestionnaire de menu existant, dans le cadre du développement d&#039;une extension ou d&#039;un nouveau module par exemple, reporter vous plutôt à la page [[Developpement module]].&lt;br /&gt;
&lt;br /&gt;
Si vous voulez remplacer intégralement un systeme de menu par le votre, le plus simple est de prendre exemple sur le gestionnaire de menu &amp;quot;eldy_backoffice&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Pour développer son &#039;&#039;&#039;système de menu haut&#039;&#039;&#039;==&lt;br /&gt;
Il suffit de&lt;br /&gt;
&lt;br /&gt;
#Copier le fichier htdocs/core/menus/standard/eldy_backoffice.php sous un autre nom comme htdocs/core/menus/standard/monmenu.php&lt;br /&gt;
#Editer ensuite le fichier monmenu.php. La fonction showmenu() de la classe MenuTop est la fonction appelée par Dolibarr lorsqu&#039;il génère une page pour afficher ce menu haut. On peut y mettre le code que l&#039;on veut, cette fonction ne modifie aucune variable extérieur et doit juste afficher par des &amp;quot;print&amp;quot; le menu que l&#039;on veut voir. On peut ainsi récupérer le menu à afficher depuis un fichier de configuration, une base de données et le personnaliser par rapport à l&#039;environnement. L&#039;environnement Dolibarr étant stocké dans les 3 objets global suivant: $user, $conf, $langs.&lt;br /&gt;
&lt;br /&gt;
 $user contient les informations propres à l&#039;utilisateur.&lt;br /&gt;
 $conf contient les informations propres à la configuration (modules actifs, permissions actives, etc...)&lt;br /&gt;
 $langs contient les informations propres à la langue active.&lt;br /&gt;
&lt;br /&gt;
Exemple de fonction showmenu() du fichier htdocs/core/menus/standard/monmenu.php&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
    function showmenu()&lt;br /&gt;
    {&lt;br /&gt;
        global $user,$conf,$langs,$dolibarr_main_db_name;&lt;br /&gt;
        &lt;br /&gt;
        print &#039;&amp;lt;table class=&amp;quot;tmenu&amp;quot;&amp;gt;&amp;lt;tr class=&amp;quot;tmenu&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
	    // Menu Home&lt;br /&gt;
	    print &#039;&amp;lt;td class=&amp;quot;tmenu&amp;quot;&amp;gt;&amp;lt;a &#039;.$class.&#039; href=&amp;quot;&#039;.DOL_URL_ROOT.&#039;/index.php?mainmenu=home&amp;amp;leftmenu=&amp;quot;&#039;.($this-&amp;gt;atarget?&amp;quot; target=&amp;quot;.$this-&amp;gt;atarget:&amp;quot;&amp;quot;).&#039;&amp;gt;&#039;.$langs-&amp;gt;trans(&amp;quot;Home&amp;quot;).&#039;&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&#039;;&lt;br /&gt;
	    &lt;br /&gt;
	    // Put here other entries&lt;br /&gt;
	    // ...&lt;br /&gt;
	    &lt;br /&gt;
        print &#039;&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pour développer son &#039;&#039;&#039;système de menu gauche&#039;&#039;&#039;==&lt;br /&gt;
Le principe est aussi simple que le menu haut.&lt;br /&gt;
&lt;br /&gt;
#Copier le fichier htdocs/core/menus/standard/eldy_backoffice.php sous un autre nom comme htdocs/core/menus/standard/monmenu.php.&lt;br /&gt;
#Il faut ensuite modifier la fonction showmenu() de la classe MenuLeft afin de fabriquer son menu gauche. Si on veut afficher le menu standard ou juste le modifier légèrement sans recréer le sien complètement, il suffit de boucler sur le contenu du tableau $menu-&amp;gt;liste. Si vous voulez afficher un menu complètement différent et totalement contrôlé par vous, il vous faut, dans la fonction showmenu(), créer un objet $newmenu=new Menu() et utiliser les méthodes $newmenu-&amp;gt;add et $newmenu-&amp;gt;add_submenu pour définir la liste des entrées menu gauche à faire apparaitre. Une fois cela fait, on affiche par des &amp;quot;print&amp;quot; le contenu du tableau $newmenu-&amp;gt;liste (qui vient d’être construit) au lieu de $menu-&amp;gt;liste.&lt;br /&gt;
&lt;br /&gt;
Exemple de fichier htdocs/core/menus/standard/monmenu.php&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
    function showmenu()&lt;br /&gt;
    {&lt;br /&gt;
        global $user,$conf,$langs,$dolibarr_main_db_name;&lt;br /&gt;
        $newmenu = new Menu();&lt;br /&gt;
        &lt;br /&gt;
	// Put here left menu entries&lt;br /&gt;
	// ***** START *****&lt;br /&gt;
&lt;br /&gt;
	$langs-&amp;gt;load(&amp;quot;admin&amp;quot;);	// Load translation file admin.lang&lt;br /&gt;
	$newmenu-&amp;gt;add(DOL_URL_ROOT.&amp;quot;/admin/index.php?leftmenu=setup&amp;quot;, $langs-&amp;gt;trans(&amp;quot;Setup&amp;quot;));&lt;br /&gt;
	$newmenu-&amp;gt;add_submenu(DOL_URL_ROOT.&amp;quot;/admin/company.php&amp;quot;, $langs-&amp;gt;trans(&amp;quot;MenuCompanySetup&amp;quot;));&lt;br /&gt;
	$newmenu-&amp;gt;add_submenu(DOL_URL_ROOT.&amp;quot;/admin/modules.php&amp;quot;, $langs-&amp;gt;trans(&amp;quot;Modules&amp;quot;));&lt;br /&gt;
	$newmenu-&amp;gt;add_submenu(DOL_URL_ROOT.&amp;quot;/admin/ihm.php&amp;quot;, $langs-&amp;gt;trans(&amp;quot;GUISetup&amp;quot;));&lt;br /&gt;
	$newmenu-&amp;gt;add_submenu(DOL_URL_ROOT.&amp;quot;/admin/boxes.php&amp;quot;, $langs-&amp;gt;trans(&amp;quot;Boxes&amp;quot;));&lt;br /&gt;
	$newmenu-&amp;gt;add_submenu(DOL_URL_ROOT.&amp;quot;/admin/delais.php&amp;quot;,$langs-&amp;gt;trans(&amp;quot;Alerts&amp;quot;));&lt;br /&gt;
	$newmenu-&amp;gt;add_submenu(DOL_URL_ROOT.&amp;quot;/admin/triggers.php&amp;quot;, $langs-&amp;gt;trans(&amp;quot;Triggers&amp;quot;));&lt;br /&gt;
	$newmenu-&amp;gt;add_submenu(DOL_URL_ROOT.&amp;quot;/admin/perms.php&amp;quot;, $langs-&amp;gt;trans(&amp;quot;Security&amp;quot;));&lt;br /&gt;
	$newmenu-&amp;gt;add_submenu(DOL_URL_ROOT.&amp;quot;/admin/dict.php&amp;quot;, $langs-&amp;gt;trans(&amp;quot;DictionnarySetup&amp;quot;));&lt;br /&gt;
	$newmenu-&amp;gt;add_submenu(DOL_URL_ROOT.&amp;quot;/admin/const.php&amp;quot;, $langs-&amp;gt;trans(&amp;quot;OtherSetup&amp;quot;));&lt;br /&gt;
		&lt;br /&gt;
	// ***** END *****&lt;br /&gt;
		&lt;br /&gt;
        // do not change code after this&lt;br /&gt;
&lt;br /&gt;
        // override menu_array by value array in $newmenu&lt;br /&gt;
	$this-&amp;gt;menu_array=$newmenu-&amp;gt;liste;&lt;br /&gt;
&lt;br /&gt;
        $alt=0;&lt;br /&gt;
        for ($i = 0 ; $i &amp;lt; sizeof($this-&amp;gt;menu_array) ; $i++) &lt;br /&gt;
        {&lt;br /&gt;
            $alt++;&lt;br /&gt;
            if ($this-&amp;gt;menu_array[$i][&#039;level&#039;]==0) {&lt;br /&gt;
                if (($alt%2==0))&lt;br /&gt;
                {&lt;br /&gt;
                    print &#039;&amp;lt;div class=&amp;quot;blockvmenuimpair&amp;quot;&amp;gt;&#039;.&amp;quot;\n&amp;quot;;&lt;br /&gt;
                }&lt;br /&gt;
                else&lt;br /&gt;
                {&lt;br /&gt;
                    print &#039;&amp;lt;div class=&amp;quot;blockvmenupair&amp;quot;&amp;gt;&#039;.&amp;quot;\n&amp;quot;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            if ($this-&amp;gt;menu_array[$i][&#039;level&#039;]==0) {&lt;br /&gt;
                if ($this-&amp;gt;menu_array[$i][&#039;enabled&#039;])&lt;br /&gt;
                    print &#039;&amp;lt;a class=&amp;quot;vmenu&amp;quot; href=&amp;quot;&#039;.$this-&amp;gt;menu_array[$i][&#039;url&#039;].&#039;&amp;quot;&amp;gt;&#039;.$this-&amp;gt;menu_array[$i][&#039;titre&#039;].&#039;&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                else &lt;br /&gt;
                    print &#039;&amp;lt;font class=&amp;quot;vmenudisabled&amp;quot;&amp;gt;&#039;.$this-&amp;gt;menu_array[$i][&#039;titre&#039;].&#039;&amp;lt;/font&amp;gt;&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            if ($this-&amp;gt;menu_array[$i][&#039;level&#039;]==1) {&lt;br /&gt;
                if ($this-&amp;gt;menu_array[$i][&#039;enabled&#039;])&lt;br /&gt;
                    print &#039;&amp;lt;a class=&amp;quot;vsmenu&amp;quot; href=&amp;quot;&#039;.$this-&amp;gt;menu_array[$i][&#039;url&#039;].&#039;&amp;quot;&amp;gt;&#039;.$this-&amp;gt;menu_array[$i][&#039;titre&#039;].&#039;&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                else &lt;br /&gt;
                    print &#039;&amp;lt;font class=&amp;quot;vsmenudisabled&amp;quot;&amp;gt;&#039;.$this-&amp;gt;menu_array[$i][&#039;titre&#039;].&#039;&amp;lt;/font&amp;gt;&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            if ($this-&amp;gt;menu_array[$i][&#039;level&#039;]==2) {&lt;br /&gt;
                if ($this-&amp;gt;menu_array[$i][&#039;enabled&#039;])&lt;br /&gt;
                    print &#039;&amp;amp;nbsp; &amp;amp;nbsp; &amp;lt;a class=&amp;quot;vsmenu&amp;quot; href=&amp;quot;&#039;.$this-&amp;gt;menu_array[$i][&#039;url&#039;].&#039;&amp;quot;&amp;gt;&#039;.$this-&amp;gt;menu_array[$i][&#039;titre&#039;].&#039;&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                else &lt;br /&gt;
                    print &#039;&amp;amp;nbsp; &amp;amp;nbsp; &amp;lt;font class=&amp;quot;vsmenudisabled&amp;quot;&amp;gt;&#039;.$this-&amp;gt;menu_array[$i][&#039;titre&#039;].&#039;&amp;lt;/font&amp;gt;&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            if ($this-&amp;gt;menu_array[$i][&#039;level&#039;]==3) {&lt;br /&gt;
                if ($this-&amp;gt;menu_array[$i][&#039;enabled&#039;])&lt;br /&gt;
                    print &#039;&amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;lt;a class=&amp;quot;vsmenu&amp;quot; href=&amp;quot;&#039;.$this-&amp;gt;menu_array[$i][&#039;url&#039;].&#039;&amp;quot;&amp;gt;&#039;.$this-&amp;gt;menu_array[$i][&#039;titre&#039;].&#039;&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                else &lt;br /&gt;
                    print &#039;&amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;lt;font class=&amp;quot;vsmenudisabled&amp;quot;&amp;gt;&#039;.$this-&amp;gt;menu_array[$i][&#039;titre&#039;].&#039;&amp;lt;/font&amp;gt;&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            &lt;br /&gt;
            if ($i == (sizeof($this-&amp;gt;menu_array)-1) || $this-&amp;gt;menu_array[$i+1][&#039;level&#039;]==0)  {&lt;br /&gt;
                print &amp;quot;&amp;lt;/div&amp;gt;\n&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Forcer l&#039;utilisation de votre gestionnaire de menu=&lt;br /&gt;
Vous pouvez aussi forcer l&#039;utilisation de votre gestionnaire au dépend de tout autre en développant un module.&lt;br /&gt;
Pour cela, il suffit d&#039;ajouter les 4 constantes suivantes dans le tableau $this-&amp;gt;const de votre descripteur de module (Voir la page [[Développement module]]).&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
* 1=&amp;gt;array(&#039;MAIN_MENU_STANDARD_FORCED&#039;,&#039;chaine&#039;,&#039;monmenu.php&#039;,&#039;Force menu handler to this value&#039;,1,&#039;current&#039;,1),&lt;br /&gt;
* 2=&amp;gt;array(&#039;MAIN_MENUFRONT_STANDARD_FORCED&#039;,&#039;chaine&#039;,&#039;monmenu.php&#039;,&#039;Force menu handler to this value&#039;,1,&#039;current&#039;,1),&lt;br /&gt;
* 3=&amp;gt;array(&#039;MAIN_MENU_SMARTPHONE_FORCED&#039;,&#039;chaine&#039;,&#039;monmenu.php&#039;,&#039;Force menu handler to this value&#039;,1,&#039;current&#039;,1),&lt;br /&gt;
* 4=&amp;gt;array(&#039;MAIN_MENUFRONT_SMARTPHONE_FORCED&#039;,&#039;chaine&#039;,&#039;monmenu.php&#039;,&#039;Force menu handler to this value&#039;,1,&#039;current&#039;,1),&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Votre gestionnaire de menu sera utilisé, quelque soit la configuration, une fois que le module aura été activé.&lt;/div&gt;</summary>
		<author><name>Quentic</name></author>
	</entry>
	<entry>
		<id>https://wiki.dolibarr.org/index.php?title=Syst%C3%A8me_de_menus&amp;diff=52106</id>
		<title>Système de menus</title>
		<link rel="alternate" type="text/html" href="https://wiki.dolibarr.org/index.php?title=Syst%C3%A8me_de_menus&amp;diff=52106"/>
		<updated>2021-09-30T08:10:31Z</updated>

		<summary type="html">&lt;p&gt;Quentic: /* Le système de menu Dolibarr */Correction d&amp;#039;erreur de frappe&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- BEGIN interlang links --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Do NOT edit this section&lt;br /&gt;
     Links below are automatically managed by PolyglotBot&lt;br /&gt;
     You can edit links on the English source page : Menus_system --&amp;gt;&lt;br /&gt;
[[en:Menus_system]]&lt;br /&gt;
[[es:Sistema_de_menús]]&lt;br /&gt;
[[de:Menü_System]]&lt;br /&gt;
[[zh:菜单]]&lt;br /&gt;
&amp;lt;!-- END interlang links --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Noyau]]&lt;br /&gt;
{{TemplateDocDev}}&lt;br /&gt;
&lt;br /&gt;
=Le système de menu Dolibarr=&lt;br /&gt;
&lt;br /&gt;
Il y a 2 systèmes de menu. Un système de menu définit les entrées de menu à afficher, conditions et localisation.&lt;br /&gt;
&lt;br /&gt;
Changer de système de menu est possible via la page &#039;&#039;&#039;Configuration - Menus&#039;&#039;&#039;. Choisir ensuite &#039;&#039;&#039;Editeur de menus&#039;&#039;&#039;. Prendre par exemple les gestionnaires de menu &amp;quot;auguria&amp;quot;, fournis en standard au lieu de &amp;quot;eldy&amp;quot;. Ces gestionnaires de menu (gauche et haut) sont complètement opérationnels et offrent la même vision mais en utilisant une technologie de stockage différente.&lt;br /&gt;
&lt;br /&gt;
Pour personnaliser ces menus par défaut, vous pouvez, soit ajouter votre propre entrée menu, soit développer votre propre gestionnaire de menu qui remplacera complètement le gestionnaire par défaut. Vous décidez alors comment stocker votre menu (en base de données comme avec le gestionnaire de menu &#039;&#039;&#039;auguria&#039;&#039;&#039;, centralisé en dur dans un fichier comme avec le gestionnaire de menu &#039;&#039;&#039;eldy&#039;&#039;&#039;, dans un fichier xml, ...). Voir les chapitres suivants pour cela....&lt;br /&gt;
&lt;br /&gt;
=Ajouter votre entrée menu=&lt;br /&gt;
Imaginez que vous vouliez ajouter une entrée menu. Allez dans &#039;&#039;&#039;Accueil - Configuration - Menus&#039;&#039;&#039;. Choisir &#039;&#039;&#039;Editeur de menu&#039;&#039;&#039;. Ajouter l&#039;entrée. &lt;br /&gt;
&lt;br /&gt;
Par exemple, pour ajouter une entrée de menu afin d&#039;arriver sur la page qui liste uniquement les opportunités avec les filtres déjà positionnées, vous ajouterez une entrée qui ressemblera à ceci:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;divforimgcentpercent&amp;quot;&amp;gt;&lt;br /&gt;
[[File:Menu editor.png]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Développer son propre système de menu=&lt;br /&gt;
&lt;br /&gt;
Le but de cet article est de décrire comment créer un nouveau système de menu dans son intégralité (remplacement de l&#039;intégralité des entrées menus, chamboulement complet du concept de navigation).&lt;br /&gt;
&lt;br /&gt;
Cela ne concerne pas le simple ajout d&#039;entrées de menus. Si tel et le cas et que vous désirez juste savoir comment ajouter des entrées menus au sein d&#039;un gestionnaire de menu existant, dans le cadre du développement d&#039;une extension ou d&#039;un nouveau module par exemple, reporter vous plutôt à la page [[Developpement module]].&lt;br /&gt;
&lt;br /&gt;
Si vous voulez remplacer intégralement un systeme de menu par le votre, le plus simple est de prendre exemple sur le gestionnaire de menu &amp;quot;eldy_backoffice&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Pour développer son &#039;&#039;&#039;système de menu haut&#039;&#039;&#039;==&lt;br /&gt;
Il suffit de&lt;br /&gt;
&lt;br /&gt;
#Copier le fichier htdocs/core/menus/standard/eldy_backoffice.php sous un autre nom comme htdocs/core/menus/standard/monmenu.php&lt;br /&gt;
#Editer ensuite le fichier monmenu.php. La fonction showmenu() de la classe MenuTop est la fonction appelée par Dolibarr lorsqu&#039;il génère une page pour afficher ce menu haut. On peut y mettre le code que l&#039;on veut, cette fonction ne modifie aucune variable extérieur et doit juste afficher par des &amp;quot;print&amp;quot; le menu que l&#039;on veut voir. On peut ainsi récupérer le menu à afficher depuis un fichier de configuration, une base de données et le personnaliser par rapport à l&#039;environnement. L&#039;environnement Dolibarr étant stocké dans les 3 objets global suivant: $user, $conf, $langs.&lt;br /&gt;
&lt;br /&gt;
 $user contient les informations propres à l&#039;utilisateur.&lt;br /&gt;
 $conf contient les informations propres à la configuration (modules actifs, permissions actives, etc...)&lt;br /&gt;
 $langs contient les informations propres à la langue active.&lt;br /&gt;
&lt;br /&gt;
Exemple de fonction showmenu() du fichier htdocs/core/menus/standard/monmenu.php&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
    function showmenu()&lt;br /&gt;
    {&lt;br /&gt;
        global $user,$conf,$langs,$dolibarr_main_db_name;&lt;br /&gt;
        &lt;br /&gt;
        print &#039;&amp;lt;table class=&amp;quot;tmenu&amp;quot;&amp;gt;&amp;lt;tr class=&amp;quot;tmenu&amp;quot;&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
	    // Menu Home&lt;br /&gt;
	    print &#039;&amp;lt;td class=&amp;quot;tmenu&amp;quot;&amp;gt;&amp;lt;a &#039;.$class.&#039; href=&amp;quot;&#039;.DOL_URL_ROOT.&#039;/index.php?mainmenu=home&amp;amp;leftmenu=&amp;quot;&#039;.($this-&amp;gt;atarget?&amp;quot; target=&amp;quot;.$this-&amp;gt;atarget:&amp;quot;&amp;quot;).&#039;&amp;gt;&#039;.$langs-&amp;gt;trans(&amp;quot;Home&amp;quot;).&#039;&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&#039;;&lt;br /&gt;
	    &lt;br /&gt;
	    // Put here other entries&lt;br /&gt;
	    // ...&lt;br /&gt;
	    &lt;br /&gt;
        print &#039;&amp;lt;/tr&amp;gt;&amp;lt;/table&amp;gt;&#039;;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Pour développer son &#039;&#039;&#039;système de menu gauche&#039;&#039;&#039;==&lt;br /&gt;
Le principe est aussi simple que le menu haut.&lt;br /&gt;
&lt;br /&gt;
#Copier le fichier htdocs/core/menus/standard/eldy_backoffice.php sous un autre nom comme htdocs/core/menus/standard/monmenu.php.&lt;br /&gt;
#Il faut ensuite modifier la fonction showmenu() de la classe MenuLeft afin de fabriquer son menu gauche. Si on veut afficher le menu standard ou juste le modifier légèrement sans recréer le sien complètement, il suffit de boucler sur le contenu du tableau $menu-&amp;gt;liste. Si vous voulez afficher un menu complètement différent et totalement contrôlé par vous, il vous faut, dans la fonction showmenu(), créer un objet $newmenu=new Menu() et utiliser les méthodes $newmenu-&amp;gt;add et $newmenu-&amp;gt;add_submenu pour définir la liste des entrées menu gauche à faire apparaitre. Une fois cela fait, on affiche par des &amp;quot;print&amp;quot; le contenu du tableau $newmenu-&amp;gt;liste (qui vient d’être construit) au lieu de $menu-&amp;gt;liste.&lt;br /&gt;
&lt;br /&gt;
Exemple de fichier htdocs/core/menus/standard/monmenu.php&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
    function showmenu()&lt;br /&gt;
    {&lt;br /&gt;
        global $user,$conf,$langs,$dolibarr_main_db_name;&lt;br /&gt;
        $newmenu = new Menu();&lt;br /&gt;
        &lt;br /&gt;
	// Put here left menu entries&lt;br /&gt;
	// ***** START *****&lt;br /&gt;
&lt;br /&gt;
	$langs-&amp;gt;load(&amp;quot;admin&amp;quot;);	// Load translation file admin.lang&lt;br /&gt;
	$newmenu-&amp;gt;add(DOL_URL_ROOT.&amp;quot;/admin/index.php?leftmenu=setup&amp;quot;, $langs-&amp;gt;trans(&amp;quot;Setup&amp;quot;));&lt;br /&gt;
	$newmenu-&amp;gt;add_submenu(DOL_URL_ROOT.&amp;quot;/admin/company.php&amp;quot;, $langs-&amp;gt;trans(&amp;quot;MenuCompanySetup&amp;quot;));&lt;br /&gt;
	$newmenu-&amp;gt;add_submenu(DOL_URL_ROOT.&amp;quot;/admin/modules.php&amp;quot;, $langs-&amp;gt;trans(&amp;quot;Modules&amp;quot;));&lt;br /&gt;
	$newmenu-&amp;gt;add_submenu(DOL_URL_ROOT.&amp;quot;/admin/ihm.php&amp;quot;, $langs-&amp;gt;trans(&amp;quot;GUISetup&amp;quot;));&lt;br /&gt;
	$newmenu-&amp;gt;add_submenu(DOL_URL_ROOT.&amp;quot;/admin/boxes.php&amp;quot;, $langs-&amp;gt;trans(&amp;quot;Boxes&amp;quot;));&lt;br /&gt;
	$newmenu-&amp;gt;add_submenu(DOL_URL_ROOT.&amp;quot;/admin/delais.php&amp;quot;,$langs-&amp;gt;trans(&amp;quot;Alerts&amp;quot;));&lt;br /&gt;
	$newmenu-&amp;gt;add_submenu(DOL_URL_ROOT.&amp;quot;/admin/triggers.php&amp;quot;, $langs-&amp;gt;trans(&amp;quot;Triggers&amp;quot;));&lt;br /&gt;
	$newmenu-&amp;gt;add_submenu(DOL_URL_ROOT.&amp;quot;/admin/perms.php&amp;quot;, $langs-&amp;gt;trans(&amp;quot;Security&amp;quot;));&lt;br /&gt;
	$newmenu-&amp;gt;add_submenu(DOL_URL_ROOT.&amp;quot;/admin/dict.php&amp;quot;, $langs-&amp;gt;trans(&amp;quot;DictionnarySetup&amp;quot;));&lt;br /&gt;
	$newmenu-&amp;gt;add_submenu(DOL_URL_ROOT.&amp;quot;/admin/const.php&amp;quot;, $langs-&amp;gt;trans(&amp;quot;OtherSetup&amp;quot;));&lt;br /&gt;
		&lt;br /&gt;
	// ***** END *****&lt;br /&gt;
		&lt;br /&gt;
        // do not change code after this&lt;br /&gt;
&lt;br /&gt;
        // override menu_array by value array in $newmenu&lt;br /&gt;
	$this-&amp;gt;menu_array=$newmenu-&amp;gt;liste;&lt;br /&gt;
&lt;br /&gt;
        $alt=0;&lt;br /&gt;
        for ($i = 0 ; $i &amp;lt; sizeof($this-&amp;gt;menu_array) ; $i++) &lt;br /&gt;
        {&lt;br /&gt;
            $alt++;&lt;br /&gt;
            if ($this-&amp;gt;menu_array[$i][&#039;level&#039;]==0) {&lt;br /&gt;
                if (($alt%2==0))&lt;br /&gt;
                {&lt;br /&gt;
                    print &#039;&amp;lt;div class=&amp;quot;blockvmenuimpair&amp;quot;&amp;gt;&#039;.&amp;quot;\n&amp;quot;;&lt;br /&gt;
                }&lt;br /&gt;
                else&lt;br /&gt;
                {&lt;br /&gt;
                    print &#039;&amp;lt;div class=&amp;quot;blockvmenupair&amp;quot;&amp;gt;&#039;.&amp;quot;\n&amp;quot;;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            if ($this-&amp;gt;menu_array[$i][&#039;level&#039;]==0) {&lt;br /&gt;
                if ($this-&amp;gt;menu_array[$i][&#039;enabled&#039;])&lt;br /&gt;
                    print &#039;&amp;lt;a class=&amp;quot;vmenu&amp;quot; href=&amp;quot;&#039;.$this-&amp;gt;menu_array[$i][&#039;url&#039;].&#039;&amp;quot;&amp;gt;&#039;.$this-&amp;gt;menu_array[$i][&#039;titre&#039;].&#039;&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                else &lt;br /&gt;
                    print &#039;&amp;lt;font class=&amp;quot;vmenudisabled&amp;quot;&amp;gt;&#039;.$this-&amp;gt;menu_array[$i][&#039;titre&#039;].&#039;&amp;lt;/font&amp;gt;&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            if ($this-&amp;gt;menu_array[$i][&#039;level&#039;]==1) {&lt;br /&gt;
                if ($this-&amp;gt;menu_array[$i][&#039;enabled&#039;])&lt;br /&gt;
                    print &#039;&amp;lt;a class=&amp;quot;vsmenu&amp;quot; href=&amp;quot;&#039;.$this-&amp;gt;menu_array[$i][&#039;url&#039;].&#039;&amp;quot;&amp;gt;&#039;.$this-&amp;gt;menu_array[$i][&#039;titre&#039;].&#039;&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                else &lt;br /&gt;
                    print &#039;&amp;lt;font class=&amp;quot;vsmenudisabled&amp;quot;&amp;gt;&#039;.$this-&amp;gt;menu_array[$i][&#039;titre&#039;].&#039;&amp;lt;/font&amp;gt;&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            if ($this-&amp;gt;menu_array[$i][&#039;level&#039;]==2) {&lt;br /&gt;
                if ($this-&amp;gt;menu_array[$i][&#039;enabled&#039;])&lt;br /&gt;
                    print &#039;&amp;amp;nbsp; &amp;amp;nbsp; &amp;lt;a class=&amp;quot;vsmenu&amp;quot; href=&amp;quot;&#039;.$this-&amp;gt;menu_array[$i][&#039;url&#039;].&#039;&amp;quot;&amp;gt;&#039;.$this-&amp;gt;menu_array[$i][&#039;titre&#039;].&#039;&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                else &lt;br /&gt;
                    print &#039;&amp;amp;nbsp; &amp;amp;nbsp; &amp;lt;font class=&amp;quot;vsmenudisabled&amp;quot;&amp;gt;&#039;.$this-&amp;gt;menu_array[$i][&#039;titre&#039;].&#039;&amp;lt;/font&amp;gt;&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            if ($this-&amp;gt;menu_array[$i][&#039;level&#039;]==3) {&lt;br /&gt;
                if ($this-&amp;gt;menu_array[$i][&#039;enabled&#039;])&lt;br /&gt;
                    print &#039;&amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;lt;a class=&amp;quot;vsmenu&amp;quot; href=&amp;quot;&#039;.$this-&amp;gt;menu_array[$i][&#039;url&#039;].&#039;&amp;quot;&amp;gt;&#039;.$this-&amp;gt;menu_array[$i][&#039;titre&#039;].&#039;&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
                else &lt;br /&gt;
                    print &#039;&amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;lt;font class=&amp;quot;vsmenudisabled&amp;quot;&amp;gt;&#039;.$this-&amp;gt;menu_array[$i][&#039;titre&#039;].&#039;&amp;lt;/font&amp;gt;&amp;lt;br&amp;gt;&#039;;&lt;br /&gt;
            }&lt;br /&gt;
            &lt;br /&gt;
            if ($i == (sizeof($this-&amp;gt;menu_array)-1) || $this-&amp;gt;menu_array[$i+1][&#039;level&#039;]==0)  {&lt;br /&gt;
                print &amp;quot;&amp;lt;/div&amp;gt;\n&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Forcer l&#039;utilisation de votre gestionnaire de menu=&lt;br /&gt;
Vous pouvez aussi forcer l&#039;utilisation de votre gestionnaire au dépend de tout autre en développant un module.&lt;br /&gt;
Pour cela, il suffit d&#039;ajouter les 4 constantes suivantes dans le tableau $this-&amp;gt;const de votre descripteur de module (Voir la page [[Développement module]]).&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
* 1=&amp;gt;array(&#039;MAIN_MENU_STANDARD_FORCED&#039;,&#039;chaine&#039;,&#039;monmenu.php&#039;,&#039;Force menu handler to this value&#039;,1,&#039;current&#039;,1),&lt;br /&gt;
* 2=&amp;gt;array(&#039;MAIN_MENUFRONT_STANDARD_FORCED&#039;,&#039;chaine&#039;,&#039;monmenu.php&#039;,&#039;Force menu handler to this value&#039;,1,&#039;current&#039;,1),&lt;br /&gt;
* 3=&amp;gt;array(&#039;MAIN_MENU_SMARTPHONE_FORCED&#039;,&#039;chaine&#039;,&#039;monmenu.php&#039;,&#039;Force menu handler to this value&#039;,1,&#039;current&#039;,1),&lt;br /&gt;
* 4=&amp;gt;array(&#039;MAIN_MENUFRONT_SMARTPHONE_FORCED&#039;,&#039;chaine&#039;,&#039;monmenu.php&#039;,&#039;Force menu handler to this value&#039;,1,&#039;current&#039;,1),&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Votre gestionnaire de menu sera utilisé, quelque soit la configuration, une fois que le module aura été activé.&lt;/div&gt;</summary>
		<author><name>Quentic</name></author>
	</entry>
	<entry>
		<id>https://wiki.dolibarr.org/index.php?title=Projet_Dolibarr&amp;diff=52105</id>
		<title>Projet Dolibarr</title>
		<link rel="alternate" type="text/html" href="https://wiki.dolibarr.org/index.php?title=Projet_Dolibarr&amp;diff=52105"/>
		<updated>2021-09-30T08:06:47Z</updated>

		<summary type="html">&lt;p&gt;Quentic: /* Et Dark Vador ? */Correction d&amp;#039;erreur de frappe&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- BEGIN interlang links --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Do NOT edit this section&lt;br /&gt;
     Links below are automatically managed by PolyglotBot&lt;br /&gt;
     You can edit links on the English source page : Dolibarr_Project --&amp;gt;&lt;br /&gt;
[[en:Dolibarr_Project]]&lt;br /&gt;
[[es:Proyecto_Dolibarr]]&lt;br /&gt;
&amp;lt;!-- END interlang links --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{TemplateDocDevFr}}&lt;br /&gt;
{{TemplateDocUtil}}&lt;br /&gt;
Cette page fournit des informations sur l&#039;organisation du projet, les rôles occupés par les différents acteurs (ainsi que les postes à pourvoir) et comment participer.&lt;br /&gt;
&lt;br /&gt;
=[[File:orientation.png]] Histoire et futur du projet (Roadmap)=&lt;br /&gt;
Voir la page [[Origines et histoire du projet|Origines, histoire et futures versions de Dolibarr]]&lt;br /&gt;
&lt;br /&gt;
=[[File:who.png]] Les acteurs et leurs rôles dans la galaxie Dolibarr=&lt;br /&gt;
&lt;br /&gt;
L&#039;équipe Dolibarr actuelle est constituée de différents responsables, soutenus (voire sponsorisés) par divers contributeurs physiques ou moral (sociétés, associations).&lt;br /&gt;
Les lignes suivantes présentent les différents rôles et postes occupés dans la gestion du projet Dolibarr et permettent ainsi de comprendre le fonctionnement interne du projet.&lt;br /&gt;
De nombreux rôles et postes sont en permanence à pourvoir.&lt;br /&gt;
&lt;br /&gt;
Les volontaires pour postuler à une responsabilité dans le projet sont invités à se manifester sur la mailing list dev de Dolibarr.&lt;br /&gt;
&lt;br /&gt;
Si vous désirez des informations pour participer en tant que développeur, la page [[FAQ_D%C3%A9veloppeur#Comment_devenir_d.C3.A9veloppeur_officiel|FAQ Développeur - Comment devenir développeur officiel]] est peut-être plus appropriée.&lt;br /&gt;
&lt;br /&gt;
Les liens suivants présentent une liste des acteurs qui participent ou ont participé au projet.&lt;br /&gt;
&lt;br /&gt;
*[[:Category:Everybody|Tout le monde (+ trombinoscope)]]&lt;br /&gt;
*[[:Category:User Retired|Tous les acteurs retraités]]&lt;br /&gt;
*[[:Category:User Active|Tous les acteurs actifs]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La suite présente les différents &#039;&#039;&#039;rôles développeurs&#039;&#039;&#039; dans un premier temps puis tous les &#039;&#039;&#039;rôles non développeurs&#039;&#039;&#039;. Tous ces rôles constituent un part du moteur de l&#039;avancement de Dolibarr.&lt;br /&gt;
&lt;br /&gt;
==Les rôles développeurs==&lt;br /&gt;
&lt;br /&gt;
===Développeur grade [[FAQ_D%C3%A9veloppeur#Yoda|Yoda]] (Chefs de projet commiteurs GIT, head release manager et B.D.F.L)===&lt;br /&gt;
&lt;br /&gt;
Objectifs/Autorisations: Gérer le projet Dolibarr au sens large. Organiser les beta, figer les releases et réaliser le packaging de la version standard.&lt;br /&gt;
&lt;br /&gt;
Ont ce rôle actuellement (par ordre alphabétique):&lt;br /&gt;
&lt;br /&gt;
{{ListOfYodas|lang=FR}}&lt;br /&gt;
&lt;br /&gt;
Fonction à pourvoir: Non (par définition, ce rôle est limité au chef de projet et backups)&lt;br /&gt;
&lt;br /&gt;
Note: Tous les gestes pour construire un package pour une nouvelle version de Dolibarr sont définis dans le fichier &#039;&#039;&#039;build/makepack-howto.txt&#039;&#039;&#039; disponible avec les sources.&lt;br /&gt;
&lt;br /&gt;
===Développeur grade Jedi (Release manager versions de maintenance)===&lt;br /&gt;
&lt;br /&gt;
Objectifs/Autorisations: Packager et diffuser les releases des versions de maintenance.&lt;br /&gt;
&lt;br /&gt;
A ce rôle actuellement:&lt;br /&gt;
{{ListOfModulesWithDedicatedJedi&lt;br /&gt;
|lang=FR}}&lt;br /&gt;
&lt;br /&gt;
Fonction à pourvoir: Oui. Se manifester pour endosser ce rôle.&lt;br /&gt;
&lt;br /&gt;
===Développeur grade Amiral (Réaliseur de GIT Pull Request)===&lt;br /&gt;
&lt;br /&gt;
Objectifs/Autorisations : Développer, intégrer ou simplement valider et commiter dans le GIT.&lt;br /&gt;
&lt;br /&gt;
L&#039;obtention du grade d&#039;Amiral est automatique dès lors que votre premier Pull Request sous Git est validé et intégré dans Dolibarr. &lt;br /&gt;
&lt;br /&gt;
Fonction à pourvoir : Oui (Surtout pour la soumission de corrections de [https://github.com/dolibarr/dolibarr/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22 bogues déclarés sur Github], fortement recommandé pour commencer).&lt;br /&gt;
&lt;br /&gt;
Articles en relation : [[FAQ_Développeur#Comment_devenir_d.C3.A9veloppeur_officiel|FAQ Comment_devenir_développeur_officiel]].&lt;br /&gt;
&lt;br /&gt;
Identifiés comme ayant ce rôle actuellement ou récemment (comptes actifs dans {{TemplateURLSCM}}) :&lt;br /&gt;
&lt;br /&gt;
*Voir {{ListOfAdmirals|lang=FR}}&lt;br /&gt;
&lt;br /&gt;
===Développeur grade Z-6PO (Traducteurs sur transifex.com)===&lt;br /&gt;
&lt;br /&gt;
Objectifs/Autorisations : Traduire Dolibarr en utilisant la plateforme collaborative Transifex.&lt;br /&gt;
&lt;br /&gt;
Tous les utilisateurs qui sont enregistrés en tant que traducteur sur le projet Transifex Dolibarr sont Z-6PO.&lt;br /&gt;
&lt;br /&gt;
Identifiés comme ayant ce rôle actuellement:&lt;br /&gt;
&lt;br /&gt;
*Beaucoup de gens sont en fait des Z-6PO (à ce jour, plus de 1 150 contributeurs dans plus de 80 langues).&lt;br /&gt;
&lt;br /&gt;
Fonction à pourvoir : Oui (aller sur https://www.transifex.com/projects/p/dolibarr/ pour trouver votre langue et aider à la traduire),&lt;br /&gt;
&lt;br /&gt;
Articles en relation : [[Documentation traducteur]]&lt;br /&gt;
&lt;br /&gt;
===Développeur grade Soldat===&lt;br /&gt;
&lt;br /&gt;
Objectifs/Autorisations: Animer les forums, la communauté, promouvoir Dolibarr.&lt;br /&gt;
&lt;br /&gt;
Fonction à pourvoir : Oui (sans limite)&lt;br /&gt;
&lt;br /&gt;
Identifiés comme ayant ce rôle actuellement:&lt;br /&gt;
&lt;br /&gt;
*Nombre trop variable pour être recensé. Tout utilisateur Dolibarr est un soldat potentiel de l&#039;armée Dolibarr.&lt;br /&gt;
&lt;br /&gt;
===Et Dark Vador ?===&lt;br /&gt;
&lt;br /&gt;
Il existe hélas. Il y aura toujours des parasites qui polluent le forum ou la mailing-list de messages ou critiques non constructives, qui ralentissent le développement de Dolibarr plutôt que d&#039;offrir des critiques aidant à progresser. Certains sont très très forts en mauvaise foi ou mauvais ton. Ce sont eux que l&#039;on appellent les Dark Vador.&lt;br /&gt;
Heureusement, statistiquement, on ne constate l&#039;apparition et la mort que d&#039;un à deux Dark Vador par an environ ... Ce qui est un ratio très très bon par rapport aux autres projets Open-Source de même taille.&lt;br /&gt;
&lt;br /&gt;
==Les autres rôles dans le projet Dolibarr==&lt;br /&gt;
 &lt;br /&gt;
===Role A: Hébergement site web (https://www.dolibarr.org ou sites locaux)=== &lt;br /&gt;
&lt;br /&gt;
Objectif: Fournir et maintenir une plateforme d&#039;hébergement du site Dolibarr basée sur Joomla.&lt;br /&gt;
&lt;br /&gt;
A ce rôle actuellement:&lt;br /&gt;
{{HosterOfWebSites}}&lt;br /&gt;
&lt;br /&gt;
Fonction à pourvoir: Oui pour les autres langues/pays. Voir la page [[Create a Dolibarr local community]].&lt;br /&gt;
&lt;br /&gt;
===Role B: Hébergement site démo (https://demo.dolibarr.org&amp;lt;nowiki/&amp;gt;)=== &lt;br /&gt;
&lt;br /&gt;
Objectif: Fournir et maintenir une plateforme d&#039;hébergement du site de démo online Dolibarr (Version internationale, langage autodétecté).&lt;br /&gt;
&lt;br /&gt;
A ce rôle actuellement:&lt;br /&gt;
&lt;br /&gt;
*Dolibarr foundation (Version internationale avec langage auto-détecté https://demo.dolibarr.orgo)&lt;br /&gt;
&lt;br /&gt;
Fonction à pourvoir: Non&lt;br /&gt;
&lt;br /&gt;
===Role C1: Hébergement wiki (https://wiki.dolibarr.org&amp;lt;nowiki/&amp;gt;)=== &lt;br /&gt;
&lt;br /&gt;
Objectif: Fournir et maintenir une plateforme d&#039;hébergement du wiki Dolibarr&lt;br /&gt;
&lt;br /&gt;
A ce rôle actuellement: &lt;br /&gt;
&lt;br /&gt;
*Dolibarr foundation&lt;br /&gt;
&lt;br /&gt;
Fonction à pourvoir: Non&lt;br /&gt;
&lt;br /&gt;
===Role C2: Hébergement place de marché (https://wwww.dolistore.com&amp;lt;nowiki/&amp;gt;)=== &lt;br /&gt;
&lt;br /&gt;
Objectif: Fournir une plateforme de diffusion et/ou vente centralisant les modules externes (basée sur prestashop). Valider les soumissions de modules.&lt;br /&gt;
&lt;br /&gt;
A ce rôle actuellement&lt;br /&gt;
&lt;br /&gt;
*Dolibarr foundation (plateforme)&lt;br /&gt;
*[[Juanjo Menent]] (validation modules)&lt;br /&gt;
&lt;br /&gt;
Fonction à pourvoir: No&lt;br /&gt;
&lt;br /&gt;
===Role E1: Responsable DoliWamp (Installeur pour Windows)===&lt;br /&gt;
&lt;br /&gt;
A ce rôle actuellement: &lt;br /&gt;
&lt;br /&gt;
*[[Laurent Destailleur]] ([https://www.nltechno.com NLTechno])&lt;br /&gt;
&lt;br /&gt;
Fonction à pourvoir: Non&lt;br /&gt;
&lt;br /&gt;
===Role E2: Responsable DoliDeb+DoliRpm (Installeur pour Ubuntu/Debian/Fedora/Mandriva/Redhat/Opensuse)===&lt;br /&gt;
&lt;br /&gt;
A ce rôle actuellement: &lt;br /&gt;
&lt;br /&gt;
*[[Laurent Destailleur]] ([https://www.nltechno.com NLTechno])&lt;br /&gt;
&lt;br /&gt;
Fonction à pourvoir: Non&lt;br /&gt;
&lt;br /&gt;
===Role E3: Responsable DoliMamp (Installeur pour Mac OS X)===&lt;br /&gt;
&lt;br /&gt;
A ce rôle actuellement: &lt;br /&gt;
&lt;br /&gt;
*Personne&lt;br /&gt;
&lt;br /&gt;
Fonction à pourvoir: Oui&lt;br /&gt;
&lt;br /&gt;
===Role G: Gestion de l&#039;association Dolibarr===&lt;br /&gt;
&lt;br /&gt;
Objectif: Créer et gérer une association de promotion et d&#039;utilisateurs Dolibarr&lt;br /&gt;
&lt;br /&gt;
Identifiés comme ayant ce rôle actuellement: &lt;br /&gt;
&lt;br /&gt;
*1 président - Voir la page [[Association Dolibarr]].&lt;br /&gt;
*1 secrétaire - Voir la page [[Association Dolibarr]].&lt;br /&gt;
*1 trésorier - Voir la page [[Association Dolibarr]].&lt;br /&gt;
*D&#039;autres acteurs, membres du conseil d&#039;administration de l&#039;association - Voir la page [[Association Dolibarr]].&lt;br /&gt;
&lt;br /&gt;
===Role H: Promoteur/Communication pour Dolibarr===&lt;br /&gt;
&lt;br /&gt;
Objectif: Faire de la &#039;&#039;&#039;communication/évangélisation&#039;&#039;&#039; pour Dolibarr, sur les forums, sites de news, presse, etc... Mettre à jour la page wiki &#039;&#039;&#039;Revues de presse&#039;&#039;&#039; ([[Presse papier]]). Saisir des articles sur les sites de Dolibarr. Animer les réseaux sociaux.&lt;br /&gt;
&lt;br /&gt;
Identifiés comme ayant ce rôle actuellement:&lt;br /&gt;
&lt;br /&gt;
*L&#039;[[Association Dolibarr]]&lt;br /&gt;
*Fonction à pourvoir. Merci aux amateurs de se manifester sur la ML Dolibarr. Volontaires fortement désirés.&lt;br /&gt;
&lt;br /&gt;
Articles en relation: Quelques exemples de [[modèles de messages]] utilisés pour annoncer les beta ou release.&lt;br /&gt;
&lt;br /&gt;
===Role I: Testeur Dolibarr===&lt;br /&gt;
&lt;br /&gt;
Objectif: Tester la version courante de Dolibarr (Branch develop dand GIT) et reporter sur la mailing-list le maximum de bugs.&lt;br /&gt;
&lt;br /&gt;
Identifiés comme ayant ce rôle actuellement: &lt;br /&gt;
&lt;br /&gt;
*Une cinquantaine de personnes régulières environ (chiffre obtenu par analyse des messages du forum), beaucoup plus si on intègre les rapporteurs occasionnels.&lt;br /&gt;
&lt;br /&gt;
===Role J: Administrer les noms de domaines===&lt;br /&gt;
Goal: Administrer les DNS/noms de domaines&lt;br /&gt;
&lt;br /&gt;
Identifiés comme ayant ce rôle actuellement:&lt;br /&gt;
{{ListOfDomainAdmins}}&lt;br /&gt;
&lt;br /&gt;
=[[File:workcomputer.png]] Les accès GIT=&lt;br /&gt;
&lt;br /&gt;
Le serveur GIT est hébergé chez {{TemplateUrlSCM}}&lt;br /&gt;
&lt;br /&gt;
*Les instructions d&#039;accès au GIT en lecture pour récupérer la version courante de développement sont sur [https://github.com/Dolibarr/dolibarr/ cette page]&lt;br /&gt;
*En ce qui concerne, les requêtes pour obtenir un accès en écriture, lire la [[FAQ_D%C3%A9veloppeur#Comment_devenir_d.C3.A9veloppeur_officiel|FAQ Comment devenir développeur officiel]] pour connaître l&#039;organisation du projet et les étapes à franchir avant d&#039;atteindre ce but.&lt;br /&gt;
&lt;br /&gt;
=[[File:communaute.png]] Les Mailing-lists et groupes d&#039;information=&lt;br /&gt;
Voir la page [[FAQ Comment être informé de ce qui se passe sur Dolibarr ?]]&lt;br /&gt;
&lt;br /&gt;
=[[File:Lug.png]] Aider le projet=&lt;br /&gt;
Voici une liste de pistes possibles pour vous permettre d&#039;aider le projet Dolibarr.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Si vous êtes une développeur&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*Si vous êtes un développeur, rejoignez l&#039;équipe de développement Dolibarr pour contribuer au projet. Voir [[FAQ Développeur]] pour cela.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Si vous parlez une langue non anglophone&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*Traduire Dolibarr dans votre langue si sa traduction n&#039;existe pas ou est incomplète. Voir [[Documentation traducteur]].&lt;br /&gt;
*Soumettre des articles pour promouvoir Dolibarr sur les sites d&#039;informations dans votre langue ou sur votre propre site. A défaut un lien vers le site https://www.dolibarr.org ne peut pas faire de mal.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Si vous n&#039;êtes ni développeur, ni traducteur&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*Vous pouvez compléter la documentation Dolibarr de ce wiki, notamment la rubrique [[Documentation utilisateur]].&lt;br /&gt;
{{Template:LinksToVoteForDolibarr}}&lt;br /&gt;
&lt;br /&gt;
*Vous pouvez adhérer à l&#039;association Dolibarr. [[Adhérer|Voir ici pour adhérer]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Si vous voulez monter un groupe d&#039;utilisateur ou une communauté locale&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*Pour cela, lisez notre guide sur la page [[Create a Dolibarr local community]] (anglais uniquement).&lt;br /&gt;
&lt;br /&gt;
=[[File:Lug.png]] Dons=&lt;br /&gt;
Même si vous ne voulez pas être membre de l&#039;association Dolibarr, vous pouvez toujours faire une adhésion pour aider le développement financièrement: [[Adh%C3%A9rer]].&lt;/div&gt;</summary>
		<author><name>Quentic</name></author>
	</entry>
	<entry>
		<id>https://wiki.dolibarr.org/index.php?title=FAQ_D%C3%A9veloppeur&amp;diff=52104</id>
		<title>FAQ Développeur</title>
		<link rel="alternate" type="text/html" href="https://wiki.dolibarr.org/index.php?title=FAQ_D%C3%A9veloppeur&amp;diff=52104"/>
		<updated>2021-09-30T08:02:09Z</updated>

		<summary type="html">&lt;p&gt;Quentic: /* Comment devenir développeur officiel */Correction d&amp;#039;erreurs de frappe. Orthographe.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- BEGIN interlang links --&amp;gt;&lt;br /&gt;
&amp;lt;!-- Do NOT edit this section&lt;br /&gt;
     Links below are automatically managed by PolyglotBot&lt;br /&gt;
     You can edit links on the English source page : Developer_FAQ --&amp;gt;&lt;br /&gt;
[[en:Developer_FAQ]]&lt;br /&gt;
[[de:Entwickler_FAQ]]&lt;br /&gt;
[[es:FAQ_Desarrolladores]]&lt;br /&gt;
&amp;lt;!-- END interlang links --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:FAQ FR]]&lt;br /&gt;
{{TemplateDocDev}}&lt;br /&gt;
Cette page contient quelques questions-réponses en rapport avec le développement de Dolibarr. Pour des questions-réponses sur l&#039;utilisation, consulter plutot la page [[FAQ Utilisateur]].&lt;br /&gt;
&lt;br /&gt;
=Comment devenir développeur officiel=&lt;br /&gt;
&lt;br /&gt;
Dans la galaxie du projet Dolibarr, il existe plusieurs intervenants de différents niveaux/grades.&lt;br /&gt;
Le nombre de développeurs et contributions est important, or tout projet qui veut atteindre un certain niveau de qualité se doit d&#039;avoir une gestion contrôlée et des modifications validées des évolutions, aussi bien au niveau des besoins fonctionnels que du code.&lt;br /&gt;
Pour cette raison, les accès en écriture sur les sources (serveur GIT) sont limités et régis par une organisation qui est décrite dans les lignes qui suivent.&lt;br /&gt;
Chaque développeur a un &#039;&#039;&#039;grade&#039;&#039;&#039; qui dépend de son ancienneté et de ses contributions passées. Le niveau d&#039;habilitation d&#039;une personne sur le projet augmente avec les étapes de promotion de grade.&lt;br /&gt;
&lt;br /&gt;
Le cursus d&#039;un développeur Dolibarr passe donc par ces étapes, que l&#039;on classe par un titre familier aux adeptes de science-fiction. Voici ces étapes.&lt;br /&gt;
Il est important de comprendre que cette organisation a pour seul but d&#039;améliorer la qualité de Dolibarr et qu&#039;il est nécessaire qu&#039;elle soit rigoureusement respectée afin d&#039;atteindre ce but. &lt;br /&gt;
&lt;br /&gt;
Les grades des contributeurs au projet Dolibarr, et ce qu&#039;il faut faire pour atteindre ce grade, sont définis sur la page suivante: [[Projet_Dolibarr#Les_r.C3.B4les_d.C3.A9veloppeurs|Projet Dolibarr]] dans la section &#039;&#039;&#039;Les rôles développeurs&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=L&#039;équipe actuelle=&lt;br /&gt;
Voir la page [[projet Dolibarr]] pour connaitre la liste des personnes, participant au projet Dolibarr, à chaque grade actuellement.&lt;br /&gt;
&lt;br /&gt;
=Démarrer le développement=&lt;br /&gt;
Consulter intégralement la [[Documentation Développeur]] pour assimiler toutes les règles et principes imposées aux développeurs.&lt;br /&gt;
Vous pouvez aussi consulter les FAQ suivantes.&lt;br /&gt;
&lt;br /&gt;
=Récupérer/mettre à jour les sources du projet=&lt;br /&gt;
Voir la page [[FAQ Récupérer, mettre à jours les sources du projet]].&lt;br /&gt;
&lt;br /&gt;
=Comment créer un nouveau theme=&lt;br /&gt;
Voir pour cela la page [[Themes]]&lt;br /&gt;
&lt;br /&gt;
=Comment développer mon propre module=&lt;br /&gt;
Pour développer son propre module de numérotation, voir [[Créer un module de numérotation]].&lt;br /&gt;
&lt;br /&gt;
Pour développer son propre modèle de document, PDF ou autre, voir [[Créer un modèle de document PDF]] ou [[Créer un modèle de document ODT]].&lt;br /&gt;
&lt;br /&gt;
Pour développer un module fonctionnel entier (écrans, tables), voir pour cela la page [[Développement module]].&lt;br /&gt;
&lt;br /&gt;
=Comment ajouter ou compléter une traduction=&lt;br /&gt;
Voir pour cela la page [[Documentation_traducteur]]&lt;br /&gt;
&lt;br /&gt;
=Changer mon système de numérotation des factures en cours de route=&lt;br /&gt;
Si le nouveau système de numérotation n&#039;entre pas en conflit avec l&#039;ancien, il suffit d&#039;aller dans le menu Configuration - Modules - Configuration factures et prendre un nouveau modèle dans la liste.&lt;br /&gt;
Si le nouveau système rentre en conflit, il est nécessaire de renuméroter vos références existantes. Cela peut-être fait avec une requête SQL.&lt;br /&gt;
Par exemple, pour passer de Jupiter (FYYYYMM99) à Terre (FAYYMM-999), vous pouvez exécuter la requête suivante:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
update llx_facture set facnumber=concat(&#039;FA&#039;,substr(facnumber,4,4),&#039;-&#039;,substr(facnumber,8))&lt;br /&gt;
where facnumber like &#039;F%&#039; and facnumber not like &#039;FA%&#039;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Par exemple, pour passer d&#039;un modele FAYYMM999 à Terre (FAYYMM-999), vous pouvez exécuter la requête suivante:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
update llx_facture set facnumber=concat(&#039;FA&#039;,substr(facnumber,3,4),&#039;-&#039;,substr(CONCAT(&#039;0000&#039;,substr(facnumber,7)),-4))&lt;br /&gt;
where facnumber like &#039;FA%&#039; and facnumber not like &#039;%-%&#039;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Soumettre un patch, amélioration ou participer au développement=&lt;br /&gt;
Si vous cherchez comment commencer ou contribuer aux développements Dolibarr, lisez le chapitre [[FAQ_Développeur#Comment devenir développeur officiel]]. Si votre patch est déjà prêt et voulez le diffuser, ce chapitre est pour vous.&lt;br /&gt;
&lt;br /&gt;
==Avec un compte GitHub==&lt;br /&gt;
Les accès au dépot des sources en lecture est publique. La soumission de contributions dépend toutefois de votre niveau dans le projet.&lt;br /&gt;
&lt;br /&gt;
*Si vous bénéficiez d&#039;un grade Yoda (rarissime), et donc un accès en écriture direct au dépôt de référence, utilisez-le (Voir [[FAQ_D%C3%A9veloppeur#Comment_devenir_d.C3.A9veloppeur_officiel|FAQ Développeur - Devenir développeur officiel]] pour les différents grades).&lt;br /&gt;
&lt;br /&gt;
*Si vous n&#039;avez pas d&#039;accès en écriture direct au dépôt de référence (votre grade est donc [[Developer FAQ#Soldier|Jedi]] ou [[Developer FAQ#Soldier|Admiral]] ou [[Developer FAQ#Soldier|Soldier]]), vous devez alors utiliser GitHub en « Forkant » le dépôt sur votre compte, puis en faisant une demande de « Pull Request » de votre branche sur le dépôt principal. C&#039;est la méthode recommandée la plus propre et la plus performante. Voir pour plus d&#039;info la page https://wiki.dolibarr.org/index.php/FAQ_Get,update_GIT_project_sources&lt;br /&gt;
&lt;br /&gt;
 Note:  Si vous ne savez pas bien utiliser l&#039;outil GIT et si votre modification est petite (porte sur un ou deux fichiers), sachez qu&#039;il est possible simplement, en allant sur votre compte GitHub et sur votre repository &amp;quot;Forké&amp;quot; depuis l&#039;interface Web de GitHub, de modifier le fichier en ligne. Une fois la modification faite, vous pouvez utiliser la fonction soumettre Pull Request pour la suggérer au projet. Un valideur l&#039;intégrera alors sans effort si elle est valide.&lt;br /&gt;
&lt;br /&gt;
*La procédure qui suit reste un alternative techniquement possible mais n&#039;est plus pratiquée que pour les toutes petites modifications...&lt;br /&gt;
&lt;br /&gt;
==Sans compte GitHub==&lt;br /&gt;
Sans compte GitHub, il est nécessaire de générer et fournir par mail, sur la mailing-list développeur &#039;&#039;&#039;dolibarr-dev&#039;&#039;&#039; votre fichier patch (Voir ici pour cela {{TemplateURLMLDev}}). Voici la procédure pour générer un fichier patch:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Sous tout OS:&#039;&#039; [[Image:Logo_windows.png|20px]] [[Image:Logo_ubuntu.png|20px]] [[Image:Logo_apple.png|20px]]&lt;br /&gt;
&lt;br /&gt;
Voici la &#039;&#039;méthode Pro&#039;&#039; selon laquelle travailler pour pouvoir générer un tel fichier patch:&lt;br /&gt;
&lt;br /&gt;
- Avoir un répertoire qui contient la version de Dolibarr de référence (résultat de la mise à jour GIT ou bien tout simplement l&#039;arborescence résultant de la décompression d&#039;un snapshot tgz de Dolibarr). On appellera ce répertoire &#039;&#039;&#039;ancien_rep&#039;&#039;&#039;. Vous pouvez récupérer le snapshot de la version de dev en cours sur le  [http://www.dolibarr.org/downloads/ site officiel de Dolibarr - espace téléchargement - version développement].&lt;br /&gt;
&lt;br /&gt;
- Avoir un autre répertoire qui contient l&#039;arborescence de Dolibarr mais dans laquelle vous faites ou avez fait vos modifications. On appellera ce répertoire &#039;&#039;&#039;nouveau_rep&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Pour générer le fichier patch, il suffit alors de lancer la commande &#039;&#039;&#039;diff&#039;&#039;&#039; (en standard sous Linux, fourni dans [http://www.cygwin.org/cygwin cygwin] sous Windows) de la manière suivante:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
diff -BNaur --exclude=CVS --exclude=&amp;quot;*.patch&amp;quot; --exclude=&amp;quot;.#*&amp;quot; --exclude=&amp;quot;*~&amp;quot; --exclude=&amp;quot;*.rej&amp;quot; \&lt;br /&gt;
     --exclude=&amp;quot;*.orig&amp;quot; --exclude=&amp;quot;*.bak&amp;quot; --exclude=conf.php --exclude=documents  \&lt;br /&gt;
     ancien_rep nouveau_rep  &amp;gt; mypatch.patch&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Un script ksh réalisant cette commande est disponible dans le répertoire &#039;&#039;&#039;build/patch&#039;&#039;&#039;.&lt;br /&gt;
Envoyer votre patch sur la ML à l&#039;adresse &#039;&#039;&#039;dolibarr-dev@nongnu.org&#039;&#039;&#039;.&lt;br /&gt;
L&#039;intégration de votre patch n&#039;est toutefois pas garantie, pas plus que le délai, mais si le patch est réalisé en suivant rigoureusement cette procédure, il a de forte chance d&#039;être au moins testé (dans le cas contraire les chances sont proches de 0).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Sous Windows:&#039;&#039; [[Image:Logo_windows.png|20px]]&lt;br /&gt;
&lt;br /&gt;
Si vous êtes sous Windows, une &#039;&#039;méthode moins Pro&#039;&#039; mais qui donne le même résultat est la suivante. Installer l&#039;excellent outil open source de comparaison Winmerge qui sait fabriquer des patchs au format &#039;&#039;diff -Naur&#039;&#039;. Pour cela, comparer avec Winmerge le fichier référence et le fichier modifié et choisir dans le menu &#039;&#039;&amp;quot;Tools - Generate patch&amp;quot;&#039;&#039; (&#039;&#039;Générer des retouches&#039;&#039; en version française). Saisir un nom de fichier comme &#039;&#039;&amp;quot;resultat.patch&amp;quot;&#039;&#039;, cocher la case &#039;&#039;&amp;quot;Append&amp;quot;&#039;&#039; et choisir l&#039;option &#039;&#039;&amp;quot;Format Unified&amp;quot;&#039;&#039; (&#039;&#039;Style : unifié&#039;&#039; en version française). Cliquer sur &#039;&#039;&amp;quot;Ok&amp;quot;&#039;&#039;.&lt;br /&gt;
Éventuellement recommencer pour chaque fichier modifié.&lt;br /&gt;
Au final, on obtient un beau fichier &#039;&#039;resultat.patch&#039;&#039; qui contient toutes les modifications au bon format.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Tester/Appliquer un patch&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Pour appliquer un fichier patch sur une version non modifié afin d&#039;intégrer les modifications décrites dans le fichier patch, vous pouvez utiliser l&#039;utilitaire &#039;&#039;&#039;patch&#039;&#039;&#039;.&lt;br /&gt;
Imaginons que vous avez un répertoire des sources d&#039;une version non modifiée de Dolibarr sur un serveur. Pour appliquer le patch, placer dans le répertoire racine de Dolibarr et lancez la commande:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
patch -u -p0 -d . &amp;lt; monfichier.patch&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;Pour information: -p0 permet d&#039;utiliser le chemin entier tel que mentionné dans le fichier de patch pour retrouver les fichiers à modifier dans votre arborescence source (-pn en retire les n premiers niveau de l&#039;arborescence)&lt;br /&gt;
-d permet de préciser le chemin relatif vers le dossier à patcher.&lt;br /&gt;
&amp;lt; permet de donner le chemin vers le fichier source à utiliser (le patch doit être au format unifié)&lt;br /&gt;
-u permet de préciser que le patch est en mode unifié&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Envoyer le patch par mail&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Une fois votre fichier patch généré et testé avec succès, vous pouvez l&#039;envoyer sur la mailing-list de développement &#039;&#039;&#039;dolibarr-dev&#039;&#039;&#039; de Dolibarr (Voir ici pour cela {{TemplateURLMLDev}}).&lt;br /&gt;
Cette mailing-list est lu de tous les développeurs principaux mais nous ne pouvons garantir que le patch sera inclus, cela dépend de sa qualité et des autres priorités de développement du moment.&lt;br /&gt;
&lt;br /&gt;
=Comment packager/livrer un module=&lt;br /&gt;
Voir la page [[Développement_module#Cr.C3.A9er_un_package_pour_livrer_et_installer_votre_module|Developpement module - Créer un package pour livrer et installer votre module]]&lt;br /&gt;
&lt;br /&gt;
La procédure est également valide pour générer un package pour le soumettre sur la place de marché https://www.dolistore.com&lt;br /&gt;
&lt;br /&gt;
=Comment être informé de ce qui se passe sur Dolibarr ?=&lt;br /&gt;
Voir la page [[FAQ Comment être informé de l&#039;actualité de Dolibarr ?]]&lt;br /&gt;
&lt;br /&gt;
=Migrer ma base de Mysql vers PostgreSQL=&lt;br /&gt;
Voir la page [[FAQ Migrer ma base Mysql vers PostgreSQL]]&lt;/div&gt;</summary>
		<author><name>Quentic</name></author>
	</entry>
</feed>