De nouvelles tables doivent-elles être créées dans hook_update_N ()?

11

Lorsque vous créez une nouvelle table dans hook_schema(), cette table doit-elle également être ajoutée dans un hook_update_N()? Ou y a-t-il une astuce, ou quelque chose que j'ai raté, pour que les mises à jour de données ajoutent automatiquement des tables?

La documentation de hook_update_N () n'explique rien sur l'introduction de nouvelles tables, alors que la documentation dehook_schema() dit:

Les tables déclarées par ce hook seront automatiquement créées lors de la première activation du module et supprimées lors de la désinstallation du module.

(Le surlignage est à moi)

Et si c'est le cas, comment éviter au mieux de dupliquer les définitions de schéma pour la nouvelle table dans hook_update_N () et hook_schema (). Se référant simplement au schéma comme suit:

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

Semble fonctionner, mais en modifiant à nouveau la table, échouera si un utilisateur exécute les mises à jour et parvient à exécuter deux ou plusieurs hook_update_N () s. Après tout: le premier hook_update_N installera alors déjà la bonne base de données et le second hook_update_M () essaiera d'ajouter / modifier / modifier des colonnes qui étaient déjà à jour.

Comment gérez-vous cela?

berkes
la source
Reportez-vous à drupal.org/node/150215 pour la documentation. Donc, fondamentalement, pour ajouter une nouvelle table après l'installation d'un module, vous devez utiliser hook_update_N, mais vous ajoutez également la définition de la table au hook_schema pour les nouveaux utilisateurs ou les nouvelles installations. Donc, résumez-le si vous apportez des modifications à la table pour mettre à jour les tables actuelles via hook_update_N, mais vous fusionnez également les modifications dans le hook_schema.
junedkazi
1
Il n'y a donc aucun moyen d'éviter de violer DRY, semble-t-il. Pitié.
berkes
rien que je sache. Mais vous pouvez écrire une petite fonction qui a la définition de schéma et appeler cette définition dans les deux fonctions.
junedkazi
@berkes On pourrait définir une autre fonction qui renvoie le schéma supplémentaire et s'y référer dans les hooks de mise à jour et d'installation.
user1359

Réponses:

15

Donc, juste un copier-coller de drupal.org. Vous devez également ajouter la définition de schéma à 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
la source
Voulez-vous dire qu'il n'y a pas d'autre moyen que de copier la définition de table de hook_schema () dans hook_update_N (). En d'autres termes: qu'il n'y a aucun moyen d'éviter de violer DRY?
berkes
3
@berkes spot on ... il y a une très bonne explication pourquoi c'est ici au cas où vous ne l'auriez pas déjà vu
Clive
@Clive C'est un exemple génial. Je ne l'ai jamais vu auparavant. +1
junedkazi
@junedkazi Il y a un lien vers celui-ci sur le lien que vous avez fourni dans votre commentaire;)
Clive
-2

mymodule_update_7101 () est bon, avec ce crochet si nous ajoutons un hook_install () pour exécuter la même chose tandis que l'installation du module au lieu de la définition de hook_schema () fonctionne aussi pour moi.


/**
 * 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
la source
Il est bien préférable que Drupal utilise l'API comme indiqué. Utilisez hook_schema () et hook_update_N () directement. Une chose que je fais est d'appeler l'implémentation hook_schema de mon module dans hook_update_N (), puis d'exécuter les fonctions db_ * respectives.
mradcliffe
hook_install()ne devrait appeler aucune implémentation hook_update_N (), pour un simple fait: hook_install()est pour installer un module pour la première fois, ce qui signifie qu'il n'y a pas de tables à mettre à jour. En outre, votre code ne fonctionnerait pas pour les mises à jour nécessitant un lot pour s'exécuter.
kiamlaluno
Cet extrait de code sera utile si vous mettez à jour le schéma et uniquement à des fins de déploiement. Pour un système live existant, cela ne peut pas être utilisé.
Akhila V Nair