11. Do not gzip output in your application , make apache do that
Thinking of using ob_gzhandler ? No dont do that. It doesnt make sense. Php is supposed to write your application. Dont worry about how to optimise data transfer between server and browser inside Php.
Use apache mod_gzip/mod_deflate to compress content via the .htaccess file.
12. Use json_encode when echoing javascript code from php
There are times when some javascript code is generated dynamically from php.
2 |
'myself.png' , 'friends.png' , 'colleagues.png' |
7 |
foreach($images as $image) |
9 |
$js_code .= "'$image' ,"; |
12 |
$js_code = 'var images = [' . $js_code . ']; '; |
Be smart. use json_encode :
2 |
'myself.png' , 'friends.png' , 'colleagues.png' |
5 |
$js_code = 'var images = ' . json_encode($images); |
Isn't that neat ?
13. Check if directory is writable before writing any files
Before writing or saving any file , make sure you check that the directory is writable or not , and flash an error message if it is not. This will save you a lot of "debugging" time. When you are working on a linux , permissions have to be dealt with and there would be many many permission issues when directories would not be writable , files would not be readable and so on.
Make sure that your application is as intelligent as possible and reports the most important information in the shortest time.
1 |
$contents = "All the content"; |
2 |
$file_path = "/var/www/project/content.txt"; |
4 |
file_put_contents($file_path , $contents); |
That is totally correct. But has some indirect problems. The file_put_contents may fail for a number of reasons :
- Parent directory does not exist
- Directory exists , but is not writable
- File locked for writing ?
So its better to make everything clear before writing out to a file.
1 |
$contents = "All the content"; |
2 |
$dir = '/var/www/project'; |
3 |
$file_path = $dir . "/content.txt"; |
7 |
file_put_contents($file_path , $contents); |
11 |
die("Directory $dir is not writable, or does not exist. Please check"); |
By doing this you get the accurate information that where is a file write failing and why
14. Change permission of files that your application creates
When working in linux environment , permission handling can waste a lot of your time. Hence whenever your php application creates some files do a chmod over them to ensure they are "accessible" outside. Otherwise for example the files may be created by "php" user and you are working as a different user and the system wont let you access or open the file , and then you have to struggle to get root privileges , change the permissions of the file and so on.
2 |
chmod("/somedir/somefile", 0644); |
5 |
chmod("/somedir/somefile", 0755); |
15. Don't check submit button value to check form submission
1 |
if($_POST['submit'] == 'Save') |
The above is mostly correct , except when your application is multi-lingual. Then the 'Save' can be many different things. How would you compare then. So do not rely on the value of submit button. Instead use this :
1 |
if( $_SERVER['REQUEST_METHOD'] == 'POST' and isset($_POST['submit']) ) |
Now you are free from the value the submit button
16. Use static variables in function where they always have same value
4 |
$sync_delay = get_option('sync_delay'); |
6 |
echo "<br />Delaying for $sync_delay seconds..."; |
Instead use static variables as :
4 |
static $sync_delay = null; |
6 |
if($sync_delay == null) |
8 |
$sync_delay = get_option('sync_delay'); |
11 |
echo "<br />Delaying for $sync_delay seconds..."; |
17. Don't use the $_SESSION variable directly
Some simple examples are :
1 |
$_SESSION['username'] = $username; |
2 |
$username = $_SESSION['username']; |
But this has a problem. If you are running multiple applications on the same domain , the session variables my conflict. 2 different applications may set the same key name in the session variable. Take for example , a frontend portal , and the backend management application , on the same domain.
Hence use application specific keys with wrapper functions :
1 |
define('APP_ID' , 'abc_corp_ecommerce'); |
4 |
function session_get($key) |
6 |
$k = APP_ID . '.' . $key; |
8 |
if(isset($_SESSION[$k])) |
17 |
function session_set($key , $value) |
19 |
$k = APP_ID . '.' . $key; |
20 |
$_SESSION[$k] = $value; |
18. Wrap utility helper functions into a class
So you have a lot of utility functions in a file like :
And you use the function throughout your application freely. You may want to wrap them into a class as static functions :
3 |
public static function utility_a() |
8 |
public static function utility_b() |
13 |
public static function utility_c() |
21 |
$a = Utility::utility_a(); |
22 |
$b = Utility::utility_b(); |
One clear benefit you get here is if php has inbuilt functions with similar names , then names will not conflict.
Another perspective , though little advanced is that you can maintain multiple versions of the same class in the same application without any conflict. Its basically encapsulation , nothing else.
19. Bunch of silly tips
20. Process arrays quickly with array_map
Lets say you want to trim all elements of an array. Newbies do it like this :
1 |
foreach($arr as $c => $v) |
But it can more cleaner with array_map :
1 |
$arr = array_map('trim' , $arr); |
This will apply trim on all elements of the array $arr. Another similar function is array_walk. Check out the
documentation on these to know more.
21. Validate data with php filters
Have you been using to regex to validate values like email , ip address etc. Yes everybody had been doing that. Now lets
try something different, called filters.
The php filter extension provides simple way to validate or check values as being a valid 'something'.
22. Force type checking
1 |
$amount = intval( $_GET['amount'] ); |
2 |
$rate = (int) $_GET['rate']; |
Its a good habit.
23. Write Php errors to file using set_error_handler()
set_error_handler() can be used to set a custom error handler. A good idea would be write some important errors in a file for logging purpose
24. Handle large arrays carefully
Large arrays or strings , if a variable is holding something very large in size then handle with care. Common mistake is to create a copy and then run out of memory and get a Fatal Error of Memory size exceeded :
1 |
$db_records_in_array_format; |
3 |
$cc = $db_records_in_array_format; |
The above thing is common when importing a csv file or exporting table to a csv file
Doing things like above can crashs scripts quite often due to memory limits. For small sized variables its not a problem , but must be avoided when handling large arrays.
Consider passing them by reference , or storing them in a class variable :
1 |
$a = get_large_array(); |
by doing this the same variable (and not its copy) will be available to the function. Check documentation
5 |
$this->a = get_large_array(); |
6 |
$this->pass_to_function(); |
9 |
function pass_to_function() |
unset them as soon as possible , so that memory is freed and rest of the script can relax.
Here is a simple demonstration of how assign by reference can save memory in some cases
3 |
ini_set('display_errors' , true); |
4 |
error_reporting(E_ALL); |
8 |
for($i = 0; $i < 100000 ; $i++) |
13 |
echo 'Memory usage in MB : '. memory_get_usage() / 1000000 . '<br />'; |
18 |
echo 'Memory usage in MB after 1st copy : '. memory_get_usage() / 1000000 . '<br />'; |
23 |
echo 'Memory usage in MB after 2st copy : '. memory_get_usage() / 1000000 . '<br />'; |
28 |
echo 'Memory usage in MB after 3st copy (reference) : '. memory_get_usage() / 1000000 . '<br />'; |
The output on a typical php 5.4 machine is :
Memory usage in MB : 18.08208
Memory usage in MB after 1st copy : 27.930944
Memory usage in MB after 2st copy : 37.779808
Memory usage in MB after 3st copy (reference) : 37.779864
So it can be seen that in the 3rd copy which was by reference memory was saved. Otherwise in all plain copies memory is used up more and more.
25. Use a single database connection, throughout the script
Make sure that you use a single connection to your database throughout your script. Open a connection right in the beginning and use it till the end , and close it at the end. Do not open connections inside functions like this :
4 |
$db->query("INSERT INTO cart ....."); |
10 |
$db->query("DELETE FROM cart ....."); |
Having multiple connections is a bad idea and moreover they slow down the execution since every connection takes time to create and uses more memory.
Use the singleton pattern for special cases like database connection.