PHP.mk документација

Започнување со градење на mysqlnd приклучок

Почист и полокален преглед на PHP референцата, со задржана структура од PHP.net и подобра читливост за примери, секции и белешки.

mysqlnd.plugin.developing.php PHP.net прокси Преводот се освежува
Оригинал на PHP.net
Патека mysqlnd.plugin.developing.php Локална патека за оваа страница.
Извор php.net/manual/en Оригиналниот HTML се реупотребува и локално се стилизира.
Режим Прокси + превод во позадина Кодовите, табелите и белешките остануваат читливи во истиот тек.
Започнување со градење на mysqlnd приклучок

Референца за `mysqlnd.plugin.developing.php` со подобрена типографија и навигација.

mysqlnd.plugin.developing.php

Започнување со градење на mysqlnd приклучок

Важно е да се запомни дека а mysqlnd приклучок е сам по себе PHP екстензија.

Следната шифра ја покажува основната структура на функцијата MINIT што ќе се користи во типичниот mysqlnd приклучок:

/* my_php_mysqlnd_plugin.c */

 static PHP_MINIT_FUNCTION(mysqlnd_plugin) {
  /* globals, ini entries, resources, classes */

  /* register 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);
}
/* my_mysqlnd_plugin.c */

 enum_func_status MYSQLND_METHOD(mysqlnd_plugin_conn, query)(/* ... */) {
  /* ... */
}
enum_func_status MYSQLND_METHOD(mysqlnd_plugin_conn, connect)(/* ... */) {
  /* ... */
}

Анализа на задачи: од C до кориснички простор

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

Процес:

  1. PHP: корисникот регистрира callback на приклучокот
  2. PHP: корисникот повикува било кој PHP MySQL API за поврзување со MySQL
  3. C: ext/*mysql* повикува mysqlnd метод
  4. C: mysqlnd завршува во ext/mysqlnd_plugin
  5. C: ext/mysqlnd_plugin

    1. Повикува кориснички callback
    2. Или оригиналниот mysqlnd метод, ако корисничкиот callback не е поставен

Треба да го направите следново:

  1. Напишете класа "mysqlnd_plugin_connection" во C
  2. Прифатете и регистрирајте proxy објект преку "mysqlnd_plugin_set_conn_proxy()"
  3. Повикајте кориснички proxy методи од C (оптимизација - zend_interfaces.h)

Корисничките методи на објектот можат да бидат повикани или со користење на call_user_function() или можете да работите на ниво поблиску до Zend Engine и да користите zend_call_method().

Оптимизација: повикување методи од C користејќи zend_call_method

Следнава шифра покажува прототипот за zend_call_method функција, земена од zend_interfaces.h.

 ZEND_API zval* zend_call_method(
  zval **object_pp, zend_class_entry *obj_ce,
  zend_function **fn_proxy, char *function_name,
  int function_name_len, zval **retval_ptr_ptr,
  int param_count, zval* arg1, zval* arg2 TSRMLS_DC
);

Zend API поддржува само два аргументи. Можеби ќе ви требаат повеќе, на пример:

 enum_func_status (*func_mysqlnd_conn__connect)(
  MYSQLND *conn, const char *host,
  const char * user, const char * passwd,
  unsigned int passwd_len, const char * db,
  unsigned int db_len, unsigned int port,
  const char * socket, unsigned int mysql_flags TSRMLS_DC
);

За да го заобиколите овој проблем, ќе треба да направите копија од zend_call_method() и да додадете можност за дополнителни параметри. Ова можете да го направите со креирање на сет од MY_ZEND_CALL_METHOD_WRAPPER macros.

Повикување PHP кориснички простор

Оваа шифра покажува оптимизиран метод за повикување корисничка функција од C:

/* my_mysqlnd_plugin.c */

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) {
    /* call userspace proxy */
    ret = MY_ZEND_CALL_METHOD_WRAPPER(global_user_conn_proxy, host, /*...*/);
  } else {
    /* or original mysqlnd method = do nothing, be transparent */
    ret = org_methods.connect(conn, host, user, passwd,
          passwd_len, db, db_len, port,
          socket, mysql_flags TSRMLS_CC);
  }
  return ret;
}

Повикување кориснички простор: едноставни аргументи

/* my_mysqlnd_plugin.c */

 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);
    /* ... */
  }
  /* ... */
}

Повикување кориснички простор: структури како аргументи

/* my_mysqlnd_plugin.c */

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);
    /* ... */
  }
  /* ... */
}

Првиот аргумент од многу mysqlnd методи е C "објект". На пример, првиот аргумент на методот connect() е покажувач до MYSQLND. Структурата MYSQLND претставува mysqlnd објект за конекција.

На mysqlnd покажувачот на објект за конекција може да се спореди со стандарден I/O рачка за датотека. Како стандардна I/O рачка за датотека mysqlnd објектот за конекција треба да биде поврзан со корисничкиот простор користејќи го типот на променлива ресурс на PHP.

Од C до кориснички простор и назад

 class proxy extends mysqlnd_plugin_connection {
  public function connect($conn, $host, ...) {
    /* "pre" hook */
    printf("Connecting to host = '%s'\n", $host);
    debug_print_backtrace();
    return parent::connect($conn);
  }

  public function query($conn, $query) {
    /* "post" hook */
    $ret = parent::query($conn, $query);
    printf("Query = '%s'\n", $query);
    return $ret;
  }
}
mysqlnd_plugin_set_conn_proxy(new proxy());

Корисниците на PHP мора да можат да ја повикаат родителската имплементација на препишаниот метод.

Како резултат на наследување, можно е да се рафинираат само избрани методи и можете да изберете да имате "пре" или "пост" куки.

Вградена класа: mysqlnd_plugin_connection::connect()

/*  my_mysqlnd_plugin_classes.c */

 PHP_METHOD("mysqlnd_plugin_connection", connect) {
  /* ... simplified! ... */
  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, /* simplified! */ TSRMLS_CC))
    RETVAL_TRUE;
  else
    RETVAL_FALSE;
}

Белешки од корисници

Нема белешки од корисници за оваа страница.
На оваа страница

Автоматски outline од активната документација.

Насловите ќе се појават тука по вчитување.

Попрегледно читање

Примерите, changelog табелите и user notes се визуелно издвоени за да не се губат во долгата содржина.

Брз совет Користи го outline-от Скокни директно на главните секции од активната страница.
Извор Оригиналниот линк останува достапен Кога ти треба целосен upstream context, отвори го PHP.net во нов tab.