Home  >  Article  >  Backend Development  >  Very teachable 36 tips to improve PHP code quality_PHP Tutorial

Very teachable 36 tips to improve PHP code quality_PHP Tutorial

WBOY
WBOYOriginal
2016-07-21 15:16:391355browse

1. Don’t use relative paths
You often see:
require_once('../../lib/some_class.php');
This method has many disadvantages:
It first looks for the specified php include path, and then looks for the current directory.
So too many paths are checked.
If the script is included by a script in another directory, its base directory becomes that of another script directory.
Another problem, when the scheduled task runs the script, its parent directory may not be the working directory.
So the best choice is to use an absolute path:
define('ROOT' , '/var/www/project/');
require_once(ROOT . '../../lib/some_class.php');
//rest of the code
We define an absolute The path and value are hard-coded. We can also improve it. The path /var/www/project may also change, so do we have to change it every time? No, we can use the __FILE__ constant, such as:
//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 external server above, the code can run correctly without any changes.
2. Do not use require, include, include_once, required_once directly
You can introduce multiple files at the head of the script, such as class libraries and tool files and helper functions, such as:
require_once('lib/Database.php');
require_once('lib/Mail.php');
require_once('helpers/utitlity_functions.php');
This usage is quite primitive. It should be more flexible. A helper function should be written to include 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 any difference? This code is more readable.
You can extend this function as needed in the future, 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 do more:
Find multiple directories for the same file
Can easily change the directory where class files are placed, without having to separate them in the code Modify them one by one
You can use similar functions to load files, such as html content.
3. Keep debugging code for the application
In the development environment, we print the database query statement and transfer There are problematic variable values, and once the problem is resolved, we comment or delete them. However, a better approach is to keep the debug code.
In a 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. Use cross-platform function execution Commands
system, exec, passthru, shell_exec These 4 functions can be used to execute system commands. The behavior of each is slightly different. The problem is that when in shared hosting, some functions may be selectively Disabled. Most novices tend to first check which function is available each time before using it.
A better solution is to encapsulate the function into a cross-platform function.
/**
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 will run the shell command as long as there is a system function available, which maintains the consistency of the code.
5. Write functions flexibly
function add_to_cart($item_id , $qty)
{
$_SESSION['cart']['item_id'] = $qty;
}
add_to_cart( 'IPHONE3' , 2 );
使用上面的函数添加单个项目. 而当添加项列表的时候,你要创建另一个函数吗? 不用, 只要稍加留意不同类型的参数, 就会更灵活. 如:
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) );
现在, 同个函数可以处理不同类型的输入参数了. 可以参照上面的例子重构你的多处代码, 使其更智能.
6. 有意忽略php关闭标签
我很想知道为什么这么多关于php建议的博客文章都没提到这点.
echo "Hello";
//Now dont close this tag
这將节约你很多时间. 我们举个例子:
一个 super_class.php 文件
class super_class
{
function super_function()
{
//super code
}
}
?>
//super extra character after the closing tag
index.php
require_once('super_class.php');
//echo an image or pdf , or set the cookies or session data
这样, 你將会得到一个 Headers already send error. 为什么? 因为 “super extra character” 已经被输出了. 现在你得开始调试啦. 这会花费大量时间寻找 super extra 的位置.
因此, 养成省略关闭符的习惯:
class super_class
{
function super_function()
{
//super code
}
}
//No closing tag
这会更好.
7. 在某地方收集所有输入, 一次输出给浏览器
这称为输出缓冲, 假如说你已在不同的函数输出内容:
function print_header()
{
echo "

";
}
function print_footer()
{
echo "";
}
print_header();
for($i = 0 ; $i < 100; $i++)
{
echo "I is : $i
';
}
print_footer();
替代方案, 在某地方集中收集输出. 你可以存储在函数的局部变量中, 也可以使用ob_start和ob_end_clean. 如下:
function print_header()
{
$o = "";
return $o;
}
function print_footer()
{
$o = "";
return $o;
}
echo print_header();
for($i = 0; $i < 100; $i++)
{
echo " I is : $i
';
}
echo print_footer();
Why output buffering is needed:
>>The output can be changed before sending to the browser. Such as str_replaces function or maybe preg_replaces or add some monitoring/debugging html content.
>>It is very bad to output to the browser and do PHP processing at the same time. You should have seen the sidebar or An error message appears in the middle. Do you know why it happens? Because processing and output are mixed.
8. Send the correct mime type header information, if non-html content is output.
Output some xml .
$xml = '';
$xml = "
< code>0
";
//Send xml data
echo $xml;
Works well. But needs some improvements.
$xml = '';
$xml = "
0
";
//Send xml data
header("content-type: text/xml");
echo $xml;
Pay attention to the header line. This line Inform the browser that the content sent is xml type. So the browser can process it correctly. Many javascript libraries also rely on header information.
Similar ones include 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
Have ever encountered unicode/utf-set in a mysql table 8 encoding, phpadmin can also display it correctly, but when you get the content and output it on the page, garbled characters will appear. The problem here lies in the character encoding of the mysql connection.
//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 connected to the database, it is best to set the connected characterset. If your application wants to support multiple languages, Doing this is necessary.
10. Use htmlentities to set the correct encoding options
Before php5.4, the default encoding of characters is ISO-8859-1, and cannot be directly output such as À â, etc. .
$value = htmlentities($this->value , ENT_QUOTES , CHARSET);
After php5.4, the default encoding is UTF-8, which will solve many problems. But if your application is multi-language Yes, you still have to pay attention to encoding issues.
11. Don’t use gzip to compress output in your application, let apache handle it.
Have you considered using ob_gzhandler? Don’t do that. Pointless. php Should only be used to write applications. You should not worry about data transmission optimization issues between servers and browsers.
Use apache's mod_gzip/mod_deflate module to compress content.
12. Use json_encode to output dynamic javascript content
PHP is often used 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' ,];
More Smart approach, 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"]
elegantly ?
13. Before writing a file, check the directory write permission
Before writing or saving a file, make sure the directory is writable. If not, output an error message. This will save you a lot of debugging. Time. In Linux systems, permissions need to be processed. Improper directory permissions will cause many problems, files may not be read, etc.
Make sure your application 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 correct. But there are some indirections Problem. file_put_contents may fail for several reasons:
>>The parent directory does not exist
>>The directory exists, but is not writable
>>The file is write-locked?
So it is better to do an explicit check before writing the 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 is not writable, or does not exist. Please check");
}
After doing this, you will get a clear message about where the file was written and why it failed.
14. Change permissions on files created by the application
In Linux environment, permission issues This may waste you a lot of time. From now on, whenever you create some files, make sure to use chmod to set the correct permissions. Otherwise, maybe the file was created by the "php" user first, but you are logged in as another user work, the system will deny access or open the file, and you have to fight to gain root permissions, change file permissions, etc.
// 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. Don’t rely on submit button value to check Form submission behavior
if($_POST['submit'] == 'Save')
{
//Save the things
}
Most of the above are correct, except The application is multilingual. 'Save' may mean other things. How do you distinguish them. Therefore, do not rely on the submit button value.
if( $_SERVER['REQUEST_METHOD'] == 'POST' and isset( $_POST['submit']) )
{
//Save the things
}
Now you are freed from the submit button value.
16. Inside the function Variables that always have the same value are defined as static variables
//Delay for some time
function delay()
{
$sync_delay = get_option('sync_delay');
echo "
Delaying for $sync_delay seconds...";
sleep($sync_delay);
echo "Done
";
}
Use static variables Replaces:
//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 < ;br />";
}
17. Do not use the $_SESSION variable directly
Some simple examples:
$_SESSION['username'] = $username;
$username = $_SESSION['username'];
This can cause some problems. If multiple applications are running in the same domain name, the session variables may conflict. Two different applications may use the same A session key. For example, a front-end portal, and a back-end management system use the same domain name.
From now on, use application-related keys and a wrapper function:
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. Encapsulate utility functions into classes
If you define many utility functions in a file:
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 scattered throughout the application. You may want to encapsulate them into 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 built-in Have functions with the same name, so that conflicts can be avoided.
Another way of looking at it 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, nothing else.
19. Bunch of silly tips
>> Use echo instead of print
>> Use str_replace instead of preg_replace, unless you absolutely need to
>> Don’t Use short tag
>> Use single quotes instead of double quotes for simple strings
>> Remember to use exit after head redirection
>> Do not call functions in a loop
> ;>isset is faster than strlen
>>Consistent formatting code
>>Don’t delete loops or if-else brackets
Don’t write code like this:
if( $a == true) $a_count++;
This is absolutely WASTE.
Write:
if($a == true)
{
$a_count++;
}
No Try to shorten your code by omitting some syntax. Instead, keep your logic short.
>>Use a text editor with syntax highlighting. Syntax highlighting allows you to reduce errors.
20 . Use array_map to quickly process arrays
For example, you want to trim all elements in the array. Newbies may:
foreach($arr as $c => $v)
{
$arr[$c] = trim($v);
}
But it’s easier to use array_map:
$arr = array_map('trim' , $arr);
This will call trim for each element of the $arr array. Another similar function is array_walk . Please check the documentation to learn more tips.
21. Use php filter to verify data
You must have used regular expressions to verify email, ip address, etc. Yes, everyone does it Use. Now, we want to try something different, called a filter.
php's filter extension provides a simple way to validate and check input.
22. Forced type checking
$ amount = intval( $_GET['amount'] );
$rate = (int) $_GET['rate'];
This is a good practice.
23. Use if necessary Profiler such as xdebug
If you use PHP to develop large-scale applications, PHP takes on a lot of calculations, and speed will be a very important indicator. Use profile to help optimize the code. You can use
xdebug and webgrid.
24. Handle large arrays with care
Large arrays and strings must be handled with care. A common error is that array copying causes memory overflow and Fatal Error of Memory size is thrown. Information:
$db_records_in_array_format; //This is a big array holding 1000 rows from a table each having 20 columns, every row is atleast 100 bytes, so total 1000 * 20 * 100 = 2MB
$cc = $db_records_in_array_format; //2MB more
some_function($cc); //Another 2MB ?
This is often done when importing or exporting csv files.
Don’t think that the above code will often cause the script to crash due to memory limitations. For small Variables are fine, but must be avoided when dealing with large arrays.
Make sure to pass by reference, or store in a class variable:
$a = get_large_array();
pass_to_function(&$a );
After doing this, pass the variable reference to the function (instead of copying the array). See the documentation.
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 to free up memory and reduce the burden on the script.
25. Use a single database connection from beginning to end
Make sure your script is connected from the beginning to the end. Always use a single database connection. Open the connection correctly at the beginning, use it until the end, and close it at the end. Do not open the connection in a function like this:
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 bad, they will slow down the application because Creating a connection takes time and takes up memory.
Use singleton mode in certain situations, such as database connections.
26. Avoid writing SQL directly, abstraction
took the trouble to write too much as follows Statement:
$query = "INSERT INTO users(name, email, address, phone) VALUES('$name', '$email', '$address', '$phone')";
$ db->query($query); //call to mysqli_query()
This is not a robust solution. It has some disadvantages:
>>Escape the value manually every time
> >Verify that the query is correct
>>Errors in the query will take a long time to identify (unless it is checked with if-else every time)
>>It is difficult to maintain complex queries
Therefore Use 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_record( 'users' , $data);
See? This will be more readable and extendable. The record_data function handles escaping carefully.
The biggest advantage is that the data is preprocessed as an array, any syntax errors will Captured.
This function should be defined in a database class, you can call it like $db->insert_record.
Check out this article to see how to make it easier for you to deal with the database.
Similar You can also write update, select, delete methods. Try it.
27. Cache the content generated by the database into static files
If all the content is obtained from the database, they Should be cached. Once generated, save them in temporary files. The next time the page is requested, it can be fetched directly from the cache without checking the database.
Benefits:
>> Save PHP Time to process page, execute faster
>>Fewer database queries means less mysql connection overhead
28. Saving session in database
File-based The session strategy will have many limitations. Using file-based sessions cannot be extended to a cluster because the session is saved in a single server. But the database can be accessed by multiple servers, which can solve the problem.
Save session data in the database , and there are more benefits:
>> Handle the problem of repeated username login. The same username cannot be logged in at two places at the same time.
>> Can more easily query online user status.
29. Avoid using global variables
>>Use define/constants
>>Use functions to get values
>>Use classes and access through $this
30. Use base tag in head
Never heard of it? Please see below:






The
base tag is very useful. Suppose your application is divided into several subdirectories, and they all contain the same navigation menu.
www.domain.com/store/home.php
www. domain.com/store/products/ipad.php
In the homepage, you can write:
Home
Ipad
But in your ipad.php you have to write:
Home
Ipad
Because the directories are different. It’s terrible to have so many different versions of the navigation menu to maintain.
So, please use base tag.




Home
Ipad


Now, this code behaves consistently in every directory file of the application.
31. Never set error_reporting to 0
Close it Corresponding error reporting. E_FATAL errors are very important.
ini_set('display_errors', 1);
error_reporting(~E_WARNING & ~E_NOTICE & ~E_STRICT);
32. Pay attention to the platform system Structure
integer length is different in 32-bit and 64-bit architectures. Therefore some functions like strtotime will behave differently.
In 64-bit machine, you will see the following output .
$ 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 machine, they will be bool (false). See here to learn more.
33. Don’t rely too much on set_time_limit
If you want to limit the minimum time, you can use the following script:
set_time_limit(30);
//Rest of the code
Sit back and relax? Note that any external execution, such as system calls, socket operations, database operations, etc., are not under the control of set_time_limits.
Therefore, even if the database spends a lot Time query, the script will not stop execution. It depends on the situation.
34. Using the extension library
Some examples:
>>mPDF -- can generate pdf from html Document
>>PHPExcel -- read and write excel
>>PhpMailer -- easily handle sending emails containing nearby content
>>pChart -- use php to generate reports
use open source The library completes complex tasks, such as generating pdf, ms-excel files, reports, etc.
35. Using the MVC framework
It’s time to use an MVC framework like codeigniter. MVC frameworks don’t force you to write object-oriented code. They only separate php code from html.
>>Clearly differentiate between php and html code. In team collaboration The advantage is that designers and programmers can work at the same time.
>> Object-oriented designed functions make it easier for you to maintain
>> Built-in functions do a lot of work, and you don’t need to write it repeatedly
>>It is necessary to develop large applications
>>Many suggestions, techniques and hacks have been implemented by the framework
36. Check phpbench often
phpbench provides some benchmark results for basic PHP operations. It shows how some small syntax changes can lead to huge differences.
Check the comments on the PHP site, ask questions on IRC, read open source code frequently, and use Linux Developed.
Original translation by OSCHINA

www.bkjia.comtruehttp: //www.bkjia.com/PHPjc/325847.htmlTechArticle1. Do not use relative paths. You will often see: require_once('../../lib/some_class. php'); This method has many shortcomings: it first looks for the specified php include path, and then looks for the current directory. Because...
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn