Dear folks,
I am composing a coding standards for our team. Bottom line, we are
using PEAR, object-oriented programming, extreme programming, and
PHPDoc. Below is the draft so far. I'd greatly appreciate it if
anybody care to give inputs on the document. Nevertheless, I hope
this could be useful to some.
Thank you.
Regards,
Steve
STYLE GUIDE FOR PHP DEVELOPERS
==============================
$Id$
0. General
----------
Understand these points and you are halfway there already.
0.1 We are writing PHP4 application here, not PHP3, nor Perl, Python, etc.
So use PHP idioms.
0.2 We use the PEAR convention, except: 1) the tests in tests/ are written
using unit test as much as possible. 2) preferred error reporting is
slightly different. See 8.2 Reporting error.
0.3 Consistency matters.
0.4 Standards is important.
0.5 Readability matters. Especially since the code will be touched by
several developers.
1. Formatting
-------------
1.0 Enclosing PHP code
Always use <?php ?>.
1.1 Indentation
Preferred indentation is using Tab (interpreted at 4 spaces).
1.2 Text width
If possible, do not write long lines exceeding 79 columns. But this is
not a strict requirement. In many cases it is much more convenient or
vertically readable to put things in one line. So do that instead.
1.3 Curly brace placement
This style:
if (...) {
...
}
is more preferred than:
if (...)
{
...
}
1.4 Whitespaces
- No whitespace after function or method name. Example:
exit()
not
exit ()
$obj->method()
not
$obj->method ()
- Generally, no whitespace inside the enclosing parenthesis, unless it
enhances readability. Examples:
ucfirst($str)
not
ucfirst( $str )
- No whitespace between = in default argument definition.
function f($a, $b=1, $c='')
not
function f($a, $b = 1, $c = '')
- Add whitespace between assignment.
$a = 1;
not
$a=1;
- Whitespace in expressions are usually not necessary. But use them when
they enhance readability.
$a = $b + $c*(5*time());
1.5 Function names
Function names are not case sensitive in PHP. Use the all-lowercase
notation.
1.6 Quotes
Use whichever ones you like. But if you can use '' for simple strings,
and "" only if you need interpolation.
Avoid backslashism! Use ' to quote ", use " to quote '. You can also
utilize PHP4's here-documents.
print <<<EOT;
Some
multiline
text
with
"quotes"
EOT
However, here-document has one disadvantage: it messes indentation. So
choose wisely.
1.7 Blank lines
- Separate each class with two blank lines.
- Separate each function and variable definition in the class with one
blank line.
- Give one blank line after the class definition.
Example:
class MyClass {
function myMethod() {
...
}
var $myAttr1;
var $myAttr2;
}
class YourClass {
}
2. Internationalization
-----------------------
gettext().
3. Comments
-----------
2.1 Inline comments.
Inline comments are used to explain a particular small part of a code.
Example:
$var = 2;
$Good or $var--; // compensate for bad weather
Use inline comments sparingly. Code should already be clear anyway.
2.2 Debugging comments.
# is used to comment out certain parts of a code during debugging.
2.3 Documentation comments.
These use the JavaDoc/PHPDoc syntax. Give to each class, class variable,
method, global constant, and function. Refer to their own documentation.
One place to start: http://java.sun.com/j2se/javadoc/
Below is the summary of the syntax.
/**
* Short description.
*
* @param type $name - description
* @return type description
*
* Longer description .... .... .... .... .... .... .... ....
* .... .... .... .... .... .... .... .... .... .... .... ....
*/
function foo() {
/**
* Short description.
*/
var $foo = '';
/**
* Short description.
*
* @var object ClassName
*/
var $bar;
/** Short description.
*
* Longer description...
*/
define('CONSTANT_NAME', 1);
No blank lines before the definition. A blank comment line between short
description - long description - @param/@return.
3. Naming
---------
3.1 Classes
ClassName
Follow PEAR-style namespace "embedding". For example:
Html_Parser
Data_Item
Data_Collection
3.2 Class attributes
attributeName
_internalAttributeName
attributeNameThatClashesWithBuiltin_ (for example, empty_)
3.3 Methods
methodName
_internalMethodName
methodNameThatClashesWithBuiltin_ (for example, empty_)
3.4 Variables
variable_name
Global_variable_name
this is also acceptable:
variableName
GlobalVariableName
3.4 Constants
CONSTANT_NAME
PEAR-style package prefix:
DB_CONSTANT_NAME
DATA_COLLECTION_CONSTANT_NAME
3.5 Functions
function_name
4. File organization
--------------------
4.1 All library codes will live in the PEAR root directory.
4.2 All PHP libraries and include files, is named with '.php' extension (ie.
no '.lib', '.inc', etc.). Test scripts is named with '.phpt' extension.
4.3 Always try to use register_once() to include libraries. If that is not
possible, use include_once(). Example:
require_once "Data/Collection.php";
4.4 All project- or product-specific library files should live under their
own directory under the PEAR root.
Example:
/this/is/the/pear/root/
Data/
Collection.php
DB/
MyProjName/
MyClass.php
4.5 For now, write one class per file (because of current PHPDoc's
limitation).
5. Testing
----------
5.1 Follow the Extreme Programming methodology.
5.2 Create test scripts and put them in tests/ subdirectory. Use phpunit for
the testing framework.
5.3 How to make test script:
- a test script tests one or more classes;
- name the script file after the [main] class you are testing. Give it
extension .phpt (to avoid PHPDoc parsing the file). For example, if
you want to test Template_Processor, create Template_Processor.phpt in
the Template/tests/ directory.
- require the phpunit file at the very top, to enable maximum warning
level.
- create one or more test case classes. For example,
Template_Processor_TestCase.
- create one function that will return the test suite class (name this
function with the _makeSuite suffix). For example,
Template_Processor_makeSuite. Add all the test case(s) and return the
resulting test case.
- create one test runner class. For example,
Template_Processor_TextRunner.
- instantiate the test runner class. For example, create the object
$Template_Processor_TestRunner. Run the test runner.
See Template_Processor.phpt in the lib/common/Template/tests/ directory
for an example implementation of this.
6. Creating documentation
-------------------------
6.1 For API documentation, use Javadoc syntax. Generate the documentation
using PHPDoc (included with PEAR). See one of the class files to see an
example of this. Refer to the Javadoc manual for more details. A few
tips on writing doc comments:
- Always use:
/**
* One sentence documentation.
*/
Instead of:
/** One sentence documentation. */
PHPDoc gets a little confused with the later.
- The short description is a short sentence, in an imperative tone,
ended with a period.
- If the longer description is composed of more than one paragraphs, use
<p>.
6.2 For other developer documentation (README files, Changelog, etc), use
plain text files (such as this guide).
6.3 For application user documentation, use whatever format you like. Stick
to simple, common, portable format like HTML and PDF.
7. Database programming
-----------------------
Perhaps we will use the database abstraction classes from PEAR in the
future. Currently we only use MySQL, so mysql_* will do. End users will
seldom touch this, however, since we are providing higher level abstraction
classes (for example, through Data_Collection classes).
8. Error handling
-----------------
8.1 Return values
Do always check return values of functions, especially those that
access/manipulate external resources like database (mysql_*), file I/O,
remote URLs, shared memory, etc. Suppress error output of the function
with @ if necessary. For example:
$res = @mysql_query(...);
if (!$res) {
# deal with error...
}
8.2 Reporting error
If you write your own function or method, I recommend a variation of the
PEAR style. The PEAR style is directly returning a PEAR_Error whenever a
function encountered an error condition. I find it rather cumbersome,
since the error checking becomes verbose:
function yourMethod($foo) {
if ($bar) {
# an error condition...
return new PEAR_Error($msg);
}
}
$result = $obj->yourMethod($foo);
if (PEAR::isError($result)) { // cumbersome!
# react accordingly
}
The common idiom is like this:
if (!$obj->yourMethod($foo)) ... // if fails, ...
if ($obj->yourMethod($foo)) ... // if success, ...
Every PHP programmer is familiar to this idiom. It is simple, and
simplicity matters because we will do a bunch of these.
So what we do is store the PEAR_Error object in the object attribute
(recommended name is $error). And we can also use raiseError() directly
if you think the error should potentially stop execution if needed (if
you want to use this style, your class must be a descendant of PEAR).
function yourMethod($foo) {
if ($bar) {
# an error condition...
$this->error = $this->raiseError($msg);
return; // return false
}
return 1; // return success
}
if ($obj->yourMethod($foo)) {
# react accordingly. PEAR_Error is available in $obj->error;
}
This is like the C errno() style but specific per object. Multithreading
is not relevant in the current PHP program so this is not a problem.
In classes that do not subclass PEAR, or in normal functions, you can
use the 'new PEAR_Error()' style.
Let's hope that PHP will soon support exceptions, so handling errors
will become easier.
9. Portability
--------------
9.1 Always use <?php ?>.
9.2 Try to make your library code work with or without register_globals
turned on. Better still, do not use globals at all in the library code.
9.3 magic quotes. This one is a pain to work with portably, since we do not
know whether an argument comes from an external source, or from
GET/POST/Cookie parameter, or neither. Therefore, all library codes
should probably assume magic_quotes_gpc is off, so it does not bother
with stripslashing.
10. References
--------------
- PHP coding standards
- PEAR documentation
- PEAR coding standards
- phpunit documentation
12. Comments, suggestions?
--------------------------
If you do not understand some part, have objection to a certain rule, or
have an idea to improving style, please discuss it with me.
Apr 19, 2001
Steven Haryanto
[EMAIL PROTECTED]
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
To contact the list administrators, e-mail: [EMAIL PROTECTED]