Home  >  Article  >  Backend Development  >  Detailed explanation of Memcache in PHP_PHP tutorial

Detailed explanation of Memcache in PHP_PHP tutorial

WBOY
WBOYOriginal
2016-07-13 10:34:37676browse

This article mainly introduces Memcache in PHP. Starting from the introduction of Memcache, it explains in detail the difference between Memcache and memcached, all operating methods of PHP's Memcache, detailed explanations of each operating method, etc., as needed Friends can refer to it

1. Introduction to Memcache

Memcache is a project of danga.com. It was first used to serve LiveJournal. Currently, many people around the world use this caching project to build their own large-load websites to share the pressure on the database. It can handle any number of connections and uses non-blocking network IO. Since its working mechanism is to open up a space in the memory and then create a HashTable, Memcached manages these HashTables, so it is very fast.

2. The difference between Memcache and memcached

Why are there two names: Memcache and memcached? In fact, Memcache is the name of this project, and memcached is the name of its main program file on the server side. You know what I mean~~~~. One is the project name, and the other is the main program file name. I saw many people on the Internet who didn’t understand, so they used them interchangeably.

3. Server-side and client-side installation of Memcache

It is divided into two processes: memcache server installation and memcached client installation.

The so-called server-side installation is to install Memcache on the server (usually a Linux system) to store data.

The so-called client installation refers to PHP (or other programs, Memcache also has other good API interfaces) to use the functions provided by Memcache on the server side. PHP needs to be added with extensions.

4. Summary of all methods of PHP’s Memcache client

The list of all methods of memcache function is as follows:

Memcache::add – Adds a value, returns false if it already exists

Memcache::addServer – Add a server address for use

Memcache::close – Close a Memcache object

Memcache::connect – Create a Memcache object

memcache_debug – Control debugging function

Memcache::decrement - Subtracts the value in a saved key

Memcache::delete – delete a key value

Memcache::flush – Clear all cached data

Memcache::get – Get a key value

Memcache::getExtendedStats – Get the running system statistics of all processes in the process pool

Memcache::getServerStatus – Get the parameters for running the server

Memcache::getStats – Returns some running statistics of the server

Memcache::getVersion – Returns the version information of running Memcache

Memcache::increment - Add the value in a saved key

Memcache::pconnect – Create a Memcache persistent connection object

Memcache::replace - Overwrite an existing key

Memcache::set – Add a value or overwrite it if it already exists

Memcache::setCompressThreshold – Compress data larger than a certain size

Memcache::setServerParams – Modify server parameters at runtime

5. Decomposition of PHP’s Memcache operation method

Memcache::add usage

The code is as follows: bool Memcache::add ( string $key , mixed $var [, int $flag [, int $expire ]] )

Description:

If $key does not exist, use this function to store the value of $var. The functionally equivalent function is memcache_add().

Parameters:

$key: The key value to be stored.

$var: The stored value, character type and integer type will be saved as the original value, other types will be automatically serialized and saved later.

$flag: Whether to use MEMCACHE_COMPRESSED to compress the stored value, true means compression, false means no compression.

$expire: The expiration time of the stored value. If it is 0, it means it will not expire. You can use a unix timestamp or description to represent the time from now, but when you use seconds to express it, it should not exceed 2592000 seconds. (meaning 30 days).

Return value:

Returns TRUE if successful, FALSE if failed. If the $key value already exists, FALSE will be returned. In other cases, the usage of Memcache::add() is similar to Memcache::set().

Example:

The code is as follows:

$memcache_obj = memcache_connect("localhost", 11211);

memcache_add($memcache_obj, 'var_key', 'test variable', false, 30);

$memcache_obj->add('var_key', 'test variable', false, 30);

?>

Memcache::addServer Usage

The code is as follows: bool Memcache::addServer ( string $host [, int $port [, bool $persistent [, int $weight [, int$timeout [, int $retry_interval [, bool $status [, callback $failure_callback ]]]]]]] )

Description:

Add a usable server address to the connection pool. The connection is opened with Memcache::addServer and closed automatically after the script is executed, or it can be closed manually with Memcache::close(). The same function is memcache_add_server().

When using this method (compared to the Memcache::connect() and Memcache::pconnect() methods), the network connection will only be established when needed, so there will be no need to add a lot of servers to the connection pool. And increase the system burden, because many servers may not be used.

