Coding Conventions/Style

It is a core goal of webERP to be easy to read for business people and newcomers to PHP. The webERP Coding Standards are not only good programming practice to reduce errors, they make the code easier to follow - which also reduces errors. The webERP Coding Standards are regarded as critically important and all code is to conform.

The webERP Coding Standards are based on WordPress Coding Standards, superceded by the standards here and also README.md and doc/INSTALL.md in the webERP code.

PHP

Simpler is generally better. Prefer logical, well structured code that is more easily understood over the easiest or quickest solution at that moment.

Code Tags

Always use <?php ?> to delimit PHP code (not the <? ?> shorthand). This is the most portable way to include PHP code on differing operating systems and setups.

Do not include a closing tag in a PHP file.

Functions and Keywords

All PHP keywords must be in lower case.

Constants

Constants should always be UPPER_CASE using underscores to separate words. Where it is possible to use a literal instead of a constant, a literal is preferred.

Include and Require File Paths

Include and require calls must give absolute paths using PathPrefix for the target file. This avoids needing to know the directory of the currently executing script which can be confusing as some scripts can be run either via an include call or executed standalone as a top-level webpage. Using a full path also increases execution speed and makes scripts more robust if they need to be relocated.

$RootPath

$RootPath is calculated in session.php and adjusted in config.php based on $DirectoryLevelsDeep.

Formatting

Code shall be formatted using tabs ("tab indented") instead of spaces.

Spacing

Lines of code should be separated by a blank line if readability is improved (separating groups of lines, or separate a line from the preceding or following lines).

Comments

Comments are bread crumbs you are leaving for future you and other developer that explain the basics of the script, what is the goal of the script and how it is achieved, and to explain in more detail when the script is complex.

Comments need to be kept current. Whenever you touch a script, check for obsolete comments to update, clarify or delete - as you see fit considering the needs of the community. Long scripts that contain several functions will benefit from an overview and list of functions with descriptions, even referencing related scripts. The goal is to help the future you and other developers to grok a script and its role in webERP as quickly as possible (arguably at the expense of writing and maintaining comments).

The code will tend to be self commenting with the aid of long variable names and the addition of the context of variables.

Explanations should be provided wherever possible using C style comment blocks in the format:

/* quick guide to next line or couple lines */

or

/*

* multiple line comment

* giving an overview or

* explaining a concept

*/

User Notifications

The standard message function prnMsg() should be used to send notifications to the user. prnMsg() has two required parameters, the string to display and the message type, either 'error', 'warn', 'success' or 'info' (a third optional parameter is a prefix heading for the message).

Function/Class/Variable/Field Naming

Long, self-explanatory variable names help a lot to decipher what's contained in that variable. Descriptive names (using PascalCase) are preferred over short variable names: e.g.

$a = 3.14159;

should be avoided in favour of:

$Pi = 3.14159;

The variables $i $j and $k can be used as a counters.

As displayed above, there should be one space on either side of an equals sign used to assign the return value of a function to a variable. In the case of a block of related assignments, more space may be inserted to promote readability:

$Short = foo($bar);
$LongVariable = foo($baz);

Good descriptive variable names consisting of several words appended together should have the first letter of each word capitalised. eg.

$longvariablename = 1;

should be written as:

$LongVariableName = 1;

Label Strings and Multi-Language

Since webERP is a multi-language system it is important not to compromise this capability by having labels in your scripts that are not enclosed in the gettext function eg.

echo 'Enter the quantity:<input type="text" name="Quantity" />';

should be written as:

echo _('Enter the quantity') . ':<input type="text" name="Quantity" />';

note that there should be no trailing spaces on the string to be translated inside the _() function call

Variable Arrays

The PHP variable arrays $_POST, $_GET, $_SERVER, $_SESSION provide context about where a variable comes from - many developers are tempted to abbreviate:

$StartingCustomer = $_POST['StartingCustomer'];

or worse:

$s = $_POST['StartingCustomer'];

This should be avoided in favour of using:

$_POST['StartingCustomer']

everywhere it is required so the reader can see where the variable comes from.

However, variables which could come from either a $_GET or a $_POST and/or a $_SESSION may be assigned as in the first example since there is no value in the context.

Quotation Marks

