Coding Standards

As with any large project, a unified standard is important to keep the coodebase maintainable and readable. The standards outlined here are required for any contribution to be considered for addition into the official codebase. For plugins and extensions it is not required, but strongly encouraged.

Naming Conventions

In general, naming conventions describe the general format for naming entities such as classes, functions, methods, etc. By following a common convention, and utilizing names that are often used for similar functionality, utilizing Bedrock becomes a more intuitive experience.

Classes

Class names must always follow the CapitalizedCamelHump format, in which all characters are lower case except for the first letter of each new word. Classes must always start with an upper case letter. Successive capital letters are never permitted. While only alphanumeric characters are allowed for class names, the use of numbers is not recommended.

When descendent from a parent class, the class name must be preceded by the name of the parent class followed by an underscore. This method can also be used when logically grouping classes with similar functionality (while not necessarily extending the same parent class).

Examples of acceptable class names:

  1. class ClassName {}
  2. class ParentClass_ClassName extends ParentClass {}
  3. class Ancestor_ParentClass_ClassName extends Ancestor_ParentClass {}

Filenames

All filenames must only include alphanumeric characters, underscores (“_”), and dashes (“-”). Spaces are never permitted. Any file containing PHP code must end with the “.php” extension.

Every class must be defined in its own separate file, with the file named after the class (excluding any underscore-delimited ancestor names). In cases where the class contains underscore-delimited names representing structure, it should be placed in subfolders representing this structure.

Examples of acceptable filenames:

ClassName.php 
ParentClass\ClassName.php 
Ancestor\ParentClass\ClassName.php 

Functions & Methods

Functions and class methods must always follow the camelHump format in which the first letter of each new word is capitalized. The first letter of a function or class method must always be a lower case letter. The use of numbers is permitted but strongly discouraged.

Exceptions to this rule are permitted when implementing interfaces or extending abstract classes that already define methods using a different format.

Examples of acceptable function and class method names:

  1. function authenticateUser() {}
  2. function openConnection() {}

Variables

Variable names must only contain alphanumeric characters and must never contain underscores (“_”). Numbers are permitted but strongly discouraged. Like function names, variables must also follow the camelHump format in which the name must start with a lower case letter, and each new word must be capitalized.

Verbosity is encouraged. Variables should always be as verbose as practical. Terse variable names such as “$i” or “$n” are discouraged for anything other than the smallest loop contexts. If a loop contains more than 20 lines of code, the variables for the indices need to have more descriptive names.

Examples of acceptable variable names:

  1. $currentDate;
  2. $userFullName;

Class variables must follow the same approach except in cases where a visibility other than public is defined. If a variable is defined as protected or private, it must be preceded with a single underscore (“_”).

Examples of acceptable class variable names:

  1. class TestClass {
  2. public $username;
  3. public $firstName;
  4. public $lastName;
  5. protected $_password;
  6. private $_secretMessage;
  7. }

Constants

Constants may contain both alphanumeric characters and the underscore. Numbers are permitted in constant names. Constants must always have all letters capitalized.

To enhance readability, words in constant names must be separated by underscore characters. For example, SUPER_LONG_CONSTANT_NAME is permitted but SUPERLONGCONSTANTNAME is not.

Constants must be defined as class members by using the “const” construct. Defining constants in the global scope with define() is permitted but discouraged.

Coding Style

Bedrock's coding style is intended to be as non-invasive as possible, while still preserving a common standard to ensure a unified codebase.

Classes

Classes must be named following the naming conventions outlined in above. Every class must have a documentation block that conforms to the PHPDocumentor standard.

Any code within a class must be indented by one tab.

Only one class is permitted per PHP file.

Placing additional code in a class file is permitted but discouraged. In these files, two blank lines must separate the class from any additional PHP code in the file.

Example of an acceptable class declaration:

  1. /**
  2.  * Documentation Block Here
  3.  */
  4. class SampleClass {
  5. // entire content of class must be indented 4 spaces
  6. }

Class Member Variables

Member variables must be named following the naming conventions outlined above.

Any variables declared in a class must be listed at the top of the class, prior to declaring any methods.

The var construct is deprecated and is not permitted. Member variables always declare their visibility by using one of the private, protected, or public constructs. Accessing member variables directly by making them public is permitted but discouraged in favor of the __set() & __get() magic functions.

Functions & Methods

Functions must be named following the naming conventions outlined above.

Functions inside classes must always declare their visibility by using one of the private, protected, or public constructs.

Functions in the global scope are strongly discouraged.

Also note that passing by-reference by prefixing a variable with an ampersand “&” is permitted in the function declaration only, call-time pass by-reference is prohibited.

