PHP coding style guide


The PHP coding style guide at Outlast is based on the existing coding style implemented within the Outlast Framework. All developers must follow this when developing in PHP at Outlast. Some of the text below is used from CodeIgniter’s style guide but updated as needed.

File formats, encoding, line endings

All files must use the .php extension.

Files should be saved with Unicode UTF-8 encoding. The BOM should not be used. Unlike UTF-16 and UTF-32, there’s no byte order to indicate in a UTF-8 encoded file, and the BOM can have a negative side effect in PHP of sending output, preventing the application from being able to set its own headers.

Unix line endings should be used (LF). Be careful, Windows users usually need to set this up in their editor manually!

PHP tags

The full PHP opening tag <?php should be used in all files.

Closing tags should not be used at the end of PHP files because they can cause errors if accidental spaces are added after the closing tag. This includes most PHP files in OFW – typically they are only PHP with no HTML output mixed in, so there will be no closing tag.

Here is a proper example:

INCORRECT:
<?php

echo "Here's my code!";

?>

CORRECT:
<?php

echo "Here's my code!";

/* End of file myfile.php, no closing tag. */

Class and method naming

Classes should be CamelCase with no underscores. Model classes should be defined as singular nouns, such as User instead of Users.

INCORRECT:
class My_class
class myclass

CORRECT:
class MyClass

Method names should be_lowercase_and_use_underscores. They should also always include public or private.

INCORRECT:
function fileproperties()		// not descriptive and needs underscore separator and private/public
public function fileProperties()		// not descriptive and uses CamelCase
public function getfileproperties()		// Better!  But still missing underscore separator
private function getFileProperties()		// wrong, uses CamelCase
public function get_the_file_properties_from_the_file()	// too wordy

CORRECT:
public function get_file_properties()	// descriptive, underscore separator, and all lowercase letters

Static and magic methods

Static methods are used in OFW to create and fetch objects. They should be styled exactly as any other method with underscores and lowercase:

CORRECT:
public static function fetch_by_user()

Magic methods are used in OFW as triggers when certain actions occur. A common example is __afterFetch() in models where caching of certain data can occur. It is important that unlike other methods, magic methods use __lowerCamelCase() and are always preceded by two underscores.

INCORRECT:
public function __AfterFetch()    // Wrong! Capitalized first letter.
public function __after_fetch()   // Wrong! Not CamelCase.
public function afterFetch()      // Wrong! No underscore preceding.
public function _afterFetch()     // Wrong! Only a single underscore preceding.

CORRECT:
public function __beforeSave()      // Correct!

Variable and method properties

The guidelines for variable naming is very similar to that used for class methods. Namely, variables should contain only lowercase letters, use underscore separators, and be reasonably named to indicate their purpose and contents. Very short, non-word variables should only be used as iterators in for() loops.

INCORRECT:
$j = 'foo';		// single letter variables should only be used in for() loops
$Str			// contains uppercase letters
$bufferedText		// uses CamelCasing, and could be shortened without losing semantic meaning
$groupid		// multiple words, needs underscore separator
$name_of_last_city_used	// too long

CORRECT:
for ($j = 0; $j < 10; $j++)
$str
$buffer
$group_id
$last_city

Method properties should use the same logic and should always be declared!

class RandomExample{
  public $example_property = true;

  public function random_method(){
    // Below is WRONG! It is a non-declared property.
      $this->some_other_property = false;
    // Below is CORRECT! It is using the declared property from above.
      $this->example_property = false;
  }
}

Constants

Constants follow the same guidelines as do variables, except constants should always be fully uppercase and need to be declared at the top of each PHP file.

declare('EXAMPLE_CONSTANT', 25);  // CORRECT!

Comments and documentation

In-code documentation and lengthy commenting is an essential part of coding style at Outlast. You MUST use comments and you MUST use it more often than you think you should. 🙂

Here’s a correct example:

function add_numbers($number1, $number2 = false){
  // Number2 defaults to the same value as number1 if it is false
    if($number2 === false) $number2 = $number1;
  // Now add and return
    return $number1 + $number2;
}

You don’t have to comment on every line, but you do have to comment each code block (every few lines). Even obvious code segments should be commented. Why? Because it makes code review and code debug much easier by others (and by yourself if you come back to the code in a few months).

Another important facet is to always use DOCBLOCK comments for each class, method, and variable. This helps software such as PHPStorm autocomplete and suggest code properly. It also helps us standardize and generate documentation.

Here’s a correct example of using DOCBLOCK:

/**
 * Returns an error message and exists. Useful for fatal errors.
 * @param string $message The error message to display and/or log.
 * @return bool Does not return anything.
 * @link http://www.externallink.com/only/if/needed/
 **/
public function error($message){
	// Manually load error reporting lib
		/* @var zajlib_error $error */
		$error = $this->load->library('error');
	// Now report the error and send 500 error
		if(!$this->output_started) header('HTTP/1.1 500 Internal Server Error');
		$error->error($message);
		exit;
}

