Get started with PHP-Fusion

PHP-Fusion Coding Standards
PHP-Fusion Coding Standards

XSS Filtering

Cross Site Scripting filter.
This filter looks for commonly used techniques to embed malicious JavaScript into your data, or other types of code that attempt to hijack cookies or do other malicious things.

CSRF protection

CSRF stands for Cross-Site Request Forgery, which is the process of an attacker tricking their victim into unknowingly submitting a request.
PHP-Fusion provides a CSRF protection out of the box, which will automatically trigger when you submit forms via PHP-Fusion Dynamics.

Validation of input data

PHP-Fusion Defender have form validation that assists you in validating, filtering, and prepping your data.
Even if that doesn’t work for your use, be sure to always validate and sanitize all input data.
If you expect a numeric string for an input variable, you can check for that with the isnum() function.
If you pass data with form posts or $_GET, you should always use the form_sanitizer() or stripinput() function to sanitize the posted data.
Please keep in mind that this includes not only $_POST and $_GET variables but also cookies, strings and basically all data that is not created directly by your own code.

Safety first

Always validate data to ensure that it contains the correct chars, types, length, size, etc.
Always filter the data as if it were tainted.
PHP-Fusion provides quite a few functions and tips to assist you in this process.

Code in English

All comments, variable names, function names, class names, strings etc should always be in English.

Index Files

Always have an empty index.php file in your directories when you do not use index.php as the standard opening file.
You must have an empty index.php in your images, js, css, templates, etc. folders as well.

File Format

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.
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).

You can read more about UTF-8 in UTF-8 Explained

Line Breaks

Files must be saved with Unix line breaks.
Ensure that your text editor is configured to save files with Unix line breaks

Limit Line Length

Our eyes are more comfortable when reading tall and narrow columns of text.
We consider it to be good practice to avoid writing horizontally long lines of code.
In general, all lines of code should not be longer than 80 chars.

Whitespace in Files

No whitespace can precede the opening PHP tag or follow the closing PHP tag.
Output can be buffered, so whitespace in your files can cause output to begin before PHP-Fusion outputs its content, leading to errors and an inability to send proper headers.

Short Open Tags

Always use full PHP opening tags, not all servers have short_open_tag enabled.

INCORRECT

Code Gist:
<? echo $foo; ?>

Code Gist:
<?=$foo?>


CORRECT
Code Gist:
<?php 
echo $foo;
?>

PHP Closing Tag

The PHP closing tag on a PHP document ?> is optional to the PHP parser.
However, if used, any whitespace following the closing tag, whether introduced by the developer, user, or an FTP application, can cause unwanted output followed by PHP errors, or if the latter are suppressed, blank pages.
For this reason we want all PHP files to omit the PHP closing tag and end with a single empty line instead.

File Naming

Class filenames should always start with an uppercase letter, while any other file name (configurations, views, generic scripts, etc.) should all be in lowercase.
Class file names should match the name of the class itself. For example, if you have a class named Myclass, then its filename should also be Myclass.php.
Multiple words should be separated with an underscore.

INCORRECT
someclass.php
someClass.php
SOMECLASS.php
Some_Class.php

CORRECT
Someclass.php
Some_class.php

Headers

Headers provides a description of the file and it should usually include Copyright, Filename, Author, License.
Example of a standard header,

Code Gist:
/*-------------------------------------------------------+
| PHP-Fusion Content Management System
| Copyright (C) PHP-Fusion Inc
| https://www.php-fusion.co.uk/
+--------------------------------------------------------+
| Filename: Filename.php
| Author: PHP-Fusion Development Team
+--------------------------------------------------------+
| This program is released as free software under the
| Affero GPL license. You can redistribute it and/or
| modify it under the terms of this license which you
| can read by viewing the included agpl.txt or online
| at www.gnu.org/licenses/agpl.html. Removal of this
| copyright header is strictly prohibited without
| written permission from the original author(s).
+--------------------------------------------------------*/

Modifying headers

When you write a Custom New File, then you are the Author of the file:

+--------------------------------------------------------+
| Filename: Filename.php
| Author: Your Name (Username/Nickname)
+--------------------------------------------------------+

When you have modified someone’s file quite a bit beyond a few fixes, you would qualify as a Co-Author and you can increment the header as follows,
+--------------------------------------------------------+
| Filename: Filename.php
| Author: PHP-Fusion Development Team
| Co-Author: Your Name (Username/Nickname)
+--------------------------------------------------------+


Your are not allowed to alter the PHP-Fusion Copyright´s or the License section unless you are a PFDN member that use EPAL

Secure Includes

When you create files that are intended to work as an include to the Core, always add a check to prevent direct access to these includes.
This also applies to panels, functions, classes and similar.
Files such as Locales, CCS, JS files etc can be excluded from this Standard.

Snippet to use,

Code Gist:
if (!defined("IN_FUSION")) { die("Access Denied"); }


The code should be one line directly after the header, as displayed below.
Code Gist:
/*-------------------------------------------------------+
| PHP-Fusion Content Management System
| Copyright (C) PHP-Fusion Inc
| https://www.php-fusion.co.uk/
+--------------------------------------------------------+
| Filename: Filename.php
| Author: PHP-Fusion Development Team
+--------------------------------------------------------+
| This program is released as free software under the
| Affero GPL license. You can redistribute it and/or
| modify it under the terms of this license which you
| can read by viewing the included agpl.txt or online
| at www.gnu.org/licenses/agpl.html. Removal of this
| copyright header is strictly prohibited without
| written permission from the original author(s).
+--------------------------------------------------------*/
if (!defined("IN_FUSION")) { die("Access Denied"); }

Always use echo

Always make use of echo to print a text in the output.

INCORRECT

Code Gist:
print "This is some text.";


CORRECT
Code Gist:
echo "This is some text.";

HTML as Lowercased

Your HTML must always be containing Lowercase characters.
Uppercase characters are not XHTML compatible.

INCORRECT

Code Gist:
echo "<STRONG>I Love PHP-Fusion.</STRONG>\n";


CORRECT
Code Gist:
echo "<strong>I Love PHP-Fusion.</strong>\n";

Control Structures

PHP-Fusion should not use Alternative syntaxes for Control Structures.
Always avoid to jump in and out of in PHP.
Do not use PHP short tags.
Content should be echoed.
Statements should be opened and closed with curly braces.

INCORRECT
// Does not use curly braces and keeps jumping in and out of PHP while PHP short tag is occasionally used.

Code Gist:
<? if ($username == 'User 1'): ?>
   <h3>Hi User 1</h3>
<?php elseif ($username == 'User 2'): ?>
   <h3>Hi User 2</h3>
<? else: ?>
   <h3>No matching users found</h3>
<?php endif; ?>


CORRECT
// Using curly braces and does not jump in and out of PHP, echos the content and not using PHP short tags.
Code Gist:
<?php 
if ($username == 'User 1') {
   echo "<h3>Hi User 1</h3>";
} elseif ($username == 'User 2') {
   echo "<h3>Hi User 2</h3>";
} else {
   echo "<h3>No matching users found</h3>";
}
?>

Indentation

PHP-Fusion use a indent style called Kernel style - 1TBS, Also known as the one true brace style.
Make sure that your editor does not automatically indent all codes with one tab level from start.

INCORRECT
// Everything is tabbed out one level, curly brace is on a new line, overall , inconsistent tabbing and spacing.

Code Gist:
   function foo($bar) 
   {
   if (x <0) {
    return $negative;
    } elseif (x>0) {
            return $positive;
    } else {
   return $unknown;
    }
   }


CORRECT
Code Gist:
function foo($bar) {
   if (x < 0) {
      return $negative;
   } elseif (x > 0) {
      return $positive;
   } else {
      return $unknown;
   }
}

Whitespace for indentation

Never use whitespace for indentation in your code, always use tabs with the exception of aligning arrays.
It results in more compact files, storing one tab character versus, say, four space characters.

Bracket and Parenthesis Spacing

Parenthesis and Brackets should not use any additional spaces.
The exception is that a space should always follow PHP control structures that accept arguments with parenthesis such as
(declare, do-while, elseif, for, foreach, if, switch, while), to help distinguish these from functions and in order to increase code readability.

INCORRECT
// Spaces around array keys

Code Gist:
$arr[ $foo ] = 'foo';


CORRECT
// No spaces around array keys
Code Gist:
$arr[$foo] = 'foo'; 


INCORRECT
// Spaces around parenthesis in function declarations
Code Gist:
function foo ( $bar ) {
}


CORRECT
// No spaces around parenthesis in function declarations
Code Gist:
function foo($bar) {
}


INCORRECT
// A single space in interior parenthesis
Code Gist:
foreach( $result->result() as $data )


CORRECT
// A single space following PHP control structures, but not in interior parenthesis
Code Gist:
foreach ($result->result() as $data) 

One File per Class

Use separate files for each class, unless the classes are closely related.

Class and Function Naming

Class functions should named to clearly indicate their function, preferably including a verb.
Try to avoid overly long and verbose names and separate multiple words with underscores.

INCORRECT

Code Gist:
class megaclass
class MegaClass


CORRECT
Code Gist:
class Mega_class {
public function __construct() {
 }
}


INCORRECT
// Not descriptive and needs underscore separator
Code Gist:
function fileproperties() {
}

// Better, still missing underscore separator
Code Gist:
function getfileproperties() {
}

// Way to much words
Code Gist:
function get_the_file_properties_from_the_file() {
}


CORRECT
// Descriptive with clear underscore separators
Code Gist:
function get_file_properties() {
}

Commenting

Comments help to describe the flow and intent of the code.
When the code is quite obvious, it is not productive to repeat it with a lot of comments.
If you comment on the code, you can simply combine it to a single line in most of the cases.

INCORRECT

Code Gist:
// Prevent any possible XSS attacks via $_GET.
// Check if we have a stripget($_GET) function request
if (stripget($_GET)) {
   // The request found a bad pattern, terminate the script
   die("Prevented a XSS attack through a GET variable!");
}
// End of function


CORRECT
Code Gist:
// Prevent any possible XSS attacks via $_GET.
if (stripget($_GET)) {
   die("Prevented a XSS attack through a GET variable!");
}


DocBlock style commenting is something we should use preceding class, method, and property declarations so they can be picked up by IDEs

CORRECT
Code Gist:
/**
* Class name
*
* @package      Package Name
* @subpackage   Subpackage
* @category      Category
* @author      Author Name
* @link         http://example.com
*/


