Main Authors: Ravindra de Silva , Isuru Samaraweera Contributors: …

Licensing Agreement

Each and every file should start with the license agreement and should adhere to the following format

/**
 * <description about the module>
 * PHP version 5
 * LICENSE: This source file is subject to LGPL license 
 * that is available through the world-wide-web at the following URI:
 * http://www.gnu.org/copyleft/lesser.html
 * @author     <Author Name> <Author Email Address> 
 * @package    Sahana - http://sahana.lk/
 * @module     <module>  
 * @copyright  Lanka Software Foundation - http://www.opensource.lk 
 * @license    http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License (LGPL) 
 */

Naming Convention

Names are the heart of programming, so select meaningful names. Furthermore specially for library functions we need to enforce a standard to prevent collisions as PHP does not support name spaces (it does though if Object Oriented Programming is done).

Choosing a module "short name" for your module in Sahana ~ <module>

A Sahana module has a “short name” that is used across the modules code and in the mdoule's folder structure. This “short name” is referred to as <module> and is limited to a string length of 6 alphanumeric characters. Therefore, each of the 6 string characters can be a letter a-z or a number 0-9. Using only lowercase characters simplifies problems with case sensitivity in different filesystems and in function names. For those familiar with regular expressions, the “short name” must adhere to this regular expression: /\A[0-9a-z]{2,6}\Z/

Example <module> names:

mod30
newmod
house

Faulty <module> names:

module420
InCaseMod
mod(2)

When a new module is created, all of its constituent files are stored in the /mod/<module> folder in the Sahana installation.

Naming functions with in a module

Definitely most of the functions in “main.inc” need to follow a standard, otherwise through the front controller mechanism the function won't be called.

The standard is

shn_<module>_<action>

for an example when the user clicks a link with URL

http://localhost/~ravi/sahana-phase2/www/index.php?mod=or&act=reg_org

front controller will look for a function named

shn_or_reg_org()

, in “main.inc” of the module “or”. If such a function does not exist in “or” it will call the default function of the module, in this case (

shn_or_default()

).

Though functions in other files of the module won't be called by the front controller , it's recommended to follow the same naming convention, with a slight difference. There are many functions declared within a module not meant to be used other modules. Since PHP does not support private functions, the best we can do is to guide the reader. Therefore a function you don't wish others to use by including the file, prefix with underscore. example: following function won't be useful for other modules to use, so should be a private function. Though we can't restrict any one from using it let's at least provide a warning.

_shn_or_viewform_allorg($no=NULL)

prefix underscore signals, ”its not meant to be used outside the module”

Naming function within a library

In this case we need to make sure the standard is strictly met, as a user will include several libraries.

The convention is

shn_<library>_<function name>

example in “lib_form” function declarations would be like as given below.

shn_form_text($label, $name, $text_opts = null,$extra_opts = null )

and in “lib_location” function declarations would be along the lines of

shn_location_get_descendants($loc)

Function names

use all simple letters and use underscore to separate words.

shn_location_get_descendants($loc)

follow the rules mentioned earlier to mimic name spaces, and of course try to make function names as meaningful as possible. following examples are without prefixes (you should prefix appropriately to avoid collisions) so use

shn_check_for_errors()

instead of

shn_error_check()

,

shn_dump_data_to_file()

instead of

shn_data_file()

Function argument naming

Function arguments should be separated by spaces, both when the function is defined and when it is called. However, there should not be any spaces between the arguments and the opening/closing brackets.

Some examples of correct/incorrect ways to write functions:
<?php
function get_user_data( $username, $password )//incorrect: spaces next to brackets
function get_user_data($username,$password)//incorrect: no spaces between arguments
function get_user_data($a, $b)//ambiguous: what do variables $a and $b hold?
function get_user_data($username, $password)//correct
?> 

Function argument names with default values

Arguments with default values should go at the end of the argument list

<?php
function shn_database_connect($dsn,$persistent=false)
{
//code
}
?> 

Commenting in functions

Actual functions should be very well commented describing the purpose and @param and @return tags are recommended.

/**Function to insert camp details
*@param campdata
*@return void
*/
function shn_cr_insert_camp_data($camp_data)
{
}

Constant Naming

Constants should always be all-uppercase, with underscores to separate words. and of course should have shn as the prefix. example:

SHN_OR_NAME

Variable Naming

General Variable Naming Convention

    Variable names should be meaningful and variables with more than one word should be separated with underscores.
