36 Counts of improving PHP code quality

Source: Internet
Author: User
Tags closing tag

1. Do not use relative paths

Often you will see:

Require_once ('.. /.. /lib/some_class.php ');

There are many drawbacks to this approach:

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

Therefore, too many paths are checked.

If the script is included in a script from another directory, its base directory becomes the directory where the other script resides.

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

So the best option is to use absolute paths:

Define (' root ', '/var/www/project/'); require_once (Root. '.. /.. /lib/some_class.php ');//rest of the Code

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

Suppose your script Is/var/www/project/index.php//then __file__ 'll always has that full path.define (' ROOT ', Pathinf O (__file__, pathinfo_dirname)); Require_once (ROOT. '.. /.. /lib/some_class.php ');//rest of the Code

Now, no matter which directory you move to, such as a server that is moved to an extranet, the code will run correctly without changes.

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

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

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 that contains the file. For example:

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.

You can expand the function as needed, such as:

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 also do more:

Find multiple directories for the same file

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

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

3. Keep Debug code for your app

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

In the development environment, you can:

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:

Define (' environment ', ' production '); if (! $db->query ($query) {    if (environment = = ' development ')    {        echo "$query failed";    }    else    {        echo "Database error. Please contact administrator ";    }}

4. Execute commands using a function that can be cross-platform

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

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

/**method to execute a command in the terminaluses:1. System2. Passthru3. Exec4. Shell_exec*/function Terminal ($command) {//systemif (function_exists (' system ')) {Ob_start (); System ($command, $ Return_var); $output = Ob_get_contents (); Ob_end_clean ();} Passthruelse if (function_exists (' PassThru ')) {Ob_start ();p assthru ($command, $return _var); $output = ob_get_ Contents (); Ob_end_clean ();} Execelse if (function_exists (' exec ')) {exec ($command, $output, $return _var); $output = Implode ("n", $output);} Shell_execelse if (function_exists (' shell_exec ')) {$output = Shell_exec ($command);} else{$output = ' Command execution not possible on the this system '; $return _var = 1;} Return array (' output ' = $output, ' status ' = ' $return _var);} Terminal (' ls ');

The above function will run the shell command, as long as a system function is available, which preserves the consistency of the code.

5. Flexible writing functions

function Add_to_cart ($item _id, $qty) {    $_session[' cart ' [' item_id '] = $qty;} Add_to_cart (' IPHONE3 ', 2);

Use the function above 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, it will be more flexible. Such as:

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 ignoring the PHP close tag

I'd like to know why so many blog posts about PHP suggestions don't mention this.

     

This will save you a lot of time. Let's give an example: a super_class.php file

Super extra character after the closing tag

index.php

Require_once (' super_class.php ');//echo an image or PDF, or set the cookie or session data

This way, you will get a Headers already send error. Why? Because "super extra character" has been output. 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:

 
   

That would be better.

7. Collect all inputs in one place, one output to the browser

This is called output buffering, if you have output content in a different function:

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, collect the output centrally in a place. You can store them in local variables of a function, or you can use Ob_start and Ob_end_clean. As follows:

function Print_header () {    $o = "Site Log and Login links";    return $o;} function Print_footer () {    $o = "Site is 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 it is sent 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 some of the site's sidebar or the middle of an error message. Do you know why it happened? Because processing and output are mixed.

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

Output some XML.

$xml = "; $xml =" 0 ";//send xml Dataecho $xml;

Work well. But some improvements are needed.

$xml = "; $xml =" 0 ";//send xml Dataheader (" Content-type:text/xml "); Echo $xml;

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

Header ("Content-type:application/x-javascript"); echo "var a = 10";

Css

Header ("Content-type:text/css"), echo "#div ID {background: #000;}";

9. Set the correct character encoding for MySQL connection

Once encountered in the MySQL table set unicode/utf-8 encoding, Phpadmin can also be displayed correctly, but when you get the content and in the output of the page, there will be garbled. The problem here is the character encoding of the MySQL connection.

Attempt to connect to Database$c = Mysqli_connect ($this->host, $this->username, $this->password);//check Connection Validityif (! $c) {die ("Could does connect to the database host:". Mysqli_connect_error ());} Set the character set of the Connectionif (!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 app supports multiple languages, this is a must.

10. Set the correct encoding options using htmlentities

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

$value = Htmlentities ($this->value, ent_quotes, CHARSET);

After php5.4, the default encoding is UTF-8, which solves many problems. But if your app is multilingual, keep an eye out for coding issues.

11. Do not use gzip compression output in your app to allow Apache to process

Have you considered using Ob_gzhandler? Don't do that. There is no point. PHP only applies to writing apps. You should not worry about server and browser data transfer optimization issues. Use Apache's Mod_gzip/mod_deflate module to compress content.

12. Using Json_encode to output dynamic JavaScript content

You can often use PHP to output dynamic JavaScript content:

$images = Array (' Myself.png ', ' friends.png ', ' colleagues.png '), $js _code = '; foreach ($images as $image) {$js _code. = "' $ Image ', ';} $js _code = ' var images = ['. $js _code. ']; '; Echo $js _code;//output is var images = [' Myself.png ', ' friends.png ', ' colleagues.png ',];

Smarter way to use Json_encode:

$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 the directory Write permission before writing the file

Before writing or saving the file, make sure the directory is writable, and if it is not writable, output the error message. This will save you a lot of debugging time. Linux system, the need to deal with permissions, directory permissions can cause a lot of problems, files may not be read and so on. Make sure your app is smart enough to output some important information.

$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:>> the parent directory does not exist >> directory exists, but cannot write >> file is written locked? So it's better to do a clear check before writing a file.

$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 are 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 the file permissions created by the app

In a Linux environment, permissions issues can be a waste of your time. Henceforth, whenever you create some files, be sure to use chmod to set the correct permissions. Otherwise, the file may be created first by "PHP" users, but you use other users to log on to work, the system will be denied access or open the file, you have to struggle to get root permissions, change the permissions of the file and so on.

Read and write for owner, read for everybody Elsechmod ("/somedir/somefile", 0644);//Everything for owner, read and EXE Cute for Otherschmod ("/somedir/somefile", 0755);

15. Do not rely on the Submit button value to check the form submission behavior

if ($_post[' submit '] = = ' Save ') {    //save the things}

Most of the above are correct, 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.

if ($_server[' request_method ') = = ' POST ' and isset ($_post[' submit ')) {    //save the things}

Now you're free from the value of the Submit button.

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

Delay for some timefunction delay () {    $sync _delay = get_option (' Sync_delay ');    echo "Delaying for $sync _delay seconds ...";    Sleep ($sync _delay);    echo "Done";}

Replace with static variables:

Delay for some timefunction 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 the $_session variable directly

Some simple examples:

$_session[' username ' = $username; $username = $_session[' username '];

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

Define (' app_id ', ' Abc_corp_ecommerce ');//function to get a session variablefunction Session_get ($key) {    $k = app_id. '.' . $key;    if (Isset ($_session[$k]))    {        return $_session[$k];    }    return false;} Function set the session variablefunction Session_set ($key, $value) {    $k = app_id. '.' . $key;    $_session[$k] = $value;    return true;}

18. Encapsulating tool functions in a class

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

function Utility_a () {    //this function does a utility thing like String processing}function utility_b () {    //this fu Nction 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 encapsulate them in a class:

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 PHP has a function with the same name, it avoids conflicts. Another view is that you can maintain multiple versions of the same class in the same application without causing a conflict. This is the basic benefit of encapsulation, without it.

Bunch of Silly tips

>> use echo instead of print>> to replace preg_replace with str_replace unless you absolutely need >> do not use short tag>> simple strings with single quotes instead of double quotes > >head redirect remember to use exit>> do not call the function in the loop >>isset format code like strlen >> start >> do not delete loops or if-else parentheses do not write this code :

if ($a = = true) $a _count++;

This is absolutely waste. Written:

if ($a = = true) {    $a _count++;}

Do not attempt to omit some syntax to shorten the code. Instead, make your logic brief .>> use a text editor that has a highlighted syntax display. Highlighting syntax can help you reduce errors.

20. Using Array_map to quickly process arrays

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

foreach ($arr as $c = + $v) {$arr [$c] = Trim ($v);}

But using Array_map is easier:

$arr = Array_map (' Trim ', $arr);

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

21. Validating Data Using PHP filter

You must have used regular expressions to verify email, IP address, and so on. Yes, everyone uses it that way. Now, we want to make a different attempt, called the filter.php Filter extension, which provides a simple way to validate and check the input.

22. Mandatory type checking

$amount = intval ($_get[' amount '); $rate = (int) $_get[' rate '];

It's a good habit.

23. If required, use profiler such as Xdebug

If you use PHP to develop large-scale applications, PHP takes a lot of computation, and speed is a very important indicator. Use profile to help optimize your code. You can use Xdebug and WebGrid.

24. Handle large arrays with care

For large arrays and strings, you must handle them with care. A common mistake is the occurrence of an array copy causing memory overflow, throwing fatal error of the Memories size information:

$db _records_in_array_format; This is a big array holding $ rows from a table each have a columns, every row is atleast 10 bytes * * = 2MB$CC = $db _records_in_array_format; 2MB moresome_function ($CC); Another 2MB?

This is often done when importing or exporting CSV files. Do not assume that the above code will often cause the script to crash due to memory limitations. There is no problem with small variables, but it must be avoided when dealing with large arrays. Make sure to pass by reference, or stored in a class variable:

$a = Get_large_array ();p ass_to_function (& $a);

When you do this, pass the variable reference to the function instead of copying the array. View the document.

Class a{    function First ()    {        $this->a = Get_large_array ();        $this->pass_to_function ();    }    function pass_to_function ()    {        //process $this->a    }}

Unset them as quickly as possible, freeing up memory to relieve the burden of scripting.

25. Use a single database connection from start to finish

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

function Add_to_cart () {    $db = new Database ();    $db->query ("INSERT into cart ..."); function Empty_cart () {    $db = new Database ();    $db->query ("DELETE from cart ...");

Using multiple connections is a bad thing, and they slow down the app because creating a connection takes time and memory. Specific scenarios use singleton mode, such as database connectivity.

26. Avoid writing SQL directly, abstract

Too much to write too many of the following statements:

$query = "INSERT into users (name, email, address, phone) VALUES (' $name ', ' $email ', ' $address ', ' $phone ') '; $db->qu Ery ($query); Call to Mysqli_query ()

This is not a plan to build strong. It has some drawbacks.:>> manually escape values >> Verify that queries are correct >> query errors can take a long time to identify (unless If-else is checked every time) >> it is difficult to maintain complex queries using function encapsulation:

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_reco RD (' users ', $data);

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

27. Cache the database-generated content in a static file

If all the content is obtained from the database, they should be cached. Once generated, they are saved in a temporary file. The next time you request the page, you can take it directly from the cache, without looking at the database. Benefits:>> Save PHP time for processing pages, execute faster >> fewer database queries means less MySQL connection overhead

28. Save the session in the 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 in a single server. But the database can be accessed by multiple servers, which solves the problem. There are many more benefits of saving session data in a database:>> handling username recurring login issues. The same username cannot be logged in two places simultaneously .>> can be more prepared to query online user status.

29. Avoid using global variables

>> use defines/constants>> to get values using functions >> use classes and access by $this

30. Using the base tag in the head

Never heard of him? Please see below:

The base tag is very useful. Suppose your app is divided into subdirectories, all of which 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:

Homeipad

But in your ipad.php you have to write:

Homeipad

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

Therefore, use the base tag.

Homeipad

Now, this code is consistent across the app's catalog files.

31. Never set the error_reporting to 0

Close the non-phase error report. It is important to e_fatal errors.

Ini_set (' display_errors ', 1); Error_reporting (~e_warning & ~e_notice & ~e_strict);

32. Pay attention to the platform architecture

Integers are different in length in 32-bit and 64-bit architectures. Therefore, some functions, such as strtotime, behave differently.

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

$ php-ainteractive shellphp > Echo strtotime ("0000-00-00 00:00:00"); -62170005200php > Echo strtotime (' 1000-01-30 ') ); -30607739600php > Echo strtotime (' 2100-01-30 '); 4104930600

But in 32-bit machines, they will be bool (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:

Set_time_limit (+);//rest of the Code

Do you have peace of mind? Note that any external execution, such as system calls, socket operations, database operations, etc., is not under set_time_limits control.

Therefore, even if the database spends a lot of time querying, the script will not stop executing. Subject to availability.

34. Using the extension library

Some examples:

>>mpdf-can generate PDF documents from HTML

>>phpexcel-Reading and writing Excel

>>phpmailer-easily handle sending messages that contain nearby

>>pchart-using PHP to generate reports

Use the open Source library for complex tasks such as generating PDFs, ms-excel files, reports, and more.

35. Using the MVC framework

It's time to use an MVC framework like CodeIgniter. The MVC framework does not force you to write object-oriented code. They only separate PHP code from HTML.

>> clearly distinguishes between PHP and HTML code. There are benefits in team collaboration, and designers and programmers can work at the same time.

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

>> built-in functions do a lot of work and you don't need to write them repeatedly

>> development of large applications is a must

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

36. Always Look at Phpbench

Phpbench provides some benchmark results for basic PHP operations, and it shows how the minor grammatical changes in some badges lead to huge differences.

Review the comments on the PHP site, ask questions to IRC, read open source code, and use Linux development.

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

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.