Czy nowe tabele należy utworzyć w hook_update_N ()?

11

Czy podczas tworzenia nowej tabeli hook_schema()należy również dodać tę tabelę hook_update_N()? A może jest jakaś sztuczka lub coś, co przeoczyłem, aby aktualizacje danych automatycznie dodawały tabele?

Dokumentacja hook_update_N () nie wyjaśnia niczego na temat wprowadzania nowych tabel, podczas gdy dokumentacjahook_schema() mówi:

Tabele zadeklarowane przez ten hook zostaną automatycznie utworzone przy pierwszym włączeniu modułu i usunięte po odinstalowaniu modułu.

(Highlight is my)

A jeśli tak, jak najlepiej uniknąć powielania definicji schematów dla nowej tabeli zarówno w hook_update_N (), jak i hook_schema (). Po prostu odnosząc się do schematu w następujący sposób:

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

Wydaje się, że działa, ale przy ponownej zmianie tabeli nie powiedzie się, jeśli użytkownik uruchomi aktualizacje i dostanie dwa lub więcej hook_update_N () s. W końcu: pierwsza hook_update_N zainstaluje już poprawną bazę danych, a druga hook_update_M () spróbuje dodać / zmienić / zmienić kolumny, które były już aktualne.

Jak sobie z tym radzisz?

berkes
źródło
Patrz drupal.org/node/150215 dokumentacji. Zasadniczo więc dodawanie nowej tabeli po zainstalowaniu modułu odbywa się za pośrednictwem hook_update_N, ale dodajesz także definicję tabeli do hook_schema dla nowych użytkowników lub nowych instalacji. Podsumuj to, jeśli dokonasz jakichkolwiek zmian w tabeli, aby zaktualizować bieżące tabele za pomocą hook_update_N, ale scalisz również zmiany w scenie hook_schema.
junedkazi
1
Wygląda więc na to, że nie można uniknąć naruszenia zasady DRY. Szkoda.
berkes
nic, czego jestem świadomy. Ale możesz napisać małą funkcję, która ma definicję schematu i wywołać tę definicję w obu funkcjach.
junedkazi
@berkes Można zdefiniować inną funkcję, która zwraca dodatkowy schemat i odnosić się do niego zarówno w przypadku aktualizacji, jak i instalacji.
user1359,

Odpowiedzi:

15

Więc po prostu skopiuj wklej z drupal.org. Musisz również dodać definicję schematu do 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
źródło
Czy masz na myśli, że nie ma innego sposobu niż skopiowanie definicji tabeli z hook_schema () do hook_update_N (). Innymi słowy: że nie można uniknąć naruszenia zasad DRY?
berkes
3
@berkes spot na ... jest bardzo dobre wytłumaczenie, dlaczego tak jest , na wypadek, gdybyś go jeszcze nie widział
Clive
@Clive To niesamowity przykład. Nigdy tego nie widziałem. +1
Jununkazkazi
@junedkazi Jest link do niego na link podany w komentarzu;)
Clive
-2

mymodule_update_7101 () jest dobry, wraz z tym hookiem, jeśli dodamy hook_install (), aby wykonać to samo, podczas gdy instalacja modułu zamiast definicji hook_schema () również działa dla mnie.


/**
 * 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
źródło
O wiele lepszą praktyką Drupala jest używanie API zgodnie z zaleceniami. Użyj bezpośrednio hook_schema () i hook_update_N (). Jedną z rzeczy, które robię, jest wywołanie implementacji hook_schema mojego modułu w hook_update_N (), a następnie uruchomienie odpowiednich funkcji db_ *.
mradcliffe
hook_install()nie powinien wywoływać żadnych implementacji hook_update_N (), dla prostego faktu: hook_install()służy do instalowania modułu po raz pierwszy, co oznacza, że ​​nie ma tabel do aktualizacji. Ponadto kod nie będzie działał w przypadku aktualizacji, które wymagają uruchomienia partii.
kiamlaluno
Ten fragment kodu będzie przydatny, jeśli aktualizujesz schemat i tylko w celu wdrożenia. W przypadku istniejącego systemu na żywo nie można tego użyć.
Akhila V Nair