Empezar a construir un complemento de mysqlnd

Es importante recordar que un complemento de mysqlnd es una extensión de PHP en sí mismo.

El siguiente código muestra la estructura básica de la función MINIT que se usará en el típico complemento de mysqlnd:

 static PHP_MINIT_FUNCTION(mysqlnd_plugin) { mysqlnd_plugin_id = mysqlnd_plugin_register(); conn_m = mysqlnd_get_conn_methods(); memcpy(org_conn_m, conn_m, sizeof(struct st_mysqlnd_conn_methods)); conn_m->query = MYSQLND_METHOD(mysqlnd_plugin_conn, query); conn_m->connect = MYSQLND_METHOD(mysqlnd_plugin_conn, connect); } 
 enum_func_status MYSQLND_METHOD(mysqlnd_plugin_conn, query)() { } enum_func_status MYSQLND_METHOD(mysqlnd_plugin_conn, connect)() { } 

Análisis de tareas: de C al espacio de usuario

 class proxy extends mysqlnd_plugin_connection { public function connect($host, ...) { .. } } mysqlnd_plugin_set_conn_proxy(new proxy()); 

Proceso:

  1. PHP: el usuario registra la llamada de retorno del complemento

  2. PHP: el usuario llama a cualquier API de MySQL de PHP para conectarse a MySQL

  3. C: ext MYSQLND_METHOD(my_conn_class,connect)( MYSQLND *conn, const char *host TSRMLS_DC) { enum_func_status ret = FAIL; zval * global_user_conn_proxy = fetch_userspace_proxy(); if (global_user_conn_proxy) { ret = MY_ZEND_CALL_METHOD_WRAPPER(global_user_conn_proxy, host, ); } else { ret = org_methods.connect(conn, host, user, passwd, passwd_len, db, db_len, port, socket, mysql_flags TSRMLS_CC); } return ret; }

Llamar al espacio de usuario: argumentos simples

 MYSQLND_METHOD(my_conn_class,connect)( , const char *host, ) { if (global_user_conn_proxy) { zval* zv_host; MAKE_STD_ZVAL(zv_host); ZVAL_STRING(zv_host, host, 1); MY_ZEND_CALL_METHOD_WRAPPER(global_user_conn_proxy, zv_retval, zv_host ); zval_ptr_dtor(&zv_host); } } 

Llamar al espacio de usuario: estrucutras como argumentos

 MYSQLND_METHOD(my_conn_class, connect)( MYSQLND *conn, ) { if (global_user_conn_proxy) { zval* zv_conn; ZEND_REGISTER_RESOURCE(zv_conn, (void *)conn, le_mysqlnd_plugin_conn); MY_ZEND_CALL_METHOD_WRAPPER(global_user_conn_proxy, zv_retval, zv_conn, zv_host ); zval_ptr_dtor(&zv_conn); } } 

El primer argumento de la mayoría de los métodos de mysqlnd es un "objeto" de C. Por ejemplo, el primer argumento del método connect() es un puntero a MYSQLND. La estructura MYSQLND representa un objeto de conexión de mysqlnd.

El puntero del objeto de conexión de mysqlnd puede ser comparado con un gestor de ficheros de E/S estándar. Al igual que un gestor de ficheros de E/S estándar, un objeto de conexión de mysqlnd será vinculado al espacio de usuario usando el tipo de variable de recurso de PHP.

Desde C al espacio de usuario y volver

 class proxy extends mysqlnd_plugin_connection { public function connect($conn, $host, ...) { printf("Connecting to host = '%s'\n", $host); debug_print_backtrace(); return parent::connect($conn); } public function query($conn, $query) { $ret = parent::query($conn, $query); printf("Query = '%s'\n", $query); return $ret; } } mysqlnd_plugin_set_conn_proxy(new proxy()); 

Los usuario de PHP pueden llamar a la implementación padre de un método sobrescrito.

Como resultado de la derivación, es posible refinar solamente los métodos seleccionados, y se puede optar por tener "pre" o "post" enganches.

Contruir la clase: mysqlnd_plugin_connection::connect()

 PHP_METHOD("mysqlnd_plugin_connection", connect) { zval* mysqlnd_rsrc; MYSQLND* conn; char* host; int host_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &mysqlnd_rsrc, &host, &host_len) == FAILURE) { RETURN_NULL(); } ZEND_FETCH_RESOURCE(conn, MYSQLND* conn, &mysqlnd_rsrc, -1, "Mysqlnd Connection", le_mysqlnd_plugin_conn); if (PASS == org_methods.connect(conn, host, TSRMLS_CC)) RETVAL_TRUE; else RETVAL_FALSE; } 
To Top