PHP Best Practices

November 11, 2013

I deal with alot of different coders from all walks of life and man, have I seen some nasty code. Its really important when coding in a team that certain practices are followed so that the codebase takes on a readable and easier to work with format.

I apply these practices whenever I can and expect anyone working with/form me to do the same.


1. PHP OPEN TAGS

Never use shorthand or ASP style PHP start tags. Always use full PHP tags.

1
2
3
<?php echo $code ?> //correct
<? echo $code ?> //incorrect
<% echo $code %> //incorrect

2. NAMING CONVENTIONS FOR FILE NAMES

Use lowercase letters and hyphens to seperate the descriptive words in a file name. This method allows the file structure to be more easily readable.

1
2
3
my-new-file.php  CORRECT!
my_new_file.php INCORRECT!
mynewfile.php INCORRECT!

3. NAMING CONVENTIONS FOR VARIABLES

We never use camel case variable names and we always use underscores in order to make the variables easier to read. This allows variables to be almost self commenting.

1
2
3
$this_is_variable //correct
$ThisIsAVariable //incorrect
$This_Is_A_Variable //incorrect

4. SINGLE OR DOUBLE QUOTES

Use single and double quotes when appropriate. If you’re not evaluating anything in the string, use single quotes.

correct: ‘this is a string’
incorrect: “this is a string”


5. CLEVER CODING

In general, readability is more important than cleverness or brevity.

1
isset($var) || $var = some_function();

Although the above line is clever, it takes a while to understand if you’re not familiar with it.

So, just write it like this:

1
2
if(!isset($var))
$var = some_function();

6. COMMENTING CODE

In order for other coders to pick up the code easier rather than having to guess what each and every function does, its very important to put in php code comments. It does not have to be a life story but a few short comments telling what certain custom lines do is always a big help when troubleshooting code.

Here is a good example of commenting.

1
2
3
4
//check if the $var variable is set and if its available execute some_function()
//added by craig@123marbella.com on 24/12/2013
if(!isset($var))
$var = some_function();

7. AVOID NESTING USING EXCESSIVE IF AND ELSE

If you have a long piece of code that is dependant on various logic in order to continue to execute or exit then its better to split up the code into blocks and use logic parameters.

In the example below, we exit the script at the top of the page allowing us to easily trouble shoot each section of code.

1
2
3
4
56
7
8
9
1011
12
13
14
1516
17
18
19
20
function write_file_function() {
// ...
if (is_writable($folder)) {
    if ($fp = fopen($file_path,'w')) {
       if ($stuff = extractSomeStuff()) {         if (fwrite($fp,$stuff)) {
         // ...
         } else {
         return false;
         }      } else {
       return false;
     }
    } else {
     return false;    }
  } else {
   return false;
 }
}

Obviously, the code on the above is difficult to read and understand. To enhance the readability,it is always possible to reduce the level of nesting as follow:

1
2
3
4
56
7
8
9
1011
12
13
14
1516
17
18
19
2021
function write_file_function() {
 
 if (!is_writable($folder)) {
 return false;
 } 
 if (!$fp = fopen($file_path,'w')) {
 return false;
 }
  if (!$stuff = extractSomeStuff()) {
 return false;
 }
 
 if (fwrite($fp,$stuff)) { 
 } else {
 return false;
 }
 }

8. SETTING VARIABLES

If you are setting a variable then you need to leave a space either side of the = sign. This makes it easier to identify new variables within the code.

1
2
$var = 1; //correct
$var=1; //incorrect

9. NEVER HARD CODE ROOT DIRECTORY PATHS

When you are building an application its a bad idea to hard code a root directory path because if you move the application to a different server, the application path might be different resulting in the application breaking and you having to make manual changes to code.

1
2
3
4
56
7
8
9
10
//Never hard code file paths like this, its a bad idea
$path = "/home/some_user/public_html/includes/some_dir/";
 
//Get root path of the site on the server
$root = realpath($_SERVER["DOCUMENT_ROOT"]);$path = "$root";
#outputs /home/some_user/public_html/
 
$path = "$root/includes/some_dir/"
#outputs /home/some_user/public_html/includes/some_dir/