Failure recovery will occur at any stage of the execution of this method. As long as other servers are normal, users will not notice the failure of these connection requests. Any kind of socket or memcached server-level error can trigger failover. Normal client errors such as adding an existing key will not trigger failover.

Parameters:

$host server address

$port server port

Whether $persistent is a persistent connection

$weightThe weight of this server among all servers

$timeoutThe duration of the connection

$retry_intervalThe interval between connection retries, the default is 15, set to -1 means no retry

$status controls the online status of the server

$failure_callback allows setting a callback function to handle error messages.

Return value:

Returns TRUE if successful, FALSE if failed.

Example:

The code is as follows:

$memcache = new Memcache;

$memcache->addServer('memcache_host', 11211);

$memcache->addServer('memcache_host2′, 11211);

$memcache_obj = memcache_connect('memcache_host', 11211);

memcache_add_server($memcache_obj, 'memcache_host2′, 11211);

?>

Memcache::close usage

bool Memcache::close (void)

Description:

Close the memcache server connection. This function will not close the long connection. The long connection will only be closed when the web server is shut down or restarted. The same function memcache_close()

Return value:

Returns TRUE if successful, FALSE if failed.

Example:

The code is as follows:

$memcache_obj = memcache_connect('memcache_host', 11211);

memcache_close($memcache_obj);

$memcache_obj = new Memcache;

$memcache_obj->connect('memcache_host', 11211);

$memcache_obj->close();

?>

Memcache::connect usage

The code is as follows: bool Memcache::connect ( string $host [, int $port [, int $timeout ]] )

Description:

Open the memcached server connection and establish a connection to the memcached server. The connection opened with Memcache::connect will be automatically closed after the script is executed. You can also use Memcache::close() to close the connection. The same function is memcache_connect().

Parameters:

$host: Points to the host of the link that memcached is listening to. This parameter will have another special connection method unix:///path/to/memcached.sock, which uses unix domain name sockets. In this case , the port must be set to 0

$port: Points to the port of the link that memcached is listening to. When using unix domain name sockets, the port must be set to 0

$timeout: The number of seconds used to connect to the daemon. When you change the default value of 1 second, you need to consider that if your connection is too slow, you may lose the advantage of caching.

Return value:

Returns TRUE if successful, FALSE if failed.

Example:

The code is as follows:

$memcache_obj = memcache_connect('memcache_host', 11211);

$memcache = new Memcache;

$memcache->connect('memcache_host', 11211);

?>

memcache::debug

The code is as follows: bool memcache_debug ( bool $on_off )

Description:

Control the debugging function, provided that PHP uses the -enable-debug option when compiling, otherwise this function will not have any effect.

Parameters:

$on_off: true means turning on debugging, false means turning off debugging

Return value:

If PHP uses the -enable-debug option when compiling, return true, otherwise return false

Memcache::decrement usage

The code is as follows: int Memcache::decrement ( string $key [, int $value ] )

Description:

The Memcache::decremen method is used to subtract the value in a saved key. Its usage is similar to Memcache::increment.

You can also use the memcache_decrement() function.

Parameters:

Key: the name of the key you want to reduce

Value: The value you want to reduce.

Return value:

If successful, return the reduced value, if failed, return false.

Example:

The code is as follows:

$memcache = new Memcache;

$memcache->connect('localhost', 11211);

$memcache->set('test_item', 8);

$memcache->increment('test_item', 4);

echo $memcache->decrement('test_item', 7);

// Show 5

?>

This example even demonstrates the Memcache::increment function.

Memcache::delete usage

The code is as follows: bool Memcache::delete ( string $key [, int $timeout ] )

Description:

Delete a key value. If the parameter $timeout is set, the stored value will expire after the set seconds. You can also use the function memcache_delete()

Return value:

Returns TRUE if successful, FALSE if failed.

Example:

The code is as follows:

$memcache_obj = memcache_connect('memcache_host', 11211);

memcache_delete($memcache_obj, 'key_to_delete', 10);

$memcache_obj = new Memcache;

$memcache_obj->connect('memcache_host', 11211);

$memcache_obj->delete('key_to_delete', 10);

?>

Memcache::flush

The code is as follows: bool Memcache::flush (void)

Description:

Clear all cached data. Memcache::flush does not actually release resources, it just marks all caches as expired, so that new caches can cover the occupied memory space. The same function is memcache_flush()

Return value:

Returns TRUE if successful, FALSE if failed.

Example:

The code is as follows:

$memcache_obj = memcache_connect('memcache_host', 11211);

memcache_flush($memcache_obj);

$memcache_obj = new Memcache;

$memcache_obj->connect('memcache_host', 11211);

$memcache_obj->flush();

?>

Memcache::get

The code is as follows:

string Memcache::get ( string $key [, int &$flags ] )

array Memcache::get ( array $keys [, array &$flags ] )

Description:

The function of the

method is to obtain a key value. The key value can be an array, and the result will contain key-value pairs.

Parameters:

$key is the key value or an array value of a key.

$flags If this parameter exists, then $flags is related to the value written to this parameter. These $flags are similar to the $flags in the Memcache::set() function.

Return value:

If successful, return the value corresponding to the key, if failed, return false.

Example:

The code is as follows:

$memcache_obj = memcache_connect('memcache_host', 11211);

$var = memcache_get($memcache_obj, 'some_key');

$memcache_obj = new Memcache;

$memcache_obj->connect('memcache_host', 11211);

$var = $memcache_obj->get('some_key');

$memcache_obj = memcache_connect('memcache_host', 11211);

$var = memcache_get($memcache_obj, Array('some_key', 'another_key'));

$memcache_obj = new Memcache;

$memcache_obj->connect('memcache_host', 11211);

$var = $memcache_obj->get(Array('some_key', 'second_key'));

?>

Memcache::getExtendedStats

The code is as follows: array Memcache::getExtendedStats ([ string $type [, int $slabid [, int $limit ]]] )

Description:

Get the running system statistics of all processes in the process pool. The same function is memcache_get_extended_stats()

Parameters:

$type indicates the type required to be returned: reset, malloc, maps, cachedump, slabs, items, sizes;

Used when the first parameter of $slabid is set to "cachedump".

Used when the first parameter of $limit is set to "cachedump".

Return value:

If successful, return statistical information, if failed, return false

Example:

The code is as follows:

$memcache_obj = new Memcache;

$memcache_obj->addServer('memcache_host', 11211);

$memcache_obj->addServer('failed_host', 11211);

$stats = $memcache_obj->getExtendedStats();

//The slabs mechanism allocates and manages memory

$statsslab = $memcache_obj->getExtendedStats(slabs);

?>

Memcache::getServerStatus

The code is as follows: int Memcache::getServerStatus ( string $host [, int $port ] )

Description:

Get the parameters for running the server. Returns the online or offline status of a server. The same function is memcache_get_server_status()

Parameters:

$host: The host of the listening connection

$port The port of the connected host that is listening, the default is 11211

Return value:

The server status is returned successfully. If the server is not started, 0 will be returned. Other numbers indicate that the server is started.

Example:

The code is as follows:

$memcache = new Memcache;

$memcache->addServer('memcache_host', 11211);

echo $memcache->getServerStatus('memcache_host', 11211);

$memcache = memcache_connect('memcache_host', 11211);

echo memcache_get_server_status($memcache, 'memcache_host', 11211);

?>

Memcache::getStats

The code is as follows: array Memcache::getStats ([ string $type [, int $slabid [, int $limit ]]] )

Description:

Returns some running statistics of the server. The same function is memcache_get_stats()

Parameters:

$type indicates the type required to be returned: reset, malloc, maps, cachedump, slabs, items, sizes;

Used when the first parameter of $slabid is set to "cachedump".

Used when the first parameter of $limit is set to "cachedump".

Memcache::getVersion

The code is as follows: string Memcache::getVersion (void)

Description:

Returns the version information of the running Memcache. Same function memcache_get_version()

Return value:

Returns the server version information successfully, and returns false if it fails.

Example:

The code is as follows:

$memcache = new Memcache;

$memcache->connect('memcache_host', 11211);

echo $memcache->getVersion();

$memcache = memcache_connect('memcache_host', 11211);

echo memcache_get_version($memcache);

?>

Memcache::increment

The code is as follows: int Memcache::increment ( string $key [, int $value ] )

Add the value in a saved key

Usage reference Memcache::decrement

Memcache::pconnect

The code is as follows: bool Memcache::pconnect ( string $host [, int $port [, int $timeout ]] )

Description:

Create a Memcache persistent connection object

The usage is similar to Memcache::connect(), the difference is that Memcache::pconnect is a persistent connection established. This connection will not be closed after the script is executed or the Memcache::close() function is run. The same function is memcache_pconnect()

Parameters:

$host: Points to the host of the link that memcached is listening to. This parameter will have another special connection method unix:///path/to/memcached.sock, which uses unix domain name sockets. In this case , the port must be set to 0

$port: Points to the port of the link that memcached is listening to. When using unix domain name sockets, the port must be set to 0

$timeout: The number of seconds used to connect to the daemon. When you change the default value of 1 second, you need to consider that if your connection is too slow, you may lose the advantage of caching.

Return value:

Returns TRUE if successful, FALSE if failed

The code is as follows:

$memcache_obj = memcache_pconnect('memcache_host', 11211);

$memcache_obj = new Memcache;

$memcache_obj->pconnect('memcache_host', 11211);

?>

Memcache::replace

The code is as follows: bool Memcache::replace ( string $key , mixed $var [, int $flag [, int $expire ]] )

Description:

Overwrite an existing key. The same function is memcache_replace()

Parameters:

$key: The key value to be stored.

$var: The stored value, character type and integer type will be saved as the original value, other types will be automatically serialized and saved later.

$flag: Whether to use MEMCACHE_COMPRESSED to compress the stored value, true means compression, false means no compression.

$expire: The expiration time of the stored value. If it is 0, it means it will not expire. You can use a unix timestamp or description to represent the time from now, but when you use seconds to express it, it should not exceed 2592000 seconds. (meaning 30 days).

Return value:

Returns TRUE if successful, FALSE if failed. If the $key value already exists, FALSE will be returned.

The code is as follows:

$memcache_obj = memcache_connect('memcache_host', 11211);

memcache_replace($memcache_obj, "test_key", "some variable", false, 30);

$memcache_obj->replace("test_key", "some variable", false, 30);

?>

Memcache::set

The code is as follows: bool Memcache::set ( string $key , mixed $var [, int $flag [, int $expire ]] )

Description:

Adds a value, or overwrites it if it already exists. The same function is memcache_set()

Parameters:

$key: The key value to be stored.

$var: The stored value, character type and integer type will be saved as the original value, other types will be automatically serialized and saved later.

$flag: Whether to use MEMCACHE_COMPRESSED to compress the stored value, true means compression, false means no compression.

$expire: The expiration time of the stored value. If it is 0, it means it will not expire. You can use a unix timestamp or description to represent the time from now, but when you use seconds to express it, it should not exceed 2592000 seconds. (meaning 30 days).

Return value:

Returns TRUE if successful, FALSE if failed.

Example:

The code is as follows:

$memcache_obj = new Memcache;

$memcache_obj->connect('memcache_host', 11211);

$memcache_obj->set('var_key', 'some really big variable', MEMCACHE_COMPRESSED, 50);

echo $memcache_obj->get('var_key');

Memcache::setCompressThreshold

The code is as follows: bool Memcache::setCompressThreshold ( int $threshold [, float $min_savings ] )

Description:

Compress data larger than a certain size. The same function is memcache_set_compress_threshold()

Parameters:

The setCompressThreshold method has two parameters. The first parameter indicates the critical point of processing data size, and the second parameter indicates the compression ratio. The default is 0.2.

Return value:

Returns TRUE if successful, FALSE if failed.

Example:

The code is as follows:

$memcache_obj = new Memcache;

$memcache_obj->addServer('memcache_host', 11211);

$memcache_obj->setCompressThreshold(20000, 0.2);

$memcache_obj = memcache_connect('memcache_host', 11211);

memcache_set_compress_threshold($memcache_obj, 20000, 0.2);

?>

Memcache::setServerParams

Copy the code as follows: bool Memcache::setServerParams ( string $host [, int $port [, int $timeout [, int$retry_interval [, bool $status [, callback $failure_callback ]]]]] )

Description:

Modify server parameters at runtime. The same function is memcache_set_server_params().

Parameters:

$host server address

$port server port

$timeoutThe duration of the connection

$retry_intervalThe interval between connection retries, the default is 15, set to -1 means no retry

$status controls the online status of the server

$failure_callback allows setting a callback function to handle error messages.

Return value:

Returns TRUE if successful, FALSE if failed.

Example:

The code is as follows:

function _callback_memcache_failure($host, $port) {

print "memcache '$host:$port' failed";

}

$memcache = new Memcache;

//Add a server in offline mode

$memcache->addServer('memcache_host', 11211, false, 1, 1, -1, false);

// Set the server online

$memcache->setServerParams('memcache_host', 11211, 1, 15, true, '_callback_memcache_failure');

$memcache_obj = memcache_connect('memcache_host', 11211);

memcache_set_server_params($memcache_obj, 'memcache_host', 11211, 1, 15, true, '_callback_memcache_failure');

?>

6. Comprehensive usage examples

The code is as follows:

//Connection

$mem = new Memcache;

$mem->connect("db.nowamagic.net", 12000);

//Save data

$mem->set('key1', 'This is first value', 0, 60);

$val = $mem->get('key1');

echo "Get key1 value: " . $val ."
";

//Replace data

$mem->replace('key1', 'This is replace value', 0, 60);

$val = $mem->get('key1');

echo "Get key1 value: " . $val . "
";

//Save the array

$arr = array('aaa', 'bbb', 'ccc', 'ddd');

$mem->set('key2', $arr, 0, 60);

$val2 = $mem->get('key2');

echo "Get key2 value: ";

print_r($val2);

echo "
";

//Delete data

$mem->delete('key1');

$val = $mem->get('key1');

echo "Get key1 value: " . $val . "
";

//Clear all data

$mem->flush();

$val2 = $mem->get('key2');

echo "Get key2 value: ";

print_r($val2);

echo "
";

//Close the connection

$mem->close();

?>

If normal, the browser will output:

The code is as follows:

Get key1 value: This is first value

Get key1 value: This is replace value

Get key2 value: Array ( [0] => aaa [1] => bbb [2] => ccc [3] => ddd )

Get key1 value:

Get key2 value:

7. Example program code analysis

Initialize a Memcache object: $mem = new Memcache;

Connect to our Memcache server. The first parameter is the IP address of the server, which can also be the host name. The second parameter is the open port of Memcache: $mem->connect("192.168.0.200" , 12000);

Save a data to the Memcache server. The first parameter is the key of the data, used to locate a data. The second parameter is the content of the data that needs to be saved. Here is a string. The third parameter is a mark. , generally set to 0 or MEMCACHE_COMPRESSED. The fourth parameter is the validity period of the data, which means that the data is valid within this time. If this time passes, the data will be cleared by the Memcache server. The unit is seconds. If set to 0, it will be valid forever. We set 60 here, which is valid for one minute: $mem->set('key1', 'This is first value', 0, 60);

Get a piece of data from the Memcache server. It has only one parameter, which is the key to get the data. Here is the key1 set in the previous step. Now output the output after getting this data:

The code is as follows:

$val = $mem->get('key1′);

echo "Get key1 value: " . $val;

Now use the replace method to replace the value of key1 above. The parameters of the replace method are the same as set, but the first parameter key1 must be the key to replace the data content. The final output is:

The code is as follows:

$mem->replace('key1', 'This is replace value', 0, 60);

$val = $mem->get('key1');

echo "Get key1 value: " . $val;

Similarly, Memcache can also save arrays. The following is an array saved in Memcache, then retrieved and output:

The code is as follows:

$arr = array('aaa', 'bbb', 'ccc', 'ddd');

$mem->set('key2', $arr, 0, 60);

$val2 = $mem->get('key2');

print_r($val2);

Now delete a piece of data, use the delte interface, the parameter is a key, and then you can delete the data of the key in the Memcache server. There is no result in the final output:

The code is as follows: $mem->delete('key1');

$val = $mem->get('key1');

echo "Get key1 value: " . $val . "
";

Finally, we clear all the data saved on the Memcache server. We will find that the data is gone. The final output key2 data is empty, and finally the connection is closed:

The code is as follows: $mem->flush();

$val2 = $mem->get('key2');

echo "Get key2 value: ";

print_r($val2);

echo "
";

8. When to use Memcache and Memcache usage environment

Websites that use Memcache generally have relatively large traffic. In order to relieve the pressure on the database, Memcache is used as a cache area to save part of the information in the memory, so that it can be accessed quickly on the front end. So the general focus is on how to share database pressure and distribute it. After all, the memory capacity of a single Memcache is limited. I simply put forward my personal opinions here. I have not practiced them and should only be used as a reference.

Distributed Applications

Memcache originally supports distributed distribution, but our client has been slightly modified to provide better support. Our keys can be encapsulated appropriately and regularly. For example, for a user-based website, each user has a User ID, so it can be extracted and accessed according to a fixed ID. For example, users starting with 1 are stored in the first On one Memcache server, the data of users starting with 2 is stored on the second Memcache server. The access data is first converted and accessed according to the User ID.

However, this has the disadvantage that it requires judgment on the User ID. If the business is inconsistent, or other types of applications may not be so suitable, then you can consider it based on your actual business, or think of a more suitable method.

Reduce database pressure

This is quite important. All data is basically stored in the database. Frequent access to the database each time leads to a severe decline in database performance and the inability to serve more users at the same time. For example, MySQL is particularly frequent. lock table, then let Memcache share the pressure on the database. We need a way to change the current architecture in a way that is relatively small and does not require large-scale changes to the front end.

A simple method I considered:

The back-end database operation module extracts all Select operations (regardless of update/delete/insert), and then performs the corresponding hash algorithm on the corresponding SQL to calculate a hash data key (such as MD5 or SHA), and then Search the data for this key in Memcache. If the data does not exist, it means that it has not been written to the cache. Then extract the data from the database, one is in array class format, and then set the data to Memcache. The key is this SQL hash value, and then set an expiration time accordingly, such as one hour, then the data in one hour will be extracted from the cache, effectively reducing the pressure on the database. The disadvantage is that the data is not real-time. When the data is modified, it cannot be displayed on the front end in real time, and it may also occupy a large amount of memory. After all, the amount of data selected each time may be huge. This is a factor that needs to be considered.

9. Security of Memcache

Our above Memcache server is operated directly through the client connection without any verification process. If the server is directly exposed to the Internet, it is more dangerous. At least the data will be leaked and viewed by other unrelated people. More seriously, the server is invaded because Mecache runs with root privileges, and there may be some unknown bugs or buffer overflows in it. These are unknown to us, so the danger is foreseeable. For the sake of security, I would like to make two suggestions to prevent hacker intrusion or data leakage.

Intranet access

It is best to make the access between the two servers in the form of an intranet, usually between the Web server and the Memcache server. Common servers have two network cards, one pointing to the Internet and one pointing to the intranet. Then let the web server access the Memcache server through the intranet network card. When our Memcache server is started, it monitors the IP address and IP address of the intranet. Ports and intranet access can effectively prevent other illegal access.

Copy the code. The code is as follows:# memcached -d -m 1024 -u root -l 192.168.0.200 -p 11211 -c 1024 -P /tmp/memcached.pid

The Memcache server is set to listen to the 11211 port of the 192.168.0.200 IP on the intranet, occupying 1024MB of memory, and allowing a maximum of 1024 concurrent connections.

Set up firewall

Firewall is a simple and effective method. If both servers are connected to the Internet and you need to access Memcache through external IP, you can consider using a firewall or proxy program to filter illegal access. Generally, under Linux, we can use iptables or ipfw under FreeBSD to specify some rules to prevent some illegal access. For example, we can set up to only allow our web server to access our Memcache server, while blocking other access.

Copy the code. The code is as follows: # iptables -F

# iptables -P INPUT DROP

# iptables -A INPUT -p tcp -s 192.168.0.2 –dport 11211 -j ACCEPT

# iptables -A INPUT -p udp -s 192.168.0.2 –dport 11211 -j ACCEPT

The above iptables rule only allows the 192.168.0.2 web server to access the Memcache server, which can effectively prevent some illegal access. Correspondingly, you can also add some other rules to enhance security. This can be based on your own Need to be done.

www.bkjia.comtruehttp: //www.bkjia.com/PHPjc/750258.htmlTechArticleThis article mainly introduces Memcache in PHP. Starting from the introduction of Memcache, it explains in detail such as Memcache and memcached. Differences, all operation methods of PHP's Memcache, details of each operation method...
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