CORRECT
Code Gist:
class Class name {
/**
* Encodes string for use in example
*
* @param string $example Input string
* @return string
*/
function encode_example($example)
/**
* Data for class manipulation
*
* @var array
*/

Code Grouping

Most often, certain tasks require quite a few lines of code.
It is a good idea to keep these tasks grouped within separate blocks of code.
This is best achived by adding a break.
By adding a comment at the beginning the blocks, you also emphasizes the visual separation.

INCORRECT

Code Gist:
if (stripget($_GET)) {
   die("Prevented a XSS attack through a GET variable!");
}
dbconnect($db_host, $db_user, $db_pass, $db_name);
unset($db_host, $db_user, $db_pass);


CORRECT
Code Gist:
// Prevent any possible XSS attacks via $_GET.
if (stripget($_GET)) {
   die("Prevented a XSS attack through a GET variable!");
}

// Establish mySQL database connection
dbconnect($db_host, $db_user, $db_pass, $db_name);
unset($db_host, $db_user, $db_pass);

Avoid Deep Nesting

With many nested levels the code is harder to read and follow, even with proper Indentation.

INCORRECT

Code Gist:
function do_stuff() {
// Things to do
   if (is_writable($folder)) {
      if ($fp = fopen($file_path,'w')) {
         if ($stuff = get_some_stuff()) {
            if (fwrite($fp,$stuff)) {
               // Things to do
            } else {
               return false;
            }
         } else {
            return false;
         }
      } else {
         return false;
      }
   } else {
      return false;
   }
}


CORRECT
Code Gist:
function do_stuff() {

// Things to do

   if (!is_writable($folder)) {
      return false;
   }

   if (!$fp = fopen($file_path,'w')) {
      return false;
   }
 
   if (!$stuff = get_some_stuff()) {
      return false;
   }

   if (fwrite($fp,$stuff)) {
   // Things to do
   } else {
      return false;
   }
}

Logical Operators

Use of the || “or” comparison operator is discouraged, as its clarity on some output devices is low (looking like the number 11, for instance).
&& is preferred over AND but either are acceptable, and a space should always precede and follow !.

INCORRECT

Code Gist:
if ($foo || $bar)

// Okay but not recommended for common syntax highlighting applications
Code Gist:
if ($foo AND $bar) 

Code Gist:
if ($foo == FALSE)


CORRECT
Code Gist:
if ($foo OR $bar)

// Best practise
Code Gist:
if ($foo && $bar) 

Code Gist:
if (!$foo)

Code Gist:
if (!is_array($foo))


Comparing Return Values and Typecasting
Some PHP functions return FALSE on failure, but may also have a valid return value of “” or 0, which would evaluate to FALSE in loose comparisons.
Be explicit by comparing the variable type when using these return values in conditionals to ensure the return value is indeed what you expect, and not a value that has an equivalent loose-type evaluation.

Use the same stringency in returning and checking your own variables. Use === and !== as necessary.

Ternary Operator

Ternary operators are encouraged, always have them test if the statement is true and not false, Otherwise, it just gets confusing.

// (if statement is TRUE) ? (Do this) : (else, do this);

Code Gist:
$standard = ($is_true == TRUE) ? "Yes" : "No";

Semicolons

The PHP language requires semicolons at the end of most lines, but allows them to be omitted at the end of code blocks.
PHP-Fusion Coding Standards requires them, even at the end of code blocks.

INCORRECT

Code Gist:
echo $variable 


CORRECT
Code Gist:
echo $variable;

Quotes

PHP-Fusion is most often using double quotes when echoing it´s content and when handling Constants, Variables etc.

INCORRECT
// Double quotes are required to avoid escaping

Code Gist:
'SELECT foo FROM bar WHERE baz = \'bag\''

// Does not use double quotes when echoing content
Code Gist:
echo 'My $varible';


CORRECT
// No Quotes are required
Code Gist:
"SELECT foo FROM bar WHERE baz = 'bag'"

// Using double quotes when echoing content and variable
Code Gist:
echo $varible." with some text";

// Using double quotes when echoing content
Code Gist:
echo "My content";

// Using double quotes when calling Constants.
Code Gist:
include INFUSIONS."my_panel//my_panel_include.php";

String Concatenations

PHP-Fusion is most often using double quotes when echoing it´s content and when handling Constants, Variables etc.
Always use a space between the dot and the concatenated parts to improve readability.

INCORRECT
// No double quotes, bas spacing.

Code Gist:
$string = "Foo" . $bar;
$string=$bar.'foo';
$string= bar() 'foo';
$string= 'foo'. 'bar';


// Concatenating assignment operator lacks spaces on the sides
Code Gist:
$string.="Foo";
$string.=$bar;
$string.=baz();



CORRECT
// When you concatenate simple variables, you can use double quotes and add the variable inside.
Code Gist:
$string = "Foo" . $bar;
$string = $bar . "foo";
$string = bar() . "foo";
$string = "foo" . "bar";


// When using the concatenating assignment operator (.=) use a space on each side.
Code Gist:
$string .= "Foo";
$string .= $bar;
$string .= baz();

Variables

The guidelines for variable naming are very similar to those used for classes and functions.
Variables should contain only lowercase letters, use underscore separators.
The naming should be made in such manner that it is and indicator of their purpose and contents.
Very short, non-wordy variables should only be used as iterators in for() loops.

INCORRECT
// Single letter variables should only be used in for() loops

Code Gist:
$k = "foo"; 

// Contains uppercase letters
Code Gist:
$Str 

// Uses CamelCasing, and could be shortened without losing semantic meaning
Code Gist:
$bufferedText 

// Uses multiple words, needs underscore separator
Code Gist:
$groupid 

// Way too long
Code Gist:
$name_of_last_city_used 


CORRECT
// Correct for() looping with use of single letter variable
Code Gist:
for ($k = 0; $k < 10; $k++)

// Lowercase letters
Code Gist:
$str

// We get the idea with no CamelCase
Code Gist:
$buffer

// Multiple words with underscore as separator
Code Gist:
$group_id

// Quite clear what it does in a short version
Code Gist:
$last_city

Constants

Constants follow the same guidelines as variables, except constants should always be fully uppercase.
Always use Core constants when appropriate, i.e. INFUSIONS, NEWS, BASEDIR, IMAGES, etc.
The naming should be made in such manner that it is and indicator of the purpose and contents.
Very short, non-wordy constants should not be used.


INCORRECT
// Missing underscore separator and not fully uppercase

Code Gist:
newbasedir

// Do not use single letter constants
Code Gist:
N 

// Not descriptive at all
Code Gist:
S_C_VER


CORRECT
Code Gist:
NEW_BASEDIR

Code Gist:
GOOD


TRUE, FALSE, and NULL keywords should always be fully uppercase.

INCORRECT
Code Gist:
if ($foo == true)
$bar = false;
function foo($bar = null)

CORRECT
Code Gist:
if ($foo == TRUE)
$bar = FALSE;
function foo($bar = NULL)

Aligning Arrays

Arrays should be formatted with a space separating each element after the comma (,) and spaces around the => key association operator if possible.
Note that if the line declaring an array spans longer than 80 characters, each element should be broken into its own line and indented one level

INCORRECT
// No spacing

Code Gist:
$my_array = array("apple"=>"red","banana"=>"yellow","watermelon"=>"green");


// Bad indentation and mixed breaks, inconsistent spacing.
Code Gist:
$my_array = array(
 "apple"=> "red", "banana"=>"yellow",
 "watermelon" =>"green",
"Lemon"=> "yellow",
"Strawberry" => "red");

CORRECT
// Spacing as required
Code Gist:
$my_array = array("apple" => "red", "banana" => "yellow", "watermelon" => "green");


// Good indentation, nice breaks, consistent spacing, ends with a ,
Code Gist:
$my_array = array(
   "apple" => "red",
   "banana" => "yellow",
   "watermelon" => "green",
   "Lemon" => "yellow",
   "Strawberry" => "red",
);


The comma at the end of the last array allows the parenthesis to have it´s own line,
it also allows help to prevent parsing errors if another element is placed at the end of the list later.

Debugging Code

Do not leave debugging code in your submissions, even when commented out.
Things such as var_dump(), print_r(), die(), exit() should not be included in your code unless it serves a specific purpose other than debugging.

Database encodings

PHP-Fusion are using utf8_unicode_ci for it´s Database encodings as default from PHP-Fusion 9.0.

You can read more about it in UTF-8 Databases

SQL Queries

SQL keywords should always be capitalized, SELECT, INSERT, UPDATE, WHERE, AS, JOIN, ON, IN, etc.

Break up extra long queries into multiple lines for readability, make the break for each clause.

INCORRECT
// Keywords are lowercase and query is on one line

Code Gist:
$result = dbquery("select foo, bar, baz, foofoo, foobar as raboof, foobaz from exp_pre_email_addresses where foo != 'oof' and baz != 'zab' order by foobaz limit 5, 100");

// One very huge line
Code Gist:
$result = dbquery("SELECT f.*, f2.forum_name AS forum_cat_name, t.thread_id, t.thread_lastpost, t.thread_lastpostid, t.thread_subject, u.user_id, u.user_name, u.user_status, u.user_avatar FROM ".DB_FORUMS." fLEFT JOIN ".DB_FORUMS." f2 ON f.forum_cat = f2.forum_id LEFT JOIN ".DB_FORUM_THREADS." t ON f.forum_lastpostid = t.thread_lastpostid LEFT JOIN ".DB_USERS." u ON f.forum_lastuser = u.user_id ".(multilang_table("FO") ? "WHERE f.forum_language='".LANGUAGE."' AND" : "WHERE")." ".groupaccess('f.forum_access')." AND f.forum_id='".intval($this->forum_info['forum_id'])."' OR f.forum_cat='".intval($this->forum_info['forum_id'])."' OR f.forum_branch='".intval($this->forum_info['forum_branch'])."' ORDER BY forum_cat ASC"); 

CORRECT
// Keywords are capitalized and the query is easily readable.
Code Gist:
$result = dbquery("SELECT foo, bar, baz, foofoo, foobar AS raboof, foobaz FROM exp_pre_email_addresses WHERE foo != 'oof' AND baz != 'zab' ORDER BY foobaz LIMIT 5, 100");


// Query have a new line at each new clause.
Code Gist:
$result = dbquery("SELECT f.*, f2.forum_name AS forum_cat_name,
t.thread_id, t.thread_lastpost, t.thread_lastpostid, t.thread_subject,
u.user_id, u.user_name, u.user_status, u.user_avatar
FROM ".DB_FORUMS." f
LEFT JOIN ".DB_FORUMS." f2 ON f.forum_cat = f2.forum_id
LEFT JOIN ".DB_FORUM_THREADS." t ON f.forum_lastpostid = t.thread_lastpostid
LEFT JOIN ".DB_USERS." u ON f.forum_lastuser = u.user_id
".(multilang_table("FO") ? "WHERE f.forum_language='".LANGUAGE."' AND" : "WHERE")." ".groupaccess('f.forum_access')."
AND f.forum_id='".intval($this->forum_info['forum_id'])."'
OR f.forum_cat='".intval($this->forum_info['forum_id'])."'
OR f.forum_branch='".intval($this->forum_info['forum_branch'])."'
ORDER BY forum_cat ASC");


See also …


References