Ampache Coding Standards

Abstract

The purpose of this document is to establish a standard for all PHP, and HTML code written for Ampache. This document will outline stylistic standard for code such as indentation and spacing. It will also detail naming conventions for functions, and files as well as the logical layout of files under the web space. This document will also outline some basic coding practices, or standards that all new Ampache PHP code should meet.

Indenting and Line Length

Use an indent of a standard tabs character. It is recommended that you break lines at approximately 75-85 characters. There is no standard rule for the best way to break a line, use your judgment. The goal is to make the PHP files easy to read by a third party.

Control Structures

These include if, for, while, switch, etc. Here is an example if statement, since it is the most complicated of them:

<?php
/* Check condition1 or condition 2 else cond3 & 4 */
if ((condition1) || (condition2)) {
    action1;
} 
elseif ((condition3) && (condition4)) {
    action2;
} 
else {
    defaultaction;
}

if ((condition1)) {
	while ($foo) { 
		do_stuff();
	} // end while
} // end if
?>

Control statements should have one space between the control keyword and opening parenthesis, to distinguish them from function calls. 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. Always add // end <control statement> in order to increase readability on nested if, while, for loops. The // end <control statement> is not required on single-level control statements.

For switch statements:

<?php
/* Simple Case */
switch (condition) {
    case 1: action1; break;
    case 2: action2; break;
    default: defaultaction; break;
} 

/* Complex Case */
switch (condition) { 
    case 1: 
	action1;
	action2;
    break;
    case 2:
    case 3:
	action1;
	action2;
    break;
    default:
	action1;
    break;
} // end switch condition
?>

Function Calls

Functions should be called with no spaces between the function name, the opening parenthesis, and the first parameter; spaces between commas and each parameter, and no space between the last parameter, the closing parenthesis, and the semicolon.

Example:

<?php
$var = foo($bar, $baz, $quux);
?>

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 tabbed space should be inserted to promote readability:

<?php
$short         = foo($bar);
$long_variable = foo($baz);
?>

Variable and Function Definitions

Classes

Classes should be given descriptive names. Avoid using abbreviations where possible. Class names should always begin with an uppercase letter. The class hierarchy is also reflected in the class name. Classes should be named using CamelCaps. Examples of good class names are:

Log
NetFinger
HtmlUploadError

Functions and Methods

Functions and methods should be named with all lower case using underscores between words or levels of hierarchy. Functions should in addition have the package name as a prefix, to avoid name collisions between packages when applicable.

Example:

connect();
get_data();
build_some_widget();
xmlrpc_serialize_data();
xmlrpc_unserialize_data();

Private class members (meaning class members that are intended to be used only from within the same class in which they are declared; PHP does not yet support truly-enforceable private name spaces) are preceded by a single underscore. For example:

_sort();
_init_tree();
$this->_status;

Constants

Constants should always be all-uppercase, with underscores to separate words. Prefix constant names with the uppercased name of the class/package they are used in. For example, the constants used by the DB:: package all begin with DB_. The true, false and null constants are excepted from the all-uppercase rule, and must always be lowercase.

Global Variables

If your scripts need to define global variables, their names should start with a single underscore followed by the package name and another underscore. For example, the PEAR package uses a global variable called $_PEAR_destructor_object_list.

Variable Names

In the interest of future readability, code must always use full named variables unless a commonly known acronym can be used in its place. For example

/* A Upload Directory */
$upload_directory	= '/tmp';

/* XMLRPC result */
$xmlrpc_result	= $xmlrpc->get_results();

Code Comments

