Konvertierung von Drupal 6.x Module auf 7.x

Bild von tobiasb

Überblick der Drupal API Änderung von 6.x nach 7.x
Übersetzung von http://drupal.org/node/224333
Liste wird erweitert, sobald es neue Änderungen gibt.

  1. Berechtigungen und Titel müssen eine Beschreibung haben
  2. Berechtigungen werden nicht mehr alphabetisch sortiert
  3. _comment_load() ist jetzt comment_load()
  4. Die Module .info Datei muss nun alle zuladenden Codedateien explizit angeben.
  5. Die hook_menu() "file" und "file path" Schlüssel sind entfernt worden.
  6. Neue Berechtigungen Tabelle.
  7. '#markup' verwenden für markup, nicht mehr '#value'.
  8. Der Wert des Kommentar-Status in der Datenbank hat sich gedreht, damit es mit dem Node-Status übereinstimmt.
  9. Die Rebuild-Funktionen haben ihren Namen geändert.
  10. Die definierte Konstante REQUEST_TIME verwenden anstelle von time()
  11. referer_uri() ist entfernt worden
  12. Ein paar #process Functionen sind umbenannt worden
  13. Eine komplett neue Datenbank Api wurde hinzugefügt
  14. file_validate_extensions() erzwingt die Überprüfung für uid=1
  15. file_scan_directory() und drupal_system_listing() verwendet preg reguläre Ausdrücke
  16. Einfachere Überprüfung für das Node-Formular während hook_form_alter()
  17. Update Funktionen in der .install Datei müssen ein Doxygen-Style Kommentar beinhalten
  18. Neue #input_format zum Zuweisen der Eingabeformat-Auswahl an Feldern. Ändert „Body”-Feld Position in node, comment, block, etc.
  19. drupal_clone() mit clone ersetzt

Berechtigungen und Titel müssen eine Beschreibung haben

(issue) und (issue) Bei der Implementierung von hook_perm(), muss der zurückgegebene Wert geändert werden:

Drupal 6 unterstützte dieses Format:

  1. <?php
  2. function example_perm() {
  3.   return array('administer my module', ...);
  4. }
  5. ?>

Drupal 7 Code muss folgendes Format verwenden:

  1. <?php
  2. function example_perm() {
  3.   return array(
  4.     'administer my module' => array(
  5.       'title' => t('Administer my module'),
  6.       'description' => t('Perform maintenance tasks for my module'),
  7.     ),
  8.     ...
  9.   );
  10. }
  11. ?>

Vorher waren die Werte die Berechtigung; jetzt ist Berechtigung der Schlüssel und der entsprechende Wert ist ein Array mit dem Titel und Beschreibung der Berechtigung. Sollte es sein, dass die Berechtigungen zusammengesetzte dynamische Werte enthält, wie die Namen der Inhaltstypen. Lohnt sich ein Blick auf das generierte Array-format von node_list_permissions(), welches von node_permission() und hook_perm()-Implementierungen von anderen Kern Node-Module wiederverwendet wird.

Berechtigungen werden nicht mehr alphabetisch sortiert

(issue) Berechtigungen werden nicht mehr alphabetisch sortiert, jedoch werden sie in der Reihenfolge angezeigt, wie diese in deiner hook_perm() definiert ist.

Die empfohlende Reihenfolge der Berechtigungen ist:

  1. Berechtigungen im Zusammenhang fürs Administrieren
  2. Berechtigungen im Zusammenhang für den Zugriff
  3. andere globaler Ebene Berechtigungen
  4. Berechtigungen im Zusammenhang fürs Erstellen
  5. Berechtigungen im Zusammenhang fürs Bearbeiten
  6. Berechtigungen im Zusammenhang fürs Löschen
  7. andere

_comment_load() ist jetzt comment_load()

(issue) _comment_load() wurde umbenannt nach comment_load(), da diese Funktion auch extern Anwendung findet.

Zusätzlich zum Funktionsname selbst muss jeder Menüpunkt, der die %_comment Wildcard anwendet, nach %comment geändert werden.

