picture of Sean Cazzell
If you've ever done any perl programming, or if you've spent any time talking to perl programmers, you have probably heard of "CPAN" - the Comprehensive Perl Archive Network. CPAN provides a central repository of perl modules, most of which are made available under the same licenses as perl itself (the GPL and The Artistic License). In many ways, CPAN has been "the killer app" that has made perl one of the most popular languages around. By using CPAN, a perl developer can quickly assemble the majority of the code needed for their programs, leaving them to simply code the glue needed to stick all the modules together into a cohesive whole.
The PHP Extension and Add-on Repository (PEAR) project is an effort to develop a repository similar to perl's CPAN and TeX's CTAN for the PHP community. PEAR will offer much more than the useful, but rather ad-hoc code snippets in the Code Gallery available on Zend's web site. By providing an infrastructure and defining a set of standards that all contributors must adhere to, PEAR, combined with PHP 4, may be just what is needed to take PHP to the next level.
The intention behind PEAR is to provide a means for library code authors to share their code with other developers, to give the PHP community an infrastructure for using third-party code, to define standards that help developers write code that runs in different PHP configurations, and to provide tools for code maintenance and distribution.
- Stig Bakken, PEAR Documentation

PEAR Standards

Perhaps the most important part of the PEAR project is finally defining an official standard for creating reusable, well documented php packages. A standard set of guidelines are necessary to make sure all PEAR packages are available to as many developers as possible. Since PEAR is still in development, the current set of rules and guidelines are subject to discussion and change. If you take issue with any of these guidelines, or have a better solution, you should let the developers know by posting to the PHP-PEAR mailing list.
Naming Guidelines
The extension .php must be used for all files containing php code. A related set of one or more classes and functions are called a "package". These packages are organized into the PEAR package structure. The package structure maps 1:1 to the file system, but is based on the argument provided to the "use" or "import" functions.
Because PHP does not implement name-spaces, class names must be based on the package they are implemented in. The class name is derived by simply replacing the slashes in the package name with under scores. Thus, the package "DB/common" has it's code in the file "DB/common.php", and defines a class called "DB_common". This strategy should prevent any naming collisions despite the lack of separate name-spaces.
Functions should be named with underscores separating lowercase words, for example my_function. Methods should use initial lowercase studly caps, like myMethod.

Error Handling

The correct way to handle errors is still a subject of discussion on the PHP-PEAR mailing list. It is important however, that you never call die or exit inside your packages. Doing so will prevent the application using your package from handling the error in a more graceful fashion. You should instead return an error to the caller, even if it is only a boolean value. One error reporting method proposed by Sterling Hughes is to create a standard PEAR_ERROR object that is created within your package and then returned to the caller.

<?php

class PEAR_ERROR {
    var 
$errno;
    var 
$errstr;
    var 
$calling_package;
    var 
$method;
}

//You can then use this code to 
//return an error from your package.

class fubar {
    function 
foo ($args) {
        if (
count ($args) < 1) {
            
$ret = new PEAR_ERROR;
            
$ret->errno WRONG_PARAM_COUNT;
            
$ret->errstr "Wrong parameter count";
            
$ret->calling_package "fubar";
            
$ret->method "foo";
            return (
$ret);
        }
    }
}

?>
The recent release of PHP 4.0.1 also brought several enhancements to PHP's built-in error handling capabilities that might prove useful in creating an error handling solution for PEAR packages.

Optional Feature Dependencies

In order to make sure your PEAR packages can be used by as many PHP developers as possible, your code should not be dependent on optional features unless it absolutely needs them.
One example is the magic_quotes_gpc configuration option. Proper PEAR packages should work with or without this option enabled. Here's an example that does just that.

<?php

// If magic_quotes_gpc is enabled, remove those slashes.
if (get_cfg_var("magic_quotes_gpc")) {
    
$arg stripslashes($arg);
}

?>
Your code should always use the <?php ... ?> syntax, since the shorter forms <? ... ?> and <% ... %> may be disabled.
Since the register_globals configuration may be disabled, your code should make use of the appropriate HTTP_*_VARS global arrays.

Scope Issues

If your package is included from within a function, any variables you define (outside your package's classes and functions) will inherit the scope of the calling function. For this reason it is a good practice to define these globals using the $GLOBALS associative array.

PHPDoc

Many modern languages have a built in documentation system which allows developers to embed documentation into their code. This makes keeping documentation up to date easier, and simple tools can be created to parse the documentation out of the code and create docs in formats such as HTML, XML, etc. PEAR has adopted Javadoc as its official inline documentation format. Development efforts are currently underway to write javadoc parsers in php, and provide "phpdoc" tools for php developers.
Writing PEAR Packages
To re-cap, here are the things you need to keep in mind when writing code that you intend to eventually submit to PEAR.

Resources

The following pages were using extensively in the writing of this document. Special credit must be given to Stig Bakken, who wrote the PEAR documentation which provided the bulk of the information in this document.