example:$missing_people_count

Common configuration variables

Common configuration variables will be placed in the

/conf/sysconf.inc.tpl

file and placed in a global associative array $conf. All system based configuration variables will be prefixed with shn_sys_. Below is an example of how to define a global configuration variable:

$conf['shn_sys_database'] = "sahana";

All other global variable (i.e not found in easily modifiable configuration files) is to be placed in the global associative array $global:

$global['module'] = "peoplereg";

Module Configuration variables

Each module can have configuration settings. Definitely there is one variable all the modules should have. That is the nice name. Example: Nice name for the 'or' module is “Organization Registry”. This nice name will be used for display purposes. specify it like this.

$conf['mod_or_name'] = "Organization Registry";

The following style is not encouraged as it can be accomplished by the above, however it is not prohibited.

$conf['mod_mpr']['search']['limit'] = 5

Braces {} Policy :Control Structures

These include if, for, while, switch, etc. The standard is to have the opening brace in the same line (I know this is just personal preference). To be consistent across the code base its better if you follow it, but its not a must. Here is an example if statement:

<?php
if ((condition1) || (condition2)) {
    action1;
} elseif ((condition3) && (condition4)) {
    action2;
} else {
    default action;
}
?>

Braces {} Policy :Functions

Start the brace on a new line

function a()
{
	//code
}

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.

Indentation/Tabs/Space Policy

Indent using 4 spaces for each level. (indent of 4 spaces is the PEAR standard) Do not use tabs, use spaces. Most editors can substitute spaces for tabs. Indent as much as needed, but no more. There are no arbitrary rules as to the maximum indenting level. If the indenting level is more than 4 or 5 levels you may think about factoring out code.

function func()
{
     if (something bad)
    {
         if (another thing bad)
        {
             while (more input)
            {
            }
        }   
    }   
}

Spaces between tokens

There should always be one space on either side of a token in expressions, statements etc. The only exceptions are commas (which should have one space after, but none before), semi-colons (which should not have spaces on either side if they are at the end of a line, and one space after otherwise). Functions should follow the rules laid out already, i.e. no spaces between the function name and the opening bracket and no space between the brackets and the arguments, but one space between each argument. Control statements such as if, for, while etc. should have one space on either side of the opening bracket, and one space before the closing bracket. However, individual conditions inside these brackets.

(e.g. ($i < 9) || ($i > 16)) should not have spaces between their conditions and their opening/closing brackets.
In these examples, each pair shows the incorrect way followed by the correct way:
<?php
$i=0;
$i = 0;

if(( $i<2 )||( $i>5 ))
if ( ($i < 2) || ($i > 5) )

foo ( $a,$b,$c )
foo($a, $b, $c)

$i=($j<5)?$j:5
$i = ($j < 5) ? $j : 5
?> 

Operator Precedence

I doubt very much that any developer knows the exact precedence of all the operators in PHP. Even if you think you know the order, don't guess because chances are you'll get it wrong and cause an unexpected bug that will be very difficult to find. Also, it will make maintaining your program a living nightmare for anyone who doesn't know the precedence tables in so much depth. Always use brackets to make it absolutely clear what you are doing.

<?php
$i = $j < 5 || $k > 6 && $m == 9 || $n != 10 ? 1 : 2; // What *is* going on here?!?
$i = ( (($j < 5) || $k > 6)) && (($m == 9) || ($n != 10)) ) ? 1 : 2; // Much clearer
?> 

Condition Format

Always put the constant on the left hand side of an equality/inequality comparison. For example:

if ( 6 == $error_num ) ...

One reason is that if you leave out one of the = signs, the parser will find the error for you. A second reason is that it puts the value you are looking for right up front where you can find it instead of buried at the end of your expression. It takes a little time to get used to this format, but then it really gets useful.

SQL Code LayOut

When writing SQL queries, capitialise all SQL keywords (SELECT, FROM, VALUES, AS etc.) and leave everything else in the relevant case. If you are using WHERE clauses to return data corresponding to a set of conditions, enclose those conditions in brackets in the same way you would use for PHP if blocks.

example:SELECT * FROM users WHERE ( (registered = 'y') AND ((user_level = 'administrator') OR (user_level = 'moderator')) )

Quoting String

Strings in PHP can either be quoted with single quotes ('') or double quotes (””). The difference between the two is that the parser will use variable-interpolation in double-quoted strings, but not with single-quoted strings. So if your string contains no variables, use single quotes and save the parser the trouble of attempting to interpolate the string for variables, like so:

