Rules

We will describe the list of rules that form the standards

Namespace prefix

All classes and functions must have a namespace of at the minimum PEAR2. An example:

<?php
namespace PEAR2;
class 
MyClass {}
?>

Classes may use longer namespaces, for instance an HTTP_Request class may instead choose to use this declarative syntax:

<?php
namespace PEAR2\HTTP;
class 
Request {}
?>

As such, underscores are no longer required of any classes if there is a namespace. Class PEAR2_HTTP_Request instead becomes PEAR2\HTTP\Request. Package names, however, will use underscores, making PEAR2_HTTP_Request the package name.

Requirement

No Exceptions to this rule

use of include/require/require_once/include_once not allowed

include/require/require_once/include_once is not allowed for loading class files. Users will be expected to load files either with __autoload() or a customized solution for more advanced users. Instead, classes should simply be used. import with a comment describing the class's location must be used to document all internal dependencies (as written below). Instead of:

<?php
require_once 'PEAR2/OtherPackage.php';
$class = new PEAR2\OtherPackage;
?>

this class should simply be used:

<?php
$class 
= new PEAR2\OtherPackage;
?>

This allows packages to work without modification no matter how they are structured on-disk, including running out of a single large file, inside a phar archive, and provides much-needed flexibility.

Requirement

No Exceptions to this rule

Directory structure

Follows the directory structure in the PEAR2 Subversion repository:

PEAR2/Package_Name/
    src/      <-- all role="php"
    data/     <-- all role="data"
    tests/    <-- all role="tests"
    docs/     <-- all role="doc"
    www/      <-- all role="www"
    examples/ <-- role="doc" example files 
                  (php executable files that exemplify package usage)

Note that all package.xml files must specify a baseinstalldir of "/" for the src/ directory:

<contents>
  <dir name="/">
  <dir name="src" baseinstalldir="/">
  ...
</contents>

Requirement

Exceptions may be made to this rule with approval from the PEAR Group

Class-to-file convention

All public classes must be in their own file with underscores (_) or namespace separators (\) replaced by directory separator, so that PEAR2_PackageName_Base class or PEAR2\PackageName\Base class is always located in PEAR2/PackageName/Base.php (this is required to make autoload work)

Requirement

Exceptions may be made to this rule only with explicit approval from the PEAR Group via a public vote

Base Exception class

PEAR2\Exception is used as base class for all exception classes. Each package must define a base class that is packagename_Exception. For example, the PEAR2\PackageName class defines an exception as follows in PEAR2/PackageName/Exception.php:

<?php
namespace PEAR2\PackageName;
class 
Exception extends PEAR2\Exception {}
?>

'PEAR2\Exception will be its own package'

Requirement

No Exceptions to this rule

Data files

package.xml replacement tasks should not be used to retrieve path locations for php, data, or www files. Replacements are still allowed in doc and test files.

The installation structure of a package has implicit php_dir/src installation location, and data files are always located in php_dir/data/channel/PackageName/. To retrieve a data file within PEAR2/PackageName/Subfile.php, you could use code like this example

<?php
...
// retrieve data from info.txt
$info file_get_contents(dirname(__FILE__) .
    
'../../../data/pear2.php.net/PEAR2_PackageName/info.txt');
?>

Requirement

No Exceptions to this rule

Loading other classes

Inside optional component loading methods (like factory or driver loading, etc.) class_exists($classname, true) should be used where a "class not found" fatal error would be confusing. For example, when loading a driver, a graceful exit via exception with helpful error message is preferrable to the fatal error:

<?php
if (!class_exists("PEAR2_PackageName_Driver_$class"true)) {
    throw new 
PEAR2\PackageName\Exception('Unknown driver ' .
    
$class ', be sure the driver exists and is loaded
    prior to use'
);
}
?>

Requirement

This rule is optional and is a suggested coding practice