Installing a proxy

The extension provides two built-in classes: MysqlndUhConnection and MysqlndUhPreparedStatement. The classes are used for hooking mysqlnd library calls. Their methods correspond to mysqlnd internal functions. By default they act like a transparent proxy and do nothing but call their mysqlnd counterparts. By subclassing the classes you can install your own proxy to monitor mysqlnd.

See also the How it works guide to learn about the inner workings of this extension.

Connection proxies are objects of the type MysqlndUhConnection. Connection proxy objects are installed by mysqlnd_uh_set_connection_proxy(). If you install the built-in class MysqlndUhConnection as a proxy, nothing happens. It behaves like a transparent proxy.

Example #1 Proxy registration, mysqlnd_uh.enable=1

<?php
mysqlnd_uh_set_connection_proxy
(new MysqlndUhConnection());
$mysqli = new mysqli("localhost""root""""test");
?>

The PHP_INI_SYSTEM configuration setting mysqlnd_uh.enable controls whether a proxy may be set. If disabled, the extension will throw errors of type E_WARNING

Example #2 Proxy installation disabled

mysqlnd_uh.enable=0
<?php
mysqlnd_uh_set_connection_proxy
(new MysqlndUhConnection());
$mysqli = new mysqli("localhost""root""""test");
?>

以上例程会输出:

PHP Warning:  MysqlndUhConnection::__construct(): (Mysqlnd User Handler) The plugin has been disabled by setting the configuration parameter mysqlnd_uh.enabled = false.  You must not use any of the base classes in %s on line %d
PHP Warning:  mysqlnd_uh_set_connection_proxy(): (Mysqlnd User Handler) The plugin has been disabled by setting the configuration parameter mysqlnd_uh.enable = false. The proxy has not been installed  in %s on line %d

To monitor mysqlnd, you have to write your own proxy object subclassing MysqlndUhConnection. Please, see the function reference for a the list of methods that can be subclassed. Alternatively, you can use reflection to inspect the built-in MysqlndUhConnection.

Create a new class proxy. Derive it from the built-in class MysqlndUhConnection. Replace the MysqlndUhConnection::connect(). method. Print out the host parameter value passed to the method. Make sure that you call the parent implementation of the connect method. Failing to do so may give unexpected and undesired results, including memory leaks and crashes.

Register your proxy and open three connections using the PHP MySQL extensions mysqli, mysql, PDO_MYSQL. If the extensions have been compiled to use the mysqlnd library, the proxy::connect method will be called three times, once for each connection opened.

Example #3 Connection proxy

<?php
class proxy extends MysqlndUhConnection {
  public function 
connect($res$host$user$passwd$db$port$socket$mysql_flags) {
   
printf("Connection opened to '%s'\n"$host);
   
/* Always call the parent implementation! */
   
return parent::connect($res$host$user$passwd$db$port$socket$mysql_flags);
  }
}
mysqlnd_uh_set_connection_proxy(new proxy());

$mysqli = new mysqli("localhost""root""""test");
$mysql mysql_connect("localhost""root""");
$pdo = new PDO("mysql:host=localhost;dbname=test""root""");
?>

以上例程会输出:

Connection opened to 'localhost'
Connection opened to 'localhost'
Connection opened to 'localhost'

The use of prepared statement proxies follows the same pattern: create a proxy object of the type MysqlndUhPreparedStatement and install the proxy using mysqlnd_uh_set_statement_proxy().

Example #4 Prepared statement proxy

<?php
class stmt_proxy extends MysqlndUhPreparedStatement {
 public function 
prepare($res$query) {
  
printf("%s(%s)\n"__METHOD__$query);
  return 
parent::prepare($res$query);
 }
}
mysqlnd_uh_set_statement_proxy(new stmt_proxy());

$mysqli = new mysqli("localhost""root""""test");
$stmt $mysqli->prepare("SELECT 'mysqlnd hacking made easy' AS _msg FROM DUAL");
?>

以上例程会输出:

stmt_proxy::prepare(SELECT 'mysqlnd hacking made easy' AS _msg FROM DUAL)

关注编程学问公众号