I wrote the following for a software engineering class, while acting
as the project code auditor, tester, and quality control person. Feel
free to use and learn from it as wanted. Note that
PostgreSQL was the assumed database
for this standard.
PHP Coding Standards
Overall Design Considerations
The following are the underlying principals to consider when making
decisions on trade-offs and courses of action to take
- Make it work correctly before you add extraneous features
- Aspects of importance are in the following order from highest importance
to least importance: correct operation, security, code readability, ease
of use, portability, efficiency, power, features.
- All components of the system should be designed with the thought of them
being used with other programming languages, settings, etc.
- Choose readable PHP code over readable resultant HTML code.
- K.I.S.S. (keep it simple stupid)
PHP Code
The following is loosely based on style(9).
- PHP files will have the extension .php.
- All files will end lines using \n instead of the \r\n
alternative, or related alternatives.
- Indentation of code block will be two spaces. Tabs should not be
used for indenting except for comments between the end of the code
on a line and the end of the line. In such cases tabs will be 8
characters wide.
- The following are how comments will look:
/*
* VERY important single-line comments look like this.
*/
/* Most single-line comments which span a whole line will look like this */
Code(); // Comments which are on the same line as code will look like this.
/*
* Multi-line comments look like this. Make them real sentences. Fill
* them so they look like real paragraphs.
*/
- Each file will begin with the CVS $Id: php_code_standards.ptml,v 1.1.1.1 2002/01/27 21:57:26 srp Exp $ tag, followed by a
one line description of the purpose of the file,
followed by a listing of the copyright With a list of
the authors who worked on the file. This will be
followed by a brief description of what the file does including the
various way it may be called (what HTTP input it might accept). Comments
about the variables may be omitted if their name clearly indicates what
will be in the variable and all rules which constrain the given variable;
firstname would be a good example of a variable that would not need a
comment. The header should conclude with default variables for the file.
The following is the start of a file named add_user.php:
= 1 for warnings and >= 5 to see database queries
- Use a single space between the keywords if, while, for
and the opening parenthesis. A space must also be placed between a closing
parenthesis and the opening bracket which must be on the same line. The
closing bracket must be at the same horizontal level of indentation as
the first letter of the keyword. The brackets around the block may
not be left out around the block of code inside a control structure unless
the code block is completely empty.
for ($i = 0; $i < $max_things; $i++) {
do_stuff();
}
while(still_returning_true($arg));
- Do not use spaces after function names. Commas have a space after them.
Do not use spaces after ( or [ or preceding ] or
) characters.
if($error = function($a1, $a2)) {
print $error;
exit;
}
- Unary operators don't require spaces, binary operators do including
the assignment operator. Don't use
parentheses unless they're required for precedence, the statement is
confusing without them. Remember that other people may be confused more
easily than you.
- PHP code must fit within a line width of 80 characters. (Note that this
rules doesn't apply to HTML lines including HTML lines which include PHP
print statements)
- When a line break must be made in the middle of the arguments being
passwd to a function, the second and further lines must be indented to
be aligned with the first variable passed to the function:
$result = create_user($username, $password, $password2, $firstname, $lastname,
$email, $phone);
- The function phpinfo must never be called in any piece
of code that is not password protected and only accessible by system
administrators.
- SQL queries in PHP must be assigned to a variable (this allows for
easy printing of the query for debugging purposes). The result from
a query must always be kept and checked, and appropriate measures taken
on warnings and errors. The SQL keywords of SQL queries must be in all
capital letters. Queries longer then one line must be broken by the
logical breaks between SQL keywords. One line per logical compare
should be used in the WHERE part of multi-line queries.
$query = "SELECT * FROM users"; // one line query
/* multi-line query */
$query = "SELECT u_username AS username, u_firstname AS firstname,
u_lastname AS lastname
FROM users, users_groups_map, groups
WHERE
u_id = ugm_u_id
AND
ugm_g_id = g_id
AND
g_name = '$desired_group'
ORDER BY username ASC";
$r = pg_exec($db, $query);
if (!$r) {
print pg_errormessage($res);
}
- Database error messages should never print the $query unless the a
$debug flag is set to specify that such is okay. (Printing a $query might
allow users to see details of the database and the query which could
potentially allow them to exploit the database and connection code)
- When referencing string indexes of an array, use quotes around the
name of key.
$tmp = $array[key]; // bad
$tmp = $array["key"]; // good
- Avoid using array syntax inside of quotes in PHP.
$str = "It is best not to try to try $things[like_this]";
$str = "It is much better to try " . $thigs["like_this"];
- $GLOBAL variables may never be used in functions or class functions,
except for configuration variables.
- Configuration variables should be included from a special configuration
file, and should have minimal variables by using arrays of related
options.
- Proceeding a function should be several lines of comments including
a description of the function, the definition and restraints of the
arguments, the possible types and values and meanings of return
values.
- All PHP code should assume that magic_quotes_gpc is turned on, and
act accordingly.
- For consistency use the print command rather then the echo
command.
- Avoid many repeated transitions from PHP mode to HTML mode in close
proximity of each other.
- When looping or dealing with conditional blocks of code, either use
print statements for HTML output, or consider functionizing the code
block for larger sections of HTML.
- The pg_close function must be called at the end of each php file
using PostgreSQL even if pg_pconnect is used.
HTML
The following is based on the
XHTML recommendation from
http://www.w3.org/.
Database
- Table names are all lowercase words separated by underscores.
- Table names are plural for the items they hold: for instance
users instead of user
- Field names are all lowercase with words separated by underscores
- Fields are singular unless multiple types are stored in it
- Fields names are prefixed with the first letter of each word of the
table name: for instance a user_group_map table would have a
field name of ugm_id field.
- Each table has a serial index as its primary key, this field is named
with the above prefix and has a postfix of id, ugm_id for
instance
- Tables which need bi-directional linking will use a third map
table which will contain at least 2 fields: fields which reference the
serial fields of the tables it links. Additional fields may be added to
a mapping table if so desired.
- Field references must make use of foreign keys and use appropriate
cascading (most likely delete and update)
- Don't make table name of reserved words. Reserved words are as follows:
abort add all allocate alter analyze and any are as asc assertion
at authorization avg begin between binary bit bit_length both by
cascade cascaded case cast catalog char character character_length
char_length check close cluster coalesce collate collation
column commit connect connection constraint continue convert
copy corresponding count create cross current current_date
current_session current_time current_timestamp current_user cursor
date datetime deallocate dec decimal declare default delete desc
describe descriptor diagnostics disconnect distinct do domain drop
else end escape except exception exec execute exists explain extend
external extract false fetch first float for foreign found from full
get global go goto grant group having identity in indicator inner
inout input insert intersect interval into is join last leading
left like listen load local lock lower max min module move names
national natural nchar new no none not notify null nullif numeric
octet_length offset on open or order out outer output overlaps
partial position precision prepare preserve primary privileges
procedure public references reset revoke right rollback rows schema
section select session session_user set setof show size some sql
sqlcode sqlerror sqlstate substring sum system_user table temporary
then timespan to trailing transaction translate translation trim
true union unique unknown unlisten until update upper usage user
using vacuum value values varchar varying verbose view when whenever
where with without work write
Field names shouldn't be concerned with reserved words as the prefix
generally will avoid this problem.
- Use the text type for all field which are character based and
do not fit into other types, unless the size is only always a
fixed length or bounded, in which case a varchar or char type may be
used.
- Date type should always be datetime type unless only ever the
date part or the time portion is all that is desired
(hopefully this will occur infrequently)
- The bool or boolean type will be used for fields having
a true or false value
- Unless needed, fields should be have the constraint not null
placed on them. Such fields should also make an have an appropriate
default value.
|