Changes

m
no edit summary
Line 24: Line 24:  
*All PHP files must start with a header that looks like
 
*All PHP files must start with a header that looks like
   −
<source lang="php">
+
<syntaxhighlight lang="php">
 
<?php
 
<?php
 
/* Copyright (C) YYYY John Doe  <email@email.com>
 
/* Copyright (C) YYYY John Doe  <email@email.com>
Line 31: Line 31:  
  */
 
  */
 
...
 
...
</source>
+
</syntaxhighlight>
 
When you edit an existing file of project, you must add a Copyright line under others.
 
When you edit an existing file of project, you must add a Copyright line under others.
   Line 47: Line 47:  
*When several variables must be initialized with the same value, you must use individual declarations (separated by ;)
 
*When several variables must be initialized with the same value, you must use individual declarations (separated by ;)
   −
<source lang="php">
+
<syntaxhighlight lang="php">
 
$var1 = 1;
 
$var1 = 1;
 
$var2 = 1;
 
$var2 = 1;
Line 55: Line 55:  
<source lang="php">
 
<source lang="php">
 
$var1 = $var2 = $var3 = 1;
 
$var1 = $var2 = $var3 = 1;
</source>
+
</syntaxhighlight>
 
which is slower.
 
which is slower.
   Line 64: Line 64:  
*Strings must be delimited by a single or double quote and a variable within the string must be outside of the quote.
 
*Strings must be delimited by a single or double quote and a variable within the string must be outside of the quote.
   −
<source lang="php">
+
<syntaxhighlight lang="php">
 
print 'My text show my '.$variable.' !';
 
print 'My text show my '.$variable.' !';
</source>
+
</syntaxhighlight>
    
<br />
 
<br />
Line 74: Line 74:  
*Comments must use the C syntax, ie a double slash for a comment on one line and a slash-star to open a bloc for several lines
 
*Comments must use the C syntax, ie a double slash for a comment on one line and a slash-star to open a bloc for several lines
   −
<source lang="php">
+
<syntaxhighlight lang="php">
 
/* Bloc of comment
 
/* Bloc of comment
 
  *
 
  *
Line 92: Line 92:  
     // code
 
     // code
 
}
 
}
</source>
+
</syntaxhighlight>
   −
<br />
+
<br>
    
*Functions must return a value equal or higher than 0 if successful and strictly lower than 0 if error.
 
*Functions must return a value equal or higher than 0 if successful and strictly lower than 0 if error.
Line 134: Line 134:  
Example: '''file for creating the table llx_mytable will be llx_mytable.sql''':
 
Example: '''file for creating the table llx_mytable will be llx_mytable.sql''':
   −
<source lang="sql">
+
<syntaxhighlight lang="sql">
 
-- ===========================================================================
 
-- ===========================================================================
 
-- Copyright (C) 2013 Author <email@author.com>
 
-- Copyright (C) 2013 Author <email@author.com>
Line 168: Line 168:  
   import_key varchar(14)                -- Use by import process
 
   import_key varchar(14)                -- Use by import process
 
)type=innodb;
 
)type=innodb;
</source>
+
</syntaxhighlight>
    
Example: '''file for creating keys/indexes for the table llx_mytable will be llx_mytable.key.sql''':
 
Example: '''file for creating keys/indexes for the table llx_mytable will be llx_mytable.key.sql''':
   −
<source lang="sql">
+
<syntaxhighlight lang="sql">
 
-- ===========================================================================
 
-- ===========================================================================
 
-- Copyright (C) 2013 Author <email@author.com>
 
-- Copyright (C) 2013 Author <email@author.com>
Line 193: Line 193:     
ALTER TABLE llx_mytable ADD CONSTRAINT fk_mytable_fk_field FOREIGN KEY (fk_field) REFERENCES llx_matablepere (rowid);
 
ALTER TABLE llx_mytable ADD CONSTRAINT fk_mytable_fk_field FOREIGN KEY (fk_field) REFERENCES llx_matablepere (rowid);
</source>
+
</syntaxhighlight>
    
==Table and fields structures==
 
==Table and fields structures==
Line 277: Line 277:  
*Using SELECT * is forbidden ! When using SELECT you must define complete list of fields to get. This avoids confusion. And above all, this make reengeering of code easier and make impact analysis of change on a field possible. Example:
 
*Using SELECT * is forbidden ! When using SELECT you must define complete list of fields to get. This avoids confusion. And above all, this make reengeering of code easier and make impact analysis of change on a field possible. Example:
   −
<source lang="sql">
+
<syntaxhighlight lang="sql">
 
SELECT field_a, field_b, field_c FROM table_1 WHERE field_d = '$id'
 
SELECT field_a, field_b, field_c FROM table_1 WHERE field_d = '$id'
</source>
+
</syntaxhighlight>
    
*Into SQL requests, you must quote fields except the fields that contain amounts which must be stored as double or real type. Quotes on numbers may result in saving as a different value. For example 412.62 in an insert will be saved as value 412.61999512 into database (due to implicit conversion string to numeric) if the target field has type double(24,8). Only PHP see value 412.61999512. Other tools will see 412.62 giving a sense that there is no problem. But it's PHP that has the good vision. There is really a wrong value into database. By removing quotes on numbers, no problem occurs.
 
*Into SQL requests, you must quote fields except the fields that contain amounts which must be stored as double or real type. Quotes on numbers may result in saving as a different value. For example 412.62 in an insert will be saved as value 412.61999512 into database (due to implicit conversion string to numeric) if the target field has type double(24,8). Only PHP see value 412.61999512. Other tools will see 412.62 giving a sense that there is no problem. But it's PHP that has the good vision. There is really a wrong value into database. By removing quotes on numbers, no problem occurs.
    
Example:
 
Example:
<source lang="sql">
+
<syntaxhighlight lang="sql">
 
Good:    INSERT INTO table_1 (field_txt, field_num) VALUES ('txt', 412.62)
 
Good:    INSERT INTO table_1 (field_txt, field_num) VALUES ('txt', 412.62)
 
Bad:      INSERT INTO table_1 (field_txt, field_num) VALUES ('txt', '412.62')
 
Bad:      INSERT INTO table_1 (field_txt, field_num) VALUES ('txt', '412.62')
</source>
+
</syntaxhighlight>
    
Note, problem of float numbers is same problem on all langauges and not only when inserting data into database. It occurs also with any language when you work on "real" numbers, so numbers must be, as soon as they are affected, cleaned with function price2num with second parameter defined to :
 
Note, problem of float numbers is same problem on all langauges and not only when inserting data into database. It occurs also with any language when you work on "real" numbers, so numbers must be, as soon as they are affected, cleaned with function price2num with second parameter defined to :
Line 295: Line 295:     
For example, don't do:
 
For example, don't do:
<source lang="php">
+
<syntaxhighlight lang="php">
 
$sql="SELECT rowid FROM table where datefield = NOW()";
 
$sql="SELECT rowid FROM table where datefield = NOW()";
</source>
+
</syntaxhighlight>
 
but do:
 
but do:
<source lang="php">
+
<syntaxhighlight lang="php">
 
$sql="SELECT rowid FROM table where datefield = '".$this->db->idate(dol_now())."'";
 
$sql="SELECT rowid FROM table where datefield = '".$this->db->idate(dol_now())."'";
</source>
+
</syntaxhighlight>
    
For example, don't do:
 
For example, don't do:
<source lang="php">
+
<syntaxhighlight lang="php">
 
$sql="SELECT rowid FROM table where DATEDIFF(table.datefield, NOW()) > 7";
 
$sql="SELECT rowid FROM table where DATEDIFF(table.datefield, NOW()) > 7";
</source>
+
</syntaxhighlight>
 
but do:
 
but do:
<source lang="php">
+
<syntaxhighlight lang="php">
 
$sql="SELECT rowid FROM table where datefield < '".$this->db->idate(dol_now() - (7 * 24 * 3600))."'";
 
$sql="SELECT rowid FROM table where datefield < '".$this->db->idate(dol_now() - (7 * 24 * 3600))."'";
</source>
+
</syntaxhighlight>
    
An other advantage of this rule, is that request benefits of index because we are making a compare of a field with a fixed value. When using datediff, you make an operation on field before comparison, this means database can't use the index on field, resulting on very bad performance compared to solution without the datediff.
 
An other advantage of this rule, is that request benefits of index because we are making a compare of a field with a fixed value. When using datediff, you make an operation on field before comparison, this means database can't use the index on field, resulting on very bad performance compared to solution without the datediff.
Line 349: Line 349:     
PgSQL Syntax:
 
PgSQL Syntax:
<source lang="sql">
+
<syntaxhighlight lang="sql">
 
UPDATE table_taget as target SET fieldtarget=source.fieldsource
 
UPDATE table_taget as target SET fieldtarget=source.fieldsource
 
FROM table_source as source WHERE source.rowid=target.rowid;
 
FROM table_source as source WHERE source.rowid=target.rowid;
</source>
+
</syntaxhighlight>
    
There is no native SQL requests "UPDATE FROM" in all Dolibarr core. But if you use one in your own code of your module, you should do :
 
There is no native SQL requests "UPDATE FROM" in all Dolibarr core. But if you use one in your own code of your module, you should do :
<source lang="php">
+
<syntaxhighlight lang="php">
 
if ($this->db->type=='pgsql') {
 
if ($this->db->type=='pgsql') {
 
$sql="UPDATE table_taget as target SET fieldtarget=source.fieldsource
 
$sql="UPDATE table_taget as target SET fieldtarget=source.fieldsource
Line 363: Line 363:  
WHERE source.rowid=target.rowid";
 
WHERE source.rowid=target.rowid";
 
}
 
}
</source>
+
</syntaxhighlight>
    
=HTML norms=
 
=HTML norms=
Line 373: Line 373:     
For example:
 
For example:
<source lang="php">
+
<syntaxhighlight lang="php">
 
print '<a href="'.dol_buildpath('/mydir/mypage.php').'">'.img_picto('Texte alt','namepictopng','').'</a>';
 
print '<a href="'.dol_buildpath('/mydir/mypage.php').'">'.img_picto('Texte alt','namepictopng','').'</a>';
</source>
+
</syntaxhighlight>
    
*HTML tables must have columns with no forced width, except for columns that contains data we know the length. For example, a column with a picto only can be forced to with="20px".
 
*HTML tables must have columns with no forced width, except for columns that contains data we know the length. For example, a column with a picto only can be forced to with="20px".
Line 383: Line 383:  
*Javascript/ajax code and call to javascript files into php pages must be avoided. However, if you need to include javascript code, you must add a condition on "$conf->use_javascript_ajax"
 
*Javascript/ajax code and call to javascript files into php pages must be avoided. However, if you need to include javascript code, you must add a condition on "$conf->use_javascript_ajax"
   −
<source lang="php">
+
<syntaxhighlight lang="php">
 
if ($conf->use_javascript_ajax) {
 
if ($conf->use_javascript_ajax) {
 
...  // php code generating javascript here
 
...  // php code generating javascript here
 
}
 
}
</source>
+
</syntaxhighlight>
    
*Popup windows must not be used, except for tooltips (and must have a condition as explained before).
 
*Popup windows must not be used, except for tooltips (and must have a condition as explained before).
Line 446: Line 446:  
With PHP, like other languages (Java for exemple), non integer data (float, real, double) are not reliable for calculation.
 
With PHP, like other languages (Java for exemple), non integer data (float, real, double) are not reliable for calculation.
 
Try to make for example  
 
Try to make for example  
<source lang="php">
+
<syntaxhighlight lang="php">
 
print 239.2 - 229.3 - 9.9;
 
print 239.2 - 229.3 - 9.9;
</source>
+
</syntaxhighlight>
 
You wont get zero but a very small decimal number. If you get zero her, you should be able to find other examples that don't work.
 
You wont get zero but a very small decimal number. If you get zero her, you should be able to find other examples that don't work.
 
Problem of float is general, so a variable that is a result of a calculation using decimal numbers must ALWAYS be cleaned using the function '''price2num()''' with the econd parameter to: 'MU', 'MT' or 'MS' depending on need (see description of function).
 
Problem of float is general, so a variable that is a result of a calculation using decimal numbers must ALWAYS be cleaned using the function '''price2num()''' with the econd parameter to: 'MU', 'MT' or 'MS' depending on need (see description of function).
<source lang="php">
+
<syntaxhighlight lang="php">
 
print price2num(239.2 - 229.3 - 9.9, 'MT');
 
print price2num(239.2 - 229.3 - 9.9, 'MT');
</source>
+
</syntaxhighlight>
 
If data manipulated is not an amount, then using MU, MT, MS has no sense, and you must use the function '''round()'''.
 
If data manipulated is not an amount, then using MU, MT, MS has no sense, and you must use the function '''round()'''.
   Line 462: Line 462:  
==Comparing version==
 
==Comparing version==
 
If your code need to make different things depending on Dolibarr version, you can use the following tip to detect and compare versions
 
If your code need to make different things depending on Dolibarr version, you can use the following tip to detect and compare versions
<source lang="php">
+
<syntaxhighlight lang="php">
 
$version=preg_split('/[\.-]/',DOL_VERSION);
 
$version=preg_split('/[\.-]/',DOL_VERSION);
 
if (versioncompare($version,array(5,0,-4)) >= 0) { //mycode for 5.0 only; } // For dolibarr 5.0.* (the -4 means we include also alpha, beta, rc and rcX)
 
if (versioncompare($version,array(5,0,-4)) >= 0) { //mycode for 5.0 only; } // For dolibarr 5.0.* (the -4 means we include also alpha, beta, rc and rcX)
</source>
+
</syntaxhighlight>
    
But this solution need to include the function versioncompare. An alternative solution to test version is to do:
 
But this solution need to include the function versioncompare. An alternative solution to test version is to do:
<source lang="php">
+
<syntaxhighlight lang="php">
 
if ((float) DOL_VERSION >= 5.0) { //mycode for 5.0 only; } // For dolibarr 5.0.*
 
if ((float) DOL_VERSION >= 5.0) { //mycode for 5.0 only; } // For dolibarr 5.0.*
</source>
+
</syntaxhighlight>
    
==Logs==
 
==Logs==
 
Add logs to your code using function
 
Add logs to your code using function
<source lang="php">
+
<syntaxhighlight lang="php">
 
dol_syslog($yourmessage, LOG_INFO|LOG_DEBUG|LOG_WARNING|LOG_ERR);
 
dol_syslog($yourmessage, LOG_INFO|LOG_DEBUG|LOG_WARNING|LOG_ERR);
</source>
+
</syntaxhighlight>
    
==Working directory==
 
==Working directory==
Line 483: Line 483:     
The directory can be created into your code by the following function:
 
The directory can be created into your code by the following function:
<source lang="php">
+
<syntaxhighlight lang="php">
 
$mymoduledir=DOL_DATA_ROOT.'/mymodule';
 
$mymoduledir=DOL_DATA_ROOT.'/mymodule';
 
dol_mkdir($mymoduledir);
 
dol_mkdir($mymoduledir);
</source>
+
</syntaxhighlight>
    
If you need a directory to store temporary data, this directory must be '''DOL_DATA_ROOT.'/mymodule/temp''''
 
If you need a directory to store temporary data, this directory must be '''DOL_DATA_ROOT.'/mymodule/temp''''