## mysqlnd のプラグインAPI

`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` の内部にすべてアクセスできます。セキュリティ上の限界や制限はありません。mysqlnd に親和性が高い、または不利なアルゴリズムを実装するためにすべてを置き換えることができます。よって、信頼できる配布元からのプラグインだけをデプロイすることを推奨します。

以前議論したとおり、プラグインはポインタを自由に使えます。これらのポインタはあらゆる点で制限されていないので、別のプラグインのデータを指すこともできます。簡単にオフセットを計算するだけで別のプラグインのデータを使うことができます。

mysqlnd と協調的なプラグインを書くこと、そして開発者はいつも親メソッドを呼び出すことを推奨します。プラグインはいつも `mysqlnd` と協調的であるべきです。

問題: 呼び出しの連鎖と協調の例
拡張モジュール | mysqlnd.query() の関数ポインタ | 親メソッドを呼んだ場合のコールスタック
--- | --- | ---
ext/mysqlnd | mysqlnd.query() | mysqlnd.query
ext/mysqlnd_cache | mysqlnd_cache.query() | mysqlnd_cache.query() mysqlnd.query
ext/mysqlnd_monitor | mysqlnd_monitor.query() | mysqlnd_monitor.query() mysqlnd_cache.query() mysqlnd.query

このシナリオでは、キャッシュ(`ext/mysqlnd_cache`) と モニタ(`ext/mysqlnd_monitor`) プラグインが読み込まれています。両方とも `Connection::query()` を継承しています。プラグインの登録が 以前説明したロジックを使って `MINIT`(モジュール初期化) 時に発生します。PHP は拡張モジュールをデフォルトではアルファベット順に呼び出します。プラグインはお互いのことを知りませんし、拡張モジュールの依存性についても設定しません。

デフォルトで、プラグインは派生したメソッドの中で query メソッドの親クラスの実装を呼び出します。

PHP 拡張モジュールの動きを再現する

サンプルのプラグイン `ext/mysqlnd_plugin` を使うと何が起こるかを以下で再現します。このプラグインは、`mysqlnd` の CプラグインAPI をPHPに公開しています。

- PHP で書かれた MySQL アプリケーションが 192.168.2.29 に接続を確立しようとします。
- PHP アプリケーションは `ext/mysql`, `ext/mysqli` または `PDO_MYSQL` のいずれかを使うでしょう。これら３つの PHP MySQL 拡張モジュールは `mysqlnd` を使って 192.168.2.29 に接続を確立しようとします。
- `mysqlnd` は `ext/mysqlnd_plugin` を継承した自分自身の connect メソッドを呼び出します。
- `ext/mysqlnd_plugin` は ユーザーが登録した ユーザースペースのフックである `proxy::connect()` を呼び出します。
- ユーザースペースのフックは接続先のホストIPアドレスを 192.168.2.29 から 127.0.0.1 に書き換え、`parent::connect()` によって確立された接続を返します。
- `ext/mysqlnd_plugin` は オリジナルの `mysqlnd`のメソッドを接続を確立するために呼び出します。これによって、`parent::connect(127.0.0.1)` を実行するのと同じことをします。
- `ext/mysqlnd` は、接続を確立し、`ext/mysqlnd_plugin` に接続を返します。`ext/mysqlnd_plugin` も同じことをします。
- どんな PHP MySQL 拡張モジュールをアプリケーションで使っていても、127.0.0.1 への接続を受け取ります。PHP MySQL 拡張モジュールそれ自体は、PHPアプリケーションにそれを返し、実行は終了します。

`↑` and `↓` to navigate • `Enter` to select • `Esc` to close • `/` to open