Spec-Zone .ru
спецификации, руководства, описания, API

22.9.5.8. API MySQL Native Driver Plugin

Copyright 1997-2012 PHP Documentation Group.

API MySQL Native Driver Plugin является функцией MySQL Native Driver, или mysqlnd. Mysqlnd плагины работают в уровне между приложениями PHP и сервером MySQL. Это сопоставимо с MySQL Proxy. MySQL Proxy управляет на уровне между любым клиентским приложением MySQL, например, приложением PHP и, сервер MySQL. Mysqlnd плагины могут предпринять типичные задачи MySQL Proxy, такие как выравнивание нагрузки, контроль и оптимизация производительности. Из-за различной архитектуры и расположения, mysqlnd у плагинов нет некоторых из недостатков Прокси MySQL. Например, с плагинами, нет никакой единственной точки отказа, никакой выделенный прокси-сервер, чтобы развернуться, и никакой новый язык программирования, чтобы учиться (Lua).

A mysqlnd плагин может считаться расширением mysqlnd. Плагины могут прервать большинство mysqlnd функции. mysqlnd функции вызываются расширениями MySQL PHP такой как ext/mysql, ext/mysqli, и PDO_MYSQL. В результате это возможно для a mysqlnd плагин, чтобы прервать все вызовы, выполненные к этим расширениям из клиентского приложения.

Внутренний mysqlnd вызовы функции могут также быть прерваны, или заменены. Нет никаких ограничений на управление mysqlnd внутренние функциональные таблицы. Возможно установить вещи так, чтобы когда бесспорный mysqlnd функции вызываются расширениями то использование mysqlnd, вызов направляется к соответствующей функции в mysqlnd плагин. Возможность управлять mysqlnd внутренние функциональные таблицы таким образом позволяют максимальную гибкость для плагинов.

Mysqlnd плагины являются фактически Расширениями PHP, записанными в C, то использование mysqlnd сменный API (который встраивается в MySQL Native Driver, mysqlnd). Плагины могут быть сделаны 100 %, прозрачными к приложениям PHP. Никакие изменения приложения не необходимы, потому что плагины работают на различном уровне. mysqlnd плагин может считаться работающий в уровне ниже mysqlnd.

Следующий список представляет некоторые возможные приложения mysqlnd плагины.

MySQL Native Driver Plugins Available

Есть много mysqlnd плагинов, уже доступных. Они включают:

22.9.5.8.1. Сравнение mysqlnd плагинов с MySQL Proxy

Copyright 1997-2012 PHP Documentation Group.

Mysqlnd плагины и MySQL Proxy являются различными технологиями, используя разные подходы. И допустимые инструменты для того, чтобы решить множество общих задач, таких как выравнивание нагрузки, контроль, и улучшения производительности. Важное различие - то, что MySQL Proxy работает со всеми клиентами MySQL, тогда как mysqlnd плагины являются определенными для приложений PHP.

Как Расширение PHP, a mysqlnd плагин устанавливается на сервере приложений PHP, наряду с остальной частью PHP. MySQL Proxy может или быть выполнен на сервере приложений PHP или может быть установлен на выделенной машине, чтобы обработать многократные серверы приложений PHP.

У развертывания MySQL Proxy на сервере приложений есть два преимущества:

  1. Никакая единственная точка отказа

  2. Легкий масштабировать (горизонтальный масштаб, масштабируйтесь клиентом),

MySQL Proxy (и mysqlnd плагины), может решить проблемы легко, которые иначе потребовали бы изменений к существующим приложениям.

Однако, у MySQL Proxy действительно есть некоторые недостатки:

  • MySQL Proxy является новым компонентом и технологией ведущему устройству, и развернуться.

  • MySQL Proxy требует знания языка сценариев Lua.

MySQL Proxy может быть настроен с программированием C и Lua. Lua является привилегированным языком сценариев MySQL Proxy. Поскольку большинство экспертов PHP Луы является новым языком, чтобы учиться. A mysqlnd плагин может быть записан в C. Также возможно записать плагины в PHP, использующем PECL/mysqlnd_uh.

MySQL Proxy работает как демон - фоновый процесс. MySQL Proxy может напомнить более ранние решения, поскольку все состояние может быть сохранено. Однако, a mysqlnd плагин связывается с основанным на запросе жизненным циклом PHP. MySQL Proxy может также совместно использовать одноразовые вычисленные результаты среди многократных серверов приложений. A mysqlnd плагин должен был бы хранить данные в персистентном носителе, чтобы быть в состоянии сделать это. Другой демон должен был бы использоваться с этой целью, такие как Memcache. Это дает MySQL Proxy преимущество в этом случае.

MySQL Proxy работает сверху проводного протокола. С MySQL Proxy необходимо проанализировать и перепроектировать MySQL Client Server Protocol. Действия ограничиваются теми, которые могут быть достигнуты, управляя протоколом связи. Если проводной протокол изменяется (который происходит очень редко), сценарии MySQL Proxy должны были бы быть изменены также.

Mysqlnd плагины работают сверху API C, который зеркально отражает libmysqlclient клиент и API Connector/C. Этот API C является в основном оберткой вокруг протокола MySQL Client Server, или проводного протокола, как это иногда вызывают. Можно прервать все вызовы API C. PHP использует API C, поэтому можно сцепить все вызовы PHP без потребности программировать на уровне проводного протокола.

Mysqlnd реализует проводной протокол. Плагины могут поэтому проанализировать, перепроектировать, управлять и даже заменить протокол связи. Однако, это обычно не требуется.

Поскольку плагины позволяют Вам создавать реализации, которые используют два уровня (C API и соединяют протокол проводом), у них есть большая гибкость чем MySQL Proxy. Если a mysqlnd плагин реализуется, используя API C, любые последующие изменения к проводному протоколу не требуют изменений к плагину непосредственно.

22.9.5.8.2. Получение mysqlnd сменного API

Copyright 1997-2012 PHP Documentation Group.

mysqlnd сменный API является просто частью расширения MySQL Native Driver PHP, ext/mysqlnd. Разработка, запущенная на mysqlnd сменный API в декабре 2009. Это разрабатывается, поскольку часть исходного репозитария PHP, и как таковой доступна общественности или через Мерзавца, или посредством исходных загрузок снимка.

Следующая таблица показывает версии PHP и соответствие mysqlnd версия, содержавшая в пределах.

Таблица 22.69. Связанная mysqlnd версия на выпуск PHP

Версия PHP Версия MySQL Native Driver
5.3.0 5.0.5
5.3.1 5.0.5
5.3.2 5.0.7
5.3.3 5.0.7
5.3.4 5.0.7

Сменные разработчики могут определить mysqlnd версия посредством доступа MYSQLND_VERSION, который является строкой формата "mysqlnd 5.0.7-dev - 091210 - $Revision: 300535", или через MYSQLND_VERSION_ID, который является целым числом такой как 50007. Разработчики могут вычислить номер версии следующим образом:

Таблица 22.70. Таблица вычисления MYSQLND_VERSION_ID

Версия (часть) Пример
Major*10000 5*10000 = 50000
Minor*100 0*100 = 0
Патч 7 = 7
MYSQLND_VERSION_ID 50007

Во время разработки разработчики должны обратиться к mysqlnd номер версии для совместимости и тестов версии, как несколько итераций mysqlnd мог произойти во время времени жизни ответвления разработки PHP с единственным номером версии PHP.

22.9.5.8.3. MySQL Native Driver Plugin Architecture

Copyright 1997-2012 PHP Documentation Group.

Этот раздел обеспечивает краткий обзор mysqlnd сменная архитектура.

MySQL Native Driver Overview

Перед разработкой mysqlnd плагины, полезно знать немногое как mysqlnd непосредственно организуется. Mysqlnd состоит из следующих модулей:

Таблица 22.71. mysqlnd организационная схема, на модуль

Статистика модулей mysqlnd_statistics.c
Соединение mysqlnd.c
Набор результатов mysqlnd_result.c
Метаданные набора результатов mysqlnd_result_meta.c
Оператор mysqlnd_ps.c
Сеть mysqlnd_net.c
Проводной протокол mysqlnd_wireprotocol.c

C Объектно-ориентированная Парадигма

На уровне кода, mysqlnd использует образец C для того, чтобы реализовать объектную ориентацию.

В C Вы используете a struct представлять объект. Элементы struct представляют объектные свойства. Элементы Struct, указывающие на функции, представляют методы.

В отличие от этого с другими языками, такими как C++ или Java, нет никаких закрепленных правил о наследовании в объектно-ориентированной парадигме C. Однако, есть некоторые соглашения, которые должны сопровождаться, который будет обсужден позже.

Жизненный цикл PHP

Рассматривая жизненный цикл PHP есть два основных цикла:

  • Запуск механизма PHP и цикл завершения работы

  • Цикл запроса

То, когда механизм PHP запустит это, вызовет инициализацию модуля (MINIT) функция каждого зарегистрированного расширения. Это позволяет каждому модулю устанавливать переменные и выделять ресурсы, которые будут существовать для времени жизни процесса механизма PHP. Когда механизм PHP завершит работу, он вызовет завершение работы модуля (MSHUTDOWN) функция каждого расширения.

Во время времени жизни механизма PHP это получит много запросов. Каждый запрос составляет другой жизненный цикл. По каждому запросу механизм PHP вызовет функцию инициализации запроса каждого расширения. Расширение может выполнить любую переменную установку и распределение ресурсов, требуемое для обработки запросов. Поскольку цикл запроса заканчивает вызовы механизма завершение работы запроса (RSHUTDOWN) функция каждого расширения, таким образом, расширение может выполнить любую требуемую уборку.

Как работает плагин

A mysqlnd сменные работы, прерывая вызовы, выполненные к mysqlnd расширениями то использование mysqlnd. Это достигается, получая mysqlnd функциональная таблица, поддерживая это, и заменяя это пользовательской функциональной таблицей, которая вызывает функции плагина как требуется.

Следующий код показывает как mysqlnd функциональная таблица заменяется:

/* a place to store original function table */struct st_mysqlnd_conn_methods org_methods;void minit_register_hooks(TSRMLS_D) {  /* active function table */  struct st_mysqlnd_conn_methods * current_methods    = mysqlnd_conn_get_methods();  /* backup original function table */  memcpy(&org_methods, current_methods,    sizeof(struct st_mysqlnd_conn_methods);  /* install new methods */  current_methods->query = MYSQLND_METHOD(my_conn_class, query);}

Табличные манипуляции функцией соединения должны быть сделаны во время Инициализации Модуля (MINIT). Функциональная таблица является глобальным совместно используемым ресурсом. В многопоточной среде, с TSRM создают, манипулирование глобальным совместно используемым ресурсом во время обработки запросов почти наверняка приведет к конфликтам.

Отметить

Не используйте логику фиксированного размера, управляя mysqlnd функциональная таблица: новые методы могут быть добавлены в конце функциональной таблицы. Функциональная таблица может измениться в любое время в будущем.

Вызов родительских методов

Если исходные функциональные записи таблицы поддерживаются, все еще возможно вызвать исходные функциональные записи таблицы - родительские методы.

В некоторых случаях, такой что касается Connection::stmt_init(), жизненно важно вызвать родительский метод до любого другого действия в полученном методе.

MYSQLND_METHOD(my_conn_class, query)(MYSQLND *conn,  const char *query, unsigned int query_len TSRMLS_DC) {  php_printf("my_conn_class::query(query = %s)\n", query);  query = "SELECT 'query rewritten' FROM DUAL";  query_len = strlen(query);  return org_methods.query(conn, query, query_len); /* return with call to parent */}

Расширение свойств

A mysqlnd объект представляется C struct. Не возможно добавить элемент к C struct во время выполнения. Пользователи mysqlnd объекты не могут просто добавить свойства к объектам.

Произвольные данные (свойства) могут быть добавлены к a mysqlnd объекты используя соответствующую функцию mysqlnd_plugin_get_plugin_<object>_data() семейство. Выделяя объект mysqlnd резервы располагают с интервалами в конце объекта содержать a void * указатель на произвольные данные. mysqlnd резервы располагают с интервалами для одного void * указатель на плагин.

Следующая таблица показывает, как вычислить позицию указателя для определенного плагина:

Таблица 22.72. Вычисления указателя для mysqlnd

Адрес памяти Содержание
0 Начало mysqlnd возражает C struct
n Конец mysqlnd возражает C struct
n + (м. x sizeof (освобождают *)), void*, чтобы возразить данным м. th плагин

Если Вы планируете разделить какой-либо на подклассы из mysqlnd возразите конструкторам, который позволяется, следует помнить это!

Следующие выставочные свойства расширения кода:

/* any data we want to associate */typedef struct my_conn_properties {  unsigned long query_counter;} MY_CONN_PROPERTIES;/* plugin id */unsigned int my_plugin_id;void minit_register_hooks(TSRMLS_D) {  /* obtain unique plugin ID */  my_plugin_id = mysqlnd_plugin_register();  /* snip - see Extending Connection: methods */}static MY_CONN_PROPERTIES** get_conn_properties(const MYSQLND *conn TSRMLS_DC) {  MY_CONN_PROPERTIES** props;  props = (MY_CONN_PROPERTIES**)mysqlnd_plugin_get_plugin_connection_data(    conn, my_plugin_id);  if (!props || !(*props)) {    *props = mnd_pecalloc(1, sizeof(MY_CONN_PROPERTIES), conn->persistent);    (*props)->query_counter = 0;  }  return props;}

Сменный разработчик ответственен за управление сменной памятью данных.

Использование mysqlnd средство выделения памяти рекомендуется для сменных данных. Эти функции называют, используя соглашение: mnd_*loc(). mysqlnd у средства выделения есть некоторые полезные функции, такие как возможность использовать средство выделения отладки в неотладочная сборка.

Таблица 22.73. Когда и как разделить на подклассы

Когда разделить на подклассы? У каждого экземпляра есть своя собственная таблица закрытой функции? Как разделить на подклассы?
Соединение (MYSQLND) MINIT Нет mysqlnd_conn_get_methods ()
Набор результатов (MYSQLND_RES) MINIT или позже Да mysqlnd_result_get_methods () или объектная работа с таблицами функции метода
Набор результатов Мета (MYSQLND_RES_METADATA) MINIT Нет mysqlnd_result_metadata_get_methods ()
Оператор (MYSQLND_STMT) MINIT Нет mysqlnd_stmt_get_methods ()
Сеть (MYSQLND_NET) MINIT или позже Да mysqlnd_net_get_methods () или объектная работа с таблицами функции метода
Проводной протокол (MYSQLND_PROTOCOL) MINIT или позже Да mysqlnd_protocol_get_methods () или объектный метод функционируют tablemanipulation

Не следует управлять функциональными таблицами в любое время позже чем MINIT, если он не позволяется согласно вышеупомянутой таблице.

Некоторые классы содержат указатель на таблицу функции метода. Все экземпляры такого class совместно используют ту же самую функциональную таблицу. Чтобы избежать хаоса, в особенности в поточных средах, такими функциональными таблицами нужно только управлять во время MINIT.

Другие классы используют копии глобально совместно используемой функциональной таблицы. Табличная копия функции class создается вместе с объектом. Каждый объект использует свою собственную функциональную таблицу. Это дает Вам две опции: можно управлять таблицей функции значения по умолчанию объекта в MINIT, и можно дополнительно совершенствовать методы объекта, не воздействуя на другие экземпляры того же самого class.

Преимущество совместно используемого функционального табличного подхода является производительностью. Нет никакой потребности скопировать функциональную таблицу для каждого объекта.

Таблица 22.74. Состояние конструктора

Выделение, конструкция, сбрасывается Может быть изменен? Вызывающая сторона
Соединение (MYSQLND) mysqlnd_init () Нет mysqlnd_connect ()
Набор результатов (MYSQLND_RES)

Выделение:

  • Соединение:: result_init ()

Сброс и повторно инициализированный во время:

  • Результат:: use_result ()

  • Результат:: store_result

Да, но родитель вызова!
  • Соединение:: list_fields ()

  • Оператор:: get_result ()

  • Оператор:: подготовьтесь () (Метаданные только)

  • Оператор:: resultMetaData ()

Набор результатов Мета (MYSQLND_RES_METADATA) Соединение:: result_meta_init () Да, но родитель вызова! Результат:: read_result_metadata ()
Оператор (MYSQLND_STMT) Соединение:: stmt_init () Да, но родитель вызова! Соединение:: stmt_init ()
Сеть (MYSQLND_NET) mysqlnd_net_init () Нет Соединение:: init ()
Проводной протокол (MYSQLND_PROTOCOL) mysqlnd_protocol_init () Нет Соединение:: init ()

Строго рекомендуется, чтобы Вы не полностью заменили конструктора. Конструкторы выполняют выделения памяти. Выделения памяти жизненно важны для mysqlnd сменный API и объектная логика mysqlnd. Если Вы не заботитесь о предупреждениях и настаиваете на том, чтобы сцеплять конструкторов, следует, по крайней мере, вызвать родительского конструктора прежде, чем сделать что-либо в Вашем конструкторе.

Независимо от всех предупреждений может быть полезно разделить конструкторов на подклассы. Конструкторы являются совершенным местом для того, чтобы изменить функциональные таблицы объектов с несовместно используемыми объектными таблицами, такими как Набор результатов, Сеть, Проводной Протокол.

Таблица 22.75. Состояние разрушения

Полученный метод должен вызвать родителя? Деструктор
Соединение да, после выполнения метода free_contents (), end_psession ()
Набор результатов да, после выполнения метода free_result ()
Набор результатов Мета да, после выполнения метода свободный ()
Оператор да, после выполнения метода dtor (), free_stmt_content ()
Сеть да, после выполнения метода свободный ()
Проводной протокол да, после выполнения метода свободный ()

Деструкторы являются соответствующим местом к свободным свойствам, mysqlnd_plugin_get_plugin_<object>_data().

Перечисленные деструкторы, возможно, не эквивалентны фактическому mysqlnd метод освобождая объект непосредственно. Однако, они - самое лучшее место для Вас, чтобы сцепиться в и освободить Ваши сменные данные. Как с конструкторами можно заменить методы полностью, но это не рекомендуется. Если многократные методы будут перечислены в вышеупомянутой таблице, то Вы должны будете сцепить все перечисленные методы и освободить Ваши сменные данные в том, какой бы ни методом вызывают сначала mysqlnd.

Рекомендуемый метод для плагинов должен просто сцепить методы, освободить Вашу память и сразу вызвать родительскую реализацию после этого.

Предостережение

Из-за ошибки в версиях PHP 5.3.0 к 5.3.3, плагины не связывают сменные данные с персистентным соединением. Это то, потому что ext/mysql и ext/mysqli не инициируйте все необходимое mysqlnd end_psession() вызовы метода и плагин могут поэтому пропустить память. Это было фиксировано в PHP 5.3.4.

22.9.5.8.4. mysqlnd сменный API

Copyright 1997-2012 PHP Documentation Group.

Следующее является списком функций, обеспеченных в mysqlnd сменный API:

  • mysqlnd_plugin_register ()

  • mysqlnd_plugin_count ()

  • mysqlnd_plugin_get_plugin_connection_data ()

  • mysqlnd_plugin_get_plugin_result_data ()

  • mysqlnd_plugin_get_plugin_stmt_data ()

  • mysqlnd_plugin_get_plugin_net_data ()

  • mysqlnd_plugin_get_plugin_protocol_data ()

  • mysqlnd_conn_get_methods ()

  • mysqlnd_result_get_methods ()

  • mysqlnd_result_meta_get_methods ()

  • mysqlnd_stmt_get_methods ()

  • mysqlnd_net_get_methods ()

  • mysqlnd_protocol_get_methods ()

Нет никакого формального определения того, что плагин и как работает сменный механизм.

Компоненты, часто находимые в механизмах плагинов:

  • Сменный менеджер

  • Сменный API

  • Прикладные службы (или модули)

  • API прикладной службы (или API модуля)

mysqlnd сменное понятие использует эти функции, и дополнительно обладает открытой архитектурой.

Никакие Ограничения

У плагина есть полный доступ к внутренним работам mysqlnd. Нет никаких пределов безопасности или ограничений. Все может быть перезаписано, чтобы реализовать дружественные или враждебные алгоритмы. Рекомендуется, чтобы Вы только развернули плагины из доверяемого источника.

Как обсуждено ранее, плагины могут использовать указатели свободно. Эти указатели не ограничиваются всегда, и могут указать в данные другого плагина. Простая арифметика смещения может использоваться, чтобы считать данные другого плагина.

Рекомендуется, чтобы Вы записали совместные плагины, и что Вы всегда вызываете родительский метод. Плагины должны всегда сотрудничать с mysqlnd непосредственно.

Таблица 22.76. Проблемы: пример объединения в цепочку и сотрудничества

Расширение mysqlnd.query () указатель стек вызовов, вызывая родителя
ext/mysqlnd mysqlnd.query () mysqlnd.query
ext/mysqlnd_cache mysqlnd_cache.query ()
  1. mysqlnd_cache.query ()

  2. mysqlnd.query

ext/mysqlnd_monitor mysqlnd_monitor.query ()
  1. mysqlnd_monitor.query ()

  2. mysqlnd_cache.query ()

  3. mysqlnd.query


В этом сценарии, кэш (ext/mysqlnd_cache) и монитор (ext/mysqlnd_monitor) плагин загружается. Оба подкласса Connection::query(). Сменная регистрация происходит в MINIT использование логики, показанной ранее. PHP вызывает расширения в алфавитном порядке по умолчанию. Плагины не знают о друг друге и не устанавливают зависимости от расширения.

По умолчанию плагины вызывают родительскую реализацию метода запроса в их полученной версии метода.

Резюме Расширения PHP

Это - резюме того, что происходит при использовании плагина в качестве примера, ext/mysqlnd_plugin, который представляет mysqlnd C сменный API к PHP:

  • Любое приложение MySQL PHP пытается установить соединение с 192.168.2.29

  • Приложение PHP будет или использовать ext/mysql, ext/mysqli или PDO_MYSQL. Все три использования расширений MySQL PHP mysqlnd установить соединение с 192.168.2.29.

  • Mysqlnd вызовы соединять метод, который был разделен на подклассы ext/mysqlnd_plugin.

  • ext/mysqlnd_plugin вызывает рычаг пространства пользователя proxy::connect() зарегистрированный пользователем.

  • Рычаг пространства пользователя изменяет IP узла соединения от 192.168.2.29 до 127.0.0.1 и возвращает соединение, установленное parent::connect().

  • ext/mysqlnd_plugin выполняет эквивалент parent::connect(127.0.0.1) вызывая оригинал mysqlnd метод для того, чтобы установить соединение.

  • ext/mysqlnd устанавливает соединение и возвращается к ext/mysqlnd_plugin. ext/mysqlnd_plugin возвраты также.

  • Независимо от того, что расширение MySQL PHP использовалось приложением, оно получает соединение с 127.0.0.1. Расширение MySQL PHP возвращается к приложению PHP. Круг закрывается.

22.9.5.8.5. Начинающий, создавая mysqlnd плагин

Copyright 1997-2012 PHP Documentation Group.

Важно помнить это a 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: пользователь регистрирует сменный обратный вызов

  2. PHP: пользователь вызывает любой API MySQL PHP, чтобы соединиться с MySQL

  3. C: ext/*mysql* вызывает mysqlnd метод

  4. C: mysqlnd заканчивается ext/mysqlnd_plugin

  5. C: ext/mysqlnd_plugin

    1. Обратный вызов пространства пользователя вызовов

    2. Или исходный mysqlnd метод, если обратный вызов пространства пользователя не набор

Вы должны выполнить следующее:

  1. Запишите class "mysqlnd_plugin_connection" в C

  2. Примите и зарегистрируйте объект прокси через "mysqlnd_plugin_set_conn_proxy ()"

  3. Вызовите методы прокси пространства пользователя от C (оптимизация - zend_interfaces.h)

Методы объекта пространства пользователя можно или вызвать, используя call_user_function() или можно работать на уровне ближе к Механизму Зенда и использованию 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);

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 макросы.

Вызов пространство пользователя 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);    /* ... */  }  /* ... */}

Вызов пространства пользователя: structs как параметры

/* 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 "объект". Например, первым параметром соединения () метод является указатель на MYSQLND. struct MYSQLND представляет a mysqlnd объект соединения.

mysqlnd указатель объекта соединения может быть по сравнению со стандартным дескриптором файла ввода-вывода. Как стандартный дескриптор файла a ввода-вывода 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 должны быть в состоянии вызвать родительскую реализацию перезаписанного метода.

В результате разделения на подклассы возможно совершенствовать только выбранные методы, и можно хотеть иметь "пред" или рычаги "сообщения".

Buildin class: mysqlnd_plugin_connection:: соединитесь ()

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