10 advanced PHP skills to improve php efficiency.
1. use an SQL injection memo form The basic principle is never to trust the data submitted by users.
Another rule is to escape the data when you send or store it ).
It can be summarized as: filter input, escape output (FIEO). input filtering, output escape.
The SQL injection vulnerability is usually caused by the following statement:
Copy codeThe code is as follows:
$ Query = "SELECT *
FROM users
WHERE name = '{$ _ GET ['name']}' ";
In this example, $ _ GET ['name'] comes from the data submitted by the user, neither escaping nor filtering ~~
For escape output, remember that the data used outside your program needs to be escaped. Otherwise, it may be incorrectly parsed.
On the contrary, filtering input ensures that the data is correct before use.
For filtering input, remember that raw data outside your program needs to be filtered because they are untrusted.
The following example demonstrates input filtering and output escaping:
Copy codeThe code is as follows:
// Initialize arrays for filtered and escaped data, respectively.
$ Clean = array ();
$ SQL = array ();
// Filter the name. (For simplicity, we require alphabetic names .)
If (ctype_alpha ($ _ GET ['name']) {
$ Clean ['name'] = $ _ GET ['name'];
} Else {
// The name is invalid. Do something here.
}
// Escape the name.
$ SQL ['name'] = mysql_real_escape_string ($ clean ['name']);
// Construct the query.
$ Query = "SELECT *
FROM users
WHERE name = '{$ SQL ['name']}' ";
?>
Another effective way to prevent SQL injection is to use prepare statements, such:
Copy codeThe code is as follows:
// Provide the query format.
$ Query = $ db-> prepare ('select *
FROM users
WHERE name =: name ');
// Provide the query data and execute the query.
$ Query-> execute (array ('name' => $ clean ['name']);
?>
2. understand the differences between comparison operators For example, if you use strpos () to check whether a substring exists in a string (if the substring is not found, the function returns FALSE), the result may cause an error:
Copy codeThe code is as follows:
$ Authors = 'Chris & Sean ';
If (strpos ($ authors, 'Chris ')){
Echo 'Chris is an author .';
} Else {
Echo 'Chris is not an author .';
}
?>
In the above example, the strpos () function returns 0 correctly because the substring is at the starting position, indicating that the substring is at the starting position in the string. Then, because the condition statement treats the result as a Boolean type, 0 is calculated as FALSE by PHP, and the condition statement fails to be judged.
Of course, this BUG can be corrected using a strict comparison statement:
Copy codeThe code is as follows:
If (strpos ($ authors, 'Chris ')! = FALSE ){
Echo 'Chris is an author .';
} Else {
Echo 'Chris is not an author .';
}
?>
3. reduce else (elastic cut the else) Remember, you always need to initialize the variables before you use them.
Consider the following condition statement to check whether a user is an administrator based on the user name:
Copy codeThe code is as follows:
If (auth ($ username) = 'admin '){
$ Admin = TRUE;
} Else {
$ Admin = FALSE;
}
?>
This seems safe enough because it is easy to understand at a glance. Imagine a more complex example. it sets variables for both name and email. for convenience:
Copy codeThe code is as follows:
If (auth ($ username) = 'admin '){
$ Name = 'admin ';
$ Email = 'admin @ example.org ';
$ Admin = TRUE;
} Else {
/* Get the name and email from the database .*/
$ Query = $ db-> prepare ('select name, email
FROM users
WHERE username =: username ');
$ Query-> execute (array ('username' => $ clean ['username']);
$ Result = $ query-> fetch (PDO: FETCH_ASSOC );
$ Name = $ result ['name'];
$ Email = $ result ['email '];
$ Admin = FALSE;
}
?>
Because $ admin is explicitly set to TRUE or FALSE, everything seems to be fine. However, if another developer adds an elseif statement to the code, it is likely that the developer will forget this:
Copy codeThe code is as follows:
If (auth ($ username) = 'admin '){
$ Name = 'admin ';
$ Email = 'admin @ example.org ';
$ Admin = TRUE;
} Elseif (auth ($ username) = 'mod '){
$ Name = 'moderator ';
$ Email = 'mod @ example.org ';
$ Moderator = TRUE;
} Else {
/* Get the name and email .*/
$ Query = $ db-> prepare ('select name, email
FROM users
WHERE username =: username ');
$ Query-> execute (array ('username' => $ clean ['username']);
$ Result = $ query-> fetch (PDO: FETCH_ASSOC );
$ Name = $ result ['name'];
$ Email = $ result ['email '];
$ Admin = FALSE;
$ Moderator = FALSE;
}
?>
If a user provides a user name (username) that can trigger the elseif condition, $ admin is not initialized, which may cause unnecessary behavior or worse, a security vulnerability. In addition, a similar situation exists for the $ moderator variable, which is not initialized in the first condition.
By initializing $ admin and $ moderator, this situation can be easily avoided:
Copy codeThe code is as follows:
$ Admin = FALSE;
$ Moderator = FALSE;
If (auth ($ username) = 'admin '){
$ Name = 'admin ';
$ Email = 'admin @ example.org ';
$ Admin = TRUE;
} Elseif (auth ($ username) = 'mod '){
$ Name = 'moderator ';
$ Email = 'mod @ example.org ';
$ Moderator = TRUE;
} Else {
/* Get the name and email .*/
$ Query = $ db-> prepare ('select name, email
FROM users
WHERE username =: username ');
$ Query-> execute (array ('username' => $ clean ['username']);
$ Result = $ query-> fetch (PDO: FETCH_ASSOC );
$ Name = $ result ['name'];
$ Email = $ result ['email '];
}
?>
No matter what the remaining code is, it is clear that the $ admin value is FALSE unless it is explicitly set to another value. The same applies to $ moderator. The worst possible situation is that $ admin or $ moderator is not modified under any conditions, so that a person who is an administrator or moderator is not treated as the corresponding administrator or moderator.
If you want to export cut something, and you see our example contains else, you feel a little disappointed. We have a bonus tip that you may be interested in. We are not sure it can be considered as a cut, but we hope it will still be helpful.
Consider the next function used to check whether a user is authorized to view a specific page:
Copy codeThe code is as follows:
Function authorized ($ username, $ page ){
If (! IsBlacklisted ($ username )){
If (isAdmin ($ username )){
Return TRUE;
} Elseif (isAllowed ($ username, $ page )){
Return TRUE;
} Else {
Return FALSE;
}
} Else {
Return FALSE;
}
}
?>
This example is quite simple, because there are only three rules to consider:
Administrators are always allowed to access,
Access to the blacklist is always prohibited,
IsAllowed () determines whether other persons are authorized to access the service.
(Another exception is that when an administrator is in the blacklist, this seems unlikely, so we ignore this situation directly ).
We use functions for this judgment to keep the code concise and then focus on the business logic.
For example:
Copy codeThe code is as follows:
Function authorized ($ username, $ page ){
If (! IsBlacklisted ($ username )){
If (isAdmin ($ username) | isAllowed ($ username, $ page )){
Return TRUE;
} Else {
Return FALSE;
}
} Else {
Return FALSE;
}
}
?>
In fact, you can refine the entire function to a composite condition:
Copy codeThe code is as follows:
Function authorized ($ username, $ page ){
If (! IsBlacklisted ($ username) & (isAdmin ($ username) | isAllowed ($ username, $ page )){
Return TRUE;
} Else {
Return FALSE;
}
}
?>
Finally, this can be reduced to only one return:
Copy codeThe code is as follows:
Function authorized ($ username, $ page ){
Return (! IsBlacklisted ($ username) & (isAdmin ($ username) | isAllowed ($ username, $ page ));
}
?>
If your goal is to clear the number of lines in the code, you can do so. However, you should note that we are using isBlacklisted (), isAdmin (), and isAllowed (), which depends on what participates in these judgments, reducing the code to only one compound condition may not be attractive.
Now let's talk about our tips. a "return now" function, so if you return as soon as possible, you can easily express these rules:
Copy codeThe code is as follows:
Function authorized ($ username, $ page ){
If (isBlacklisted ($ username )){
Return FALSE;
}
If (isAdmin ($ username )){
Return TRUE;
}
Return isAllowed ($ username, $ page );
}
?>
This example uses more lines of code, but it is very simple and unnoticeable. More importantly, this method reduces the number of contexts you must consider. For example, once you decide whether the user is in the blacklist, you can safely forget about it. Especially when your logic is complex, this is quite helpful.
4. always use braces PS: Forgive me for throwing away the square Brackets Drop Those Brackets"
According to the content in this article, the author should mean "braces," rather than brackets. "Curly brackets" may mean braces, but "brackets" usually means square brackets. This technique should be ignored unconditionally because, without braces, readability and maintainability are damaged.
Here is a simple example:
Copy codeThe code is as follows:
If (date ('D M') = '21 May ')
$ Birthdays = array ('al franken ',
'Chris shiflett ',
'Chris wallacs ',
'Lawrence Tureaud ');
?>
If you're good enough, smart enough, secure enough, notorous enough, or pitied enough, you may want to join a social networking party in May 21:
Copy codeThe code is as follows:
If (date ('D M') = '21 May ')
$ Birthdays = array ('al franken ',
'Chris shiflett ',
'Chris wallacs ',
'Lawrence Tureaud ');
Party (TRUE );
?>
No Braces. this simple condition causes you to join a social gathering every day. Maybe you have perseverance, so this mistake is a popular one. I hope that the stupid example will not spread out, that is, the excessive Carnival is an unexpected side effect.
In order to advocate losing braces, the previous articles used short statements similar to the following as an example:
Copy codeThe code is as follows:
If ($ gollum = 'halfling') $ height --;
Else $ height ++;
?>
Because each condition is placed in a single row, this error seems to occur less, but this will lead to another problem: code inconsistency and requires more time to read and understand. Consistency is an important feature that developers often follow a coding standard, even if they do not like the encoding standard itself.
We advocate that braces always be used:
Copy codeThe code is as follows:
If (date ('D M') = '21 May '){
$ Birthdays = array ('al franken ',
'Chris shiflett ',
'Chris wallacs ',
'Lawrence Tureaud ');
Party (TRUE );
}
?>
It's okay for you to meet every day, but make sure you think about it. Also, please invite us!
5. use str_replace () instead of ereg_replace () and preg_replace () whenever possible () We hate to hear the denial, but the (original) small technique used to demonstrate misuse leads to the same abuse problems it tries to avoid. (
We hate to sound disparaging, but this tip demonstrates the sort of misunderstanding that leads to the same misuse it's trying to prevent .)
Obviously, string functions are faster and more efficient than regular expression functions in character matching, but the author tries to draw a conclusion from failure:
(Fix me: It's an obvious truth that string functions are faster at string matching than regular expression functions, but the author's attempt to draw a corollary from this fails miserably :)
If you're using regular expressions, then ereg_replace () and preg_replace () will be much faster than str_replace ().
Because str_replace () does not support pattern matching, this statement makes no sense. the choice between string functions and regular expression funich comes down to which is fit for purpose, not which is faster. if you need to match a pattern, use a regular expression function. if you need to match a string, use a string function.
6. use triple operators The advantages of the ternary operators are worth discussing. The following is a line taken from the code of the recent audit:
Copy codeThe code is as follows:
$ Host = strlen ($ host)> 0? $ Host: htmlentities ($ host );
?>
Ah, the true intention of the author is to escape $ host if the string length is greater than 0, but accidentally did the opposite. Is it easy to make mistakes? Maybe. Is it easy to miss in the code audit process? Of course. Simplicity does not necessarily make the code very good.
The triple operator is suitable for single row, prototype, and template, but we believe that a normal condition statement is always better. PHP is descriptive and detailed, and we think the code should also be.
7. Memcached Disk access is slow and network access is slow, which is usually used by databases.
Memory is fast. Using local cache can avoid Network and disk access overhead. In combination with these principles, you think of memcached, a "distributed memory object cache system" that was initially developed for the Perl-based blog platform LiveJournal.
If your program is not distributed across multiple servers, you may not need memcached. Single cache method-serialize the data and save it in a temporary file. For example? Each request can eliminate a lot of unnecessary work. In fact, this is the type of low-hanging fruit that we consider helping our customers optimize their applications.
What is low-hanging fruit:
A fruit-bearing tree often contains some branches low enough for animals and humans to reach without much effort. the fruit contained on these lower branches may not be as ripe or attractive as the fruit on higher limbs, but it is usually more abundant and easier to harvest. from this we get the popular expression "low hanging fruit", which generally means selecting the easiest targets with the least amount of effort.
One of the simplest and most common ways to cache data in memory is to use the sharing type auxiliary method in APC, a cache system originally developed by our colleague George Schlossnagle, consider the following example:
Copy codeThe code is as follows:
$ Feed = apc_fetch ('news ');
If ($ feed = FALSE ){
$ Feed = file_get_contents ('http: // example.org/news.xml ');
// Store this data in shared memory for five minutes.
Apc_store ('new', $ feed, 300 );
}
// Do something with $ feed.
?>
With this type of cache, you do not have to wait for the remote server to send the Feed data for each request. Is there any latency? In this example, the upper limit is five minutes, but can be adjusted to near real-time according to your application needs.
8. framework All decisions will have results. We like frameworks-in fact, cakePHP and major Solar developers work with us on OmniTI-but using a framework won't miraculously make what you are doing better.
In February October, our colleague Paul Jones wrote an article for HP Advent called The Framework as Franchise, in which he compared The Framework with The commercial Franchise. He cited The suggestion in Michael Gerber's book "The E-Myth Revisited:
Ge Bai pointed out that an entrepreneur who runs a successful enterprise needs to act like he wants to sell his enterprise as a prototype of a franchise. This is the only way for an enterprise owner to operate an enterprise without being personally involved in every decision.
(Gerber notes that to run a successful business, the entrepreneur needs to act as if he is going to operate his business as a franchise prototype. it is the only way the business owner can make the business operate without him being personally involved in every demo .)
This is a good suggestion. Whether you are planning to use a framework or define your own labels and conventions, value is important from the perspective of future developers.
Although we are happy to give you a universally accepted truth, extending this idea to show that a framework is always appropriate and is not what we want to do.
If you ask us if we should use a framework, the best answer we can give is: "This depends on the situation ."
9. correct use of the error suppression operator Always try to avoid using error suppression operation symbols. In the previous article, the author states:
@ Operator is quite slow, and if you need to write high-performance code, it will cause high overhead.
Slow error suppression is because PHP dynamically changes the error_reporting level to 0 before executing the suppression statement, and then immediately restores it. This is overhead.
Even worse, it is difficult to track the root cause of the problem by using the error blocker.
The following example is used in the previous article to support the method of assigning values to a variable through reference... (How to translate this sentence? I am dizzy ~~~ )
The previous article uses the following example to support the practice of assigning a variable by reference when it is unknown if $ albus is set:
Copy codeThe code is as follows:
$ Albert = & $ albus;
?>
Although it works like this-it's a good way to understand why this job works with a strange, undefined behavior.
Because $ albert references $ albus, later modifications to $ albus will also affect $ albert.
A better solution is to use isset () with braces:
Copy codeThe code is as follows:
If (! Isset ($ albus )){
$ Albert = NULL;
}
?>
Assigning NULL to $ albert has the same effect as assigning a non-existent reference to it, but it is more explicit, greatly improving the definition of the code and avoiding the reference relationship between the two variables.
If you inherit code that uses the error suppression operator excessively, we 've got a bonus tip for you. There is a new PECL extension called Scream that disables error suppression.
10. use isset () instead of strlen () This is actually a clever method, although the previous article did not explain this at all. The following is a supplementary example:
Copy codeThe code is as follows:
If (isset ($ username [5]) {
// The username is at least six characters long.
}
?>
When you think of a string as an array (no light in the wilderness: in fact, in C language, characters usually exist in the form of an array), each character in the string is an element of an array. By checking whether a specific element exists, you can check whether the string contains at least so many characters. (Note that the first character is element 0, so $ username [5] is the 6th character in $ username .)
The reason why isset is faster than strlen is complicated. The simple explanation is that strlen () is a function, and isset () is a syntax structure. Generally,
Calling a function is more expensive than using a language structure.
About Author:
Hi, we are Chris Shiflett and Sean Coates. we all work in OmniTI ("the most important web company you 've never heard of"), blog about PHP and other stuff at shiflett.org and seancoates.com, curate PHP Advent, and do the Twitter thing as @ shiflett and @ coates.
Translated FROM: http://coding.smashingmagazine.com/2009/03/24/10-useful-php-tips-revisited/
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.