The Zoop Framework coding standard is based on the PEAR Coding Standard with minor modifications.
Code must be readable. Code is written once, but reviewed and modified multiple times. Make sure the code is readable, and thereby understandable. Understandable code is maintainable code.
Performance is important. If there is a choice between performance and readability, readability should take precedence.
Class and function declarations have their opening brace on the same line, and follow a modified "K&R style".
class Foo { //... code goes here }
function fooFunction($arg1, $arg2 = 'default') { if (condition) { statement; } return $val; }
Arguments with default values go at the end of the argument list. Always attempt to return a meaningful value from a function if one is appropriate. Here is a slightly longer example:
function connect(&$dsn, $persistent = false) { if (is_array($dsn)) { $dsninfo = &$dsn; } else { $dsninfo = DB::parseDSN($dsn); } if (!$dsninfo || !$dsninfo['phptype']) { return $this->raiseError(); } return true; }
Complete inline documentation comment blocks (docblocks) must be provided. Please read the Sample File and Header Comment Blocks sections of the Coding Standards to learn the specifics of writing docblocks for dotProject. Further information can be found on the phpDocumentor website.
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. Use of Perl/shell style comments (#) is discouraged.
Control statements include if, for, while, switch, etc. Here is an example if statement, since it is the most complicated:
if ((condition1) || (condition2)) { action1; } elseif ((condition3) && (condition4)) { action2; } else { defaultaction; }
Control statements should have one space between the control keyword and opening parenthesis, to distinguish them from function calls.
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.
For switch statements:
switch (condition) { case 1: action1; break; case 2: case 3: action2; break; default: defaultaction; break; }
All source code files should contain a "file-level" docblock at the top of each file and a "class-level" docblock immediately above each class. The only exception to this rule is where a file contains a single class. In this case only the class docblock is required. Included is a brief example of such docblocks, see the index below for more in-depth examples.
/** * @file * * Short description for file. * * Long description for file (if any)... * * @ingroup GroupName * @author Original Author <author@example.com> * @author Another Author <another@example.com> * @copyright 1997-2005 Supernerd, LLC and Contributors * @license http://www.gnu.org/copyleft/gpl.html GPL License 2 or later * @version CVS: $Id:$ * @link http://www.zoopframework.com/ * @see zoop::zoop * @since File available since Release 1.2.0 * @deprecated File deprecated in Release 2.0.0 */ /* * Place includes, constant defines and $_GLOBAL settings here. * Make sure they have appropriate docblocks to avoid phpDocumentor * construing they are documented by the page-level docblock. */ /** * Short description for class. * * Long description for class (if any)... * * @ingroup GroupName * @ingroup AnotherGroup * @author Original Author <author@example.com> * @author Another Author <another@example.com> * @copyright 1997-2005 Supernerd, LLC and Contributors * @license http://www.gnu.org/copyleft/gpl.html GPL License 2 or later * @version CVS: $Id:$ * @link http://www.zoopframework.com * @see zoop, zoop::zoop() * @since Class available since Release 1.2.0 * @deprecated Class deprecated in Release 2.0.0 */ class foo { /** * Brief method description. * * Extended description for method (if any)... * * @code * //code examples can be added with @ code blocks * $var = fooFunction($arg); * @endcode * * @param mixed $arg1 Argument 1 description. * @param mixed $arg3 Argument 2 short description. * Extended description for Argument 2. Perhaps talk about the default value? * @access public * @return mixed Return value description. * Can also have an extended definition. */ function fooFunction($arg1, $arg2 = 'default') { if (condition) { statement; } return $val; } }
Every branch of Zoop should contain one @mainpage docblock. This docblock is currently found in zoop.php, and looks something like this:
/**
* @mainpage Welcome to the Zoop Framework
*
* Welcome to the Zoop Framework. Newcomers to Zoop should check out
* {@link http://zoopframework.com/docs/from-a-to-zoop From A to Zoop},
* a beginner's guide to Zoop.
*
* - {@link http://zoopframework.com/docs Zoop Documentation}
* - {@link http://zoopframework.com/docs/from-a-to-zoop From A to Zoop}
* - {@link http://zoopframework.com/docs/user-manual The Zoop Users Manual}
* - {@link http://zoopframework.com/docs/cookbook The Zoop Cookbook}
* - {@link http://zoopframework.com/docs/user-manual/components Zoop Components}
* - App
* - Auth
* - Cache
* - Chart
*
* ...
*/The @mainpage docblock is used as the landing page for the branch at api.zoopframework.com. You may also define sections, subsections and subsubsections to break up more complex documentation pages:
/**
* @section sectionName Section Title
* ...
*
* @subsection subSectionName Subsection Title
* ...
*
* @subsubsection subSubSectionName Subsection Title
* ...
*
*/Use example.com, example.org and example.net for all example URLs and email addresses, per RFC 2606.
All files in must be stored as UTF-8 character encoding. In general most files that do not contain accented characters should use the 7 bit ASCII representation, which is a valid subset of UTF-8.
There should be no whitespace before the first <?php tag or after the closing ?> tag. TODO: should use of the closing ?> tag be discouraged as well?
Files must have lines ending in LineFeed (0x0A) characters when stored in the CVS. This is normally handled automatically by the client, but some clients (especially on Windows) do not automatically convert.
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. Here's an example:
$var = foo($bar, $baz, qux($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 space may be inserted to promote readability:
$short = foo($bar); $long_variable = foo($baz);
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. 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.
Tabs and only tabs should be used for indenting. Each level of indent should be exactly one tab.
For vi/vim users who dislike the amount of space taken up by tabs the following mode line should be inserted in a comment in the first or last 5 lines of the file:
vi:set ai sw=2 ts=2 noexpandtab:
Given that modern editors are no longer limited to 80 character widths, line lengths are less important, however readability is important. Lines longer than 75 characters should be considered for breaking. Lines longer than 100 characters must be broken.
Line breaks should be at an operator, and the following line should be indented.
Classes should be given descriptive names. Avoid using abbreviations where possible. Class names should always begin with an uppercase letter. Component class names should start with the component name. Examples of good class names are:
class MyClass class MyComponentClass
Constants should always be all-uppercase, with underscores to separate words. Prefix constant names with the uppercased name of the class/module they are used in.
TODO: Decide what to do about file naming conventions.
Functions and methods should be named using the "studly caps" style (also referred to as "bumpy case" or "camel caps"). Functions should in addition have the package name as a prefix, to avoid name collisions between packages. The initial letter of the name (after the prefix) is lowercase, and each letter that starts a new "word" is capitalized. Some examples:
function connect() function getData() function buildSomeWidget() function XML_RPC_serializeData()
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 namespaces) are preceded by a single underscore. For example:
function _sort() function _initTree() $this->_status()
Note: The following applies to PHP5.
Protected class members (meaning class members that are intended to be used only from within the same class in which they are declared or from subclasses that extend it) are not preceded by a single underscore. For example:
protected $somevar protected function initTree()
TODO: Decide what to do about global variables, and naming conventions.
Always use <?php ?> to delimit PHP code, not the <? ?> shorthand. This is required for PEAR compliance and is also the most portable way to include PHP code on differing operating systems and setups.
The strict use of single quotes is preferred—not mandated—and the rule of readability over performance is to be maintained. As an example:
'Short String' . "\n"; "Short String\n";
Either form allowed where the string is short. Where the string is long the first form is required. Where the literal is to be followed by a variable instead of an escaped literal, the first form should prevail:
'Any String ' . $var; NOT "Any String $var"; NOR "Any String {$var}";
In all cases, readability is improved with increased whitespace, squishing stuff together to "save space" makes for a headache when you have to go back and maintain code.
There is never an excuse to quote a variable on its own, e.g. "$var", "{$var}", "{$class->var}", etc.