Die Module .info Datei muss nun alle zuladenden Codedateien explizit angeben.

(issue) Drupal unterstützt jetzt eine dynamisch-ladende Code-Registrierung. Alle Module müssen daher ihre Codedateien in der info.-Datei angeben. Wie im folgenden Beispiel:

  1. name = Node
  2. description = Allows content to be submitted to the site and displayed on pages.
  3. ...
  4. files[] = node.module
  5. files[] = content_types.inc
  6. files[] = node.admin.inc
  7. files[] = node.pages.inc
  8. files[] = node.install

Wenn ein Modul aktiviert wird, wird Drupal alle angebenden Dateien untersuchen und gefundenen Funktionen und Klassen indexieren. Das bedeutet jede Klasse oder Funktion, welches indirekt aufgerufen werden (z.B. wie ein hook), kann außerhalb einer .module Datei untergebracht sein und wird On-demand eingebunden.

Klassen werden automatisch geladen durch PHP, wenn auf sie das erste Mal zugegriffen wird. Bei Funktionen, ersetze alle Aufrufe von function_exists() mit drupal_function_exists(), welches die notwendige Datei lädt und TRUE oder FALSE zurückgibt abhängig, ob die Funktion jetzt existiert.
Im Falle von hooks oder irgendein anderen aufgerufenen Code durch module_invoke*(), node_invoke(), etc. wird dies dann automatisch durchgeführt.

In Drupal 6 konnten Menüpunkte eine inc-Datei angeben, welche dann beim Seitenaufruf geladen wurde. In Drupal 7 ist das nicht mehr länger nötig, da diese Dateien automatisch durch registry geladen werden. Die file und der file path-Einträge sollten innerhalb von hook_menu() und hook_theme() entfernt werden.

Neue Berechtigungen Tabelle.

(Issue) Die {permission} Tabelle ist weg, stattdessen gibt es eine {role_permission}, welches die (role ID, permission string) Paare speichert. Demnach ist jede bewilligte Berechtigung für eine gegebene Rollen-ID in eine separate Zeile in der Tabelle.
Dieses Update ist in der system.install, so dass es bereits abgeschlossen ist, wenn ein Update eines anderen Kern oder bereitgestellte Modul läuft. Dies soll die Veränderung der vorhandenen Berechtigungen viel leichter machen.

'#markup' verwenden für markup, nicht mehr '#value'.

(Issue) Der Standardtyp für Elemente in Formulare oder andere strukturierte Array Daten (z.B. node content), welche an drupal_render() übergeben wird, ist '#type' => 'markup'. In Drupal 6 und früher wurde der HTML Inhalt zum Array mit dem #value Attribut hinzugefügt.

In Drupal 7 muss es auf #markup geändert werden. Diese Änderung gilt auch für diese Formularelemente von '#type' => 'Element'. Diese Änderung verringert die Verwirrung zwischen Formularwerte und Markup und ermöglicht, dass der Code in drupal_render() vereinfacht wird.

Beispiel 1, aus system.admin.inc

In Drupal 6:

  1. <?php
  2. $screenshot ? theme('image', $screenshot, t('Screenshot for %theme theme', array('%theme' => $theme->info['name'])), '', array('class' => 'screenshot'), FALSE) : t('no screenshot');
  3. $form[$theme->name]['screenshot'] = array('#value' => $screenshot);        
  4. ?>

In Drupal 7:

  1. <?php
  2. $screenshot ? theme('image', $screenshot, t('Screenshot for %theme theme', array('%theme' => $theme->info['name'])), '', array('class' => 'screenshot'), FALSE) : t('no screenshot');
  3. $form[$theme->name]['screenshot'] = array('#markup' => $screenshot);
  4. ?>

Beispiel 2, aus contact.pages.inc

In Drupal 6:

  1. <?php
  2.   $form['from'] = array(
  3.     '#type' => 'item',
  4.     '#title' => t('From'),
  5.     '#value' => check_plain($user->name) . ' &lt;' . check_plain($user->mail) . '&gt;',
  6.   );
  7. ?>

