10 Advanced PHP Skills [Revised version]_php tips]

Source: Internet
Author: User
Tags auth memcached prepare sql injection
1. Use a SQL injection memo
A basic principle is that you should never trust the data the user submits.
Another rule is to escape (escape) when you send or store data.
Can be summed up as: Filter input, Escape output (FIEO). Input filter, output escape.
A common cause of SQL injection vulnerabilities is that the input is not filtered, as follows:
Copy Code code as follows:

<?php
$query = "SELECT *
From users
WHERE name = ' {$_get[' name ']} ';

In this example, $_get[' name ' comes from user-submitted data that is neither escaped nor filtered.
For the escape output, remember that the data that is used outside of your program needs to be escaped, otherwise it may be parsed incorrectly.
Instead, filtering input ensures that the data is correct before it is used.
For filter input, remember that raw data outside of your program needs to be filtered because they are not trusted.
The following examples demonstrate input filtering and output escaping:
Copy Code code as follows:

<?php
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 way to effectively prevent SQL injection is to use the prepare statement, such as:
Copy Code code as follows:

<?php
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. Understanding the differences between comparison operators
For example, if you use Strpos () to detect whether a substring exists in a string (if the fruit string is not found and the function returns FALSE), the result may be an error:
Copy Code code as follows:

<?php
$authors = ' Chris & Sean ';
if (Strpos ($authors, ' Chris ')) {
Echo ' Chris is a author. ';
} else {
The echo ' Chris is not a author. ';
}
?>

In the example above, because the substring is in its first position, the Strpos () function correctly returns 0, indicating that the substring is at the beginning of the string. Then, because the conditional statement treats the result as a Boolean (Boolean) type, 0 is evaluated by PHP as FALSE, which ultimately results in a conditional statement judgment failure.
Of course, this bug can be fixed with a strict comparison statement:
Copy Code code as follows:

<?php
if (Strpos ($authors, ' Chris ')!== FALSE) {
Echo ' Chris is a author. ';
} else {
The echo ' Chris is not a author. ';
}
?>

3. Reduce else (shortcut the Else)
Remember, you always have to initialize the variables before you use them.
Consider the following conditional statement used to detect whether a user is an administrator based on the user name:
Copy Code code as follows:

<?php
if (auth ($username) = = ' admin ') {
$admin = TRUE;
} else {
$admin = FALSE;
}
?>

This seems to be safe enough because it's easy to understand at a glance. Imagine a more complex example of setting variables for name and email at the same time, for convenience:
Copy Code code as follows:

<?php
if (auth ($username) = = ' admin ') {
$name = ' Administrator ';
$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 still explicitly set to TRUE or FALSE, everything seems to be intact. However, if another developer later added a ElseIf statement to the code, chances are he will forget about it:
Copy Code code as follows:

<?php
if (auth ($username) = = ' admin ') {
$name = ' Administrator ';
$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 triggers the ElseIf condition, the $admin is not initialized, which can lead to unnecessary behavior, or worse, a security vulnerability. In addition, a similar situation exists for $moderator variable, which is not initialized in the first condition.
By initializing $admin and $moderator, it is entirely easy to avoid this scenario:
Copy Code code as follows:

<?php
$admin = FALSE;
$moderator = FALSE;
if (auth ($username) = = ' admin ') {
$name = ' Administrator ';
$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 '];
}
?>

Whatever the rest of the code is, it is now clear that the $admin value is false unless it is explicitly set to another value. The same is true for $moderator. The worst possible scenario is that $admin or $moderator are not modified under any conditions, causing someone who is an administrator or moderator not to be treated as the corresponding administrator or moderator.
If you want to shortcut something, and you see our example that contains any else feel a little disappointed. We have a bonus tip you might be interested in. We are not sure that it can be considered a shortcut, but we hope it will still be helpful.
Consider a function that detects whether a user is authorized to view a particular page:
Copy Code code as follows:

<?php
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 is always allowed access,
The blacklist is always forbidden to access,
Isallowed () Determines whether other persons are entitled to visit.
(Another exception is this: When an administrator is blacklisted, it seems unlikely, so we ignore this directly here).
We use functions to make this decision to keep the code simple and then focus on the business logic.
Such as:
Copy Code code as follows:

<?php
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 reduce the entire function to a compound condition:
Copy Code code as follows:

<?php
function authorized ($username, $page) {
if (!isblacklisted ($username) && (ISAdmin ($username) | | | isallowed ($username, $page)) {
return TRUE;
} else {
return FALSE;
}
}
?>

Finally, this can be reduced to just one return:
Copy Code code as follows:

<?php
function authorized ($username, $page) {
Return (!isblacklisted ($username) && (ISAdmin ($username) | | | isallowed ($username, $page));
}
?>

If your goal is to copy the number of lines of code, then you do it. However, you should note that we are using isblacklisted (), ISAdmin () and isallowed (), depending on what is involved in these judgments, and that reducing the code to only one compound condition may not be appealing.
Here's our little trick, a "go back" function, so if you return as soon as possible, you can simply express these rules:
Copy Code code as follows:

<?php
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 not noticeable. More importantly, this approach reduces the number of contexts you must consider. For example, once you decide whether a user is in a blacklist, you can safely forget about it. Especially when your logic is complicated, it's quite helpful.
4. Always use curly braces
PS: Forgiveness is "throw away those square brackets drop those brackets"
According to the content of this article, our corresponding author's meaning should be "braces," rather than brackets. "Curly brackets" may mean curly braces, but "brackets" usually means "square brackets." This technique should be ignored unconditionally because, without braces, readability and maintainability are compromised.
To give a simple example:
Copy Code code as follows:

<?php
if (date (' d ') = = ' May ')
$birthdays = Array (' Al Franken ',
' Chris Shiflett ',
' Chris Wallace ',
' Lawrence Tureaud ');
?>

If you are good enough, smart enough, secure enough, notorious enough, or pitied enough, you may want to attend a social gathering on May 21:
Copy Code code as follows:

<?php
if (date (' d ') = = ' May ')
$birthdays = Array (' Al Franken ',
' Chris Shiflett ',
' Chris Wallace ',
' Lawrence Tureaud ');
Party (TRUE);
?>

Without curly braces, this simple condition causes you to attend social gatherings every day. Maybe you have perseverance, so this mistake is a popular one. Hopefully that stupid example doesn't distract from the idea that binge-partying is an unexpected side effect.
To promote the loss of curly braces, the previous article uses a short statement similar to the following as an example:
Copy Code code as follows:

<?php
if ($gollum = = ' halfling ') $height--;
else $height + +;
?>

Because each condition is placed on a separate line, this error seems to occur less often, but this leads to another problem: the inconsistency of the Code and the need for more time to read and understand. Consistency is such an important feature that developers often follow a coding standard, even if they do not like the coding standard itself.
We advocate always using curly braces:
Copy Code code as follows:

<?php
if (date (' d ') = = ' May ') {
$birthdays = Array (' Al Franken ',
' Chris Shiflett ',
' Chris Wallace ',
' Lawrence Tureaud ');
Party (TRUE);
}
?>

It's okay for you to party every day, but make sure it's a thought, and, please, be sure to invite us!
5. Try to use Str_replace () instead of ereg_replace () and Preg_replace ()
We hate the denial that we hear, but this little trick used to demonstrate misuse leads to the same abuses that it tries to avoid. (
We hate to sound disparaging, but this tip demonstrates the sort of misunderstanding which leads to the same misuse it ' s TR Ying to prevent.)
It's obvious that string functions are faster and more efficient at character matching than regular expression functions, but the author has a bad attempt to draw a conclusion from failure:
(FIX me:it ' s obvious truth that string functions are faster at string matching than regular expression functions, but The author ' s attempt to draw a corollary from-fails miserably:)
If you ' re using regular expressions, then ereg_replace () and Preg_replace () is much faster than ().
Because Str_replace () does not support pattern matching, this statement makes no sense. The choice between string functions and regular expression functions comes down to which are fit for purpose, not which is Faster. If you are need to match-a, use a regular expression function. If you are need to match a string, use a string function.
6. Using the triple operator
The benefits of ternary operators are worth discussing. The following is a line taken from the code of the recent audit we conducted:
Copy Code code as follows:

<?php
$host = strlen ($host) > 0? $host: Htmlentities ($host);
?>

Ah, the author's real intention is to escape $host if the length of the string is greater than 0, but unexpectedly do the opposite thing. It's easy to make a mistake, right? Well, maybe. Easy to miss in the code audit process? Of course. Simplicity does not necessarily make code very good.
The triple operator is also appropriate for a single, prototype, and template, but we believe that an ordinary conditional statement is always better. PHP is descriptive and detailed, and we think the code should be.
7. Memcached
Disk access is slow, network access is slow, and databases typically use both.
The memory is fast. Using a local cache avoids the overhead of network and disk access. Combined with these truths, you then think of memcached, a "Distributed memory object Caching System", originally developed for the LiveJournal blog platform based on Perl.
If your program is not distributed across multiple servers, you may not need to memcached. Single caching Method--serializes the data and then saves it in a temporary file. For example – You can eliminate a lot of extra work for each request. In fact, this is the type of low hanging fruit that we are considering to help our customers optimize their applications.
What is low-hanging fruit:
A fruit-bearing tree often contains some branches the for enough and animals to reach humans much without. The fruit contained on this lower branches may being not being as ripe or attractive as the fruit on higher limbs and but it is us ually more abundant and easier to harvest. From-we get the popular expression ' low hanging fruit ' which generally the means the selecting easiest with the least amount of effort.
One of the easiest and most versatile ways to cache data in memory is to use the shared-type helper method in the APC, a caching system that was originally developed by our colleague George Schlossnagle, considering the following example:
Copy Code code as follows:

<?php
$feed = Apc_fetch (' News ');
if ($feed = = FALSE) {
$feed = file_get_contents (' Http://example.org/news.xml ');
Store this data in the shared memory for five minutes.
Apc_store (' News ', $feed, 300);
}
Do something with $feed.
?>

With this type of caching, you do not have to wait for the remote server to send feed data at every request. Some delays have been generated – in this case the upper limit is five minutes, but can be adjusted to near real-time depending on your application needs.
8. Use of the framework
All decisions come with results, we like frameworks--in fact, the main developers of cake and Solar are working with us in omniti--but using a framework doesn't magically make things better for what you're doing.
In October, our colleague Paul Jones wrote an article for HP Advent, called the framework as franchise, in which he compared the framework to the business franchise. He cites Michael Gerber's recommendations in the book "The Reappearance of Electronic myths" ("The E-myth Revisited"):
Gerber points out that to run a successful business, an entrepreneur needs to act like he's going to sell his business as a prototype of a franchise. This is the only way for business owners to be able to operate without personally participating in each decision.
(Gerber notes this to run a successful business, the entrepreneur needs to act as if it's going to sell his business as A franchise prototype. It is the ' only way ' business owner can make the business operate without him being personally involved in every Decisio N.)
This is a good suggestion. Whether you're using a framework or defining your own tags and conventions, it's important to look at value from a future developer's perspective.
Although we are happy to give you a universal truth, extend the idea to show that a framework is always appropriate, not what we want to do.
If you ask if we should use a framework, the best answer we can give is, "it depends." ”
9. Correct use of error suppression operators
Always try to avoid using the error suppression action symbol. In the previous article, the author shows:
The @ operator is quite slow and if you need to write high-performance code it can make a lot of overhead.
Error suppression is slow because PHP dynamically changes the error_reporting level to 0 before executing the suppression statement, and then restores it immediately. It's going to cost.
Worse, using the error suppressor makes it difficult to trace the root cause of the problem.
Previous articles Use the following example to support the practice of assigning values to a variable by reference ... (How to translate this sentence?) I faint ~ ~ ~ ~)
The previous article uses the following example to support the practice of assigning of the A variable by reference where it is UN Known if $albus is set:
Copy Code code as follows:

<?php
$albert =& $albus;
?>

Although this is working--for now--relying on strange, undefined behavior, and having a good understanding of why it works is a good way to create bugs.
Because the $albert is quoted $albus, later changes to $albus will also affect the $albert.
A better solution is to use Isset (), plus braces:
Copy Code code as follows:

<?php
if (!isset ($albus)) {
$albert = NULL;
}
?>

assigning null to $albert and giving it a nonexistent reference are the same, but more explicit, greatly improving the clarity of the code and avoiding the reference relationship between the two variables.
If you inherit code this uses the error suppression operator excessively, we ' ve got a bonus tip for you. There is a new PECL extension called scream error disables.
10. Use Isset () instead of strlen ()
This is actually an ingenious method, although the previous article does not explain this at all. The following is a supplementary example:
Copy Code code as follows:

<?php
if (Isset ($username [5])) {
The username is at least six characters long.
}
?>

When you treat a string as an array (wilderness without lights: In fact, in the C language, the character is usually in an array form), each character in the string is an element of the array. By detecting the presence of a particular element, you can detect whether or not there are at least as many characters in the string. (Note that the first character is element 0, so $username [5] is the 6th character in the $username.) )
The reason for using isset to be slightly faster than strlen is complicated. The simple explanation is that strlen () is a function, and isset () is a syntactic structure. Generally speaking,
Calling a function is more expensive than using a language structure.
About the Author:
Hi, we are Chris Shiflett and Sean Coates. We are working on Omniti ("The most important web company for you ' ve never heard of"), blogs about PHP and other stuff at shiflett.org and seancoates.com, curate PHP Advent, and do the Twitter thing as @shiflett and @coates.
Translation from:http://coding.smashingmagazine.com/2009/03/24/10-useful-php-tips-revisited/

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.