<?php
$str = "Avoid this - it just makes more work for the parser."; // Double quotes
$str = 'This is much better.' // Single quotes
?>

Likewise, if you are passing a variable to a function, there is no need to use double quotes:

<?php
foo("$bar"); // No need to use double quotes
foo($bar); // Much better
?> 

Finally, when using associative arrays, you should include the key within single quotes to prevent any ambiguities, especially with constants:

<?php
$foo = $bar[example]; // Wrong: what happens if 'example' is defined as a constant elsewhere?
$foo = $bar['example']; // Correct: no ambiguity as to the name of the key
?> 

PHP Code Tags

PHP Tags are used to delimit PHP from html in a file. There are several ways to do this.

<?php ?>, <? ?>, <script language="php"> </script>, <% %>, and <?=$name?>.

Some of these may be turned off in your PHP settings. Use

<?php ?>

Justification

<?php ?>

is always available in any system and setup.

But you might use the following format for echoing/printing strings.Specially when we use localization.Its the short cut for localizing :)

<?=_("Organization Name")?>

Refer to the localization section for more information. Even if you use the above format for echoing/printing strings , you must start the php file with

<?php

POST and GET variables

avoid $_REQUEST as much as possible. $_REQUEST array holds the values of both GET & POST variables. only if your code accept the input from GET or POST use $_REQUEST. If you want to differentiate between GET and POST don't use. generally if you know your input is coming from POST , use $_POST why accept it from GET also if it does not give you any feature , other than a security hole.

Including Code

Anywhere you are unconditionally including a class file, use

require_once()

. Anywhere you are conditionally including a class file (for example, factory methods), use

include_once()

. Furthermore remember that

include_once()

will allow to continue , even if the inclusion does not succeed. Therefore unless you want to continue like that ( if the inclusion includes optional functionality) don't continue. Therefore try to stick to

require_once()

as much as possible. Either of these will ensure that class files are included only once. They share the same file list, so you don't need to worry about mixing them - a file included with

require_once()

will not be included again by

include_once()

. Note:

include_once()

and

require_once()

are statements, not functions. You don't need parentheses around the filename to be included.

PHP Object Oriented Programming Coding Convention

Class Naming

* Class names should be meaningful according to the responsibility.

  • Minimize using compound names(Having a compundname implies that the design is bad)
  • Use upper case letters as word separators, lower case for the rest of a word
  • First character in a name is upper case
  • No underbars ('_')
example:
class CampOwner
       {
       }

Method and function Naming Inside a class

Usually every method and function performs an action, so the name should make clear what it does:

CheckForErrors() instead of ErrorCheck(), DumpDataToFile() instead of DataFile()

. This will also make functions and data objects more distinguishable.

Suffixes are sometimes useful: 
Max - to mean the maximum value something can have. 
Cnt - the current count of a running count variable. 
Key - key value. 
For example: RetryMax to mean the maximum number of retries, RetryCnt to mean the current retry count. 
Prefixes are sometimes useful: 
Is - to ask a question about something. Whenever someone sees Is they will know it's a question. 
Get - get a value. 
Set - set a value

For example: IsHitRetryLimit. 

Class Attribute Names

*Attribute names should be prepended with the character 'm'.
*After the 'm' use the same rules as for class names.
*'m' always precedes other name modifiers like 'r' for reference.

class NameOneTwo
   {
      function VarAbc() {};
      function ErrorNumber() {};
      var $mVarAbc;
      var $mErrorNumber;
      var $mrName;
   }

Method Argument Names

        The first character should be lower case.All word beginnings after the first letter should be upper case as with class names. 
class NameOneTwo
   {
      function StartYourEngines(&$someEngine, &$anotherEngine) 
      {
        $this->someEngine = $someEngine;
        $this->anotherEngine = $anotherEngine;
      }

      var $someEngine;
      var $anotherEngine;
   }

Localization

Please remember to localize all the strings.Its very easy to localize in sahana. example:

<?php echo _t("Organization Name")?>

You can't use un-escaped double quotes (””) inside of the string. This usually happens when you use single quotes (``) to enclose a string.

Try to always use double quotes to enclose strings and escapse (\”) any other double quotes inside the string

e.g:
_t('Home page "http://sahana.lk" ')
 
this should be,
_t("Home page \"http://sahana.lk\" ")

If there are number of quotation marks inside the gettext function you can follow the following coding convention

