<?php
include_once $_SERVER['DOCUMENT_ROOT'] . '/include/shared-manual.inc';
$TOC = array();
$TOC_DEPRECATED = array();
$PARENTS = array();
include_once dirname(__FILE__) ."/toc/mysqlnd.plugin.inc";
$setup = array (
  'home' => 
  array (
    0 => 'index.php',
    1 => 'PHP Manual',
  ),
  'head' => 
  array (
    0 => 'UTF-8',
    1 => 'ja',
  ),
  'this' => 
  array (
    0 => 'mysqlnd.plugin.api.php',
    1 => 'mysqlnd のプラグインAPI',
    2 => 'mysqlnd のプラグインAPI',
  ),
  'up' => 
  array (
    0 => 'mysqlnd.plugin.php',
    1 => 'MySQL Native Driver プラグインAPI',
  ),
  'prev' => 
  array (
    0 => 'mysqlnd.plugin.architecture.php',
    1 => 'MySQL Native Driverプラグイン のアーキテクチャ',
  ),
  'next' => 
  array (
    0 => 'mysqlnd.plugin.developing.php',
    1 => 'mysqlndプラグインの開発をはじめよう',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'ja',
    'path' => 'reference/mysqlnd/plugin.xml',
  ),
  'history' => 
  array (
  ),
);
$setup["toc"] = $TOC;
$setup["toc_deprecated"] = $TOC_DEPRECATED;
$setup["parents"] = $PARENTS;
manual_setup($setup);

contributors($setup);

?>
<div id="mysqlnd.plugin.api" class="section">
  <h2 class="title">mysqlnd のプラグインAPI</h2>
  <p class="simpara">
   <code class="literal">mysqlnd</code>プラグインAPI で提供されている関数のリストを以下に示します:
  </p>
  <ul class="itemizedlist">
   <li class="listitem">
    <span class="simpara">
     mysqlnd_plugin_register()
    </span>
   </li>
   <li class="listitem">
    <span class="simpara">
     mysqlnd_plugin_count()
    </span>
   </li>
   <li class="listitem">
    <span class="simpara">
     mysqlnd_plugin_get_plugin_connection_data()
    </span>
   </li>
   <li class="listitem">
    <span class="simpara">
     mysqlnd_plugin_get_plugin_result_data()
    </span>
   </li>
   <li class="listitem">
    <span class="simpara">
     mysqlnd_plugin_get_plugin_stmt_data()
    </span>
   </li>
   <li class="listitem">
    <span class="simpara">
     mysqlnd_plugin_get_plugin_net_data()
    </span>
   </li>
   <li class="listitem">
    <span class="simpara">
     mysqlnd_plugin_get_plugin_protocol_data()
    </span>
   </li>
   <li class="listitem">
    <span class="simpara">
     mysqlnd_conn_get_methods()
    </span>
   </li>
   <li class="listitem">
    <span class="simpara">
     mysqlnd_result_get_methods()
    </span>
   </li>
   <li class="listitem">
    <span class="simpara">
     mysqlnd_result_meta_get_methods()
    </span>
   </li>
   <li class="listitem">
    <span class="simpara">
     mysqlnd_stmt_get_methods()
    </span>
   </li>
   <li class="listitem">
    <span class="simpara">
     mysqlnd_net_get_methods()
    </span>
   </li>
   <li class="listitem">
    <span class="simpara">
     mysqlnd_protocol_get_methods()
    </span>
   </li>
  </ul>
  <p class="simpara">
   プラグインが何かとか、どのようにプラグインが機能するのか、という疑問に対する公式な定義はありません。
  </p>
  <p class="simpara">
   プラグインのメカニズムでよく見つかるコンポーネントは以下の通りです:
  </p>
  <ul class="itemizedlist">
   <li class="listitem">
    <span class="simpara">
     プラグインマネージャー
    </span>
   </li>
   <li class="listitem">
    <span class="simpara">
     プラグインAPI
    </span>
   </li>
   <li class="listitem">
    <span class="simpara">
     アプリケーションサービス(またはモジュール)
    </span>
   </li>
   <li class="listitem">
    <span class="simpara">
     アプリケーションサービスAPI (またはモジュールAPI)
    </span>
   </li>
  </ul>
  <p class="simpara">
   <code class="literal">mysqlnd</code>プラグインのコンセプトにはこれらが取り入れられており、追加でオープンなアーキテクチャの恩恵を受けています。
  </p>
  <p class="simpara">
   <strong> mysqlnd の内部には無制限にアクセスできる </strong>
  </p>
  <p class="simpara">
   プラグインは <code class="literal">mysqlnd</code> の内部にすべてアクセスできます。セキュリティ上の限界や制限はありません。mysqlnd に親和性が高い、または不利なアルゴリズムを実装するためにすべてを置き換えることができます。よって、信頼できる配布元からのプラグインだけをデプロイすることを推奨します。
  </p>
  <p class="simpara">
   以前議論したとおり、プラグインはポインタを自由に使えます。これらのポインタはあらゆる点で制限されていないので、別のプラグインのデータを指すこともできます。簡単にオフセットを計算するだけで別のプラグインのデータを使うことができます。
  </p>
  <p class="simpara">
   mysqlnd と協調的なプラグインを書くこと、そして開発者はいつも親メソッドを呼び出すことを推奨します。プラグインはいつも <code class="literal">mysqlnd</code> と協調的であるべきです。
  </p>
  <table id="mysqlnd.plugin.chaining" class="doctable table">
   <caption><strong>問題: 呼び出しの連鎖と協調の例</strong></caption>
   
    <thead>
     <tr>
      <th>拡張モジュール</th>
      <th>mysqlnd.query() の関数ポインタ</th>
      <th>親メソッドを呼んだ場合のコールスタック</th>
     </tr>

    </thead>

    <tbody class="tbody">
     <tr>
      <td>ext/mysqlnd</td>
      <td>mysqlnd.query()</td>
      <td>mysqlnd.query</td>
     </tr>

     <tr>
      <td>ext/mysqlnd_cache</td>
      <td>mysqlnd_cache.query()</td>
      <td><ol type="1">
        <li class="listitem">
         <span class="simpara">
          mysqlnd_cache.query()
         </span>
        </li>
        <li class="listitem">
         <span class="simpara">
          mysqlnd.query
         </span>
        </li>
       </ol></td>
     </tr>

     <tr>
      <td>ext/mysqlnd_monitor</td>
      <td>mysqlnd_monitor.query()</td>
      <td><ol type="1">
        <li class="listitem">
         <span class="simpara">
          mysqlnd_monitor.query()
         </span>
        </li>
        <li class="listitem">
         <span class="simpara">
          mysqlnd_cache.query()
         </span>
        </li>
        <li class="listitem">
         <span class="simpara">
          mysqlnd.query
         </span>
        </li>
       </ol></td>
     </tr>

    </tbody>
   
  </table>

  <p class="simpara">
   このシナリオでは、キャッシュ(<code class="literal">ext/mysqlnd_cache</code>) と モニタ(<code class="literal">ext/mysqlnd_monitor</code>) プラグインが読み込まれています。両方とも <code class="literal">Connection::query()</code> を継承しています。プラグインの登録が 以前説明したロジックを使って <code class="literal">MINIT</code>(モジュール初期化) 時に発生します。PHP は拡張モジュールをデフォルトではアルファベット順に呼び出します。プラグインはお互いのことを知りませんし、拡張モジュールの依存性についても設定しません。
  </p>
  <p class="simpara">
   デフォルトで、プラグインは派生したメソッドの中で query メソッドの親クラスの実装を呼び出します。
  </p>
  <p class="simpara">
   <strong> PHP 拡張モジュールの動きを再現する </strong>
  </p>
  <p class="simpara">
   サンプルのプラグイン <code class="literal">ext/mysqlnd_plugin</code> を使うと何が起こるかを以下で再現します。このプラグインは、<code class="literal">mysqlnd</code> の CプラグインAPI をPHPに公開しています。
  </p>
  <ul class="itemizedlist">
   <li class="listitem">
    <span class="simpara">
     PHP で書かれた MySQL アプリケーションが 192.168.2.29 に接続を確立しようとします。
    </span>
   </li>
   <li class="listitem">
    <span class="simpara">
     PHP アプリケーションは <code class="literal">ext/mysql</code>, <code class="literal">ext/mysqli</code> または <code class="literal">PDO_MYSQL</code> のいずれかを使うでしょう。これら３つの PHP MySQL 拡張モジュールは <code class="literal">mysqlnd</code> を使って 192.168.2.29 に接続を確立しようとします。
    </span>
   </li>
   <li class="listitem">
    <span class="simpara">
     <code class="literal">mysqlnd</code> は <code class="literal">ext/mysqlnd_plugin</code> を継承した自分自身の connect メソッドを呼び出します。
    </span>
   </li>
   <li class="listitem">
    <span class="simpara">
     <code class="literal">ext/mysqlnd_plugin</code> は ユーザーが登録した ユーザースペースのフックである <code class="literal">proxy::connect()</code> を呼び出します。
    </span>
   </li>
   <li class="listitem">
    <span class="simpara">
     ユーザースペースのフックは接続先のホストIPアドレスを 192.168.2.29 から 127.0.0.1 に書き換え、<code class="literal">parent::connect()</code> によって確立された接続を返します。
    </span>
   </li>
   <li class="listitem">
    <span class="simpara">
     <code class="literal">ext/mysqlnd_plugin</code> は オリジナルの <code class="literal">mysqlnd</code>のメソッドを接続を確立するために呼び出します。これによって、<code class="literal">parent::connect(127.0.0.1)</code> を実行するのと同じことをします。
    </span>
   </li>
   <li class="listitem">
    <span class="simpara">
     <code class="literal">ext/mysqlnd</code> は、接続を確立し、<code class="literal">ext/mysqlnd_plugin</code> に接続を返します。<code class="literal">ext/mysqlnd_plugin</code> も同じことをします。
    </span>
   </li>
   <li class="listitem">
    <span class="simpara">
     どんな PHP MySQL 拡張モジュールをアプリケーションで使っていても、127.0.0.1 への接続を受け取ります。PHP MySQL 拡張モジュールそれ自体は、PHPアプリケーションにそれを返し、実行は終了します。
    </span>
   </li>
  </ul>
 </div><?php manual_footer($setup); ?>