Complete inline documentation comment blocks (docblocks) must be provided. Non-documentation comments are strongly encouraged. 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. C style comments (/* */) and standard C++ comments (//) are both fine.

Including Code

Anywhere you are unconditionally including a class file, use require_once '/path/to/file' . Anywhere you are conditionally including a class file (for example, factory methods), use include_once. 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. Only libraries, classes, modules and templates should be included. All includes should whenever possible be placed at the top of the file before any functions, or operations are performed. For readability never include files that contain additional action conditions.

Example of Incorrect Including:

index.php <<
<?php

if ($_REQUEST['action'] == foo) { 
	do_stuff();
}

include_once 'default_action.php';
?>
>>
default_action.php <<
<?php

/* This is the default action performed when visiting index.php */
if ($_REQUEST['action'] != foo OR !isset($_REQUEST['action'])) { 
	do_default_stuff();
}
?>
>>

Example of Correct Including:

index.php <<
<?php

include_once conf('prefix') . '/default_action.php';

if ($_REQUEST['action'] == foo) { 
	do_stuff();
}
else { 
	default_action();
}
?>
>>
default_action.php <<
<?php

function default_action() { 
	do_default_stuff(); 
}
?>
>>

PHP Code Tags

Always use <?php ?> to delimit PHP code, not the <? ?> shorthand. There are no exceptions to compliance of this rule. This is the only way to ensure the PHP code will work on differing operating systems and setups.

Naming Conventions

Follow the below naming conventions when creating new functions to make your code easy to read. When creating functions use the following prefixes:

  • print echo info
  • get get info
  • show include html
  • create create object
  • delete delete object
  • update update object
  • clean verify, data integrity checks/modification
  • check error checking
  • has check if object has property
  • exec run a process
  • format Re-formats existing data
  • put Inserting data into lists,database,files,objects etc

Examples:

/* Echo's information, doesn't return */
print_foo() 
/* Returns information */
get_foo() 
/* Gets information then includes an html template */
show_foo() 
/* Create new Object */
create_foo() 
/* Delete Object */
delete_foo() 

File Formats

All scripts written must:

  • Be stored as ASCII text
  • Use UTF-8 character encoding

There should be no line feeds after the closing PHP tag (?>) to prevent output before headers are sent.

File Organization

In order to maintain some semblance of organization on the web servers all files should be organized based on their function. <ROOT> refers to the top of the file path for the web server. All libraries should be located in <ROOT>/lib. Any additional modules that are not written in shop should be put in <ROOT>/modules/<name of module>. All HTML templates should be put in <ROOT>/templates. All images for the site should be under <ROOT>/images. If a single subsection is going to contain a large number of images although not require it would most likely be a good idea to create a sub-directory under <ROOT>/images.

Example:

<ROOT>
	/* Contains Documents */
	/
	/* Contains GPL/Changelog & Readme */
	/docs
	/* Contains All library files */
	/lib
	/* Contains All Class Files */
	/lib/class
	/* Contains All Modules not written in house */
	/modules/foomodule
	/* Contains All HTML templates */
	/templates
      /* Contains documents that are not directly accessed, AJAX/XML-RPC and the like */
      /server
	/* Contains All Images */
	/images
	/* Contains All Images for Reservations */
	/images/reservation
	/* Contains All commandline scripts */
	/bin
</ROOT>

When naming files in order to make it easy for others to figure out their purpose they should follow the following naming conventions. All PHP files should end in a .php extension, all lower case. Library files should end in .lib.php. All PHP classes should be in their own distinct files which end in .class.php. All HTML files which are conditionally included from other PHP scripts should end in .inc.php. The name of the file should represent what is contained within. Templates should match the function that calls them. See the examples below:

/* Example document */
/user.php

/* Example User { .... } Class File */
/lib/user.class.php 

/* Example Library File */
/lib/general.lib.php

/* Example Template file for show_user() */
/templates/show_user.inc.php

User Input

Special attention must be paid to user input. The general assumption must be made that every attempt will be made by the user to maliciously disrupt the script, or case data loss when submitted to a database. User Input includes information pulled from cookies which reside on the user's computer. All user Input should be escaped and error checked before being used.

Database Connections and Calls

In order to not only ensure reliable database connections and data integrity but to account for future changes standardization of SQL statements and database calls is necessary. All SQL statements should use all capital letters for actual SQL commands and lowercase for field and table names when possible. Query statements should also always use the full name for fields for expandability. All user inputted values should be escaped and all field names should be escaped using the correct escape character

Example MySQL Query:

/* Simple Query */
SELECT * FROM `user`;

/* Complex Query */
SELECT `user.id`,`preferences.value` FROM `user` 
LEFT JOIN `preferences` ON `user.id`=`preferences.user`
WHERE `user.username` = 'dude' AND `user.pass` = PASSWORD('mypassword')
ORDER BY `user.id`
LIMIT 5,10;

When creating a database connection complete error suppression and checking should be performed. Database connections should, when possible, be centrally managed by a single function or script to ensure easy troubleshooting. For performance reasons the mssql functions should be used in lieu of the odbc functions. If enabled all database connection failures should be logged. On production sites database connection failures should send notification e-mail.

Example MYSQL DB Connect Function:

function dbh($databasename='helpdesk') { 
	
      /* If we don't have a db connection yet */
	if (!is_resource(conf($databasename))) { 
	
		$hostname	= conf('database_hostname');
		$username	= conf('database_username');
		$password	= conf('database_password');

		$dbh = @mysql_pconnect($hostname, $username, $password);

		$select_db = @mysql_select_db($databasename, $dbh);

		if (!is_resource($dbh) || !$select_db) { 

			log_event(' error ',"Error" . mssql_error());
			show_header();
			echo "<div class=\"outer\"><br /><br /><br />";
			echo Database Error: <br />"; 
			echo "<br />Error:" . mysql_error() . "<br />";
			show_footer();
			exit();
		}
		conf(array($databasename => $dbh),1);
	} // if no db connection 

	else {
		$select_db = @mysql_select_db($databasename,conf($databasename));
		if (!$select_db) { 
			show_header();
			echo "<div class=\"outer\"><br /><br /><br />";
			echo "Error:<br />"; 
			echo "<br />" . mysql_error() . "<br />";
			show_footer();
			exit();
		} // if there is an error
	} // else
		
	return conf($databasename);
	
} // dbh

Once a database connection has been established it should always be referenced explicitly in order to avoid unexpected results, and account for multiple database handles in the future. When returning results all attempts should be made to minimize database access and memory usage. For example with returning multiple results if you only need an associative array use fetch_assoc rather than fetch_array. All SQL queries must be assigned to a variable, and should never be called directly from a mysql_query function for debugging and expandibility.

Example MYSQL Query:

/**
 * Returns the User 
 * 
 * @package User
 */
function get_use() { 

	/* Setup Query String */
	$sql = "SELECT * FROM user WHERE (user.username = 'theman')"

	/* Run Query */
	$db_results = mysql_query($sql, dbh());

	/* Return Results as assoc array */
	if ($results = mysql_fetch_assoc($db_results)) { 
		return $results;
	} // end if

	/* Else Something bad happened */
	return false;

} // get_use

Version Compatibility

All PHP code written should work on any version, and almost any configuration of PHP from PHP 4.3.x up to PHP 5.x. If necessary version specific functions and syntax can be used, however it should be avoided whenever possible. All code should be written referencing the superglobals ($_POST,$_GET,$_SERVER) as if 'register_globals' is off.

File and URL Paths

All file paths, and URL's should be fully qualified and yet relational. There should be a single point where the file prefix and URL prefix is defined for all scripts. All links and includes should be relational to the prefixes. $PHP_SELF should never be used for security reasons unless it is sanity checked beforehand.

Example:

/* Global Definitions of web path and prefix */
$_PATH_web	= "http://example.com/pathtoprogram"
$_PATH_file	= "/pathtoweb/pathtoprogram"

/* Generated URL using Web Path */
$link = $_PATH_web . "/index.php"

/* Include Statement using Prefix */
include_once ($_PATH_file . "/templates/cool.inc.php”);

HTML Output

All HTML written for PHP projects should conform to W3.org's XHTML 1 Transitional standards. All user input that is to be echoed out must be sanitized before being displayed to the screen.

 
dev/codingstandards.txt · Last modified: 2008/09/10 22:16 (external edit)
 
Except where otherwise noted, content on this wiki is licensed under the following license:CC Attribution-Noncommercial-Share Alike 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki