Coding Guidelines
Coding Guidelines
Table of contents
1. Files
i. File Format
ii. Filename
2. Skeleton
3. PHP Tags
i. Open Tag
ii. Close Tag
iii. Open/Close Tag
iv. Short Open Tag
v. Short Echo Tag
4. End of File
5. Namespaces
i. Namespace Declaration
ii. Namespace Name
iii. Multiple Namespaces
iv. Magic Constant
6. Comments
i. Single-line Comments
ii. Multi-line Comments
iii. Header Comments
iv. Divider Comments
v. Comments
vi. Blocks of Code
vii. Ambiguous Numbers
viii.External Variables
7. Includes
i. Include/Require Once
ii. Parenthesis
iii. Purpose of Include
8. Formatting
i. Line Length
ii. Line Indentation
iii. Blank Lines
iv. Text Alignment
v. Trailing Whitespace
vi. Keywords
vii. Variables
viii.Global Variables
1
ix. Constants
x. Statements
xi. Operators
xii. Unary Operators
xiii.Concatenation Period
xiv.Single Quotes
xv. Double Quotes
9. Functions
i. Function Name
ii. Function Prefix
iii. Function Call
iv. Function Arguments
v. Function Declaration
vi. Function Return
10. Control Structures
i. If, Elseif, Else
ii. Switch, Case
iii. While, Do While
iv. For, Foreach
v. Try, Catch
11. Classes
i. Class File
ii. Class Namespace
iii. Class Name
iv. Class Documentation
v. Class Definition
vi. Class Properties
vii. Class Methods
viii.Class Instance
12. Best Practices
i. Variable Initialization
ii. Initialization/Declaration Order
iii. Globals
iv. Explicit Expressions
v. Good To Have
13. PHP Security
i. Cross-site scripting (XSS)
ii. SQL Injection Attacks
iii. Cross site request forgery XSRF/CSRF
iv. Session Hijacking
v. Hide Files from the Browser
2
vi. Securely Upload Files
vii. Log all Errors and Hide in Production
viii. Use URL encoding
ix. Avoid remote file inclusion
1. Files
This section describes the format and naming convention of PHP files.
File Format
Filename
2. Skeleton
This section showcases a barebones PHP file with its minimum requirements.
3
● Line 5: End-of-file comment
● Line 6: Blank line
<?php
// your code
// EOF
3. PHP Tags
This section describes the use of PHP tags in PHP and PHP/HTML files.
1. Open tag MUST be on its own line and MUST be followed by a blank line
○ i.e. <?php ↵ ↵ ...
2. Close tag MUST NOT be used in PHP files
○ i.e. no ?>
3. Open/close tag MUST be on one line in PHP/HTML files
○ i.e. <?php ... ?>
4. Short open tag MUST NOT be used
○ i.e. <? → <?php
5. Short echo tag SHOULD be used in PHP/HTML files
○ i.e. <?php echo → <?=
1. Open Tag
Open tag MUST be on its own line and MUST be followed by a blank line.
✖ Incorrect
<?php print_welcome_message();
<?php
print_welcome_message();
✔ Correct
<?php
4
print_welcome_message();
2. Close Tag
Close tag MUST NOT be used in PHP files.
✖ Incorrect
<?php
print_welcome_message();
?>
✔ Correct
<?php
print_welcome_message();
3. Open/Close Tag
Open/close tag MUST be on one line in PHP/HTML files.
✖ Incorrect
<div>
<h1><?php
print_welcome_message();
?></h1>
</div>
✔ Correct
<div>
<h1><?php print_welcome_message(); ?></h1>
</div>
5
✖ Incorrect
<?
print_welcome_message();
✔ Correct
<?php
print_welcome_message();
~ Acceptable
<div>
<p><?php echo get_welcome_message(); ?></p>
</div>
↳ Acceptable, but <?= should be used over <?php echo when possible.
✔ Preferred
<div>
<p><?= get_welcome_message(); ?></p>
</div>
4. End of File
This section describes how every PHP file must end.
End-of-file comment:
6
✖ Incorrect
<?php
print_welcome_message();
<?php
print_welcome_message(); // EOF
<?php
print_welcome_message();
// EOF
✔ Correct
<?php
print_welcome_message();
// EOF
5. Namespaces
This section describes how to use one or more namespaces and their naming
convention.
1. Namespace Declaration
7
Namespace declaration MUST be the first statement and MUST be followed by a
blank line.
✖ Incorrect
<?php
print_welcome_message();
namespace MyCompany;
// EOF
<?php
namespace MyCompany;
print_welcome_message();
// EOF
✔ Correct
<?php
namespace MyCompany;
print_welcome_message();
// EOF
2. Namespace Name
Namespace names MUST start with a capital letter and MUST be camelcase.
✖ Incorrect
<?php
namespace myCompany;
// EOF
8
↳ Incorrect because myCompany does not start with a capital letter.
<?php
namespace MyCOMPANY;
// EOF
✔ Correct
<?php
namespace MyCompany;
// EOF
3. Multiple Namespaces
Multiple namespaces MUST use the curly brace syntax.
✖ Incorrect
<?php
namespace MyCompany\Model;
namespace MyCompany\View;
// EOF
↳ Incorrect because there are two namespaces and the curly brace syntax was not
used.
✔ Correct
<?php
namespace MyCompany\Model {
// model body
}
namespace MyCompany\View {
// view body
}
9
// EOF
4. Magic Constant
Magic constant SHOULD be used to reference the namespace name.
~ Acceptable
<?php
namespace MyCompany\Model {
// model body
}
namespace MyCompany\View {
$welcome_message = MyCompany\View\get_welcome_message();
}
// EOF
✔ Preferred
<?php
namespace MyCompany\Model {
// ModuleOne body
}
namespace MyCompany\View {
$welcome_message = __NAMESPACE__ . '\\' . get_welcome_message();
}
// EOF
6. Comments
This section describes how comments should be formatted and used.
10
3. Header comments SHOULD use the block format
○ i.e. /** ↵ * Name of code section ↵ */
4. Divider comments SHOULD use the block format with asterisks in between
○ i.e. /** 75 asterisks */
5. Comments MUST be on their own line
○ i.e. ↵ // My comment
6. Blocks of code SHOULD be explained or summarised
○ e.g. // Compare user accounts from export against expired
accounts in system
7. Ambiguous numbers MUST be clarified
○ e.g. // 1,000 processable records per hour API limit
8. External variables MUST be clarified
○ e.g. // Database object included in file.php
1. Single-line Comments
Single-line comments MUST use two forward slashes.
✖ Incorrect
<?php
/* This is a comment */
// EOF
11
✔ Correct
<?php
// This is a comment
// EOF
2. Multi-line Comments
Multi-line comments MUST use the block format.
✖ Incorrect
<?php
// This is a
// multi-line
// comment
// EOF
✔ Correct
<?php
/**
* This is a
* multi-line
* comment
*/
// EOF
3. Header Comments
Header comments SHOULD use the block format.
<?php
/**
* Global application settings
*/
12
define('SETTING_ONE', '');
define('SETTING_TWO', '');
define('SETTING_THREE', '');
// EOF
4. Divider Comments
Divider comments SHOULD use the block format with 75 asterisks in between.
✖ Incorrect
<?php
/**#######################################################################*/
// EOF
<?php
/*************/
// EOF
✔ Correct
<?php
/**
* Beginning + Middle + End
* 3 stars + 75 stars + 2 slash = 80 character line limit
*/
/****************************************************************************
**/
// EOF
5. Comments
Comments MUST be on their own line.
13
✖ Incorrect
<?php
// EOF
✔ Correct
<?php
// EOF
6. Blocks of Code
Blocks of code SHOULD be explained or summarised.
~ Acceptable
<?php
// EOF
14
✔ Preferred
<?php
/**
* Get active website bloggers with profile photo for the author page.
* If no photo exists on the website, check intranet.
* If neither location has a photo, send a user email to upload one.
*/
foreach ($users as $user) {
if ($expr1) {
// ...
} else {
// ...
}
if ($expr2) {
// ...
} elseif ($expr3) {
// ...
} else {
// ...
}
// ...
}
// EOF
7. Ambiguous Numbers
Ambiguous numbers MUST be clarified.
✖ Incorrect
<?php
// EOF
✔ Correct
<?php
15
while ($expr && $x < 1000) {
// ...
}
// EOF
8. External Variables
External variables MUST be clarified.
✖ Incorrect
<?php
include_once 'some-file.php';
// ...
foreach($users as $user) {
// ...
}
// EOF
✔ Correct
<?php
include_once 'some-file.php';
// ...
// EOF
7. Includes
This section describes the format for including and requiring files.
16
○ i.e. include → include_once, require → require_once
2. Parenthesis MUST NOT be used
○ e.g. include_once('file.php'); → include_once 'file.php';
3. Purpose of include MUST be documented with a comment
○ e.g. // Provides WordPress environment ↵ require_once
'wp-load.php';
1. Include/Require Once
Include/require once SHOULD be used.
~ Acceptable
<?php
include 'some-file.php';
require 'some-other-file.php';
// EOF
✔ Preferred
<?php
include_once 'some-file.php';
require_once 'some-other-file.php';
// EOF
2. Parenthesis
Parenthesis MUST NOT be used.
✖ Incorrect
<?php
include_once('some-file.php');
require_once('some-other-file.php');
// EOF
17
↳ Incorrect because include_once and require_once are used with parenthesis.
✔ Correct
<?php
include_once 'some-file.php';
require_once 'some-other-file.php';
// EOF
3. Purpose of Include
Purpose of include MUST be documented with a comment.
✖ Incorrect
<?php
require_once 'some-file.php';
// EOF
✔ Correct
<?php
// EOF
8. Formatting
This section outlines various, general formatting rules related to whitespace and text.
18
○ i.e. ... ↵ ↵ ...
4. Text alignment MUST be accomplished using spaces
○ i.e. $var · · · = ...;
5. Trailing whitespace MUST NOT be present after statements or serial comma
break or on blank lines
○ i.e. no ... · · ↵ · ↵ ...
6. Keywords MUST be all lowercase
○ e.g. false, true, null, etc.
7. Variables MUST be all lowercase and words MUST be separated by an
underscore
○ e.g. $welcome_message
8. Global variables MUST be declared one variable per line and MUST be
indented after the first
○ e.g. global $var1, ↵ ⇥ $var2;
9. Constants MUST be all uppercase and words MUST be separated by an
underscore
○ e.g. WELCOME_MESSAGE
10. Statements MUST be placed on their own line and MUST end with a
semicolon
○ e.g. welcome_message();
11. Operators MUST be surrounded by a space
○ e.g. $total = 15 + 7;, $var .= '';
12. Unary operators MUST be attached to their variable or integer
○ e.g. $index++, --$index
13. Concatenation period MUST be surrounded by a space
○ e.g. echo 'Read:' . $welcome_message;
14. Single quotes MUST be used
○ e.g. echo 'Hello, World!';
15. Double quotes SHOULD NOT be used
○ e.g. echo "Read: $welcome_message"; → echo 'Read: ' .
$welcome_message;
1. Line Length
Line length MUST NOT exceed 80 characters, unless it is text.
✖ Incorrect
<?php
19
// EOF
<?php
// EOF
~ Acceptable
<?php
$text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec
posuere rutrum tincidunt. Duis lacinia laoreet diam, nec consectetur magna
facilisis eget. Quisque elit mauris, auctor quis vulputate id, sagittis nec
tortor. Praesent fringilla lorem eu massa convallis ultricies. Maecenas
lacinia porta purus, sollicitudin condimentum felis mollis a. Proin sed augue
purus. Quisque scelerisque eros vitae egestas porta. Suspendisse vitae purus
justo. Pellentesque justo nunc, luctus quis magna sit amet, venenatis rutrum
ante. Nam eget nisi ultricies, sodales lectus vel, luctus dui. Cras
pellentesque augue vitae nulla laoreet convallis. Mauris ut turpis mollis,
elementum arcu eu, semper risus. Mauris vel urna ut felis blandit dictum.
Aliquam sit amet tincidunt arcu. Nunc et elit quam. Aliquam hendrerit magna
ut lacus semper consequat blandit eu ipsum.';
// EOF
↳ Acceptable because line length was exceeded due to text, not code.
✔ Correct
<?php
$my_movies = array(
'Slumdog Millionaire',
'Silver Linings Playbook',
'The Lives of Others',
'The Shawshank Redemption'
);
$has_all_movies = true;
20
foreach($my_movies as $my_movie) {
if(!in_array($my_movie, $movies)) {
$has_all_movies = false;
}
}
if($has_all_movies) {
// if body
}
$some_long_variable = get_something_else(
'from_some_other_function',
'another_long_argument'
);
// EOF
2. Line Indentation
Line indentation MUST be accomplished using tabs.
✖ Incorrect
<?php
function print_welcome_message() {
echo WELCOME_MESSAGE;
}
// EOF
✔ Correct
<?php
function print_welcome_message() {
echo WELCOME_MESSAGE;
}
// EOF
3. Blank Lines
21
Blank lines SHOULD be added between logical blocks of code.
~ Acceptable
<?php
$my_movies = array(
'Slumdog Millionaire',
'Silver Linings Playbook',
'The Lives of Others',
'The Shawshank Redemption'
);
$has_all_movies = true;
foreach($my_movies as $my_movie) {
if(!in_array($my_movie, $movies)) {
$has_all_movies = false;
}
}
if($has_all_movies) {
// if body
}
// EOF
✔ Preferred
<?php
$my_movies = array(
'Slumdog Millionaire',
'Silver Linings Playbook',
'The Lives of Others',
'The Shawshank Redemption'
);
$has_all_movies = true;
foreach($my_movies as $my_movie) {
if(!in_array($my_movie, $movies)) {
$has_all_movies = false;
}
}
if($has_all_movies) {
// if body
}
// EOF
22
4. Text Alignment
Text alignment MUST be accomplished using spaces.
✖ Incorrect
<?php
$movie_quotes = array(
'slumdog_millionaire' => 'When somebody asks me a question, I
tell them the answer.',
'silver_linings_playbook' => 'I opened up to you, and you judged
me.',
'the_lives_of_others' => 'To think that people like you ruled
a country.',
'the_shawshank_redemption' => 'Get busy living, or get busy dying.'
);
// EOF
↳ Incorrect because tabs are used instead of spaces to vertically align =>.
<?php
$movie_quotes = array(
'slumdog_millionaire' => 'When somebody asks me a question, I tell
them the answer.',
'silver_linings_playbook' => 'I opened up to you, and you judged me.',
'the_lives_of_others' => 'To think that people like you ruled a
country.',
'the_shawshank_redemption' => 'Get busy living, or get busy dying.'
);
// EOF
↳ Incorrect because spaces are used instead of tabs to indent array keys.
✔ Correct
<?php
$movie_quotes = array(
'slumdog_millionaire' => 'When somebody asks me a question, I
tell them the answer.',
'silver_linings_playbook' => 'I opened up to you, and you judged
me.',
'the_lives_of_others' => 'To think that people like you ruled a
country.',
'the_shawshank_redemption' => 'Get busy living, or get busy dying.'
23
);
// EOF
5. Trailing Whitespace
Trailing whitespace MUST NOT be present after statements or serial comma break
or on blank lines.
✖ Incorrect
<?php
$quotes_exist = false;
print_welcome_message();
// EOF
<?php
$my_movies = array(
'Slumdog Millionaire',
'Silver Linings Playbook',
'The Lives of Others',
'The Shawshank Redemption'
);
// EOF
<?php
$quotes_exist = false;
print_welcome_message();
// EOF
↳ Incorrect because there are two spaces on the blank line below $quotes_exist =
false;.
24
✔ Correct
<?php
$quotes_exist = false;
print_welcome_message();
// EOF
<?php
$my_movies = array(
'Slumdog Millionaire',
'Silver Linings Playbook',
'The Lives of Others',
'The Shawshank Redemption'
);
// EOF
6. Keywords
Keywords MUST be all lowercase.
✖ Incorrect
<?php
$is_true = FALSE;
$is_false = TRUE:
$movie_quote = NULL;
// EOF
↳ Incorrect because FALSE, TRUE and NULL are not all lowercase.
✔ Correct
<?php
$is_true = false;
$is_false = true:
$movie_quote = null;
// EOF
25
7. Variables
Variables MUST be all lowercase and words MUST be separated by an underscore.
Or camel case.
✖ Incorrect
<?php
$welcome_Message = '';
$Welcome_Message = '';
$WELCOME_MESSAGE = '';
// EOF
<?php
$welcomemessage = '';
// EOF
✔ Correct
26
<?php
$welcomeMessage = '';
// or $welcome_message = '';
// EOF
8. Global Variables
Global variables MUST be declared one variable per line and MUST be indented
after the first.
✖ Incorrect
<?php
// EOF
<?php
global $app_config,
$cache,
$db_connection;
// EOF
✔ Correct
<?php
global $app_config,
$cache,
$db_connection;
// EOF
27
9. Constants
Constants MUST be all uppercase and words MUST be separated by an
underscore.
✖ Incorrect
<?php
define('welcome_Message', '');
define('Welcome_Message', '');
define('welcome_message', '');
// EOF
<?php
define('WELCOMEMESSAGE', '');
// EOF
↳ Incorrect because WELCOME and MESSAGE are not separated with an underscore.
✔ Correct
<?php
define('WELCOME_MESSAGE', '');
// EOF
10. Statements
Statements MUST be placed on their own line and MUST end with a semicolon.
✖ Incorrect
<?php
// EOF
28
↳ Incorrect because $quotes_exist = false; and print_welcome_message(); are on
one line.
<div>
<h1><?= print_welcome_message() ?></h1>
</div>
✔ Correct
<?php
$quotes_exist = false;
print_welcome_message();
// EOF
<div>
<h1><?= print_welcome_message() ?></h1>
</div>
11. Operators
Operators MUST be surrounded by space.
✖ Incorrect
<?php
$total=3+14;
$string='Hello, World! ';
$string.='Today is a good day!';
// EOF
✔ Correct
<?php
$total = 3 + 14;
$string = 'Hello, World! ';
29
$string .= 'Today is a good day!';
// EOF
✖ Incorrect
<?php
$index ++;
-- $index;
// EOF
✔ Correct
<?php
$index++;
--$index;
// EOF
✖ Incorrect
<?php
// EOF
✔ Correct
30
<?php
// EOF
✖ Incorrect
<?php
// EOF
✔ Correct
<?php
// EOF
~ Acceptable
<?php
// EOF
↳ Acceptable, but burries the $date variable, which is why single quotes are
preferred.
<?php
31
echo "Hello, World! He's watching movies and she's reading books.";
// EOF
↳ Acceptable when long pieces of text have apostrophies that would need to be
escaped.
✔ Preferred
<?php
echo 'Hello, World! He\'s watching movies and she\'s reading books.';
// EOF
9. Functions
This section describes the format for function names, calls, arguments and
declarations.
32
○ MUST then indent each argument once
○ MUST be ordered from required to optional first
○ MUST be ordered from high to low importance second
○ MUST use descriptive defaults
○ MUST use type hinting
○ e.g. func($arg1, $arg2 = 'asc', $arg3 = 100);
5. Function declaration MUST be documented using phpDocumentor tag style
and SHOULD include
○ Short description
○ Optional long description, if needed
○ @access: private or protected (assumed public)
○ @author: Author name
○ @global: Global variables function uses, if applicable
○ @param: Parameters with data type, variable name, and description
○ @return: Return data type, if applicable
6. Function return
○ MUST occur as early as possible
○ MUST be initialised prior at top
○ MUST be preceded by blank line, except inside control statement
○ i.e. if (!$expr) { return false; }
1. Function Name
Function names MUST be all lowercase and words MUST be separated by an
underscore.
✖ Incorrect
<?php
get_Welcome_Message();
Get_Welcome_Message();
GET_WELCOME_MESSAGE();
// EOF
<?php
getwelcomemessage();
// EOF
33
↳ Incorrect because get, welcome and message are not separated with an underscore.
✔ Correct
<?php
get_welcome_message();
// EOF
2. Function Prefix
Function prefix MUST start with a verb.
✖ Incorrect
<?php
active_users();
network_location($location1, $location2);
widget_form($id);
// EOF
✔ Correct
<?php
get_active_users();
move_network_location($location1, $location2);
delete_widget_form($id);
// EOF
3. Function Call
Function calls MUST NOT have a space between function name and open
parenthesis.
✖ Incorrect
<?php
34
print_welcome_message ();
// EOF
✔ Correct
<?php
print_welcome_message();
// EOF
4. Function Arguments
Function arguments:
✖ Incorrect
<?php
// EOF
<?php
my_function($arg1,$arg2,$arg3);
// EOF
35
↳ Incorrect because there is no space after ,.
<?php
my_other_function($arg1_with_a_really_long_name,
$arg2_also_has_a_long_name,
$arg3
);
// EOF
<?php
my_other_function(
$arg1_with_a_really_long_name,
$arg2_also_has_a_long_name,
$arg3
);
// EOF
<?php
// EOF
↳ Incorrect because $type, $order and $limit are not in order of required to optional.
<?php
// EOF
↳ Incorrect because $limit, $order and $type are not in order of importance.
<?php
36
// ...
}
// EOF
<?php
// EOF
↳ Incorrect because $users and $office are missing their data type.
✔ Correct
<?php
my_other_function(
$arg1_with_a_really_long_name,
$arg2_also_has_a_long_name,
$arg3
);
// EOF
5. Function Declaration
Function declaration MUST be documented using phpDocumentor tag style and
SHOULD include:
● Short description
● Optional long description, if needed
● @access: private or protected (assumed public)
37
● @author: Author name
● @global: Global variables function uses, if applicable
● @param: Parameters with data type, variable name, and description
● @return: Return data type, if applicable
✖ Incorrect
<?php
// EOF
✔ Correct
<?php
/**
* Get photo from blog author
*
* Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut id volutpat
* orci. Etiam pharetra eget turpis non ultrices. Pellentesque vitae risus
* sagittis, vehicula massa eget, tincidunt ligula.
*
* @access private
* @author Firstname Lastname
* @global object $post
* @param int $id Author ID
* @param string $type Type of photo
* @param int $width Photo width in px
* @param int $height Photo height in px
* @return object Photo
*/
function my_function($id, $type, $width, $height) {
// ...
return $Photo;
}
// EOF
6. Function Return
38
Function return:
✖ Incorrect
<?php
function get_object() {
$var = false;
if($expr1) {
// ...
if($expr2) {
// ...
}
}
return $var;
}
// EOF
<?php
function get_movies() {
// ...
return $movies;
}
// EOF
<?php
function get_movies() {
$movies = array();
// ...
return $movies;
}
// EOF
39
↳ Incorrect because return $movies is not preceded by blank line.
✔ Correct
<?php
function get_object() {
$var = false;
if (!$expr1) {
return $var;
}
if (!$expr2) {
return $var;
}
// ...
return $var;
}
// EOF
<?php
function get_movies() {
$movies = array();
// ...
return $movies;
}
// EOF
40
○ e.g. $expr) {, $i++) {
● Structure body MUST be indented once and MUST be enclosed with curly
braces (no shorthand)
○ e.g. if ($expr) { ↵ ⇥ ... ↵ }
● Closing brace MUST start on the next line
○ i.e. ... ↵ }
● Nesting MUST NOT exceed three levels
○ e.g. no if ($expr1) { if ($expr2) { if ($expr3) { if ($expr4) {
... }}}}
In addition to the rules above, some control structures have additional requirements:
✖ Incorrect
<?php
if ($expr1) {
// if body
} else if ($expr2) {
// elseif body
} else {
// else body
}
41
// EOF
<?php
if ($expr1) {
// if body
}
elseif ($expr2) {
// elseif body
}
else {
// else body
}
// EOF
↳ Incorrect because elseif and else are not between } and { on one line.
<?php
if($expr2)
$result2 = true;
// EOF
✔ Correct
<?php
if ($expr1) {
// if body
} elseif ($expr2) {
// elseif body
} else {
// else body
}
if ($expr1) {
$result1 = true;
} else {
$result1 = false;
42
}
if ($expr2) {
$result2 = true;
}
// EOF
2. Switch, Case
● Case statement MUST be indented once
● Case body MUST be indented twice
● Break keyword MUST be indented twice
● Case logic MUST be separated by one blank line
✖ Incorrect
<?php
switch ($expr) {
case 0:
echo 'First case, with a break';
break;
case 1:
echo 'Second case, which falls through';
// no break
case 2:
case 3:
case 4:
echo 'Third case, return instead of break';
return;
default:
echo 'Default case';
break;
}
// EOF
<?php
switch ($expr) {
case 0:
echo 'First case, with a break';
break;
43
case 1:
echo 'Second case, which falls through';
// no break
case 2:
case 3:
case 4:
echo 'Third case, return instead of break';
return;
default:
echo 'Default case';
break;
}
// EOF
↳ Incorrect because echo, break and return are not indented twice.
<?php
switch ($expr) {
case 0:
echo 'First case, with a break';
break;
case 1:
echo 'Second case, which falls through';
// no break
case 2:
case 3:
case 4:
echo 'Third case, return instead of break';
return;
default:
echo 'Default case';
break;
}
// EOF
↳ Incorrect because case 0, case 1 thru case 4, and default are not separated by
one blank line.
✔ Correct
<?php
switch ($expr) {
case 0:
echo 'First case, with a break';
44
break;
case 1:
echo 'Second case, which falls through';
// no break
case 2:
case 3:
case 4:
echo 'Third case, return instead of break';
return;
default:
echo 'Default case';
break;
}
// EOF
3. While, Do While
✔ Correct
<?php
while ($expr) {
// structure body
}
do {
// structure body;
} while ($expr);
// EOF
4. For, Foreach
✔ Correct
<?php
45
// EOF
5. Try, Catch
✖ Incorrect
<?php
try {
// try body
}
catch (FirstExceptionType $e) {
// catch body
}
catch (OtherExceptionType $e) {
// catch body
}
// EOF
✔ Correct
<?php
try {
// try body
} catch (FirstExceptionType $e) {
// catch body
} catch (OtherExceptionType $e) {
// catch body
}
// EOF
11. Classes
This section describes class files, names, definitions, properties, methods and
instantiation.
1. Class file MUST only contain one definition and MUST be prefixed with class-
○ i.e. class User → class-user.php, class Office → class-office.php
2. Class namespace MUST be defined and MUST include vendor name
46
○ e.g. namespace MyCompany\Model;, namespace MyCompany\View;,
namespace MyCompany\Controller;
3. Class name MUST start with a capital letter and MUST be upper camelcase
○ e.g. MyCompany
4. Class documentation MUST be present and MUST use phpDocumentor tag
style
○ i.e. @author, @global, @package
5. Class definition MUST place curly braces on their own line
○ i.e. class User ↵ { ↵ ... ↵ }
6. Class properties
○ MUST follow variable standards
○ MUST specify visibility
○ MUST NOT be prefixed with an underscore if private or protected
○ e.g. $var1;, private $var2;, protected $var3;
7. Class methods
○ MUST follow function standards
○ MUST specify visibility
○ MUST NOT be prefixed with an underscore if private or protected
○ e.g. func1(), private func2(), protected func3()
8. Class instance
○ MUST start with capital letter
○ MUST be camelcase
○ MUST include parenthesis
○ e.g. $user = new User();, $OfficeProgram = new OfficeProgram();
1. Class File
Class file MUST only contain one definition and MUST be prefixed with class-.
✖ Incorrect
Filename: class-user.php
<?php
namespace MyCompany\Model;
class User
{
// ...
}
class Office
{
// ...
}
47
// EOF
Filename: user.php
<?php
namespace MyCompany\Model;
class User
{
// ...
}
// EOF
✔ Correct
Filename: class-user.php
<?php
namespace MyCompany\Model;
class User
{
// ...
}
// EOF
Filename: class-office.php
<?php
namespace MyCompany\Model;
class Office
{
// ...
}
// EOF
48
2. Class Namespace
Class namespace MUST be defined and MUST include vendor name.
✖ Incorrect
<?php
class User
{
// ...
}
// EOF
<?php
namespace Model;
class User
{
// ...
}
// EOF
✔ Correct
<?php
namespace MyCompany\Model;
class User
{
// ...
}
// EOF
3. Class Name
Class names MUST start with a capital letter and MUST be camelcase.
49
✖ Incorrect
<?php
namespace MyCompany\Model;
class officeProgram
{
// ...
}
// EOF
<?php
namespace MyCompany\Model;
class Officeprogram
{
// ...
}
// EOF
✔ Correct
<?php
namespace MyCompany\Model;
class OfficeProgram
{
// ...
}
// EOF
4. Class Documentation
Class documentation MUST be present and MUST use phpDocumentor tag style.
✖ Incorrect
50
<?php
namespace MyCompany\Model;
class User
{
// ...
}
// EOF
<?php
namespace MyCompany\View;
/**
* User View
*/
class User
{
// ...
}
// EOF
✔ Correct
<?php
namespace MyCompany\View;
/**
* User View
*
* @author Firstname Lastname
* @global object $post
* @package MyCompany\API
*/
class User
{
// ...
}
// EOF
51
5. Class Definition
Class definition MUST place curly braces on their own line.
✖ Incorrect
<?php
namespace MyCompany\Model;
class User {
// ...
}
// EOF
✔ Correct
<?php
namespace MyCompany\Model;
class User
{
// ...
}
// EOF
6. Class Properties
Class properties:
✖ Incorrect
<?php
namespace MyCompany\Model;
class User
{
52
// Public
$var1;
// Protected
$var2;
// Private
$var3;
}
// EOF
↳ Incorrect because visibility is not specified for $var1, $var2 and $var3.
<?php
namespace MyCompany\Model;
class User
{
public $var1;
protected $_var2;
private $_var3;
}
// EOF
✔ Correct
<?php
namespace MyCompany\Model;
class User
{
public $var1;
protected $var2;
private $var3;
}
// EOF
7. Class Methods
Class methods:
53
● MUST follow function standards
● MUST specify visibility
● MUST NOT be prefixed with an underscore if private or protected
✖ Incorrect
<?php
namespace MyCompany\Model;
class User
{
// ...
// Public
function get_var1() {
return $this->var1;
}
// Protected
function get_var2() {
return $this->var2;
}
// Private
function get_var3() {
return $this->var3;
}
}
// EOF
<?php
namespace MyCompany\Model;
class User
{
// ...
54
private function _get_var3() {
return $this->var3;
}
}
// EOF
✔ Correct
<?php
namespace MyCompany\Model;
class User
{
// ...
// EOF
8. Class Instance
Class instance:
✖ Incorrect
<?php
55
$OfficeProgram = new OfficeProgram;
// EOF
✔ Correct
<?php
// EOF
1. Variable Initialization
Variable initialization SHOULD occur prior to use and SHOULD occur early.
~ Acceptable
<?php
$movies = get_movies();
// EOF
56
↳ Acceptable, but $movies should be initialised prior to use.
<?php
if ($expr) {
// ....
}
$movies = array();
$movies = get_movies();
// EOF
✔ Preferred
<?php
$movies = array();
if ($expr) {
// ....
}
$movies = get_movies();
// EOF
2. Initialization/Declaration Order
Initialization/declaration order:
● MUST lead with globals, follow with constants, conclude with local variables
● MUST lead with properties and follow with methods in classes
● MUST lead with public, follow with protected, conclude with private methods
in classes
● SHOULD be alphabetical within their type
✖ Incorrect
<?php
define('ENVIRONMENT', 'PRODUCTION');
57
$id = 0;
global $app_config;
// EOF
↳ Incorrect because $app_config is not first, ENVIRONMENT not second, and $id not
third.
<?php
namespace MyCompany\Model;
class Office
{
public function get_name() {
// ...
}
private $name;
}
// EOF
<?php
namespace MyCompany\Model;
class Office
{
private $id;
private $name;
private $status;
// EOF
58
↳ Incorrect because get_id() is not first, get_status() not second, and get_name()
not third.
~ Acceptable
<?php
global $db_connection,
$app_config,
$cache;
define('MODE', 1);
define('ENVIRONMENT', 'PRODUCTION');
$id = 0;
$firstname = '';
$lastname = '';
// EOF
<?php
function get_movies() {
// ...
}
function get_actors() {
// ...
}
// EOF
✔ Correct
<?php
global $app_config,
$cache,
$db_connection;
define('ENVIRONMENT', 'PRODUCTION');
define('MODE', 1);
59
$id = 0;
$firstname = '';
$lastname = '';
// EOF
<?php
namespace MyCompany\Model;
class Office
{
private $id;
private $name;
private $status;
// EOF
✔ Preferred
<?php
function get_actors() {
// ...
}
function get_movies() {
// ...
}
// EOF
3. Globals
Globals SHOULD NOT be used.
60
~ Acceptable
<?php
function get_user($id) {
global $pdo;
// ...
}
// EOF
✔ Preferred
<?php
function get_database_object() {
return new PDO('mysql:host=localhost;dbname=test', $user, $pass);
}
function get_user($id) {
$pdo = get_database_object();
// ...
}
// EOF
4. Explicit Expressions
Explicit expressions SHOULD be used.
~ Acceptable
<?php
if ($expr == true) {
// ...
}
// EOF
✔ Preferred
61
<?php
// EOF
5. Good to have
✔ Correct
● Controller must not IDEALLY and CONCEPTUALLY contain any database
queries. If you have some queries in the controller itself then it will take away
some key advantages of the MVC architecture such as Code Segregation and so
on.
● Ideally your Model Classes (M) must contain DB queries and any interactions
with DB via DB objects. A model ideally represents a Table in the DB or a file
used for io
● Views (V) must contain HTML with very little PHP. In most conditions only loops
and conditional statements are used
● Controller Classes (C) must contain all the business logic of your application,
error handlers and so on.
62
URL: http://example.com/search.php?search=<script>alert('test')</script>
You can figure out this attack by using htmlspecialchars. Also by using
ENT_QUOTES, you can escape single and double quotes.
Meanwhile, XSS attacks can also execute via attributes, encoded URI schemes and
code encoding.
The $username can contain altered data which can damage the database including
deleting the whole database in the blink of an eye. So, what’s the solution? PDO. I
recommend that you always use prepared statements. PDO helps you in securing
SQL queries.
The connection between the database and application is made with the below
statement:
63
You can select a username based on the above ID but wait! Here SQL code ‘GET
data’ gets injected in your query. Be careful to avoid such coding and use prepared
statements instead:
$row['email']);
Now you can avoid the above SQL injection possibility by using
$users = $sth->fetchAll();
Also, a good practice is to use ORM like doctrine or eloquent, as there is the least
possibility of injecting SQL queries in them. Read more on Documentation
Prevention is better than cure. You must take the following precautions as these are
the best ways to prevent SQL injection in php:
● To avoid SQL injections, user input should be authenticated for a definite set
of rules for syntax, type, and length.
● While giving administrative rights to the database to particular users, try to
give the least rights in order to avoid any future attacks on sensitive data.
● If a user is given rights for a specific application, make sure that he does not
access the application unnecessarily.
● Removing unused stored procedures may also help in the prevention of SQL
injections.
● Be careful when using stored procedures as they are easily exploited.
64
3. Cross site request forgery XSRF/CSRF
The CSRF attack is quite different to XSS attacks. In a CSRF attack, the end user
can perform unwanted actions on the authenticated websites and can transfer
malicious commands to the site to execute any undesirable action. CSRF can’t read
the request data and mostly targets the state changing request by sending any link
or altered data in HTML tags. It can force the user to perform state changing
requests like transferring funds, changing their email addresses etc. Let’s see this
URL in which GET requests is sending money to another account:
Now if someone wants to exploit the web application he/she will change the URL
with name and amount like this
http://bank.com/transfer.do?acct=Sandy&amount=100000
Now this URL can be sent via email in any file, Image etc and the attacker might ask
you to download the
file or click on the image. And as soon as you do that, you instantly end up with
sending a huge amount of money you never knew about.
4. Session Hijacking
Session hijacking is a particular type of malicious web attack in which the attacker
secretly steals the session ID of the user. That session ID is sent to the server where
the associated $_SESSION array validates its storage in the stack and grants
access to the application. Session hijacking is possible through an XSS attack or
when someone gains access to the folder on a server where the session data is
stored.
Watch for it when working on localhost as it doesn’t provide you the exact IP but :::1
or :::127 type values. You should invalidate (unset cookie, unset session storage,
65
remove traces) sessions quickly whenever a violation occurs and should always try
not to expose IDs under any circumstances.
For cookies, the best practice is to never use serialize data stored in a cookie.
Hackers can manipulate cookies easily, resulting in adding variables to your scope.
Safely delete the cookies like this:
unset($_COOKIE[$name]);
The first line of the code ensures that the cookie expires in the browser, the second
line depicts the standard way of removing a cookie (thus you can’t store false in a
cookie). The third line removes the cookie from your script.
If you have used micro-frameworks of PHP, then you must have seen the specific
directory structure which ensures the placement of files properly. Frameworks allow
to have different files like controllers, models, configuration file(.env) etc in that
directory, but most of the time the browser doesn’t process all the files, yet they are
available to see in the browser. To resolve this issue, you must not place your files in
the root directory but in a public folder so that they are not accessible all the time in
the browser.
File uploading is a necessary part of any user data processing application. But
remember at some points, files are also used for XSS attacks as I have already
explained above in the article. Returning to the basics, always use the POST request
in the form and declare the property enctype=”multipart/form-data” in <form> tag.
Then validate the file type using finfo class like this:
$fileContents = file_get_contents($_FILES['some_name']['tmp_name']);
66
$mimeType = $finfo->buffer($fileContents);
Developers can create their own custom and ultra-secure file validation rules, but
some frameworks like Laravel, Symfony and codeigniter already have pre-defined
methods to validate file types.
Let’s look at another example. The HTML of form should be like this:
<input type="submit">
</form>
if ($error == UPLOAD_ERR_OK) {
$tmpName = $_FILES['pictures']['tmp_name'][$key];
$name = basename($_FILES['pictures']['name'][$key]);
move_uploaded_file($tmpName, "/var/www/project/uploads/$name");
67
Once you have developed the website and deployed it on live server. The first thing
you must do is disable the display of errors, because hackers might get the same
valuable information from the errors. Set this parameter in your php.ini file:
display_errors=Off
Now, after making display off, log PHP errors to a specific file for future needs:
log_errors=On
error_log=/var/log/httpd/php_scripts_error.log
PHP gives developers the urlencode function to safely generate valid URLs.
According to the PHP documentation, the function is convenient when encoding a
string to be used in a query part of a URL.
Imagine that user input is used for generating a URL. In that case, you can use the
urlencode function to generate a safe URL.
<?php
?>
Example:
68
✖ Incorrect
https://www.beatoapp.com/user/63535
✔ Correct
https://www.beatoapp.com/user/hgdgfj253426
Never accept user input for requiring a file. The example below shows a required
statement that uses user-generated input and enables remote file inclusion.
✖ Incorrect
<?php
$page = $_GET['location']
require($page . ".php");
?>
In this case, a user can input a malicious path such as ../../../etc/passwd and display
the contents of the passwd file on a Linux/Unix server. Therefore, never accept user
input for requiring a page. If you still want to accept user input for opening a file,
make sure to validate the user input.
Note: The open_basedir function allows you to limit the files that PHP can access in
your filesystem. If you set the open_basedir function to the root of your project, this
means it can only access files in the root of your project and downward.
In case a malicious user gains access to your server via PHP and tries to access
sensitive files such as /etc/passwd, the open_basedir function will prevent this.
69
For example, if the input matches home, you navigate the user to the homepage.
See the example below, which illustrates a conditional switch for navigating the user.
If the page doesn’t exist, we show an error page.
✔ Correct
<?php
$page = $_POST['page'];
if ($page == "home") {
require("./pages/home.php");
} elseif ($page == "contact") {
require("./pages/contact.php");
} else {
require("./pages/error.php");
}
?>
70