In Drupal 7:

  1. <?php
  2.   $form['from'] = array(
  3.     '#type' => 'item',
  4.     '#title' => t('From'),
  5.     '#markup' => check_plain($user->name) . ' &lt;' . check_plain($user->mail) . '&gt;',
  6.   );
  7. ?>

Der Wert des Kommentar-Status in der Datenbank hat sich gedreht, damit es mit dem Node-Status übereinstimmt.

Diese kleine Tabelle zeigt den Status eines Nodes oder Kommentars und dessen numerischer Wert:

Version Type Veröffentlicht Nicht-Veröffentlicht
6.x und davor Nodes 1 0
6.x und davor Comments 0 1
7.x Nodes 1 0
7.x Comments 1 0

Die Hauptänderung liegt in den SQL-Abfragen und Code, welche mit den Kommentaren interargiert.

Wenn man in Drupal 6.x und davor Code hatte, der wie folgt aussieht:

  1. <?php
  2. // Holt sich eine Liste aller unveröffentlichten Kommentar-IDs.
  3. $results = db_query("SELECT cid FROM {comments} WHERE status = 1");
  4. ?>

Muss das dann in Drupal 7.x so aussehen:

  1. <?php
  2. // Holt sich eine Liste aller unveröffentlichten Kommentar-IDs.
  3. $results = db_query("SELECT cid FROM {comments} WHERE status = 0");
  4. ?>

Man kann auch die Konstanten verwenden, die im Comment-Modul für eine erhöhte Code-Klarheit und künftigen Korrekturhilfen definiert sind:

  1. <?php
  2. // Holt sich eine Liste aller unveröffentlichten Kommentar-IDs.
  3. $results = db_query("SELECT cid FROM {comments} WHERE status = %d", COMMENT_NOT_PUBLISHED);
  4. ?>

Die Rebuild-Funktionen haben ihren Namen geändert:

6.x:

  1. <?php
  2.  drupal_rebuild_code_registry();
  3. ?>

7.x:

  1. <?php
  2.  drupal_theme_rebuild();
  3.  registry_rebuild();
  4. ?>

Die definierte Konstante REQUEST_TIME verwenden anstelle von time().

(Issue) Um eine bessere Leistung zu erzielen, wird es dringend empfohlen alle Aufrufe von time() mit einer definierten Konstante REQUEST_TIME zu ersetzen, welche immer den UNIX Zeitstempel zurückgibt von dem Startzeit der aktuellen Anfrage. Wenn es nicht vermeidbar ist kann time() weiterhin verwenden, um die aktuelle Uhrzeit zu erhalten, welches jedoch nicht empfohlen wird.

referer_uri ist entfernt worden.

(Issue) referer_uri() ist entfernt worden und wurde mit der von PHP zur Verfügung gestellte globale Variable $_SERVER['HTTP_REFERER'] ersetzt. Wenn es kein Referrer gibt, wird Drupal $_SERVER['HTTP_REFERER'] automatisch auf ein leeren String setzen.

Einige der #process Funktionen sind umbenannt worden

