Bo Allen's Web Coding Standards
This is a very basic set of web coding standards aimed to maintain code consistency. Last updated: December 29, 2010
General Practices
Indentation and Line Breaks
All indentation is done with 4 spaces, not tabs.
Why spaces?
- Helps to avoid problems with diffs, patches, SVN history and annotations.
- When people using different tab settings the code is impossible to read or print, which is why spaces are preferable to tabs.
- Makes your code consistent if you happen to edit it in a web interface (textarea).
- Zend framework uses 4 spaces.
Vim rules for 4 spaces:
set expandtab
set shiftwidth=4
set softtabstop=4
set tabstop=4
Line breaks must be in UNIX format (LF: Line Feed, U+000A, chr(10), \n).
Maximum Line Length
Lines of code should not exceed 120 characters in all reasonable circumstances.
Naming Conventions
Everything falls into one of five of the following naming conventions:
- lower_case_underscore
- PHP variables, including instantiated objects (not properties)
- PHP functions (not methods)
- Associative array keys
- Non-public file and directory names
- lower-case-hyphen
- UPPER_CASE
- Constants
- CamelCase
- Class names
- lowerCamelCase
- Methods
- Properties
Private and protected variables begin with an underscore.
Camel-cased acronyms remain camel-cased (i.e., getHtml, getDbTable, etc.).
Indent Style
K & R Style: Variant 1TBS
http://en.wikipedia.org/wiki/Indent_style#Variant:_1TBS
function favorite_indent_style($style) {
if ($style != '1TBS') {
return false;
} else {
return true;
}
}
Code Documentation
Source code should always be generously commented and documented. Please use the appropriate inline documentation system (i.e., phpDoc).
Cross Browser Testing
The latest versions of the following browsers should be tested for compatibility.
- Firefox
- IE (7, and 8)
- Chrome
- Safari (Mac)
IE6 died on march 1, 2010. Let's not support dead browsers.
Third-Party Conventions and Standards
When using a third-party script, library, or framework, the conventions and standards of that script, library, or framework should be used when appropriate.
For example, if I were building an application with CodeIgniter I would stick with these standards mostly since the CodeIgniter standards are so contrary, and my application can be encapsulated in the "application" directory. Although, when writing libraries and such that need to be auto-loaded, I have to stick with the CodeIgniter standards for it to work properly. If I were to write a community library for CodeIgniter, I would stick to the Code Igniter standards 100%.
HTML
Doctype
XHTML 1.0 Transitional will be used (until HTML5 is solidly supported (2012? 2022?)).
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link type="text/css" href="css/reset.css" rel="stylesheet" /> <title>Valid XHTML 1.0 Transitional Template</title> </head> <body> </body> </html>
Layout
The div element is to be used for layout elements. HTML tables are intended for tabular data only.
All div elements with an id attribute must be marked at the closing div. See
the example below.
<div id="header">
<h1>Title</h1>
</div> <!-- end #header -->
Self-closing Elements
A space is required before the forward slash of a self-closing element.
<br />
<br/>
Tags and Attributes
All tags and attributes must be written in lowercase. Additionally, it is preferred that any attribute values also be lowercase, when the purpose of the text therein is only to be interpreted by machines. For instances in which the data needs to be human readable, proper title capitalization should be followed, such as:
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<a href="http://example.com/" title="Description Goes Here">Example.com</a>
Quotes
In keeping with the strictness of XHTML code conventions, according to the W3C, all attributes must have a value, and must use double-quotes. The following are examples of proper and improper usage of quotes and attribute/value pairs.
<input type="text" name="email" disabled="disabled" />
<input type=text name=email disabled>
CSS
Inline Styles
Inline style attributes should be avoided (style="..."). Please use external stylesheets or style tag
declarations in the head section. Do not put style tag declarations outside of the head section.
An exception to this rule is style="display: none;" for revealing hidden elements via JavaScript.
CSS Validation
All cascading stylesheets should be verified against the W3C validator, to ensure correct syntax and to check for possible accessibility issues with text and background colors. This in and of itself is not directly indicative of good code, but it helps to weed out problems that are able to be tested via automation. It is no substitute for manual code review.
Validation errors related to -moz*, -khtml*, -webkit*, and opacity should be considered "warnings" rather than errors. Just be sure to cross-browser test your styles.
CSS Reset
It is recommended to implement a CSS reset in order to minimalize cross-browser style differences.
CSS Formatting
To ease potential headaches for maintenance, all CSS must be written in a consistent manner. For one, all CSS selectors must be listed on their own line. As a general rule of thumb, if there is a comma in CSS, it should immediately be followed by a line break. This way, we know that all text on a single line is part of the same selector. Likewise, all property/value pairs must be on their own line with standard indentation (4 spaces), and end with a semicolon. All property values must begin with a space (after the colon). The closing brace must be on the same level of indentation as the selector that began it - flush left.
#selector-1 span,
#selector-2 span,
#selector-3 span {
background: #fff;
color: #000;
}
#selector-1 span, #selector-2 span, #selector-3 span {
background:#fff; color: #000
}
#selector { background: #fff; color: #000; }
Hex Colors
Hex values should be lowercase. No upper-case or RGB, please! Additionally, all colors should be written as tersely as possible. This means that colors such as full blue, which can be written lengthily as #0000FF, should be simply written as #00f. Obviously, for colors that require more precision, all six characters should be used. For example, a light shade of grayish beige: #f9f9f0.
Background
#selector {
background: #fff url(../images/file.png) repeat-x fixed left bottom;
}
#selector {
background-color: #fff;
background-image: url(../images/file.png);
background-repeat: repeat-x;
background-attachment: fixed;
background-position: left bottom;
}
Internet Explorer Bugs
Inevitably, when all other browsers appear to be working correctly, any and all versions of Internet Explorer will introduce a few nonsensical bugs, delaying time to deployment. While it is encouraged to troubleshoot and build code that will work in all browsers without special modifications, sometimes it is necessary to use conditional if IE comments to serve up specific fixes, which are ignored by other browsers.
<!--[if IE 7]> <link type="text/css" rel="stylesheet" href="/assets/styleshseets/ie7.css" /> <![endif]--> <!--[if IE 8]> <link type="text/css" rel="stylesheet" href="/assets/styleshseets/ie8.css" /> <![endif]-->
Javascript
Variables
All JavaScript variables shall be written in lowerCamelCase, because every variable in Javascript is a property of an object.
Quotes
The preferred method of delineating strings is to use single quotes for everything. Since JavaScript exists to manipulate markup, and because HTML is generally written with double quotes in W3C specifications, using single quoted strings will better facilitate handling HTML fragments, and keep code more readable.
var my_html = '<img class="photo" src="/path/file.jpg" alt="Text" />';
var my_html = "<img class=\"photo\" src=\"/path/file.jpg\" alt=\"Text\" />";
CDATA
CDATA tags should be used around inline Javascript blocks in order to prevent it from being parsed by the XHTML validator.
<script type="text/javascript">
//<![CDATA[
$(function() {
$('a.confirm').bind('click', function() {
return confirm('Are you sure?');
});
});
//]]>
</script>
Event Listeners
Rather than using attributes such as onload, onfocus, onsubmit, or onclick directly in markup, it is recommended to attach event listeners to these elements via unobtrusive techniques. The reasoning for this is the same philosophy that is behind not using inline declarations. So doing inextricably ties the behavior of a web page to its data, and makes maintenance more difficult.
<button class="toggle-list">Toggle List</button>
<ul id="list">
<li>Item A</li>
<li>Item B</li>
<li>Item C</li>
</ul>
<script type="text/javascript">
//<![CDATA[
// We're setting up the event handler here instead of
// using the "onclick" parameter in the <button> tag.
$(function() {
$('button.toggle-list').bind('click', function() {
$('ul#list').toggle('fast');
});
});
//]]>
</script>
Event Delegation
When assigning unobtrusive event listeners, it is typically acceptable to assign the event listener directly to the element(s) which will trigger some resulting action. However, occasionally there may be multiple elements which match the criteria for which you are checking, and attaching event listeners to each one might negatively impact performance. In such cases you should use event delegation instead.
<table id="data">
<thead>
<tr>
<td>ID</td>
<td>Name</td>
<td>Value</td>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Biofuel Gourmet Caffeinated Popcorn</td>
<td>7.99</td>
</tr>
<tr>
<td>2</td>
<td>Javapops</td>
<td>9.99</td>
</tr>
<tr>
<td>3</td>
<td>Caffeinated Perky Jerky</td>
<td>5.99</td>
</tr>
</tbody>
</table>
<script type="text/javascript">
//<![CDATA[
// We're setting up the event handler on the whole table, instead of each table row.
// If this table were 1000 rows, we'd have 1000 event listeners without delegation.
$(function() {
$('table#data').delegate('tr', 'hover', function() {
$(this).toggleClass('tr-hover');
});
});
//]]>
</script>
Closures & Scope
To maintain proper scope for variables, it is highly recommended that self-executing anonymous function be used as a closure. For the most part, variables defined correctly using the var syntax, within the scope of a function will not add to global scope pollution. However, from time to time, you may need to access variables via two or more functions. In such cases, multiple functions can be grouped together inside a closure.
(function() {
var first_variable = 'value 1';
var second_variable = 'value 2';
function first_func() {
// Do something.
}
function second_func() {
// Do something.
}
})();
Inline Documentation
Doxygen should be used for inline Javascript documentation.
PHP
General
- Do not do any real logic in object constructors. Create class methods to do so.
- true, false, and null should always be lowercase.
(Why?)
- For consistency with it's buddy web language, Javascript, whose booleans are lowercase and case-sensitive.
- Avoid embedded assignments (ex: $d = ($a = $b + $c) is bad).
- Use & & and || instead of AND and OR.
- Avoid using global variables if at all possible.
Parenthesis
- Do not put parenthesis next to keywords. Put a space between.
- Do not use parenthesis when using include, require, include_once, and require_once.
- Do not use parenthesis in return statements when it's not necessary.
- Do put parenthesis next to function names.
- Examples:
require_once './config.php';
if ($test) {
// ...
}
if (!$test) {
// ...
}
while ($test == $other) {
// ...
}
array_push($one, $two);
return $test;
Classes, Methods, and Properties
- Class names are CamelCase
- Method and property names are lowerCamelCase.
- Private and protected methods and properties must be prefixed with the underscore _ character.
- Class file names are in the format ClassName.php.
- Classes make use of inline documentation.
/**
* A simple car class example.
*
* <code>
* require_once 'Car.php';
* $lambo = new Car('Lamborghini', 'Countach', 'ZA9CA05A8JLA12353', array('xm_radio' => true, 'nitrous' => true);
* echo $lambo->getOption('nitrous');
* </code>
*
* @author Bo Allen http://boallen.com
*/
class Car {
/**
* The make (i.e., Ford, Honda, etc.)
*
* @var string
*/
public $make;
/**
* The model (i.e., Focus, Civic, etc.)
*
* @var string
*/
public $model;
/**
* The VIN
*
* @var string
*/
private $_vin;
/**
* Car options
*
* @var array
*/
protected $_options;
/**
* Car class constructor
*
* @param string $make The make of the car (i.e., Honda)
* @param string $model The model of the car (i.e., Civic)
* @param string $_vin (Optional) The VIN.
* @param array $_options (Optional) Car options
*/
public function __construct($make, $model, $_vin = '', $_options = array()) {
$this->make = $make;
$this->model = $model;
$this->_vin = $_vin;
$this->_options = $_options;
}
/**
* Returns the car make
*
* @return string
*/
public function getMake() {
return $this->make;
}
/**
* Returns the car model
*
* @return string
*/
public function getModel() {
return $this->model;
}
/**
* Returns the VIN
*
* @return string
*/
private function _getVin() {
return $this->_vin;
}
/**
* Returns a car option
*
* @param string $key The option name
* @return mixed
*/
protected function _getOption($key) {
if (isset($this->_options[$key])) {
return $this->_options[$key];
} else {
return false;
}
}
}
Functions and Variables
Functions and variables user lower_case_underscore format.
/**
* Returns a true random number from RANDOM.ORG's integer http interface. Requires cURL.
*
* @author Bo Allen http://boallen.com
* @param int $min Minimum number
* @param int $max Maximum number
* @return mixed Returns random integer on success, and a string error or message on failure
*/
function get_true_random_number($min, $max) {
// Sanitize parameters
$min_int = (int) $min;
$max_int = (int) $max;
// Curl options
$options = array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => false,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_ENCODING => "",
CURLOPT_USERAGENT => "PHP",
CURLOPT_AUTOREFERER => true,
CURLOPT_CONNECTTIMEOUT => 120,
CURLOPT_TIMEOUT => 120,
CURLOPT_MAXREDIRS => 10,
);
// Run curl
$ch = curl_init("http://www.random.org/integers/?num=1&min={$min_int}&max={$max_int}&col=1&base=10&format=plain&rnd=new");
curl_setopt_array($ch, $options);
$content = curl_exec($ch);
curl_close($ch);
return trim($content);
}
Arrays
- Associate array indexes, whenever possible, should be lowercase and use the underscore _ as a separator.
- Associate array indexes are always encapsulated with single quotes.
$user['salt_type'] = 'iodized';
Constants
- Constants must be in all UPPERCASE letters.
Source Formatting
While a bit of source formatting can help readability, excessive formatting should be avoided.
$string = "MegaMan\n";
$string .= "X7\n";
$array = array('level' => 30, 'head_armor' => 4, 'body_armor' => 4, 'x_buster' => 9, 'energy' => 200, 'lives' => 3);
$string = "MegaMan\n";
$string .= "X7\n";
$array = array( 'level' => 30,
'head_armor' => 4,
'body_armor' => 4,
'x_buster' => 9,
'energy' => 200,
'lives' => 3);
$string = "MegaMan\n";
$string .= "X7\n";
$array = array(
'level' => 30,
'head_armor' => 4,
'body_armor' => 4,
'x_buster' => 9,
'energy' => 200,
'lives' => 3
);
File Structure
- Public file names and directories are lower-case with hyphens.
For SEO purposes, because Google does not see an underscore as a separator. - Non-public file names and directories are lower_case with underscores.
- Private and protected directories begin with an underscore and are lower-case with underscores.
Files and directories of this type should be kept out of the webroot anyway. - PHP class files should be in the format: ClassName.php (FormValidator.php).
Inline Documentation
phpDoc should be used for inline PHP documentation.