e.g:
_t('To do this in the navigation bar click on "Multiple Incidents" followed by <a href="?mod=admin&act=ims_level1">
  "Manage Disaster"</a> and add the disaster name');
 
this should be,
 
_t('To do this in the navigation bar click on ').'&#34;'._t('Multiple Incidents').'&#34;'._t(' followed by ').
'<a href="?mod=admin&act=ims_level1">'.'&#34;'._t('Manage Disaster').'&#34;'.'</a> '._t(' and add the disaster name.');

Above coding shows rather than using quotation marks you can use html special character available for quotation mark which is &#34; . Make sure to keep space between words.

Don't localize variables. example: we don't want to see code similar to following

<?php echo _t($org)?>

gettext Best Practices

  • 1. Please make sure gettext contain only word phrases.
e.g:
_t('<h2>Welcome to the Sahana FOSS Disaster Management System</h2>');
 
this should be,
echo "<h2>"._t('Welcome to the Sahana FOSS Disaster Management System')."</h2>";
  • 2. If there are html tags which you have to put within word phrase make sure to separate them from gettext. (see above example)
  • 3. When writing a paragraph within gettext make sure line brakes are not put (In this case line breaks are behaving in different manner in different editors. For instance Eclipse put line break when you press enter but Qunata won't,it just wrap it).
e.g:
Eclipse behaves as follows
_t("The SAHANA Disaster Victim Registry is a central online repository " .
"where information on all the disaster victims can be stored. Information like name, age" .
", contact number, id card number, religion, race, displaced location, current location and other ")
 
This paragraph appears in sahana.po file in separate lines,not in a paragraph.Solution for Eclipse IDE users is  
writing the paragraph in same line.
 
Quanta will wrap this paragraph and appears in sahana.po file as a paragraph,which is allright :-).
  • 4. Html special characters should be separated from gettext.
  • 5. Beware of quotation marks ,please put html special characters for quotation marks(Quotation marks always bother developers :) )

Rule of thumb is to keep the content of gettext as simple as possible

Database Localization

Gettext framework doesn't support localization of strings stored in the database directly. Because of that Sahana uses a separate table named 'lc_fields'. This table holds the name of the table and field where the data in that field should be translated along with the Sahana web-interface translation.

The Structure of 'lc_fields'

id table field
1 rms_req_category category
2 rms_req_category description

The database fields that need to be translated in to other languages should be added to this table (lc_fields).

Database Localization Usage

To display a value retrieved from the database in some other language, the developer has to use use the function _lc(). This function takes a single string as the parameter and will return the translated value of that string. If a translation is not available this will return the same value.

_lc() function
[ string ] _lc ( $string )
example

    $sql = "SELECT * FROM rms_req_priority";
    $recordSet_prio = $global['db']->Execute($sql);

    $rs = $recordSet_prio->getArray();

    ....

    foreach($rs as $r)
    {
    ?>
    <tr>
        <td><?php print  $r['priority_id'] ?></td>
        <td><?php print  _lc($r['priority']) ?></td>
        <td><?php print  _lc($r['description']) ?></td>
    </tr>
    <?php
    }


This will display the translated values of Priority, Description.


Commenting the Code

Putting meaningful comments where ever necessary is highly reccommended.A general rule of thumb is that if you look at a section of code and think “Wow, I don't want to try and describe that”, you need to comment it before you forget how it works.

Single line Comments

example ://this is a php single line comment 

Multiline Comments

example:
/*This is a PHP
 paragraph comment. 
*/

Libraries

Any Libraries created should start with

<?php

but should NOT have an ending

?>

. This is because any white spaces after the ending tags will be written to the output and hence will affect any header information to be sent. A sample library file would be like as follows.

<?php
 
function funct1(){
 
}
 
function funct2(){
 
}

Methodology to check for the coding conventions

Currently we use 'Spike PHPCheckstyle' which is a free software tool that helps to check for the violation of coding convention. The tool can be downloaded at,

https://sourceforge.net/project/showfiles.php?group_id=143297 After you have downloaded the 'Spike PHPCheckstyles', click the link below and follow the instructions provided there.

http://developer.spikesource.com/wiki/index.php?title=Projects:phpcheckstyleDocs

however, there are several issues. For an example, Sahana uses 4 space indentation rule, but this tool checks only for existence of tabs in a line. It does not check that every line follows the 4 space indentation rule. It does not check the coding convention of SQL queries as well.

References


Navigation
  • Navigate