(Issue) Einige Funktionen, die zur Verarbeitung von Formularelementen (definiert durch ein #form Item in der Forms API) verwendet wurden, sind umbenannt worden, um Ihre allgemeinen Benennung zu vereinheitlichen. Dies betrifft folgende Funktionen:

Alter Name Neuer Name
expand_password_confirm form_process_password_confirm
expand_date form_process_date
expand_radios form_process_radios
form_expand_ahah form_process_ahah
expand_checkboxes form_process_checkboxes
process_weight form_process_weight

Wenn das Modul ein neues Element mit der hook_elements() definiert, müssen die #process-Callbacks aktualisiert werden.

Eine komplett neue Datenbank Api wurde hinzugefügt

(Issue) Mit Drupal 7 wird eine komplett neue Datenbank-API eingeführt, die sich eine Reihe an dynamischen Query-Builder und bestehende Statements zu nutze macht. Der folgende Konvertierungs-Führer sollte grundlegendste Fälle abdecken, aber das Lesen der vollständigen Dokumentation wird empfohlen.

Normale SELECT-Anweisung

  1. <?php
  2. // Drupal 6
  3. $result = db_query("SELECT nid, title FROM {node} WHERE uid = %d AND created < %d", 5, time());
  4.  
  5. // Drupal 7
  6. $result = db_query("SELECT nid, title FROM {node} WHERE uid = :uid AND created < :created", array(
  7.   ':uid' => 5,
  8.   ':created' => REQUEST_TIME,
  9. ));
  10. ?>

Iterieren mit dem Ergebnis von db_query().

  1. <?php
  2. // Drupal 6
  3. while ($record = db_fetch_object($result)) {
  4.   // Mach was mit $record, welches ein Object ist
  5. }
  6.  
  7. // Drupal 7
  8. foreach ($result as $record) {
  9.   // Mach was mit $record, welches ein Object ist
  10. }
  11. ?>

INSERT Anweisung

  1. <?php
  2. // Drupal 6
  3. db_query("INSERT INTO {mytable} (intvar, stringvar, floatvar) VALUES (%d, '%s', %f)", 5, 'hello world', 3.14);
  4.  
  5. // Drupal 7
  6. $id = db_insert('mytable')
  7.   ->fields(array(
  8.     'intvar' => 5,
  9.     'stringvar' => 'hello world',
  10.     'floatvar' => 3.14,
  11.   ))
  12.   ->execute();
  13. ?>

UPDATE Anweisung

  1. <?php
  2. // Drupal 6
  3. db_query("UPDATE {node} SET title='%s', status=%d WHERE uid=%d", 'hello world', 1, 5);
  4.  
  5. // Drupal 7
  6. db_update('node')
  7.   ->fields(array('title' => 'hello world', 'status' => 1))
  8.   ->condition('uid', 5)
  9.   ->execute();
  10. ?>

DELETE Anweisung

  1. <?php
  2. // Drupal 6
  3. db_query("DELETE FROM {node} WHERE uid=%d AND created < %d", 5, time() - 3600);
  4.  
  5. // Drupal 7
  6. db_delete('node')
  7.   ->condition('uid', 5)
  8.   ->condition('created', time() - 3600, '<')
  9.   ->execute();
  10. ?>

Weitere Beispiele siehe (Units Tests).

file_validate_extensions() erzwingt die Überprüfung für uid=1

(issue) In 6.x umgeht die Funktion bei der Überprüfung von Dateierweiterungen die uid=1. Dies wurde in 7.x entfernt. Wenn dein Modul auf dieses Verhalten abhängig ist, musst du die uid des Benutzers überprüfen, da dies so in file_validate_extensions()- Validator vorgegeben ist.

file_scan_directory() und drupal_system_listing() verwendet PREG Reguläre-Ausdrücke

(issue) Die file_scan_directory() und drupal_system_listing() Funktionen verwenden jetzt preg_match() anstatt ereg(), welches einen Groß-und Kleinschreibung Abgleich ermöglicht und zudem die Geschwindigkeit verbessert. Folglich ergibt sich durch die Formate der Regulären-Ausdrücke dieser Funktionen, dass die Parameter geändert wurden.

Bei den meisten Modulen braucht man nur einfach ein führendes und abschließendes / (Schrägstrich) hinzufügen.

Drupal 6.x:

  1. <?php
  2.    // Get current list of modules
  3.   $files = drupal_system_listing('\.module$', 'modules', 'name', 0);
  4. ?>

Drupal 7.x:

  1. <?php
  2.   // Get current list of modules
  3.   $files = drupal_system_listing('/\.module$/', 'modules', 'name', 0);
  4. ?>

Bei etwas komplexeren Regulären-Ausdrücken sollte man sich die PHP-Dokumentation für die ereg() und preg_match() Funktionen nochmals anschauen.

Einfachere Überprüfung für das Node-Formular während hook_form_alter()

Module, die das Node-Formular ändern wollen können nun die Überprüfung mit !empty($form['#node_edit_form']) durchführen anstatt mit der ausführlichen Variante

  1. <?php
  2. if (isset($form['type']) && isset($form['#node']) && $form['type']['#value'] .'_node_form' == $form_id)
  3. ?>

Siehe #161301.

Update Funktionen in der .install Datei müssen ein Doxygen-Style Kommentar beinhalten

Der Doxygen-Style Kommentar ist für Administratoren auf update.php einsehbar. Hintergrund-Info - #286035.

Neue #input_format zum Zuweisen der Eingabeformat-Auswahl an Feldern. Ändert „Body”-Feld Position in node, comment, block, etc.

(issue) In Drupal 6 wurde das Eingabeformat ein Textbereich zugewiesen, indem ein übergeordnetes Element den Textbereich umschloss und ein Filterformat-Auswahl wurde dem untergeordneten Element hinzugefügt, wie z.B.:

  1. <?php
  2.   $form['comment_filter']['comment'] = array(
  3.     '#type' => 'textarea',
  4.     '#title' => t('Comment'),
  5.     '#rows' => 15,
  6.     '#default_value' => $default,
  7.     '#required' => TRUE,
  8.   );
  9.   if (!isset($edit['format'])) {
  10.     $edit['format'] = FILTER_FORMAT_DEFAULT;
  11.   }
  12.   $form['comment_filter']['format'] = filter_form($edit['format']);
  13. ?>

Es gab kein Standard für die Benennung, Zuweisung der Format-Auswahl zum übergeordneten Element, deshalb war es unmöglich, Textbereiche und deren zugeordneten Eingabeformate zu identifizieren (im Vergleich zu Nur-Text-Eingabe-Widgets). Zudem war es Allgemein üblich für dieses Konstrukt eine Baumstruktur zu verwenden. So würde man ['comment_filter']['comment'] und ['comment_filter']['filter'] Werte erhalten oder eine Nicht-Baumstruktur, so das man ['comment'] und ['filter'] bekommt.

Dies ist in Drupal 7 alles streng definiert und automatisiert mit der Einführung von der #input_format FAPI-Eigenschaft. Man muss einfach nur das zu verwendende Standard-Eingabeformat angeben und Drupal wird automatisch das Element mit ein 'value' und 'format' Element erweitern, aus dem o.g. Code wird:

  1. <?php
  2.   $form['comment'] = array(
  3.     '#type' => 'textarea',
  4.     '#title' => t('Comment'),
  5.     '#rows' => 15,
  6.     '#default_value' => $default,
  7.     '#input_format' => isset($edit['format']) ? $edit['format'] : FILTER_FORMAT_DEFAULT,
  8.     '#required' => TRUE,
  9.   );
  10. ?>

Die Weg ist einfacher und Drupal 7 kümmert sich um den Rest. #input_format sollte den Wert des Standard-Eingabeformats haben, die mit der Auswahl verwendet wird. Durch die Formular-Verarbeitung, wandeln Drupal diese Struktur innerhalb form_process_input_format() in 'value' und 'format' Kinder um.

Obwohl die Struktur ['comment']['value'] und ['comment']['format'] ergeben, enthält $form_values Array die abgesendeten Formular-Daten den Kommentar-Wert in ['comment'] und das Format in ['comment_format']. Mit diesem kann man zwischen formatierte und nicht-formatierte Eingabe einfach umschalten ohne aufwendiges Programmieren. Dieses neue Format lässt es auch zu, dass WYSIWYG-Editoren ihre unterstützten Eingabeformate an die Steuerelemente zuordnen können.

drupal_clone() mit clone ersetzt

(issue) Da Drupal 7 mind. PHP 5 voraussetzt, ist es möglich die Funktion drupal_clone zu entfernen und clone direkt aufzurufen.

Drupal 6.x:

  1. <?php
  2.    // Make a copy of the node
  3.   $cloned_node = drupal_clone($node);
  4. ?>

Drupal 7.x:

  1. <?php
  2.   // Make a copy of the node
  3.   $cloned_node = clone $node;
  4. ?>