36 Ways to improve PHP code quality

Source: Internet
Author: User

You will often see:

1
require_once ( '../../lib/some_class.php' );

There are many drawbacks to this approach:

It first finds the specified PHP include path, and then finds the current directory.

Therefore, too many paths are checked.

If the script is contained by a script in another directory, its base directory becomes the directory where another script resides.

Another problem is that when a timed task runs the script, its parent directory may not be a working directory.

So the best option is to use an absolute path:

1
2
3
4
define( 'ROOT' , '/var/www/project/' );
require_once (ROOT . '../../lib/some_class.php' );
//rest of the code

We have defined an absolute path, and the value is written dead. We can also improve it. Path/var/www/project may also change, so do we have to change it every time? No, we can use __file__ constants, such as:

1
2
3
4
5
6
7
//suppose your script is /var/www/project/index.php
//Then __FILE__ will always have that full path.
define( 'ROOT' , pathinfo ( __FILE__ , PATHINFO_DIRNAME));
require_once (ROOT . '../../lib/some_class.php' );
//rest of the code

Now, no matter which directory you move to, such as moving to an extranet server, the code can run correctly without changing it.

2. Do not use require directly, include, Include_once, required_once

You can introduce multiple files, such as class libraries, tool files, and helper functions, in the script header, such as:

1
2
3
require_once ( 'lib/Database.php' );
require_once ( 'lib/Mail.php' );
require_once ( 'helpers/utitlity_functions.php' );

This usage is quite primitive. should be more flexible. You should write an assistant function containing the file. For example:

1
2
3
4
5
6
7
8
9
function load_class( $class_name )
{
     //path to the class file
     $path = ROOT . '/lib/' . $class_name . '.php' );
     require_once ( $path );
}
load_class( 'Database' );
load_class( 'Mail' );

Is there anything different? The code is more readable.

? ⒗ irresolute green onion stable ┱ scale coal?? Such as:

1
2
3
4
5
6
7
8
9
10
function load_class( $class_name )
{
     //path to the class file
     $path = ROOT . '/lib/' . $class_name . '.php' );
     if ( file_exists ( $path ))
     {
         require_once ( $path );
     }
}

You can do more:

Find multiple directories for the same file

It's easy to change the directory where the class files are placed, without having to modify one by one of the code everywhere

You can use similar functions to load files, such as HTML content.

3. Keep Debug code for application

In the development environment, we print the database query statements, dump the variable values of the problem, and once the problem is resolved, we annotate or delete them. A better practice, however, is to keep the debug code.

In the development environment, you can:

