Novas tabelas devem ser criadas em hook_update_N ()?

11

Quando você cria uma nova tabela hook_schema(), essa tabela deve ser adicionada hook_update_N()também? Ou há algum truque, ou algo que eu perdi, para que as atualizações de dados adicionem tabelas automaticamente?

A documentação de hook_update_N () não explica nada sobre a introdução de novas tabelas, enquanto a documentaçãohook_schema() diz:

As tabelas declaradas por esse gancho serão criadas automaticamente quando o módulo for ativado pela primeira vez e removidas quando o módulo for desinstalado.

(Destaque é meu)

E se sim, como evitar a duplicação das definições de esquema para a nova tabela em hook_update_N () e hook_schema (). Simplesmente consultando o esquema da seguinte maneira:

 function hook_update_N(&$sandbox) {
   $schema = hook_schema();
   $name = "foo";
   $table = $schema["foo"];
   db_create_table($name, $table);
 }

Parece funcionar, mas, ao mudar a tabela novamente, falhará se um usuário executar as atualizações e executar dois ou mais hook_update_N () s. Afinal: o primeiro hook_update_N já instalará o banco de dados correto e o segundo hook_update_M () tentará adicionar / alterar / alterar colunas que já estavam atualizadas.

Como você lida com isso?

berkes
fonte
Consulte drupal.org/node/150215 para obter documentação. Então, basicamente, adicionar uma nova tabela após a instalação de um módulo é via hook_update_N, mas você também adiciona a definição da tabela ao hook_schema para novos usuários ou novas instalações. Portanto, resumir se você fizer alterações na tabela para atualizar as tabelas atuais via hook_update_N, mas também mesclar as alterações no hook_schema.
junedkazi
1
Portanto, não há como evitar violar o DRY, ao que parece. Pena.
Berkes
nada do que eu saiba. Mas você pode escrever uma função pequena que tenha a definição de esquema e chamar essa definição nas duas funções.
junedkazi
@berkes Pode-se definir outra função que retorne o esquema adicional e faça referência a ele nos ganchos de atualização e instalação.
User1359

Respostas:

15

Então, basta copiar e colar a partir de drupal.org. Você também precisa adicionar a definição de esquema ao hook_schema.

/**
 * Create new database table {mytable2}.
 */
function mymodule_update_7101() {
  $schema['mytable2'] = array(
     // table definition array goes here
  );
  db_create_table('mytable2', $schema['mytable2']);
}
junedkazi
fonte
Você quer dizer que não há outra maneira de copiar a definição de tabela de hook_schema () para hook_update_N (). Em outras palavras: que não há como evitar violar o DRY?
Berkes
3
@berkes local ... há uma boa explicação de por que é aqui , caso você ainda não tenha visto isso
Clive
@ Clive Esse é um exemplo incrível. Nunca vi isso antes. 1
junedkazi 4/10/12
@junedkazi Há um link para ele no link que você forneceu no seu comentário;)
Clive
-2

mymodule_update_7101 () é bom, junto com este gancho, se adicionarmos um hook_install () para executar o mesmo enquanto a instalação do módulo, em vez da definição hook_schema (), também funciona para mim.


/**
 * Implements hook_install().
 */
function mymodule_install() {
  // Change the update number accordingly for more updates.
  for ($i = 7101; $i < 7102; $i++) {
    $update_func = 'mymodule_update_' . $i;
    if (function_exists($update_func)) {
      $update_func();
    }
  }
}

Akhila V Nair
fonte
É uma prática muito melhor do Drupal usar a API conforme indicado. Use hook_schema () e hook_update_N () diretamente. Uma coisa que faço é chamar a implementação hook_schema do meu módulo em hook_update_N () e, em seguida, execute as respectivas funções db_ *.
Mrclclfefe
hook_install()não deve chamar nenhuma implementação hook_update_N (), simplesmente: hook_install()é para instalar um módulo pela primeira vez, o que significa que não há tabelas para atualizar. Além disso, seu código não funcionaria para atualizações que precisam de um lote para serem executadas.
kiamlaluno
Esse trecho de código será útil se você estiver atualizando o esquema e apenas para fins de implantação. Para um sistema ativo existente, isso não pode ser usado.
Akhila V Nair