Example of an acceptable class function declaration:

  1. /**
  2.  * Documentation Block Here
  3.  */
  4. class foo {
  5. /**
  6.   * Documentation Block Here
  7.   */
  8. public function bar(&$baz) {
  9. // entire content of function must be indented 1 tab
  10. }
  11. }

Try/Catch Blocks

It is considered good practice to never leave exceptions unhandled. For this reason, code should always be contained within try/catch blocks where practical. This provides the developer with an opportunity to set an alternative course of action should an error arise. This is much more preferable than presenting a cryptic error to the end-user.

Try/catch blocks should follow a format similar to control statements:

  1. try {
  2. // entire content of try block must be indented 1 tab
  3. }
  4. catch(Exception $ex) {
  5. // handle the exception
  6. }

Control Statements

Within the conditional statements between the parentheses, operators must be separated by spaces for readability. Inner parentheses are encouraged to improve logical grouping of larger conditionals:

  1. if($a != 2) {
  2. $a = 2;
  3. }
  4. else {
  5. $a = 5;
  6. }

The construct default may never be omitted from a switch statement. Each case declaration in a switch statement must be indented by one tab. The contents of a case must start on a new line and must be indented an additional tab:

  1. switch($value) {
  2. default:
  3. echo 'Unknown';
  4. break;
  5.  
  6. case 1:
  7. echo 'First';
  8. break;
  9.  
  10. case 2:
  11. echo 'Second';
  12. break;
  13.  
  14. case 3:
  15. echo 'Third';
  16. break;
  17. }

Inline Documentation

All documentation blocks, also known as docblocks must be compatible with the phpDocumentor format. The details of this format are beyond the scope of this document, but can be reviewed on the official phpDocumentor website.

Files

Every non-class file that contains PHP code must have a docblock at the top of the file that contains these phpDocumentor tags at a minimum:

  1. /**
  2.  * Short description for file
  3.  *
  4.  * Long description for file (optional)...
  5.  *
  6.  * @package [name of package]
  7.  * @author [author name] (can have multiple @author tags)
  8.  * @version 1.0.0
  9.  * @created [date file was created MM/DD/YY] (optional)
  10.  * @updated [date file was updated MM/DD/YY] (optional)
  11.  */

Classes

Every class must have a docblock at the top of the file that contains these phpDocumentor tags at a minimum:

  1. /**
  2.  * Short description for class
  3.  *
  4.  * Long description for class (optional)...
  5.  *
  6.  * @package [name of package]
  7.  * @author [author name] (can have multiple @author tags)
  8.  * @version 1.0.0
  9.  * @created [date class was created MM/DD/YY] (optional)
  10.  * @updated [date class was updated MM/DD/YY] (optional)
  11.  */

Functions & Methods

Every function and class method must have a docblock that contains at a minimum:

  1. /**
  2.  * Short description for function
  3.  *
  4.  * @param [data_type] $arg description of each argument
  5.  * @return [data_type] a description of the return value
  6.  * @throws [exception_class] [description] (optional)
  7.  */

Implementation Standards

These implementation standards are not required for applications utilizing the Bedrock Framework, but may prove useful depending on the needs of the application. However, they are required for all plugins/extensions and any code being submitted for integration into the framework itself.

Classes

In general, all classes should descend from the base Bedrock class or one of its descendants. This insures common functionality across the entire class hierarchy.

Exceptions are allowed in cases where external libraries are used that are either designed by third parties, part of another framework, or otherwise not originally designed to be part of Bedrock or a plugin/extension. Developers are encouraged to use their own discretion when following this standard, and only follow it where practical.

Functions & Methods

All functions should utilize Bedrock's logger to log both function entries, exits, exceptions, and any other information the developer deems useful. This allows for the most usable log information to be available across not only the core framework, but external plugins and extensions as well. At a minimum, every function should implement the following logging actions (also note the use of try/catch blocks):

  1. /**
  2.  * Documentation Block Here
  3.  */
  4. function calculateSum($a, $b) {
  5. Bedrock_Common_Logger::logEntry();
  6.  
  7. try {
  8. // Place all function code here.
  9.  
  10. $sum = $a + $b;
  11.  
  12. Bedrock_Common_Logger::logExit();
  13. return $sum;
  14. }
  15. catch(Exception $ex) {
  16. Bedrock_Common_Logger::exception($ex);
  17. Bedrock_Common_Logger::logExit();
  18. }
  19. }

Note that the exiting of the function must be logged before its return value is returned, as no code following the return will be executed. This is the only case in which any function code should appear after a call to ::logExit().