No Shorthand PHP tags
Never use shorthand PHP start tags. Always use full PHP tags. This is important because
- short tags rely on deprecated PHP configuration
- short tags violate XML specifications (“
<?
” starts a PI (processing instruction) and must be followed by a name) - full tags are more readable
<?php
// INCORRECT: ?>
<?php ... ?>
<?php echo $var ?>
<?php
// CORRECT: ?>
<?php ... ?>
<?php echo $var ?>
Semicolons End Statements
PHP generally uses semicolons “;
” to mark the end of a statement. However, if the PHP closing tag is on the same line after a statement, the semicolon is optional and should not be used.
A code block, enclosed in braces “{}
” is not a statement, it is a group of statements. Each statement within the code block must be terminated with a semicolon, but the code block itself is NOT terminated with a semicolon.
No PHP Closing Tag At EOF
The closing “?>
” tag at the end of a PHP file is optional to the PHP parser and is not required. However, if used, any whitespace following the closing tag, whether introduced by the developer, user, or an FTP application, will be immediately written to the output. This will prevent any more headers from being sent to the browser, can cause PHP errors, and if the latter are suppressed, blank pages. Leaving it out reduces the processing necessary for the module.
For source files that end in PHP mode (as opposed to HTML mode),omitthe closing PHP tag and instead use a comment block to mark the end of file:
<?php
//
// EOF: filename.php
where “filename
” is replaced with the name of the source file. There should be one newline after the last non-empty line in the file: When the cursor is at the very end of the file, it should be one line below the closing text.
Having the “end of file” marker in place will make it easier to find unwanted truncations of the file that might accidentally occur.
Line Lengths
Source code statements should always be limited to 80 characters per line, taking into account expansion of tabs to four character spaces. While wide desktop display screens and horizontally scrolling editors make it possible to create and view longer lines in an original development environment, the longer lines are more difficult to comprehend, and will cause wrapping issues on less capable displays. (The first time you open a file with long lines in a terminal window on your smart phone you'll understand the problem.) In addition, when attempting to do side-by-side comparisons of different versions of the same file, the longer lines will either cause wrapping or scrolling issues in the comparison utility.
If necessary, an empty PHP segment can be inserted to wrap a long line of HTML code and keep it within the 80 character line length.
<?php
// For example: ?>
<a href="http://www.example.com/n/deeply/nested/page.php" rel="external" <?php
?>class="anchor-class-name">The Anchor Text</a>
There will be times when limiting lines to 80 characters will be impossible, such as within a "heredoc" where there isn't a mechanism available for folding long lines. Such cases are generally rare, so following the 80 character limit usually should not be an issue.
One Statement Per Line
Do not combine statements on one line. Doing so reduces the line count (volume) but increases the line density, and more dense lines are harder to comprehend. In addition, the fact that multiple statements are combined on one line may be overlooked when quickly reading code during maintenance, resulting in confusion at best, and quite probably, leading to insertion of additional errors.
<?php
// INCORRECT:
$foo='this'; $bar='that'; $bat=str_replace($foo,$bar,$bag);
// CORRECT:
$foo='this';
$bar='that';
$bat=str_replace($foo,$bar,$bag);
There are a few cases where this rule may be broken to improve readability of the code. The permitted exceptions are:
- A single statement may be included on the same line with one of the PHP control structure statements -
if
,else
,for
,foreach
,do while
orwhile
- as long as line length limits are maintained. - Nested assignments where the value being assigned is immediately used in another assignment or computation. This type of construct has been known to improve processing speed by avoiding swapping variables out of the processor's registers. Don't nest the assignments too heavily, though, or the increased line density will have an adverse effect on readability.
- Simple case assignments within a
switch
block where thecase
, assignment andbreak
can all fit within the line length limits:
<?php
switch ($_REQUEST['tag'])
{ default: $string=FALSE; break;
case 1: $string='first choice'; break;
case 2: $string='another possible choice'; break;
case 3: $string='maybe something else'; break;
case 4: $string='yet another idea'; break;
}
Whitespace
The PHP parser ignores whitespace outside of quoted strings. Whitespace is solely used for the convenience and comprehension of human readers.
No whitespace can precede a file's opening PHP tag or follow a closing PHP tag: extraneous whitespace at the boundaries of your files can cause output to begin before it is supposed to, leading to errors and, potentially, blank pages.
Whitespace is required after the PHP start tag - a single space, one or more tab characters, or a newline. For single line statements or control structures where an opening brace starts the next line, the start tag and statement can be on the same line - use a space as the separator if the current indentation level is less than two tabstops from the left margin, otherwise use the correct number of tabs to indent the statement for the current indentation level.
A single space should be used between the PHP code and the close tag unless the close tag is at the start of a new line where there should be no leading space.
In general, parenthesis and brackets should not use any additional spaces. The exception is a space must always follow PHP control structure keywords that take arguments with parenthesis (declare
,do-while
,while
,if-else
,switch
,for
,foreach
), to help distinguish them from function calls and increase readability. Function names should not have any whitespace between them and the parentheses enclosing their argument list. When referring to array items, never use spaces around the index.
<?php
// INCORRECT:
foreach( $query->result() as $row )
// CORRECT:
foreach ($query->result() as $row) // single space after PHP keyword, not within parenthesis
// INCORRECT:
function Foo ( $bar )
{
}
// CORRECT:
function Foo($bar) // no spaces around parenthesis in function declarations
{
}
// INCORRECT:
$arr[ $foo ] = 'foo';
// CORRECT:
$arr[$foo]='foo'; // no spaces around array keys
Remove trailing spaces
Remove trailing spaces at the end of each line of code. Extraneous whitespace at the end of a line serves no useful purpose, may cause diff errors, and increases network overhead. Your text editor should have an option to assist in meeting this requirement.
Alignment of assignments
To support readability, the equal signsmaybe aligned in block-related assignments.
<?php
$short =foo($bar);
$longername=foo($baz);
The rule should be broken when the length of the variable name is at least eight characters longer or shorter than the surrounding ones
<?php
$short=foo($bar);
$thisVariableNameIsVeeeeeeeeeeryLong=foo($baz);
When PHP emits whitespace
One thing that needs to be understood to have PHP generate readable HTML code is when PHP sends whitespace to the browser.
Any whitespace to the left of a PHP opening tag will be emitted - once. This means that if you indent an opening tag for aninclude
statement, thefirst line, andonlythe first line, of any HTML or text in the included file will be indented by the whitespace to the left of the opening tag: PHP doesnotinterpret indenting aninclude
statement to mean "indent each line in the file by the amount theinclude
statement was indented by."
On the other hand, unless there are non-whitespace characters on the line after a PHP closing tag, PHP ignores any whitespace up to and including the newline terminating the source statement. This frequently results in run-on HTML statements with embedded tabs where the code's author was expecting nicely formatted output:
<?php
// expected newlines are not emitted ?>
<tr>
<td>
<?php /* intentional indent */ echo $some_variable ?>
</td>
</tr>
<?php // yields this HTML output: ?>
<tr>
<td>
some_variable's value </td>
</tr>
<?php // better code would be: ?>
<tr>
<td><?php echo $some_variable; /* non-whitespace after close tag */ ?></td>
</tr>
<?php // which yields this HTML output: ?>
<tr>
<td>some_variable's value</td>
</tr>
Indentation
The PHP parser doesn't care about indentation, it is solely used for the convenience and comprehension of human readers. Consequently, indentation should be used to enhance readability of the source code. Three simple rules underly the rest of the indentation patterns to be used:
- don't indent unnecessarily
- indent on purpose
- indent consistently
Your indentation should always reflect the logical structure of the code.
At the start of a code module, the code is at the [local] root level - so startallcode lines in column 1 (the leftmost column of the page). Each time a new nesting level is entered, whether braces or parentheses are present or not,indentonetab, and use that level of indentation until the nesting level changes - whether indenting another tab to enter another nesting level, or outdenting when leaving the current nesting level.
Most people find that 4-space tabstops provide the best balance between making indentation visible and using screen space. By using tabs, rather than spaces, for indentation, that preference can be adjusted without reformatting the code: If you think four spaces is too much for each indentation level, set your editor to use two or three space tabstops and the tab width will adjust to suit your view. On the other hand, if you want more indentation, you can use eight space tabstops with the same file.Just be sure that when you save the file that you are usingTABcharacters,not SPACES, for the indentation written to permanent storage.
Withinswitch
statements, theswitch
statement is the parent indentation level, thecase
statements (including thedefault
statement, if present) are the next indentation level, and the action statements within eachcase
, including thebreak
statement, are at the next indentation level. Thus, the correct indentation structure for aswitch
block is:
<?php
switch (condition)
{
case 1:
action1;
break;
case 2:
action2;
break;
default:
defaultaction;
break;
}
Use real tabs and not spaces, allowing the most flexibility across editors and operating systems. An acceptable exception is if you have a block of code that would be more readable if things are aligned, use spaces:
<?php
[tab]$foo ='somevalue';
[tab]$foo2 ='somevalue2';
[tab]$foo34='somevalue3';
[tab]$foo5 ='somevalue4';
For associative arrays, values should start on a new line. Note the comma after the last array item: This is recommended because it makes it easier to change the order of the array, and makes for cleaner diffs too. (Unlike Javascript running in InternetExploiter, PHP ignores a trailing comma in an array declaration.)
<?php
$my_array=array
([tab]'foo' =>'somevalue',
[tab]'foo2' =>'somevalue2',
[tab]'foo3' =>'somevalue3',
[tab]'foo34'=>'somevalue3',
);
The rule of thumb here is that tabs should be used for indentation at the beginning of the line and spaces for alignment within the line.
When concatenating strings in an assignment, long lines should be broken at clauses to improve readability or if the line length limit would be exceeded. In these cases, each successive line should be padded with white space so the ".
" operator is aligned under the "=
" operator:
<?php
$sql='SELECT id,name FROM people '
."WHERE name='Susan' "
.'ORDER BY name ASC';
Exceptions: try and catch
The exception handlingtry
andcatch
mark control structure blocks, just asif
andelse
do. They are indented to the same level as the surrounding code, withtry
andcatch
aligned with each other, and with the braces surrounding their code blocks:
<?php
try
{
// code that might fail
}
catch (FirstExceptionType $e)
{
// first catch body
}
catch (OtherExceptionType $e)
{
// other catch body
}
Interspersed PHP and HTML
When HTML and PHP are interspersed,ALWAYSput PHP start tags (“<?php
”) at the left margin unless one of these specific conditions exists:
the PHP code will be emitting [HTML] which should be indented. In this case, include a comment within the PHP to indicate the indentation is intentional:
<?php
<p><strong>Area</strong><br />
<?php /* intentional indent */ echo $person['AREANAME'] ?></p>
the PHP code is emitting output inline
<?php
<a href="<?php echo $theLink ?>"><?php echo $theAnchorText ?></a>
When HTML and PHP are interspersed, indent the PHP statements at the indentation level that would be in force if there were no HTML tags: The HTML and PHP codes should be considered as maintaining separate indentation levels.
Parentheses
As a general rule, only use parentheses where they are required. Additional parentheses may be used to clarify groupings in complex conditional constructs, but knowing operator precedence should eliminate their necessity.
Do not use parentheses when using language constructs such asecho
,print
,include
, orrequire
. These are not functions and don't require parentheses around their parameters.
When calling class constructors with no arguments, always include parentheses: The constructors are functions, so constructor calls need to look like function calls.
Braces
Use Allman style indenting, or preferably, Horstmann style (a.k.a. "compacted Allman") indenting. Braces are never at the end of a line, but rather always placed on a new line, and indented at the same level as the control statement that "owns" them. This makes it easier to find the matching braces and provides a logical view of the structure of the code. Code within a block enclosed by braces must be indentedonelevel from the surrounding code, and all statements at the current nesting level begin in the same vertical column of the page. This makes it easier to identify the structure of the code.
With Allman style code, braces are always on a line by themselves. In Horstmann style, the opening brace is also at the same indentation level as the parent statement, but is followed by a tab and the first (or only) statement within the child block.
<?php
// INCORRECT: // K & R
function Foo($bar) {
// ...
// ...
}
foreach ($arr as $key => $val) {
// ...
// ...
}
if ($foo == $bar) {
// ...
// ...
}
else {
// ...
// ...
}
for ($i = 0; $i < 10; $i++) {
for ($j = 0; $j < 10; $j++) {
// ...
}
// ...
}
<?php
// CORRECT, PREFERRED: // Horstmann
function Foo($bar)
{ // ...
// ...
}
foreach ($arr as $key=>$val)
{ // ...
// ...
}
if ($foo == $bar)
{ // ...
// ...
}
else
{ // ...
// ...
}
for ($i=0; $i < 10; $i++)
{ for ($j=0; $j < 10; $j++)
{ // ...
}
// ...
}
<?php
// CORRECT, ACCEPTABLE: // Allman
function Foo($bar)
{
// ...
// ...
}
foreach ($arr as $key=>$val)
{
// ...
// ...
}
if ($foo == $bar)
{
// ...
// ...
}
else
{
// ...
// ...
}
for ($i=0; $i < 10; $i++)
{
for ($j=0; $j < 10; $j++)
{
// ...
}
// ...
}
If you have a really long block, consider whether it can be broken into two or more shorter blocks or functions. If you consider such a long block unavoidable, put a short comment at the end on the same line the closing brace so people can tell at glance what that ending brace ends. Typically this is appropriate for a logic block, longer than about "35" rows, but any code that’s not intuitively obvious should be commented.
<?php
if (some_condition && !some_other_condition)
{ // ...
// ...
// ...
} // end if (some_condition && !some_other_condition)
while (yet_other_condition) // describe how this happens
{ // ...
// ...
// ...
} // end of "how this happens"
Single line blocks can omit braces for brevity as long as the indentation rules are followed as though the braces were present. The only exception is single statement
else
clauses are preferably written on the same line as theelse
keyword:
<?php
if (condition)
action1();
else if (condition2)
action2();
else action3();
If and else
if
andelse
are words, "elseif
" is not. Always useelse if
when specifying an alternate branch in anif
control structure,notelseif
.
Alternative control structure syntax
PHP supports using an alternative syntax for some of its control structures -if
,while
,for
,foreach
, andswitch
. In each case, the basic form of the alternate syntax is to change the opening brace to a colon (:) and the closing brace toendif;
,endwhile;
,endfor;
,endforeach;
, orendswitch;
, respectively. Using the alternative syntax yields codeEXTREMELYdifficult to grasp at a glance (unless you are a BASIC programmer, maybe), especially when interspersed with HTML. It also requires using a whole set of additional keywords instead of consistent braces.
<?php
// INCORRECT:
?>
<table>
<tbody>
<?php
foreach ($foo as $bar) : ?>
<tr>
<?php
if ($bar == 'example') : ?>
<th>My Heading</th>
<?php
else : ?>
<td>My Data</td>
<?php
endif; ?>
</tr>
<?php
endforeach; ?>
</tbody>
</table>
<?php
// CORRECT:
?>
<table>
<tbody>
<?php foreach ($foo as $bar)
{ ?>
<tr>
<?php if ($bar == 'example')
{ ?>
<th>My Heading</th>
<?php
}
else
{ ?>
<td>My Data</td>
<?php
} ?>
</tr>
<?php
} ?>
</tbody>
</table>
When considering using the alternative syntax, keep in mind a simple rule:DON’T DO IT!!
Single and Double Quotes
Single-quoted strings are not examined for escape sequences or embedded variable names and therefore require less processing when a page is being parsed. Always use single quoted strings unless you need variables or escape sequences parsed, or to avoid excessive quote escaping. In most cases where you would want variables embedded in a string parsed, it is preferable to use single-quoted strings concatenated to either side of the variable which is faster to parse. Use double-quoted strings if the string contains single quotes so you do not have to use escape characters.
<?php
// INCORRECT:
"My String" // no variable parsing, so no use for double quotes
"My string $foo" // not optimal
'SELECT foo FROM bar WHERE baz=\'bag\'' // ugly
$foo='something';
"My string is $something_else" // PHP looks for $something_else
"My string is ${something}_else" // ugly and unobvious
// CORRECT:
'My String'
'My string '.$foo // string catenation is faster than embedding variables
"SELECT foo FROM bar WHERE baz='bag'"
$foo='something';
'My string is '.$something.'_else' // no ambiguity
Comments
In general, code should be commented prolifically. It not only helps describe the flow and intent of the code for less experienced programmers, but can prove invaluable when returning to your own code months down the line. Non-documentation comments - those which describe the logic and flow of the program, rather than the interface with the rest of the system - 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 (delimited by/* */
) should be used for creating large comment blocks, comments within a line of PHP code, or when commenting out sections of code. C++ style inline comments (delimited by//
) may be used when the comment extends through the remainder of the current line, or for commenting outsinglePHP statements. Do not use Perl/shell style inline comments (delimited by#
).
When adding end of line comments, separate the code statement from the comment delimiter using a single tab. If multiple statements in a group have end of line comments attached, the comment delimiters can be tab aligned to improve readability.
Do not use C++ style inline comment markers (//
) at the start of a series of lines for a multi-line comment: It look sloppy, takes more typing, increases the file size, and it requires more processing power, since the interpreter has to repeatedly go in and out of its "parsing a comment" mode.
Further, N.B. - DoNOTuse//
comment delimiters to comment out blocks of code: It takes more work to comment/uncomment the block, in addition to looking sloppy. If you want to comment out a block of code, insert a/*
before the block and a/**/
after it. Then, if you want to uncomment it, all you have to do is add a*/
immediately after the opening mark, or remove the comment delimiters - one or two changes rather than having to modify every line that had been commented out.
It is sometimes useful to write acase
statement that falls through to the nextcase
by not including abreak
orreturn
within the firstcase
. To distinguish code so constructed from bugs, anycase
statement wherebreak
orreturn
are omitted should contain a comment indicating that thebreak
was intentionally omitted:
<?php
switch (condition)
{
case 1:
action1;
// no "break" here, we drop through
case 2:
action2;
break;
default:
defaultaction;
break;
}
Docblock comments
Complete inline documentation comment blocks (docblocks) must be provided for files, classes and functions (including class methods). A docblock is a special type of comment that provides verbose information about an element in your code. The information can be used by developers to gain understanding of the purpose and operation of a given element. It can also be used by integrated development environments (IDEs) to provide hints and auto-completion, and by automatic tools to generate API documentation.
Two popular programs designed for reading docblocks to produce documentation arephpDocumentorandDoxygen.
Using consistently constructed docblocks makes "newly found" code easier to understand when doing maintenance, and simplifies re-use of existing code by providing a firm grasp of the interface, effects and results of a set of a functional block or class. This is an example docblock for a function:
<?php
/**
* brief description of the function
*
* (optional) longer description of the function, side effects, etc.
* the longer description usually spans more than one line.
*
* @param type $param1, what it's for
* @param type $param2, what it's for, default='something'
* @global type $global1, what's expected in the global variable
* @global type $global2, what's expected in the global variable
* @return type, description of the return value
*/
function FunctionName($param1,$param2='something')
{ global $global1,$global2;
$internalName=processed($param1,$param2);
return $internalName;
}
Docblocks must also precede class and method declarations. In this example, some tags needed for publishing classes in repositories such as
PEAR(thePHP Extension and Application Repository) are illustrated. They are not, however, required for internal use:
<?php
/**
* Super Class
*
* @package Package Name
* @subpackage Subpackage
* @category Category
* @author Author Name
* @link http://example.com
*/
class Super_class
{
/**
* Encodes string for use in XML
*
* @access public
* @param string
* @return string
*/
function xml_encode($str)
Docblock format
In general, a docblock comment starts with a C-style comment start tag with an extra asterisk attached/**
followed by a newline. Each docblock line starts with an asterisk under the slash of the comment start marker to provide visual continuity of the extent of the docblock. Donotspace the column of asterisks over to line up under the first opening asterisk because editors with "smart indentation" (following the indentation of the line above when starting a new line) will improperly indent the first line of the comment or function declaration. Text within the docblock is separated from the column of asterisks by a single space, and the docblock is terminated with a standard C-style comment close tag*/
under the column of asterisks and immediately above the code being described (no intervening blank lines).
A docblock generally contains three sections, separated from each other by a blank line (consisting solely of the required asterisk in the left column):
- a short description - a one-liner which globally states the function of the documented element. This can be used in overviews to allow the user to skim the documentation in search of the required template.
- a long description - an extended description with concise information about the function of the documented element. Examples of what to put in the long description include:
- explanations of algorithms
- code examples
- array specification
- relations to other elements
- license information (in the case of file docblocks)
tags - a series of descriptors for properties of the element, such as
@param
and@return
. Tags represent meta-data which human readers, IDEs, external tooling or even the application itself can use to know how to interpret an element. The most common tags are:- @param
- documents a single function/method argument Syntax: @param Type name [description]
- @return
- documents function/method return values Syntax: @return Type [description]
- @global
- declares a global variable or its usage Use Syntax: @global Type name [description] Declaration Syntax: @global Type name
The full list of tags supported by phpDocumentor can be found here; those supported by Doxygen are documented here. Use of tags specific to one application or the other is discouraged: For maximum flexibility, only use tags with common descriptions.
- @param
Documentation of any globals used by functions or methods is not required, but should be included.
An@global
tag may be used in a docblock preceding the definition of a global variable. Only one@global
tag is allowed per global variable docblock. A global variable docblock must be followed by the global variable’s definition before any other element or docblock occurs in the source. The name must be the exact name of the global variable as it is declared in the source
<?php
/**
* short description of this variable
*
* longer description of the variable, e.g., where it's used and how it affects
* the rest of the application
*
* @global int $foo
*/
$foo=0;
Including Code
Anywhere you are unconditionally including a [class] file, userequire_once
. Anywhere you are conditionally including a [class] file (for example, factory methods), useinclude_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 withrequire_once
is not be included again byinclude_once
.
include_once
andrequire_once
are language constructs, not functions. Parentheses should not surround the subject filename.
TRUE, FALSE, and NULL
TRUE
,FALSE
, andNULL
are PHP keywords that should always be written fully uppercase.
TRUE
andFALSE
are BOOLEAN values which express truth (or not),notdefined constants with respective values of one and zero. Symbolic constants are specifically designed to always and only reference their constant value. Booleans are not symbolic constants, they are distinct values.TRUE
happens to cast to integer 1 when you print it or use it in an expression, but it's not the same as a constant for the integer value 1 and you shouldn't use it as one.FALSE
casts to empty when you print it or to zero if you cast it to an integer or use it in an expression. Again, it's not a constant for empty or zero, and should not be used as such.
<?php
echo FALSE; // prints nothing - FALSE is empty
echo (FALSE); // prints nothing - FALSE is empty
echo FALSE+FALSE; // prints 0 - FALSE is cast to integer for addition
echo (FALSE+FALSE); // prints 0 - FALSE is cast to integer for addition
echo intval(FALSE); // prints 0 - FALSE is zero when explicitly cast
echo '"'.FALSE.'"'; // prints "" - FALSE is empty
echo TRUE; // prints 1
echo (TRUE); // prints 1
echo TRUE+TRUE; // prints 2
echo (TRUE+TRUE); // prints 2
echo intval(TRUE); // prints 1
echo '"'.TRUE.'"'; // prints 1
Similarly,NULL
is a special value indicating the absense of anything, not a defined constant equal to zero.NULL
, zero andFALSE
are all empty, but they are not equivalent
Logical Operators
Always use the||
and&&
operators instead of the wordsOR
andAND
because the word operators have lower priority than assignment operators, which can lead to very unobvious logical errors. For example, what is the value of$z
after this code sequence?
<?php
$x=TRUE;
$y=FALSE;
$z=$y OR $x;
ANSWER:$z
isFALSE
because the last statement is equivalent to($z=$y) OR $x
rather than$z=($x OR $y)
as would naively be expected. On the other hand, afterthiscode sequence:
<?php
$x=TRUE;
$y=FALSE;
$z=$y || $x;
$z
isTRUE
because the||
operator has higher precedence than assignment operators.
Naming
When writing code meant to be shared across more than one application, global names (classes, functions, variables, defines) must be prefixed to prevent name collisions with PHP itself or other code. When selecting a prefix, pick one relevant to the code being developed, and isn't likely to clash with PHP.
Other than in names of constants, or to specify class hierarchy, underscores should not be used within names. They should only be used as a prefix for private members of classes (variables or methods).
Caution:PHP reserves all function names starting with two underscores (__
) as magical. Do not use names starting with two underscores unless you want some documented magic functionality.
Constants and defines
Use all capital letters with underscores separating the words in a name
<?php
define('A_STRING_CONSTANT','Hello World!');
define('SOME_BOOLEAN',TRUE);
define('ZERO',0);
Functions and variables
Global function names should beProperCased(a.k.a.StudlyCaps): They start with an uppercase letter, and each new word begins with an uppercase letter. Acronyms are treated as normal words when used as a name: The first letter is capitalized, others are lower case.
Variables should be named concisely, usingcamelCase(also known asbumpyCase). Make names descriptive without being overly long. Don't create new variables by appending an integer to an existing variable name. Removing vowels from variable names may shorten them, but don't remove so many that the name becomes incomprehensible: don't use indecipherable abbreviations.
<?php
$aGlobalVariable=1;
$someThing=array();
function MyPublicFunction()
Classes and methods
Classes should be given descriptive names. Avoid using abbreviations where possible. Class names should beProperCased, starting with an uppercase letter, and each new word begins with an uppercase letter. The PEAR class hierarchy is also reflected in class names where each level of the hierarchy separated with a single underscore.
Class variables (a.k.a. properties) and methods should be named usingcamelCase. Private class methods and variables that are only accessed internally by your class, such as utility and helper functions that your public methods use for code abstraction, should have their names prefixed with a single underscore
<?php
class Log // shows PEAR hierarchy
class Net_Finger // shows PEAR hierarchy
class HTML_Upload_Error // shows PEAR hierarchy
class AMoreCompleteExample
{
public $counter; // public property
function connect() // public method
function getData() // public method
function buildSomeWidget() // public method
private $_status; // private property
private function _sort() // private method
private function _initTree() // private method
function convertText() // public method
private function _convertText() // private method
Filenames
PHP requires class definitions to be contained within a single file. When writing classes designed for reuse beyond the page the were originally written for, each class should be in its own file whose name is the same as the class. Several closely related classes may be included within one file, e.g., a base class and subclasses directly derived from it. In such a case, the file should be named for the base class.
When several classes are defined specifically for use in a single page, they should be put in a file in aninclude
directory under the one containing the page's script. The filename should then be the page's name with_class
appended, e.g.,index.php
would use classes found ininclude/index_classes.php
Arrays
Assignments in arrays may be aligned. When splitting array definitions onto several lines, the last value should also have a trailing comma. This is valid PHP syntax and helps to keep code diffs minimal.
Function Declarations
Function declarations follow the Horstmann (preferred) or Allman style:
<?php
function FooFunction($arg1,$arg2='')
{ if (condition)
{ statement;
}
return $val;
}
Whenever appropriate, provide default values for function arguments to reduce the overhead required for calling the function.Do notuse default values for required parameters to avoid having errors logged when they are not supplied: If a parameter is truly required to be supplied at run time, the logged error message will help debug the faulty code, rather than masking it through use of a default value.
As required by the PHP language specification, arguments with default values must follow ones that do not have default values. When deciding the order of arguments with default values, consider which one(s) will be changed most often: If a non-default value is needed for a function call, all of the default values to the left of the one being modified must be specified with their default value to preserve their default behaviour. Consequently, defaults that are most likely to be kept should be rightmost in the argument list, and the most often changed specified first (leftmost).
<?php
function MyFunction($required,$changed='often',$mostly='static')
{ return $required.' = '.$changed.' '.$mostly;
}
MyFunction(); // returns " = often static" (NULL used for $required)
// also "PHP Notice: Undefined variable: $required" is written to the log file
MyFunction(1); // returns "1 = often static"
MyFunction(2,'frequently'); // returns "2 = frequently static"
MyFunction(3,'sometimes'); // returns "3 = sometimes static"
MyFunction(4,'often','noise'); // returns "4 = often noise"
MyFunction(5,'screeching'); // returns "5 = screeching static"
MyFunction(6,'','screeching'); // returns "6 = screeching"
Always return a meaningful value from a function if one is appropriate. If any code branches return a value from a function, all branches MUST return a value. N.B. The functions used as illustration here will not work as expected - see the notes re. booleans above in the TRUE, FALSE, and NULL section.
<?php
// INCORRECT:
function Broken($param)
{ // ...
if ($param == 'true')
return TRUE;
else if ($param == 123)
return $param;
// error: NULL is returned for any other $param values
}
// CORRECT:
function Fixed($param)
{ // ...
if ($param == 'true')
return TRUE;
else if ($param == 123)
return $param;
return 'error: invalid param value: '.strval($param);
Functions with many parameters may need to be split onto several lines to keep within the 80 characters per line limit. The first parameters may be put onto the same line as the function name if there is enough space. Subsequent parameters on following lines are to be indented two tab stops. The closing parenthesis immediately follows the last parameter. The opening brace follows on the next line, at the same indentation level as the "function" keyword.
<?php
function MyVeryLongFunctionName($firstRequiredParameter,$secondRequiredOne,
$thirdRequiredParameter,$firstOptionalOne=TRUE,$lastOptional=NULL)
{ // code starts here
// ...
}
Function Calls
Functions should be called with no spaces in the statement. For example:
<?php
$var=foo($bar,$baz,$quux);
As displayed above, there should be no spaces 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 left of the equals sign to promote readability:
<?php
$short =foo($bar);
$long_variable=foo($baz);
Return Values and Typecasting
Some PHP functions returnFALSE
on failure and also have return values which evaluate toFALSE
in loose comparisons, such as an empty string or zero. Be explicit by comparing the variable type when using these return values in conditionals to ensure the return value is indeed what you expect, and not a value that has an equivalent loose-type evaluation.
Use the same stringency in returning and checking your own variables. Use the===
and!==
comparison operators as necessary.
<?php
// INCORRECT:
/* If 'foo' is at the beginning of the string, strpos will return a 0,
* resulting in this conditional evaluating as TRUE
*/
if (strpos($str,'foo') == FALSE)
// CORRECT:
if (strpos($str,'foo') === FALSE)
// INCORRECT:
function build_string($str='')
{
if ($str=='') // uh-oh! What if FALSE or the integer 0 is passed as an argument?
{
}
}
// CORRECT:
function build_string($str='')
{
if ($str==='')
{
}
}
Typecasting has a slightly different effect whichmaybe desirable. When casting a variable as a string,NULL
andFALSE
become empty strings, zero (and other numbers) become strings of digits, andTRUE
becomes'1'
:
<?php
$str=(string) $str; // cast $str as a string
SQL Queries
SQL keywords are always capitalized:SELECT
,INSERT
,UPDATE
,WHERE
,AS
,JOIN
,ON
,IN
, etc.
Break up long queries into multiple lines for legibility, preferably breaking for each clause. Use string concatenation to allow alignment of the clauses in the source code without introducing extraneous whitespace into the SQL query.
<?php
// INCORRECT: // keywords are lowercase and query is too long for a
// single line (... indicates continuation of the line)
$query = $this->db->query("select foo, bar, baz, foofoo, foobar as raboof, foobaz from exp_pre_email_addresses
...where foo != 'oof' and baz != 'zab' order by foobaz limit 5, 100");
// CORRECT:
$query=$this->db->query( 'SELECT foo,bar,baz,foofoo,foobar AS raboof,foobaz '
.'FROM exp_pre_email_addresses '
."WHERE foo!='oof' AND baz!='zab' "
.'ORDER BY foobaz LIMIT 5,100');