10. USE THE DRY APPROACH

DRY stands for Don’t Repeat Yourself, and it’s a valuable programming concept, no matter what the language. DRY programming, as the name implies, is ensuring that you don’t write redundant code.

This code:

1
2
3
4
56
7
8
9
1011
12
13
//embedded approach (incorrect)
$mysql = mysql_connect('localhost', 'some_user', 'secret_hash');
mysql_select_db('some_db') or die("cannot select DB");
 
//Now using DRY approach (correct) 
$db_host = 'localhost';
$db_user = 'some_user';
$db_password = 'secret_hash';
$db_database = 'some_db'; 
$mysql = mysql_connect($db_host, $db_user, $db_password);
mysql_select_db($db_database);

11. DO NOT TRUST THE USERS – PROTECT AGAINST SQL INJECTION

If you don’t escape your characters used in SQL strings, your code is vulnerable to SQL injections. You can avoid this by either using the mysql_real_escape_string, or by using prepared statements.

1
2
$username = mysql_real_escape_string( $GET['username'] ); //correct
$username = $GET['username']; //incorrect

12. PROTECT PHPINFO

The php info file is a very useful tool during development or troubleshooting process, however leaving it in a live location on a web server is a really bad idea. Use $_SERVER[‘REMOTE_ADDR’] to lock down the phpinfo file to your own ip address.

Here is how to lock down the phpinfo to your ip address.

1
2
3
if($_SERVER["REMOTE_ADDR"] == "255.255.255.255") {
 phpinfo();
}

If you have more than one user on the team and need to allow multiple ip’s then use the following code.

1
2
3
4
56
7
8
9
$allowed_ips = array(
"255.255.255.1", //my ip
"255.255.255.2", //my buddys ip
"255.255.255.3" //someone elses ip
"; 
if(in_array($_SERVER['REMOTE_ADDR'], $allowed_ips)){
   phpinfo();
}

13. PHP ERROR LOGGING

The php error log is an essential tool when developing applications as you can see through the logs any major issues that will cause your users any possible disruptions.

Firstly, you should define the location of your php error log and then lock down access to the log file so malicious users cannot see any details about possible vulnerabilities on your system.

Add the following lines to your root php.ini file.

1
2
log_errors = On
error_log = '{path_to_error_log}/PHP_errors.log'

After that you need to make sure no-one can view the file online so you need to lock it down through the .htaccess file like so:

1
2
3
4
56
7
8
9
######################################
# PREVENT PHP ERROR LOG FROM BEING READ (see php.ini)
# added by craig@craig-edmonds.com
######################################
<Files PHP_errors.log> Order allow,deny
 Deny from all
 Satisfy All
</Files>

14. SET TIMEZONE

Depending where the hosting server is located you should define the correct timezone for the application. For example, if the server is located in New York but the owner of the site is in London and they work on London time, then you should be setting the timezone to London otherwise any dates inserted through php, will be logged in New York time, which is not helpful for the client at all.

Simply add the following line to your php.ini file.

A full list of timezone formats can be obtained from http://php.net/manual/en/timezones.php

1
date.timezone = "Europe/London"

15. DONT HARD CODE URLS IN YOUR SOFTWARE MORE THAN ONCE

This is an extension of the DRY approach, but if a url (or setting) is to be used multiple times throughout an application, then avoid hardcoding the url.

Rather, use a “define” to define the url throughout the whole application. This way if something changes in the settings, then you do not need to go about changing it manually.

1
2
3
4
define("URL_NON_SSL", 'http://some-domain.com');
define("URL_WITH_SSL", 'https://some-domain.com');
 
echo URL_WITH_SSL //will output https://some-domain.com

16. DONT USE $_GET TO PASS HTML/MESSAGES TO YOUR PAGES

If you need to post a message on a thank you page, NEVER pass any text through the GET parameter. Its possible through Cross Site Scripting someone could inadvertently post html/links/malware to your web pages through a browser request.

1
2
3
4
56
7
8
9
//this is BAD
$message = $_GET['message'];
echo $message;
 
//this is BETTER$message = $_GET['message'];
if($message = 'thanks') {
  echo 'Thank you for filling in our form';
}
Tags: