<?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 => 'pt_BR',
  ),
  'this' => 
  array (
    0 => 'mysqlnd.plugin.architecture.php',
    1 => 'Arquitetura do Plugin do Driver Nativo MySQL',
    2 => 'Arquitetura do Plugin do Driver Nativo MySQL',
  ),
  'up' => 
  array (
    0 => 'mysqlnd.plugin.php',
    1 => 'API do plugin do Driver Nativo MySQL',
  ),
  'prev' => 
  array (
    0 => 'mysqlnd.plugin.obtaining.php',
    1 => 'Obtendo a API do plugin mysqlnd',
  ),
  'next' => 
  array (
    0 => 'mysqlnd.plugin.api.php',
    1 => 'A API do plugin mysqlnd',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'pt_BR',
    '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.architecture" class="section">
  <h2 class="title">Arquitetura do Plugin do Driver Nativo MySQL</h2>
  <p class="simpara">
   Esta seção fornece uma visão geral da arquitetura do plugin
   <code class="literal">mysqlnd</code>.
  </p>
  <p class="simpara">
   <strong>Visão Geral do Driver Nativo MySQL</strong>
  </p>
  <p class="simpara">
   Antes de desenvolver plugins <code class="literal">mysqlnd</code>, é útil
   saber um pouco de como o próprio <code class="literal">mysqlnd</code> é organizado.
   <code class="literal">Mysqlnd</code> consiste nos seguintes módulos:
  </p>
  <table id="mysqlnd.plugin.orgchart" class="doctable table">
   <caption><strong>O organograma mysqlnd, por módulo</strong></caption>
   
    <thead>
     <tr>
      <th>Estatísticas de Módulos</th>
      <th>mysqlnd_statistics.c</th>
     </tr>

    </thead>

    <tbody class="tbody">
     <tr>
      <td>Conexão</td>
      <td>mysqlnd.c</td>
     </tr>

     <tr>
      <td>Conjunto de resultados</td>
      <td>mysqlnd_result.c</td>
     </tr>

     <tr>
      <td>Metadados do conjunto de resultados</td>
      <td>mysqlnd_result_meta.c</td>
     </tr>

     <tr>
      <td>Declaração</td>
      <td>mysqlnd_ps.c</td>
     </tr>

     <tr>
      <td>Rede</td>
      <td>mysqlnd_net.c</td>
     </tr>

     <tr>
      <td>Protocolo de fio</td>
      <td>mysqlnd_wireprotocol.c</td>
     </tr>

    </tbody>
   
  </table>

  <p class="simpara">
   <strong>Paradigma de C Orientado a Objetos</strong>
  </p>
  <p class="simpara">
   No nível do código, <code class="literal">mysqlnd</code> usa um padrão C para
   implementar orientação a objetos.
  </p>
  <p class="simpara">
   Em C você usa uma <code class="literal">struct</code> para representar um objeto.
   Os membros da estrutura representam propriedades do objeto. Membros da estrutura
   que apontam para funções representam métodos.
  </p>
  <p class="simpara">
   Ao contrário de outras linguagens como C++ ou Java, não existem regras
   fixas sobre herança no paradigma do C orientado a objetos. No entanto,
   existem algumas convenções que precisam ser seguidas e que serão
   discutidas posteriormente.
  </p>
  <p class="simpara">
   <strong>O Ciclo de Vida do PHP</strong>
  </p>
  <p class="simpara">
   Ao considerar o ciclo de vida do PHP, existem dois ciclos básicos:
  </p>
  <ul class="itemizedlist">
   <li class="listitem">
    <span class="simpara">
     Ciclo de inicialização e desligamento do mecanismo PHP
    </span>
   </li>
   <li class="listitem">
    <span class="simpara">
     Ciclo de requisição
    </span>
   </li>
  </ul>
  <p class="simpara">
   Quando o mecanismo PHP for iniciado ele chamará a função de inicialização do módulo
   (MINIT) de cada extensão registrada. Isso permite que cada
   módulo configure variáveis ​​e aloque recursos que existirão durante
   a vida útil do processo do mecanismo PHP. Quando o mecanismo PHP for desligado,
   ele chamará a função de desligamento do módulo (MSHUTDOWN) de cada
   extensão.
  </p>
  <p class="simpara">
   Durante a vida útil do mecanismo PHP, ele receberá diversas
   solicitações. Cada solicitação constitui outro ciclo de vida. Em cada
   solicitação, o mecanismo PHP chamará a função de inicialização de solicitação
   de cada extensão. A extensão pode executar qualquer configuração de variável e
   alocação de recursos necessária para o processamento de solicitações. À medida que o
   ciclo de solicitação termina, o mecanismo chama a função de desligamento de solicitação (RSHUTDOWN)
   de cada extensão para que ela possa realizar qualquer limpeza necessária.
  </p>
  <p class="simpara">
   <strong>Como um plugin funciona</strong>
  </p>
  <p class="simpara">
   Um plugin <code class="literal">mysqlnd</code> funciona interceptando chamadas feitas
   para <code class="literal">mysqlnd</code> por extensões que usam
   <code class="literal">mysqlnd</code>. Isto é conseguido obtendo a
   tabela de funções <code class="literal">mysqlnd</code>, fazendo backup dela e
   substituindo-a por uma tabela de funções customizada, que chama as funções do
   plugin conforme necessário.
  </p>
  <p class="simpara">
   O código a seguir mostra como a tabela de funções <code class="literal">mysqlnd</code>
   é substituída:
  </p>
<div class="example-contents">
<div class="cdata"><pre>
/* um lugar para armazenar a tabela de funções original */
struct st_mysqlnd_conn_methods org_methods;

void minit_register_hooks(TSRMLS_D) {
  /* tabela de funções ativas */
  struct st_mysqlnd_conn_methods * current_methods
    = mysqlnd_conn_get_methods();

  /* tabela de funções original de backup */
  memcpy(&amp;org_methods, current_methods,
    sizeof(struct st_mysqlnd_conn_methods);

  /* instala novos métodos */
  current_methods-&gt;query = MYSQLND_METHOD(my_conn_class, query);
}
</pre></div>
</div>

  <p class="simpara">
   As manipulações da tabela de funções de conexão devem ser feitas durante a
   inicialização do módulo (MINIT). A tabela de funções é um recurso global
   compartilhado. Em um ambiente multithread, com construção de TSRM, a
   manipulação de um recurso global compartilhado durante o processamento
   da solicitação quase certamente resultará em conflitos.
  </p>
  <blockquote class="note"><p><strong class="note">Nota</strong>: 
   <span class="simpara">
    Não use nenhuma lógica de tamanho fixo ao manipular a
    tabela de funções <code class="literal">mysqlnd</code>: novos métodos podem ser adicionados
    ao final da tabela de funções. A tabela de funções pode mudar a
    qualquer momento no futuro.
   </span>
  </p></blockquote>
  <p class="simpara">
   <strong>Chamando métodos da classe pai</strong>
  </p>
  <p class="simpara">
   Se for feito backup das entradas originais da tabela de funções, ainda será
   possível chamar as entradas originais da tabela de funções - os métodos
   pai.
  </p>
  <p class="simpara">
   Em alguns casos, como em
   <code class="literal">Connection::stmt_init()</code>, é vital chamar o
   método pai antes de qualquer outra atividade no método derivado.
  </p>
<div class="example-contents">
<div class="cdata"><pre>
MYSQLND_METHOD(my_conn_class, query)(MYSQLND *conn,
  const char *query, unsigned int query_len TSRMLS_DC) {

  php_printf(&quot;my_conn_class::query(query = %s)\n&quot;, query);

  query = &quot;SELECT &#039;query rewritten&#039; FROM DUAL&quot;;
  query_len = strlen(query);

  return org_methods.query(conn, query, query_len); /* retorna com chamada ao método pai */
}
</pre></div>
</div>

  <p class="simpara">
   <strong>Estendendo propriedades</strong>
  </p>
  <p class="simpara">
   Um objeto <code class="literal">mysqlnd</code> é representado por uma estrutura C. Não
   é possível adicionar um membro a uma estrutura C em tempo de execução. Usuários de
   objetos <code class="literal">mysqlnd</code> não podem simplesmente adicionar propriedades aos
   objetos.
  </p>
  <p class="simpara">
   Dados arbitrários (propriedades) podem ser adicionados a
   um objeto <code class="literal">mysqlnd</code> usando uma função apropriada
   da família
   <code class="literal">mysqlnd_plugin_get_plugin_&lt;object&gt;_data()</code>.
   Ao alocar um objeto, <code class="literal">mysqlnd</code> reserva
   espaço no final do objeto para conter um ponteiro <code class="literal">void *</code>
   para dados arbitrários. <code class="literal">mysqlnd</code> reserva espaço
   para um ponteiro <code class="literal">void *</code> por plugin.
  </p>
  <p class="simpara">
   A tabela a seguir mostra como calcular a posição do
   ponteiro para um plugin específico:
  </p>
  <table id="mysqlnd.plugin.pointercalc" class="doctable table">
   <caption><strong>Cálculo de ponteiro para mysqlnd</strong></caption>
   
    <thead>
     <tr>
      <th>Endereço de memória</th>
      <th>Conteúdo</th>
     </tr>

    </thead>

    <tbody class="tbody">
     <tr>
      <td>0</td>
      <td>Início da estrutura C do objeto mysqlnd</td>
     </tr>

     <tr>
      <td>n</td>
      <td>Final da estrutura C do objeto mysqlnd</td>
     </tr>

     <tr>
      <td>n + (m x sizeof(void*))</td>
      <td>void* para dados do objeto do m-ésimo plugin</td>
     </tr>

    </tbody>
   
  </table>

  <p class="simpara">
   Se for planejada uma sub-classe de qualquer dos construtores de objeto <code class="literal">mysqlnd</code>,
   que é permitido, deve-se ter isto em mente!
  </p>
  <p class="simpara">
   O código a seguir mostra extensão de propriedades:
  </p>
<div class="example-contents">
<div class="cdata"><pre>
/* qualquer dado que se queira associar */
typedef struct my_conn_properties {
  unsigned long query_counter;
} MY_CONN_PROPERTIES;

/* id do plugin */
unsigned int my_plugin_id;

void minit_register_hooks(TSRMLS_D) {
  /* obtém ID único para o plugin */
  my_plugin_id = mysqlnd_plugin_register();
  /* recorte - consulte Estendendo Conexão: métodos */
}

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-&gt;persistent);
    (*props)-&gt;query_counter = 0;
  }
  return props;
}
</pre></div>
</div>

  <p class="simpara">
   O desenvolvedor do plugin é responsável pelo gerenciamento de memória dos
   dados do plugin.
  </p>
  <p class="simpara">
   O uso do alocador de memória <code class="literal">mysqlnd</code> é recomendado
   para dados do plugin. Essas funções são nomeadas usando a convenção:
   <code class="literal">mnd_*loc()</code>. O alocador <code class="literal">mysqlnd</code>
   possui alguns recursos úteis, como a capacidade de usar um
   alocador de depuração em uma compilação sem depuração.
  </p>
  <table id="mysqlnd.plugin.subclass" class="doctable table">
   <caption><strong>Quando e como usar uma sub-classe</strong></caption>
   
    <thead>
     <tr>
      <th class="empty">&nbsp;</th>
      <th>Quando usar uma sub-classe?</th>
      <th>Cada instância tem sua própria tabela de funções privadas?</th>
      <th>Como usar uma sub-classe</th>
     </tr>

    </thead>

    <tbody class="tbody">
     <tr>
      <td>Conexão (MYSQLND)</td>
      <td>MINIT</td>
      <td>Não</td>
      <td>mysqlnd_conn_get_methods()</td>
     </tr>

     <tr>
      <td>Conjunto de resultados (MYSQLND_RES)</td>
      <td>MINIT ou depois</td>
      <td>Sim</td>
      <td>mysqlnd_result_get_methods() ou manipulação de tabela de funções
      de métodos de objeto</td>
     </tr>

     <tr>
      <td>Metadados do conjunto de resultados (MYSQLND_RES_METADATA)</td>
      <td>MINIT</td>
      <td>Não</td>
      <td>mysqlnd_result_metadata_get_methods()</td>
     </tr>

     <tr>
      <td>Instrução (MYSQLND_STMT)</td>
      <td>MINIT</td>
      <td>Não</td>
      <td>mysqlnd_stmt_get_methods()</td>
     </tr>

     <tr>
      <td>Rede (MYSQLND_NET)</td>
      <td>MINIT ou depois</td>
      <td>Sim</td>
      <td>mysqlnd_net_get_methods() ou manipulação de tabela de funções de métodos de objeto</td>
     </tr>

     <tr>
      <td>Protocolo de fio (MYSQLND_PROTOCOL)</td>
      <td>MINIT ou depois</td>
      <td>Sim</td>
      <td>mysqlnd_protocol_get_methods() ou manipulação de tabela de funções
      de métodos de objeto</td>
     </tr>

    </tbody>
   
  </table>

  <p class="simpara">
   Não se deve manipular tabelas de funções em nenhum momento posterior ao MINIT
   se isso não for permitido de acordo com a tabela acima.
  </p>
  <p class="simpara">
   Algumas classes contêm um ponteiro para a tabela de funções do método. Todas as
   instâncias dessa classe compartilharão a mesma tabela de funções. Para
   evitar o caos, especialmente em ambientes com threads, tais tabelas
   de funções só devem ser manipuladas durante o MINIT.
  </p>
  <p class="simpara">
   Outras classes usam cópias de uma tabela de funções compartilhada globalmente. A
   cópia da tabela de funções de classe é criada junto com o objeto. Cada
   objeto usa sua própria tabela de funções. Isso dá duas opções: pode-se
   manipular a tabela de funções padrão de um objeto no MINIT, e
   também pode-se refinar os métodos de um objeto sem afetar
   outras instâncias da mesma classe.
  </p>
  <p class="simpara">
   A vantagem da abordagem de tabela de funções compartilhadas é o desempenho.
   Não há necessidade de copiar uma tabela de funções para cada objeto.
  </p>
  <table id="mysqlnd.plugin.constatus" class="doctable table">
   <caption><strong>Estado do construtor</strong></caption>
   
    <thead>
     <tr>
      <th>Tipo</th>
      <th>Alocação, construção, redefinição</th>
      <th>Pode ser modificada?</th>
      <th>Chamadora</th>
     </tr>

    </thead>

    <tbody class="tbody">
     <tr>
      <td>Conexão (MYSQLND)</td>
      <td>mysqlnd_init()</td>
      <td>Não</td>
      <td>mysqlnd_connect()</td>
     </tr>

     <tr>
      <td>Conjunto de resultados (MYSQLND_RES)</td>
      <td><span class="simpara">
        Alocação:
       </span>
       <ul class="itemizedlist">
        <li class="listitem">
         <span class="simpara">
          Connection::result_init()
         </span>
        </li>
       </ul>
       <span class="simpara">
        Redefinida e reinicializada durante:
       </span>
       <ul class="itemizedlist">
        <li class="listitem">
         <span class="simpara">
          Result::use_result()
         </span>
        </li>
        <li class="listitem">
         <span class="simpara">
          Result::store_result
         </span>
        </li>
       </ul></td>
      <td>Sim, mas deve-se chamar o método pai!</td>
      <td><ul class="itemizedlist">
        <li class="listitem">
         <span class="simpara">
          Connection::list_fields()
         </span>
        </li>
        <li class="listitem">
         <span class="simpara">
          Statement::get_result()
         </span>
        </li>
        <li class="listitem">
         <span class="simpara">
          Statement::prepare() (Somente metadados)
         </span>
        </li>
        <li class="listitem">
         <span class="simpara">
          Statement::resultMetaData()
         </span>
        </li>
       </ul></td>
     </tr>

     <tr>
      <td>Metadados do conjunto de resultados (MYSQLND_RES_METADATA)</td>
      <td>Connection::result_meta_init()</td>
      <td>Sim, mas deve-se chamar o método pai!</td>
      <td>Result::read_result_metadata()</td>
     </tr>

     <tr>
      <td>Instrução (MYSQLND_STMT)</td>
      <td>Connection::stmt_init()</td>
      <td>Sim, mas deve-se chamar o método pai!</td>
      <td>Connection::stmt_init()</td>
     </tr>

     <tr>
      <td>Rede (MYSQLND_NET)</td>
      <td>mysqlnd_net_init()</td>
      <td>Não</td>
      <td>Connection::init()</td>
     </tr>

     <tr>
      <td>Protocolo de fio (MYSQLND_PROTOCOL)</td>
      <td>mysqlnd_protocol_init()</td>
      <td>Não</td>
      <td>Connection::init()</td>
     </tr>

    </tbody>
   
  </table>

  <p class="simpara">
   É altamente recomendável que não se substitua totalmente um
   construtor. Os construtores realizam alocações de memória. As alocações
   de memória são vitais para a API do plugin <code class="literal">mysqlnd</code>
   e para a lógica do objeto <code class="literal">mysqlnd</code>. Se não houver
   preocupação com avisos e houver insistência em conectar os construtores, deve-se
   pelo menos chamar o construtor pai antes de fazer qualquer coisa no
   construtor.
  </p>
  <p class="simpara">
   Independentemente de todos os avisos, pode ser útil criar sub-classes de
   construtores. Os construtores são o lugar perfeito para modificar as
   tabelas de funções de objetos com tabelas de objetos não compartilhados, como
   Conjunto de Resultados, Rede, Protocolo de Fio.
  </p>
  <table id="mysqlnd.plugin.deststatus" class="doctable table">
   <caption><strong>Estado do destruidor</strong></caption>
   
    <thead>
     <tr>
      <th>Tipo</th>
      <th>Método derivado deve chamar o pai?</th>
      <th>Destruidor</th>
     </tr>

    </thead>

    <tbody class="tbody">
     <tr>
      <td>Conexão</td>
      <td>sim, após execução do método</td>
      <td>free_contents(), end_psession()</td>
     </tr>

     <tr>
      <td>Conjunto de resultados</td>
      <td>sim, após execução do método</td>
      <td>free_result()</td>
     </tr>

     <tr>
      <td>Metadados do conjunto de resultados</td>
      <td>sim, após execução do método</td>
      <td>free()</td>
     </tr>

     <tr>
      <td>Instrução</td>
      <td>sim, após execução do método</td>
      <td>dtor(), free_stmt_content()</td>
     </tr>

     <tr>
      <td>Rede</td>
      <td>sim, após execução do método</td>
      <td>free()</td>
     </tr>

     <tr>
      <td>Protocolo de fio</td>
      <td>sim, após execução do método</td>
      <td>free()</td>
     </tr>

    </tbody>
   
  </table>

  <p class="simpara">
   Os destruidores são o local apropriado para liberar propriedades,
   <code class="literal">mysqlnd_plugin_get_plugin_<span class="replaceable">&lt;object&gt;</span>_data()</code>.
  </p>
  <p class="simpara">
   Os destruidores listados podem não ser equivalentes ao método
   <code class="literal">mysqlnd</code> real que libera o próprio objeto. No entanto,
   eles são o melhor lugar possível para se conectar e liberar os dados do
   plugin. Tal como acontece com os construtores, pode-se substituir totalmente
   os métodos, mas isso não é recomendado. Se vários métodos estiverem listados
   na tabela acima, será necessário conectar todos os métodos listados
   e liberar os dados do plugin em qualquer método chamado primeiro pelo
   <code class="literal">mysqlnd</code>.
  </p>
  <p class="simpara">
   O método recomendado para plugins é simplesmente conectar os métodos,
   liberar memória e chamar a implementação pai imediatamente
   após isso.
  </p>
 </div><?php manual_footer($setup); ?>