Notice that each @param is documented as is the @return value. Also, notice how @var is used within the code to tell the compiler what return value it should expect from the method. Unlike the method DOCBLOCK, this is not required but it is quite helpful for autocomplete and code validation.

Finally, notice how every few lines are commented (and the code is indented – more about that later). Such commenting is required, even if the code segment logic is obvious to you as you are writing it.

Helpful tip For reusable models (such as those used in plugins or the OFW system) you should create a separate doc.php file to document the various fields available in that model. See OFW’s /system/doc/doc.php as an example.

Helpful tip For a full list of DOCBLOCK tags, see the documentation.

Booleans and null

Always use the lower case version.

INCORRECT:
$variable = TRUE;
CORRECT:
$variable = false;

Logical Operators

Always use the symbol version.

INCORRECT:
if($var1 == 1 AND $var2 == 2) echo "woo!";
CORRECT:
if($var1 == 1 && $var2 == 2) echo "woo!";

Always use the strict type comparison (===, !==, etc.) where possible.

INCORRECT:
if(strpos($str, 'foo') == false)
CORRECT:
if(strpos($str, 'foo') === false)

Error handling

Do not use exceptions within the context of Outlast Framework. Instead use the notice(), warning(), and error() and return its values.

Here’s an example:

function do_something(){
  // ....
  // If I failed
    if($failed) return $this->zajlib->warning("Failed to do something");
}

Warnings will continue execution, errors are fatal and halt execution. Warning and errors are only displayed in debug mode. If you want to display the error in live mode as well (which is usually not recommended) then you can use set the second parameter to true:

return $this->zajlib->error("Fatally failed to do something", true);

Brackets and code blocks

Short code blocks can be placed on a single line:

if($is_true) echo "It's true!";

Longer lines or multi-line code blocks require brackets and else blocks are on separate lines:

if($is_true){
  echo "Indeed, I must say that this is rather true";
}
else{
  echo "Nope, it is not true.";
}

There is no space before opening brackets.

Indentation and whitespace

Do not place any whitespace before the opening php tag and just skip using the closing tag (see above). Whitespace before the <?php tag will cause errors!

For indentation, set your IDE to use tabs instead of spaces. If you must use spaces, you should set it to 4 spaces.

Although not always the case in OFW core code currently, indentation should generally follow the Stroustrup variant of K&R style but with some modifications.

Here are some proper examples:

public function redirect($url, $frame_breakout = false){  // Opening bracket on same line, no preceding space
	// Comments are on the first level of indentation, code is indented further
		if(!$this->url->valid($url)) $url = $this->baseurl.$url; // If statements can be on the same line if simple, single line logic
	// If test is running, return url
		if($this->test->is_running()) return $url;
	// Frame breakout or standard?
		if($frame_breakout){
			// You can also have multi-line if statements, with brackets. Again, bracket on same line, no space.
			exit("<script>window.top.location='".addslashes($url)."';</script>");
		}
		else{  // Else is not nested, bracket is the same as before.
			header("Location: ".$url);
		}
	exit;
}

Spacing is also quite limited:

INCORRECT:
foreach( $query->result() as $row )

CORRECT:
foreach($query->result() as $row)  // No space after foreach, no space after or before parenthesis

SQL Queries

MySQL keywords are always capitalized: SELECT, INSERT, UPDATE, WHERE, AS, JOIN, ON, IN, etc.

IMPORTANT! Always use the dbo library and properly escape all variables.

Break up long queries into multiple lines for legibility, preferably breaking for each clause.

Strings and concatenation

Always use single quoted strings unless you need variables parsed, and in cases where you do need variables parsed, use braces to prevent greedy token parsing. You may also use double-quoted strings if the string contains single quotes, so you do not have to use escape characters.

INCORRECT:
"My String"					// no variable parsing, so no use for double quotes
"My string $foo->var"				// needs braces
'SELECT foo FROM bar WHERE baz = \'bag\''	// ugly

CORRECT:
'My String'
"My String $var"     // correct with or without braces
"My String {$var}"
"My string {$foo->var}"
"SELECT foo FROM bar WHERE baz = 'bag'"

When concatenating, do not use spaces between dots:

INCORRECT:
$string = 'Lorem ipsum, ' . $var . ' More...';

CORRECT:
$string = 'Lorem ipsum, '.$var.' More...';

Version control

All code must use version control (Git). Never leave old code segments in /** comments **/ – instead commit often and rely on Git to have quick access to all previous versions of your code.

For more on version control see the Outlast Git and deployment workflow.

Autoformatting

Autoformatting is not recommended because it can change lots of rows all at once (which causes confusion during code review) and can sometimes mess things up. Instead, programmers should manually follow all rules in this document.

Outlast Web & Mobile Development (c) 2023 | Privacy Policy |