1
2
3
4
5
6
7
8
9
10
11
12
13
define( 'ENVIRONMENT' , 'development' );
if (! $db ->query( $query )
{
     if (ENVIRONMENT == 'development' )
     {
         echo "$query failed" ;
     }
     else
     {
         echo "Database error. Please contact administrator" ;
     }
}

In the server, you can:

1
2
3
4
5
6
7
8
9
10
11
12
13
define( 'ENVIRONMENT' , 'production' );
if (! $db ->query( $query )
{
     if (ENVIRONMENT == 'development' )
     {
         echo "$query failed" ;
     }
     else
     {
         echo "Database error. Please contact administrator" ;
     }
}

4. Use Cross-platform functions to execute commands

System, exec, PassThru, shell_exec these 4 functions can be used to execute systems commands. Every action has a slight difference. The problem is that when in a shared host, some functions may be selectively disabled. Most beginners tend to check which function is available at a time, but use it again.

A better solution is to marshal the function into a cross-platform function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21st
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/**
     Method to execute a command in the terminal
     Uses :
     1. system
     2. passthru
     3. exec
     4. shell_exec
*/
function terminal( $command )
{
     //system
     if (function_exists( 'system' ))
     {
         ob_start();
         system( $command , $return_var );
         $output = ob_get_contents();
         ob_end_clean();
     }
     //passthru
     else if (function_exists( 'passthru' ))
     {
         ob_start();
         passthru ( $command , $return_var );
         $output = ob_get_contents();
         ob_end_clean();
     }
     //exec
     else if (function_exists( 'exec' ))
     {
         exec ( $command , $output , $return_var );
         $output = implode( "n" , $output );
     }
     //shell_exec
     else if (function_exists( 'shell_exec' ))
     {
         $output = shell_exec( $command ) ;
     }
     else
     {
         $output = 'Command execution not possible on this system' ;
         $return_var = 1;
     }
     return array ( 'output' => $output , 'status' => $return_var );
}
terminal( 'ls' );

The above function? ⒃ the hell command, which keeps the code consistent as long as a system function is available.

5. Flexible writing functions

1
2
3
4
5
6
function add_to_cart( $item_id , $qty )
{
     $_SESSION [ 'cart' ][ 'item_id' ] = $qty ;
}
add_to_cart( 'IPHONE3' , 2 );

Use the above function to add a single item. And when you add a list of items, do you want to create another function? No, just a little attention to the different types of parameters, you will be more flexible. Such as:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function add_to_cart( $item_id , $qty )
{
     if (! is_array ( $item_id ))
     {
         $_SESSION [ 'cart' ][ 'item_id' ] = $qty ;
     }
     else
     {
         foreach ( $item_id as $i_id => $qty )
         {
             $_SESSION [ 'cart' ][ 'i_id' ] = $qty ;
         }
     }
}
add_to_cart( 'IPHONE3' , 2 );
add_to_cart( array ( 'IPHONE3' => 2 , 'IPAD' => 5) );

Now, the same function can handle different types of input parameters. You can refactor your multiple code to make it smarter by referencing the example above.

6. Intentionally ignore PHP close tag

I'd like to know why so many blog posts about PHP recommendations do not mention this.

1
2
3
4
5
<?php
echo "Hello" ;
//Now dont close this tag

⒔ voluntarily send Su du fast sulphon ben? Let's give an example:
A super_class.php file

1
//super extra character after the closing tag

index.php

1
2
3
require_once ( 'super_class.php' );
//echo an image or pdf , or set the cookies or session data

In this way, you? ⒒ Cape Mei-jie-huan; Headers already send error. Why? Because   "Super extra character" has been exported. Now you have to start debugging. This will take a lot of time to find the location of  super extra.
Therefore, develop the habit of omitting the closing character:

1
2
3
div> 4
5
6
7
8
9
Ten
<!--? php
class Super_class
{
     function Super _function ()
     {
& nbsp;        //super code
      }
 
//no closing tag</pre-->

It would be better.

7. Collect all input at one place, output to browser at a time

This is called the output buffer, if you have already output the content in a different function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function print_header()
{
     echo "Site Log and Login links" ;
}
function print_footer()
{
     echo "Site was made by me" ;
}
print_header();
for ( $i = 0 ; $i ';
}
print_footer();

Alternative, where the output is collected centrally. You can store it in a local variable of a function, or you can use Ob_start and Ob_end_clean. As follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function print_header()
{
     $o = "Site Log and Login links" ;
     return $o ;
}
function print_footer()
{
     $o = "Site was made by me" ;
     return $o ;
}
echo print_header();
for ( $i = 0 ; $i ';
}
echo print_footer();

Why output buffering is required:
>> can change the output before sending it to the browser. such as the Str_replaces function or may be preg_replaces or add some monitoring/debugging HTML content.
>> output to the browser while doing PHP processing is very bad. You should have seen an error message in the sidebar or in the middle of some sites. Do you know why it happened? Because processing and output are mixed.

8. Send the correct MIME type header information if the output is not HTML content.

Output some XML.

1
2
3
4
5
6
$xml = '';
$xml = "0
";
//Send xml data
echo $xml;

Work well. But some improvements are needed.

1
2
3
4
5
6
7
$xml = '';
$xml = "0
";
//Send xml data
header("content-type: text/xml");
echo $xml;

Note Header line. The line tells the browser to send the content of the XML type. So the browser can handle it correctly. Many JavaScript libraries also rely on header information.
Similar to JavaScript, CSS, jpg image, PNG image:
Javascript

1
2
header("content-type: application/x-javascript");
echo "var a = 10";

Css

1
2
header( "content-type: text/css" );
echo "#div id { background:#000; }" ;

9. Set the correct character encoding for the MySQL connection

Have encountered in the MySQL table set unicode/utf-8 encoding, Phpadmin can also be displayed correctly, but when you get the content and output in the page, there will be garbled. Here's the problem with the character encoding of the MySQL connection.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//Attempt to connect to database
$c = mysqli_connect( $this ->host , $this ->username, $this ->password);
//Check connection validity
if (! $c
{
     die ( "Could not connect to the database host: " . mysqli_connect_error());
}
//Set the character set of the connection
if (!mysqli_set_charset ( $c , 'UTF8' ))
{
     die ( 'mysqli_set_charset() failed' );
}

Once the database is connected, it is best to set the characterset of the connection. If your application is to support multiple languages, it is necessary to do so.

10. Use Htmlentities to set the correct encoding options

Before php5.4, the character's default encoding is iso-8859-1 and cannot be directly output such as àa.

1
$value = htmlentities( $this ->value , ENT_QUOTES , CHARSET);

After php5.4, the default encoding is UTF-8, this? ⒔ 饩 龊 du waiter? But if your application is multilingual, still pay attention to coding problems.

11. Do not use gzip compression output in the application, let Apache processing

Have you considered using Ob_gzhandler? Don't do that. It doesn't make any sense. PHP applies only to write applications. You should not worry about server and browser data transfer optimization issues.
Use Apache's Mod_gzip/mod_deflate module to compress content.

12. Output dynamic JavaScript content using Json_encode

PHP is often used to output dynamic JavaScript content:

1
2
3
4
5
6
7
8
9
Ten
one
(
)
"
$images = Array (
  ' myself. PNG ' , ' friends.png ' , ' colleagues.png '
);
 
$js _code = " ;
 
foreach ($images as $image)
{
div> $js _code. = ' $image ', ' ';
}
 
$js _code = ' var images = [' /code> . $js _code. ']; ' ;
 
echo $js _code;
 
//output is var images = [' Myself.png ', ' friends.png ', ' colleagues.png ',];< /code>

Smarter way to use Json_encode:

1
2
3
4
5
6
7
8
9
$images = array (
  'myself.png' , 'friends.png' , 'colleagues.png'
);
$js_code = 'var images = ' . json_encode( $images );
echo $js_code ;
//Output is : var images = ["myself.png","friends.png","colleagues.png"]

Elegant?

13. Check directory Write permissions before writing files

Before you write or save the file, make sure that the directory is writable, if not writable, and output error messages. This will save you a lot of debugging time. Linux system, the need to process permissions, directory permissions will cause a lot of problems, files may not read and so on.
Make sure your application is smart enough to output some important information.

1
2
3
4
$contents = "All the content";
$file_path = "/var/www/project/content.txt";
file_put_contents($file_path , $contents);

This is generally true. But there are some indirect problems. File_put_contents may fail for several reasons:
>> Parent Directory does not exist
>> directory exists, but not writable
>> files are written and locked?
So it's better to make a clear check before writing a file.

1
2
3
4
5
6
7
8
9
10
11
12
$contents = "All the content";
$dir = '/var/www/project';
$file_path = $dir . "/content.txt";
if(is_writable($dir))
{
     file_put_contents($file_path , $contents);
}
else
{
     die("Directory $dir is not writable, or does not exist. Please check");
}

After doing so, you will get a clear message of where the file is written and why it failed.

14. Change file permissions created by application

In a Linux environment, permissions issues can waste you a lot of time. From now on, whenever you create some files, be sure to use chmod to set the correct permissions. Otherwise, it is possible that the file was first created by the "PHP" user, but you logged in to work with other users, the system? ⒒ rocks. You have to struggle to get root permissions, change file permissions, and so on.

1
2
3
4
5
// Read and write for owner, read for everybody else
chmod ( "/somedir/somefile" , 0644);
// Everything for owner, read and execute for others
chmod ( "/somedir/somefile" , 0755);

15. Do not rely on submit button values to check form submission behavior

1
2
3
4
if ( $_POST [ 'submit' ] == 'Save' )
{
     //Save the things
}

Most of the above is true, except that the application is multilingual. ' Save ' may represent other meanings. How do you tell them apart? Therefore, do not rely on the value of the Submit button.

1
2
3
4
if ( $_SERVER [ 'REQUEST_METHOD' ] == 'POST' and isset( $_POST [ 'submit' ]) )
{
     //Save the things
}

Now you are freed from the value of the Submit button.

16. Define a static variable for a variable that always has the same value within a function

1
2
3
4
5
6
7
8
9
//Delay for some time
function delay()
{
     $sync_delay = get_option( 'sync_delay' );
     echo "Delaying for $sync_delay seconds..." ;
     sleep( $sync_delay );
     echo "Done " ;
}

Replace with static variables:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//Delay for some time
function delay()
{
     static $sync_delay = null;
     if ( $sync_delay == null)
     {
     $sync_delay = get_option( 'sync_delay' );
     }
     echo "Delaying for $sync_delay seconds..." ;
     sleep( $sync_delay );
     echo "Done " ;
}

17. Do not use $_session variables directly

Some simple examples:

1
2
$_SESSION [ 'username' ] = $username ;
$username = $_SESSION [ 'username' ];

This can cause some problems. If multiple applications are running in the same domain name, the session variable may conflict. Two different applications may use the same session key. For example, a front-end portal, and a background management system using the same domain name.
From now on, use the application-related key and a wrapper function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21st
22
23
define( 'APP_ID' , 'abc_corp_ecommerce' );
//Function to get a session variable
function session_get( $key )
{
     $k = APP_ID . '.' . $key ;
     if (isset( $_SESSION [ $k ]))
     {
         return $_SESSION [ $k ];
     }
     return false;
}
//Function set the session variable
function session_set( $key , $value )
{
     $k = APP_ID . '.' . $key ;
     $_SESSION [ $k ] = $value ;
     return true;
}

18. ⒐ぞ yo?? Yu is chewing?/h3>

If you define a lot of tool functions in a file:

1
2
3
4
5
6
7
8
9
Ten
one
function utility_a()
{
     //This function does a utility thing like string processing
}
function utility_b()
{
     //This function does nother utility thing like database processing
}
function utility_c()
{
     //This function is ...
}

The use of these functions is dispersed throughout the application. You might want to ⑺ owe Yu dark richest the falcon?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21st
22
class Utility
{
     public static function utility_a()
     {
     }
     public static function utility_b()
     {
     }
     public static function utility_c()
     {
     }
}
//and call them as
$a = Utility::utility_a();
$b = Utility::utility_b();

The obvious benefit is that if you have a function with the same name in PHP, you can avoid conflicts.
Another view is that you can maintain multiple versions of the same class in the same application without causing conflicts. This is the basic benefit of encapsulation, without it.

Bunch of Silly tips

>> use echo instead of print
>> use Str_replace instead of preg_replace unless you absolutely need
>> do not use short tag
>> simple strings replace double quotes with single quotes
Remember to use exit after >>head redirection
>> do not call functions in loops
>>isset faster than strlen.
>> formatting code in the beginning
>> do not delete loops or if-else parentheses
Do not write code like this:

1
if ( $a == true) $a_count ++;

This is absolutely waste.
Written:

1
2
3
4
if ( $a == true)
{
     $a_count ++;
}

Do not attempt to omit some syntax to shorten the code. But to keep your logic short.
>> use a text editor with the highlighted syntax. Highlighting syntax can make you less wrong.

20. Using Array_map to quickly process arrays

For example, you want to trim all the elements in an array. Novice May:

1
2
3
4
foreach ( $arr as $c => $v )
{
     $arr [ $c ] = trim( $v );
}

But using Array_map is simpler:

1
$arr = array_map ( 'trim' , $arr );

This applies to call trim for each element of the $arr array. Another similar function is Array_walk. Consult your documentation for more tips.

21. Validating Data with PHP filter

You must have used regular expressions to validate emails, IP addresses, and so on. Yes, everyone uses it that way. Now, we want to do a different try, called filter.
The PHP Filter extension provides a simple way to validate and check input.

22. Mandatory type checking

1
2
$amount = intval ( $_GET [ 'amount' ] );
$rate = (int) $_GET [ 'rate' ];

It's a good habit.

23. If necessary, use profiler such as Xdebug

If you use PHP to develop a large application, PHP takes on a lot of computing, and speed is an important indicator. Use profile to help optimize your code. can be used
Xdebug and WebGrid.

24. Handle large arrays with care

For large arrays and strings, it must be handled with care. A common error occurs when an array copy causes a memory overflow and throws fatal error of Memory size information:

1
2
3
4
5
$db _records_in_array_format ; //this is a big array holding 1000 rows from a table each has a columns, every row is atleast bytes Tal 1000 = 2MB
 
$cc = $db _records_in_array_format ; //2MB more
 
some_function ( $cc ); //another 2MB?

This is often done when you import or export a CSV file.
Do not assume that the above code will often cause the script to crash due to memory limitations. Small variables are fine, but they must be avoided when dealing with large arrays.
Make sure that it is passed by reference or stored in a class variable:

1
2
$a = get_large_array();
pass_to_function(& $a );

After doing so, pass the variable reference to the function instead of the copy array. View the document.

1
2
3
4
5
6
7
8
9
10
11
12
13
class A
{
     function first()
     {
         $this ->a = get_large_array();
         $this ->pass_to_function();
     }
     function pass_to_function()
     {
         //process $this->a
     }
}

Unset them as soon as possible, so that the memory can be released, reduce the burden of the script.

25. Use a single database connection from beginning to end

Make sure that your scripts use a single database connection from beginning to end. Open the connection correctly at the beginning, use it until it ends, and close it at the end. Do not open the connection in the function as follows:

1
2
3
4
5
6
7
8
9
10
11
function add_to_cart ()
{
     $db = new Database ();
     $db ->query ( INSERT into C Art ... " );
}
 
function empty_cart ()
{
     $db = New Database ();
     $db ->query ( "DELETE from C Art ... " );
}

Using multiple connections is a bad thing, they slow down applications because it takes time and memory to create a connection.
Specific cases use a single case pattern, such as a database connection.

26. Avoid writing SQL directly, abstract

Patiently wrote too many of the following statements:

1
2
$query = "INSERT INTO users(name , email , address , phone) VALUES('$name' , '$email' , '$address' , '$phone')" ;
$db ->query( $query ); //call to mysqli_query()

This is not a plan to build a strong one. It has some disadvantages:
>> manually escape values each time
>> Verify that the query is correct
>> query errors can take a long time to identify (unless you use a if-else check every time)
>> difficult to maintain complex queries
So use function encapsulation:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function insert_record( $table_name , $data )
{
     foreach ( $data as $key => $value )
     {
     //mysqli_real_escape_string
         $data [ $key ] = $db ->mres( $value );
     }
     $fields = implode( ',' , array_keys ( $data ));
     $values = "'" . implode( "','" , array_values ( $data )) . "'" ;
     //Final query
     $query = "INSERT INTO {$table}($fields) VALUES($values)" ;
     return $db ->query( $query );
}
$data = array ( 'name' => $name , 'email' => $email , 'address' => $address , 'phone' => $phone );
insert_record( 'users' , $data );

Did you see it? This makes it easier to read and expand. The Record_data function handles the escape carefully.
The biggest advantage is that the data is preprocessed into an array, and any grammatical errors are captured.
The function should be defined in a database class, and you can call it like $db->insert_record.
Check out this article to see how it's easier to work with your database.
Similarly, you can write Update,select,delete methods. Give it a try.

27. ⑹? What a silly 谌莼 to defend Xian arrogant cai? /h3>

If all of the content is retrieved from the database, they should be cached. Once it's generated, ⑺ 4 favorite subjects Suwa. The next time the page is requested, it can be taken directly from the cache without having to check the database again.
Benefits:
>> save time for PHP to process pages and perform faster
>> fewer database queries mean less MySQL connection overhead

28. Save session in Database

There are many limitations to the file-based session strategy. Using a file-based session cannot be extended to the cluster because the session is saved on a single server. However, the database can be accessed by multiple servers, which resolves the problem.
There are additional benefits to saving session data in the database:
>> handle Username Repeat login problem. The same username cannot log in at the same time in two places.
>> can be more prepared to query online user status.

29. Avoid using global variables

>> Use Defines/constants
>> Get values using functions
>> use classes and access via $this

30. Use base label in head

Never heard of him? Please look below:

1
< img alt = "" src = "happy.jpg" />

Base tags are useful. Suppose your application is divided into subdirectories, and they all include the same navigation menu.

www.domain.com/store/home.php

www.domain.com/store/products/ipad.php

In the home page, you can write:

1
2
< a href = "home.php" >Home</ a >
< a href = "products/ipad.php" >Ipad</ a >

But in your ipad.php have to write:

1
2
< span style = "color:#333333;font-family:''Helvetica, Arial, sans-serif'';" >< a href = "../home.php" >Home</ a >
< a href = "ipad.php" >Ipad</ a ></ span >

Because the directory is not the same. There are so many different versions of the navigation menu to maintain, very bad AH.

Therefore, use the base label.

1
2
3
4
5
6
7
8
< span style = "color:#333333;font-family:''Helvetica, Arial, sans-serif'';" >< head >
< base href = "http://www.domain.com/store/" >
</ head >
< body >
< a href = "home.php" >Home</ a >
< a href = "products/ipad.php" >Ipad</ a >
</ body >
</ html ></ span >

Now, the code will behave in the same directory file as the application.

31. Never? Error_reporting set to 0

Turn off error reporting that is not a phase. It is important to e_fatal mistakes.

1
2
ini_set ( 'display_errors' , 1);
error_reporting (~E_WARNING & ~E_NOTICE & ~E_STRICT);

32. Note Platform Architecture

integers are different in length in 32-bit and 64-bit architectures. So some functions like the behavior of Strtotime will be different.

In a 64-bit machine, you will see the following output.

1
2
3
4
5
6
7
8
9
$ php -a
Interactive shell
php > echo strtotime ( "0000-00-00 00:00:00" );
-62170005200
php > echo strtotime ( '1000-01-30' );
-30607739600
php > echo strtotime ( '2100-01-30' );
4104930600

But in 32-bit machines, they are ⑹?ool (false).

33. Do not rely too much on set_time_limit

If you want to limit the minimum time, you can use the following script:

1
2
3
<span style= "color:#333333;font-family:''Helvetica, Arial, sans-serif'';" >set_time_limit(30);
//Rest of the code</span>

Do you have peace of mind? Note that any external execution, such as system calls, socket operations, database operations, and so on, is not under the control of Set_time_limits.

Therefore, even if the database spends a lot of time querying, the script will not stop executing. Depending on the situation.

34. Using an extension library

Some examples:

>>mpdf-can generate PDF documents via HTML

>>phpexcel-Read and write Excel

>>phpmailer-easy to handle sending messages containing nearby

>>pchart-use PHP to generate reports

use open source libraries to accomplish complex tasks, such as building PDFs, ms-excel files, reports, etc.

35. Using the MVC framework

It's time to use like CodeIgniter such an MVC framework. The MVC framework does not force you to write object-oriented code. They only?? HP code is separated from HTML.

>> clearly differentiate between PHP and HTML code. The benefits of teamwork are that designers and programmers can work together.

>> Object-oriented design functions to make it easier for you to maintain

>> built-in functions do a lot of work, you don't need to write it over and over again

>> development of large applications is necessary

>> Many suggestions, tips and hack have been implemented by the framework

36. Often look at Phpbench

Phpbench provides benchmark results for basic PHP operations that show how some of the small variations of the grammar can cause significant differences.

Check the PHP site comments, have questions to IRC questions, often read open source code, using Linux development.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

Tags Index: