Spec-Zone .ru
спецификации, руководства, описания, API
|
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
плагины.
Выравнивание нагрузки
Разделение чтения-записи. Примером этого является PECL/mysqlnd_ms (Основное Ведомое устройство) расширение. Это расширение разделяет запросы чтения-записи для установки репликации.
Failover
Круговой, наименее загруженный
Контроль
Журналирование запроса
Анализ запроса
Контроль запроса. Примером этого является PECL/mysqlnd_sip (Защита Инжекции SQL) расширение. Это расширение осматривает запросы и выполняет только тех, которые разрешаются согласно ruleset.
Производительность
Кэширование. Примером этого является PECL/mysqlnd_qc (Кэш Запроса) расширение.
Регулировка
Sharding. Примером этого является PECL/mysqlnd_mc (Много, Соединяются), расширение. Это расширение попытается разделить оператор SELECT на n-части, используя ИЗБРАННЫЙ... ОГРАНИЧЬТЕ part_1, ВЫБЕРИТЕ ПРЕДЕЛ part_n. Это отправляет запросы отличным серверам MySQL и объединяет результат в клиенте.
MySQL Native Driver Plugins Available
Есть много mysqlnd плагинов, уже доступных. Они включают:
PECL/mysqlnd_mc - Много Соединяют плагин.
PECL/mysqlnd_ms - Основной Ведомый плагин.
PECL/mysqlnd_qc - плагин Кэша Запроса.
PECL/mysqlnd_pscache - Готовый плагин Кэша описателей Оператора.
PECL/mysqlnd_sip - плагин Защиты Инжекции SQL.
PECL/mysqlnd_uh - Пользовательский плагин Обработчика.
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 на сервере приложений есть два преимущества:
Никакая единственная точка отказа
Легкий масштабировать (горизонтальный масштаб, масштабируйтесь клиентом),
MySQL Proxy (и mysqlnd
плагины), может решить проблемы легко, которые иначе
потребовали бы изменений к существующим приложениям.
Однако, у MySQL Proxy действительно есть некоторые недостатки:
MySQL Proxy является новым компонентом и технологией ведущему устройству, и развернуться.
MySQL Proxy требует знания языка сценариев Lua.
MySQL Proxy может быть настроен с программированием C и Lua. Lua является привилегированным языком сценариев
MySQL Proxy. Поскольку большинство экспертов PHP Луы является новым языком, чтобы учиться. A mysqlnd
плагин может быть записан в C. Также возможно записать плагины в PHP,
использующем
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, любые последующие изменения к проводному протоколу не требуют изменений
к плагину непосредственно.
Copyright 1997-2012 PHP Documentation Group.
mysqlnd
сменный API является просто частью расширения MySQL Native Driver PHP,
ext/mysqlnd
. Разработка, запущенная на mysqlnd
сменный API в декабре 2009. Это разрабатывается, поскольку часть исходного репозитария PHP, и как таковой
доступна общественности или через Мерзавца, или посредством исходных загрузок снимка.
Следующая таблица показывает версии PHP и соответствие mysqlnd
версия,
содержавшая в пределах.
Таблица 21.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. Разработчики
могут вычислить номер версии следующим образом:
Таблица 21.70. Таблица вычисления MYSQLND_VERSION_ID
Версия (часть) | Пример |
---|---|
Major*10000 | 5*10000 = 50000 |
Minor*100 | 0*100 = 0 |
Патч | 7 = 7 |
MYSQLND_VERSION_ID | 50007 |
Во время разработки разработчики должны обратиться к mysqlnd
номер версии для
совместимости и тестов версии, как несколько итераций mysqlnd
мог произойти во
время времени жизни ответвления разработки PHP с единственным номером версии PHP.
Copyright 1997-2012 PHP Documentation Group.
Этот раздел обеспечивает краткий обзор mysqlnd
сменная архитектура.
MySQL Native Driver Overview
Перед разработкой mysqlnd
плагины, полезно знать немногое как mysqlnd
непосредственно организуется. Mysqlnd
состоит из следующих модулей:
Таблица 21.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 *
указатель на плагин.
Следующая таблица показывает, как вычислить позицию указателя для определенного плагина:
Таблица 21.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
у средства выделения есть некоторые полезные функции, такие как
возможность использовать средство выделения отладки в неотладочная сборка.
Таблица 21.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.
Преимущество совместно используемого функционального табличного подхода является производительностью. Нет никакой потребности скопировать функциональную таблицу для каждого объекта.
Таблица 21.74. Состояние конструктора
Выделение, конструкция, сбрасывается | Может быть изменен? | Вызывающая сторона | |
Соединение (MYSQLND) | mysqlnd_init () | Нет | mysqlnd_connect () |
Набор результатов (MYSQLND_RES) | Выделение:
Сброс и повторно инициализированный во время:
|
Да, но родитель вызова! |
|
Набор результатов Мета (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
. Если Вы не заботитесь о предупреждениях и настаиваете на том, чтобы
сцеплять конструкторов, следует, по крайней мере, вызвать родительского конструктора прежде, чем сделать
что-либо в Вашем конструкторе.
Независимо от всех предупреждений может быть полезно разделить конструкторов на подклассы. Конструкторы являются совершенным местом для того, чтобы изменить функциональные таблицы объектов с несовместно используемыми объектными таблицами, такими как Набор результатов, Сеть, Проводной Протокол.
Таблица 21.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.
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
непосредственно.
Таблица 21.76. Проблемы: пример объединения в цепочку и сотрудничества
Расширение | mysqlnd.query () указатель | стек вызовов, вызывая родителя |
ext/mysqlnd | mysqlnd.query () | mysqlnd.query |
ext/mysqlnd_cache | mysqlnd_cache.query () |
|
ext/mysqlnd_monitor | mysqlnd_monitor.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. Круг закрывается.
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());
Процесс:
PHP: пользователь регистрирует сменный обратный вызов
PHP: пользователь вызывает любой API MySQL PHP, чтобы соединиться с MySQL
C: ext/*mysql* вызывает mysqlnd метод
C: mysqlnd заканчивается ext/mysqlnd_plugin
C: ext/mysqlnd_plugin
Обратный вызов пространства пользователя вызовов
Или исходный mysqlnd
метод, если
обратный вызов пространства пользователя не набор
Вы должны выполнить следующее:
Запишите class "mysqlnd_plugin_connection" в C
Примите и зарегистрируйте объект прокси через "mysqlnd_plugin_set_conn_proxy ()"
Вызовите методы прокси пространства пользователя от 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;}