Notice that single quotes (') are used in preference to double quotes (") - there is additional overhead for php in parsing data within double quotes. They should only be used where absolutely necessary and concatenation of variables is preferred to having variables inside double quotes. eg.

echo "Some text with a $Variable";

would be better written as:

echo _('Some text with a') . ' ' . $Variable;

to reduce the parsing job required of the web-server. Notice all strings need to be inside the gettext _() function.

Arrays and super global arrays should always have the element name within single quotes not doubles eg.

$_POST["FormVariableName"]

should be written as:

$_POST['FormVariableName']

The only exception to this is that when constructing SQL statements, due to the requirement to single quote string literals in SQL statements, the entire SQL string should always be written using double quotes. (See below)

Control Structures

Where there are many comparisons new lines should be created for each comparison

if ($OneTwoThree==$_POST['OneTwoThree']
    and $MyRow['onetwothree']==$_SESSION['OneTwoThree']) {

All control structures (these include if, for, while, switch) must always use "1 True Brace" style statement blocks.

You are strongly encouraged to always use curly braces even in situations where they are technically optional. Having them increases readability and decreases the likelihood of logic errors being introduced when new lines are added. eg.

if ($VariableName == true) echo _('Variable was true');

Whilst legal PHP syntax, this should be avoided in favour of the following syntax:

if ($VariableName == true) {
    echo _('Variable was true');
}

Parenthesis should open on the same line (after a space) as the initiating control structure and close the statement block at the same level of indenting as the initiating line.

Else statements should be on the same line as the closing statement block from the preceding elseif or if statement eg.

if ($VariableName == true) {
    echo 'Variable was true';
} else {
    echo 'Variable was false';
} /*end else $VariableName was false*/

This is the only time there should be anything other than a comment on the closing curly brace line. Comments on a closing curly brace line where the block has been quite a few lines of code are encouraged to show the control structure to which they related.

Whenever a statement block is used code within the block should be one tab indented. Indenting code correctly is critical to avoid logic errors and to improve readability.

Function definitions should follow the same conventions.

Most programming editors have word wrap and this is preferred to manual line breaks.

Repeated Code

In general shorter scripts are easier to understand but too much abstraction can make a path hard to follow. The the best solution will depend on the context.

HTML

HTML keywords and tags should be in lower case to improve xhtml compatibility.

HTML table cell tags in echo statements should use carriage returns to keep cells together so it is easy to see what is in each cell. eg.

echo '<table> <tr> <td>' . _('Label text') . ':</td> <td>' . $SomeVariable . '</td> <td>' . _('Some Other Label') . ':</td> <td align="right">' . number_format($SomeNumber,2) . '</td> </tr> </table> ';

Would be more easily digested and should be written as

echo '<table>
        <tr>
            <td>' . _('Label text') . ':</td>
            <td>' . $SomeVariable . '</td>
            <td>' . _('Some Other Label') . '</td>
            <td align="right">' . number_format($SomeNumber,2) . '</td>
        </tr>
    </table>';

Carriage returns and indentation should be used in a similar way for printf statements.

All values of xhtml properties should be between double quotes e.g.

<input type="text" name="InputBox" value="Default" />

This goes hand in hand with using single quotes for all echo statements see below.

SQL

The SQL should be ANSI compliant. Using SQL particular to a specific RDBMS is to be avoided in favour of the ANSI equivalent.

The webERP goal of providing "low footprint" efficient system - requires careful thought. The number of "round trips" must be minimised - never go off to the database to get data that could have been got in a prior query. This is inefficient design and to be avoided.

There should never be any database specific calls in scripts other than includes/ConnectDB_XXXX.inc where XXXX is the abbreviation for the RDBMS the abstraction code refers to.

All database calls should be performed by calling the abstraction functions in those scripts. (currently only includes/ConnectDB_mysql.inc exists ConnectDB_postgres.inc was depreciated but could easily be revived if we stick with this convention

Table and field names should always use lower case and should be descriptive of the data they hold. e.g. Field names such as "nw" should be avoided in favour of "netweight"

SQL statements should be on several lines for easier reading eg.

$SQL = "select transno, trandate, debtortrans.debtorno, branchcode, reference, invtext, order_, rate, ovamount+ovgst+ovfreight+ovdiscount as totalamt, currcode from debtortrans inner join debtorsmaster on debtortrans.debtorno=debtorsmaster.debtorno";

is harder to read than:

$SQL = "SELECT transno,
               trandate,
               debtortrans.debtorno,
               branchcode, reference,
               invtext,
               order_,
               rate,
               ovamount+ovgst+ovfreight+ovdiscount AS totalamt,
               currcode
           FROM debtortrans
           INNER JOIN debtorsmaster
               ON debtortrans.debtorno=debtorsmaster.debtorno";

SQL keywords should be capitalised as above eg. SELECT, CASE, FROM, WHERE, GROUP BY, ORDER BY, AS, INNER JOIN etc.

Line breaks after every comma and on major SQL reserved words as above.

Quoting SQL variables - variables incorporated into SQL strings need to be inside SINGLE quotes so that the variable cannot be used by a hacker to send spurious SQL to retrieve private data.

NOTE: Since variables incorporated into an SQL string need to be quoted with single quotes inside the SQL string, the SQL strings themselves need to be quoted inside double quotes. This is the one exception to the general rule to always use single quotes for strings for easier quicker PHP parsing.