Pear PHP Coding Standards
Author: Pair Networks
Indenting and Line Length
Use an indent of 4 spaces, with no tabs. If you use Emacs to edit PEAR
code, you should set indent-tabs-mode to nil. Here is an example mode
hook that will set up Emacs according to these guidelines (you will
need to ensure that it is called when you are editing PHP files):
(defun php-mode-hook ()
(setq tab-width 4
c-basic-offset 4
c-hanging-comment-ender-p nil
indent-tabs-mode
(not
(and (string-match "/\\(PEAR\\|pear\\)/" (buffer-file-name))
(string-match "\.php$" (buffer-file-name)))))) |
Here are vim rules for the same thing:
set expandtab
set shiftwidth=4
set softtabstop=4
set tabstop=4 |
It is recommended that you break lines at approximately 75-85 characters.
There is no standard rule for the best way to break a line, use your
judgment and, when in doubt, ask on the PEAR Quality Assurance mailing
list.
Control Structures
These include if, for, while, switch, etc. Here is an example if
statement, since it is the most complicated of them:
<?php
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:
<?php
switch (condition) {
case 1:
action1;
break;
case 2:
action2;
break;
default:
defaultaction;
break;
}
?>
|
Function Calls
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:
<?php
$var = foo($bar, $baz, $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:
<?php
$short = foo($bar);
$long_variable = foo($baz);
?>
|
Function Definitions
Function declarations follow the "one true brace"
convention:
<?php
function fooFunction($arg1, $arg2 = '')
{
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:
<?php
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;
}
?>
|
Comments
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 PEAR packages.
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.
Including Code
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.
Note:
include_once and
require_once are statements, not
functions. Parentheses should not surround the subject filename.
PHP Code Tags
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.
Header Comment Blocks
All source code files in the PEAR repository shall contain a
"page-level" docblock at the top of each file
and a "class-level" docblock immediately above
each class. Below are examples of such docblocks.
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Short description for file
*
* Long description for file (if any)...
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category CategoryName
* @package PackageName
* @author Original Author <author@example.com>
* @author Another Author <another@example.com>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id:$
* @link http://pear.php.net/package/PackageName
* @see NetOther, Net_Sample::Net_Sample()
* @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)...
*
* @category CategoryName
* @package PackageName
* @author Original Author <author@example.com>
* @author Another Author <another@example.com>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: @package_version@
* @link http://pear.php.net/package/PackageName
* @see NetOther, Net_Sample::Net_Sample()
* @since Class available since Release 1.2.0
* @deprecated Class deprecated in Release 2.0.0
*/
class foo
{
}
?>
|
- Short Descriptions
Short descriptions must be provided for all docblocks.
They should be a quick sentence, not the name of the item.
Please read the Coding Standard's Sample File about how to write good descriptions.
- PHP Versions
One of the following must go in the page-level docblock:
- @license
There are several possible licenses. One of the
following must be picked and placed in the page-level
and class-level docblocks:
For more information, see the PEAR Group's
Licensing Announcement.
- @link
The following must be used in both the page-level and
class-level docblocks. Of course, change
"PackageName" to the name of your package.
This ensures the generated documentation links back your package.
- @author
There's no hard rule to determine when a new code
contributor should be added to the list of authors
for a given source file. In general, their changes
should fall into the "substantial" category (meaning
somewhere around 10% to 20% of code changes).
Exceptions could be made for rewriting functions or
contributing new logic.
Simple code reorganization or bug fixes would not
justify the addition of a new individual to the
list of authors.
- @since
This tag is required when a file or class is added
after the package's initial release. Do not use it
in an initial release.
- @deprecated
This tag is required when a file or class is no
longer used but has been left in place for
backwards compatibility.
- @copyright
Feel free to apply whatever copyrights you desire.
When formatting this tag, the year should be in
four digit format and if a span of years is involved,
use a hyphen between the earliest and latest year.
The copyright holder can be you, a list of people, a
company, the PHP Group, etc. Examples:
- License Summary
If you are using the PHP License, use the summary text
provided above. If another license is being used,
please remove the PHP License summary. Feel free to
substitute it with text appropriate to your license,
though to keep things easy to locate, please preface
the text with LICENSE: .
- @see
Add a @see tag when you want to refer users to other
sections of the package's documentation. If you have
multiple items, separate them with commas rather than
adding multiple @see tags.
To ease long term readability of PEAR source code, the
text and tags must conform to the order and spacing
provided in the example above. This standard is
adopted from the JavaDoc standard.
There are two ways to implement the
@package_version@ replacements. The procedure depends on
whether you write your own package.xml files or if you
use the PackageFileManager.
For those authoring package.xml files directly, add a
<replace> element for each file. The XML for
such would look something like this:
Maintainers using the PackageFileManager need to
call addReplacement() for each file:
- Existing Small Packages
Existing packages that have only a few files are required
to adopt these docblocks before the next release.
- Existing Large Packages
Existing packages with many files are encouraged to
adopt the new headers as soon as possible. When such
packages come out with a new major version upgrade,
these docblocks must be implemented therein.
- New and Unreleased Packages
New packages and existing packages which have no
releases yet must include these docblocks before
their first release.
Using CVS
This section applies only to packages using CVS at cvs.php.net.
Include the $Id$ CVS keyword in each file. As each file
is edited, add this tag if it's not yet present (or replace
existing forms such as "Last Modified:", etc.).
The rest of this section assumes that you have basic knowledge
about CVS tags and branches.
CVS tags are used to label which revisions of the files in your
package belong to a given release. Below is a list of the
required and suggested CVS tags:
- RELEASE_n_n_n
(required) Used for tagging a release. If you don't use it,
there's no way to go back and retrieve your package from the
CVS server in the state it was in at the time of the release.
- QA_n_n_n
(branch, optional) If you feel you need to roll out a
release candidate before releasing, it's a good idea to make a
branch for it so you can isolate the release and apply only
those critical fixes before the actual release. Meanwhile,
normal development may continue on the main trunk.
- MAINT_n_n_n
(branch, optional) If you need to make
"micro-releases" (for
example 1.2.1 and so on after 1.2.0), you can use a branch for
that too, if your main trunk is very active and you want only
minor changes between your micro-releases.
Only the RELEASE tag is required, the rest are recommended for
your convenience.
Below is an example of how to tag the 1.2.0 release of the
Money_Fast package:
By doing this you make it possible for the PEAR web site to take
you through the rest of your release process.
Here's an example of how to create a QA branch:
The QA_2_0_0_BP tag is a
"branch point" tag, which is the start
point of the tag. It's always a good idea to start a CVS branch
from such branch points. MAINT branches may use the RELEASE tag
as their branch point.
Naming Conventions
Classes
Classes should be given descriptive names. Avoid using abbreviations
where possible. Class names should always begin with an uppercase
letter. The PEAR class hierarchy is also reflected in the class name,
each level of the hierarchy separated with a single underscore.
Examples of good class names are:
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:
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:
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:
Constants should always be all-uppercase, with underscores to
separate words. Prefix constant names with the uppercased name
of the class/package they are used in. For example, the constants
used by the DB:: package all begin with
DB_.
Note:
The true, false and
null constants are excepted from the all-uppercase
rule, and must always be lowercase.
If your package needs to define global variables, their name
should start with a single underscore followed by the package
name and another underscore. For example, the PEAR package uses
a global variable called $_PEAR_destructor_object_list.
File Formats
All scripts contributed to PEAR must:
Be stored as ASCII text
Use ISO-8859-1 character encoding
Be Unix formatted
"Unix formatted" means two things:
1) Lines must end only with a line feed (LF).
Line feeds are represented as
ordinal 10,
octal 012 and
hex 0A.
Do not use carriage returns (CR)
like Macintosh computers do
or the carriage return/line feed combination
(CRLF) like Windows computers do.
2) There should be one line feed
after the closing PHP tag (?>).
This means that when the cursor is at the very end
of the file, it should be one
line below the closing PHP tag.
Sample File (including Docblock Comment standards)
The source code of PEAR packages are read by thousands
of people. Also, it is likely other people will become
developers on your package at some point in the future.
Therefore, it is important to make life easier for
everyone by formatting the code and docblocks in
standardized ways. People can then quickly find the
information they are looking for because it is in the
expected location. Your cooperation is appreciated.
Each docblock in the example contains many details about writing
Docblock Comments.
Following those instructions is important for two reasons.
First, when docblocks are easy to read, users and developers can quickly
ascertain what your code does.
Second, the PEAR website now contains the phpDocumentor generated
documentation for each release of each package, so keeping things straight
here means the API docs on the website will be useful.
Please take note of the vertical and horizontal spacing.
They are part of the standard.
The "fold markers" (// {{{ and
// }}}) are optional.
If you aren't using fold markers,
remove foldmethod=marker from the vim header.
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Short description for file
*
* Long description for file (if any)...
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category CategoryName
* @package PackageName
* @author Original Author <author@example.com>
* @author Another Author <another@example.com>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id:$
* @link http://pear.php.net/package/PackageName
* @see NetOther, Net_Sample::Net_Sample()
* @since File available since Release 1.2.0
* @deprecated File deprecated in Release 2.0.0
*/
/**
* This is a "Docblock Comment," also known as a "docblock." The class'
* docblock, below, contains a complete description of how to write these.
*/
require_once 'PEAR.php';
// {{{ constants
/**
* Methods return this if they succeed
*/
define('NET_SAMPLE_OK', 1);
// }}}
// {{{ GLOBALS
/**
* The number of objects created
* @global int $GLOBALS['NET_SAMPLE_Count']
*/
$GLOBALS['NET_SAMPLE_Count'] = 0;
// }}}
// {{{ Net_Sample
/**
* An example of how to write code to PEAR's standards
*
* Docblock comments start with "/**" at the top. Notice how the "/"
* lines up with the normal indenting and the asterisks on subsequent rows
* are in line with the first asterisk. The last line of comment text
* should be immediately followed on the next line by the closing asterisk
* and slash and then the item you are commenting on should be on the next
* line below that. Don't add extra lines. Please put a blank line
* between paragraphs as well as between the end of the description and
* the start of the @tags. Wrap comments before 80 columns in order to
* ease readability for a wide variety of users.
*
* Docblocks can only be used for programming constructs which allow them
* (classes, properties, methods, defines, includes, globals). See the
* phpDocumentor documentation for more information.
* http://phpdoc.org/docs/HTMLSmartyConverter/default/phpDocumentor/tutorial_phpDocumentor.howto.pkg.html
*
* The Javadoc Style Guide is an excellent resource for figuring out
* how to say what needs to be said in docblock comments. Much of what is
* written here is a summary of what is found there, though there are some
* cases where what's said here overrides what is said there.
* http://java.sun.com/j2se/javadoc/writingdoccomments/index.php#styleguide
*
* The first line of any docblock is the summary. Make them one short
* sentence, without a period at the end. Summaries for classes, properties
* and constants should omit the subject and simply state the object,
* because they are describing things rather than actions or behaviors.
*
* Below are the tags commonly used for classes. @category through @access
* are required. The remainder should only be used when necessary.
* Please use them in the order they appear here. phpDocumentor has
* several other tags available, feel free to use them.
*
* @category CategoryName
* @package PackageName
* @author Original Author <author@example.com>
* @author Another Author <another@example.com>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: @package_version@
* @link http://pear.php.net/package/PackageName
* @see NetOther, Net_Sample::Net_Sample()
* @since Class available since Release 1.2.0
* @deprecated Class deprecated in Release 2.0.0
*/
class Net_Sample
{
// {{{ properties
/**
* The status of foo's universe
*
* Potential values are 'good', 'fair', 'poor' and 'unknown'.
*
* @var string
*/
var $foo = 'unknown';
/**
* The status of life
*
* Note that names of private properties or methods must be
* preceeded by an underscore.
*
* @var bool
* @access private
*/
var $_good = true;
// }}}
// {{{ setFoo()
/**
* Registers the status of foo's universe
*
* Summaries for methods should use 3rd person declarative rather
* than 2nd person imperative, begining with a verb phrase.
*
* Summaries should add description beyond the method's name. The
* best method names are "self-documenting", meaning they tell you
* basically what the method does. If the summary merely repeats
* the method name in sentence form, it is not providing more
* information.
*
* Summary Examples:
* + Sets the label (preferred)
* + Set the label (avoid)
* + This method sets the label (avoid)
*
* Below are the tags commonly used for methods. A @param tag is
* required for each parameter the method has. The @return and
* @access tags are mandatory. The @throws tag is required if the
* method uses exceptions. @static is required if the method can
* be called statically. The remainder should only be used when
* necessary. Please use them in the order they appear here.
* phpDocumentor has several other tags available, feel free to use
* them.
*
* The @param tag contains the data type, then the parameter's
* name, followed by a description. By convention, the first noun in
* the description is the data type of the parameter. Articles like
* "a", "an", and "the" can precede the noun. The descriptions
* should start with a phrase. If further description is necessary,
* follow with sentences. Having two spaces between the name and the
* description aids readability.
*
* When writing a phrase, do not capitalize and do not end with a
* period:
* + the string to be tested
*
* When writing a phrase followed by a sentence, do not capitalize the
* phrase, but end it with a period to distinguish it from the start
* of the next sentence:
* + the string to be tested. Must use UTF-8 encoding.
*
* Return tags should contain the data type then a description of
* the data returned. The data type can be any of PHP's data types
* (int, float, bool, string, array, object, resource, mixed)
* and should contain the type primarily returned. For example, if
* a method returns an object when things work correctly but false
* when an error happens, say 'object' rather than 'mixed.' Use
* 'void' if nothing is returned.
*
* Here's an example of how to format examples:
* <code>
* require_once 'Net/Sample.php';
*
* $s = new Net_Sample();
* if (PEAR::isError($s)) {
* echo $s->getMessage() . "\n";
* }
* </code>
*
* Here is an example for non-php example or sample:
* <samp>
* pear install net_sample
* </samp>
*
* @param string $arg1 the string to quote
* @param int $arg2 an integer of how many problems happened.
* Indent to the description's starting point
* for long ones.
*
* @return int the integer of the set mode used. FALSE if foo
* foo could not be set.
* @throws exceptionclass [description]
*
* @access public
* @static
* @see Net_Sample::$foo, Net_Other::someMethod()
* @since Method available since Release 1.2.0
* @deprecated Method deprecated in Release 2.0.0
*/
function setFoo($arg1, $arg2 = 0)
{
/*
* This is a "Block Comment." The format is the same as
* Docblock Comments except there is only one asterisk at the
* top. phpDocumentor doesn't parse these.
*/
if ($arg1 == 'good' || $arg1 == 'fair') {
$this->foo = $arg1;
return 1;
} elseif ($arg1 == 'poor' && $arg2 > 1) {
$this->foo = 'poor';
return 2;
} else {
return false;
}
}
// }}}
}
// }}}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* c-hanging-comment-ender-p: nil
* End:
*/
?>
|
|