it-swarm.com.de

Best Practice für Drittanbieter PHP klassenbasierte Bibliothek

Ich arbeite derzeit an einem Modul, für das eine PHP - Bibliothek eines Drittanbieters erforderlich ist, bei der es sich im Wesentlichen um eine einzelne PHP - Klasse handelt. Normalerweise würde ich sie in eine Klasse einfügen enthält/Unterverzeichnis und hinzufügen

files[] = includes/Foo.php

in meine .info-Datei und lassen Sie den Drupal 7 Klasse Auto Loader seine Sache machen, wenn ich eine $foo = new Foo() mache.

Ich habe jedoch die Erlaubnis, dieses Modul für die Öffentlichkeit freizugeben, und möchte die Bibliothek lieber nicht in das Modul aufnehmen. Ich bin mir der Komplikationen bei der Lizenzierung bewusst, aber um dieser Frage willen möchte ich sie ignorieren.

Es gibt eine ähnliche Frage: Wie füge ich eine PHP Bibliothek? hinzu, aber ich glaube nicht, dass dies mein Dilema beantwortet.

Diese Antworten auf diese Frage sagen im Wesentlichen, dass die Libraries API verwendet werden soll, aber jedes einzelne Modul, das ich gefunden habe und das dies verwendet, führt nur alibraries_get_path() aus, um den Basispfad zu erhalten (und enthält den Fallback-Pfad, wenn es ist nicht verfügbar) und führt dann ein require oder include mit einer Fehlerprüfung durch (oder nicht). Alle machen so etwas wie:

if (!class_exists('Foo')) {
  $path = function_exists('libraries_get_path') ?
    libraries_get_path('foo') : 'sites/all/libraries/foo';
  if (!include($path . '/Foo.php')) {
      // handle this error
  }
}

In diesem Fall macht die Bibliotheks-API eigentlich nichts. Ich sehe keinen Vorteil darin, dies zu verwenden, gegenüber der alten Methode, Benutzer aufzufordern, eine Kopie herunterzuladen und im Modulordner selbst abzulegen. Und es gibt immer noch das Problem, dass der Modulentwickler immer noch manuell Laden Sie mit include/require. Beispielsweise lädt das Facebook-Modul die Bibliothek nur in einem hook_init Und das HTML Purifier-Modul verfügt über eine interne Funktion zum Überprüfen und Laden jedes Mal, wenn die Bibliothek benötigt wird.

Dies mag eine weit verbreitete Praxis sein, aber es scheint keine beste trainieren.

Sollte mein Modul die Initiative ergreifen und einen hook_libraries_info Deklarieren, damit ich libraries_load('foo') verwenden kann? Auch das scheint seltsam.

16
mpdonadio

Mit Branch 2.x des Libraries API-Moduls können Entwickler über hook_libraries_info () oder eine .info-Datei für die Bibliothek die folgenden Informationen definieren (siehe library.api ):

  • Die Abhängigkeiten der Bibliothek
  • Die Version, mit der die Bibliothek kompatibel ist, für jede der Abhängigkeiten
  • Die Liste der Dateien, die geladen werden müssen (CSS, JavaScript oder PHP Dateien)

Die Liste der Dateien, die geladen werden müssen, wird zum Laden dieser Dateien verwendet, wenn die Bibliothek benötigt wird. Dies bedeutet, dass Ihr Modul kein CSS und keine JavaScript-Dateien mit drupal_add_css() oder drupal_add_js() laden muss, wie dies bereits über das Libraries API-Modul erfolgt. Das Laden der Abhängigkeiten ist eine Aufgabe, die vom Bibliotheks-API-Modul ausgeführt wird, ohne dass das aufrufende Modul etwas unternimmt.

Das Modul verwendet lediglich den folgenden Code zum Laden einer Bibliothek. (Siehe Verwenden der Libraries API 2.x (als Modulentwickler) .)

// Try to load the library and check if that worked.
if (($library = libraries_load($name)) && !empty($library['loaded'])) {
  // Do something with the library here.
}

Wenn Sie nur feststellen müssen, ob eine Bibliothek vorhanden ist, sollte das Modul einen Code verwenden, der dem folgenden ähnlich ist.

if (($library = libraries_detect($name)) && !empty($library['installed'])) {
  // The library is installed.
}
else {
  $error = $library['error'];
  $error_message = $library['error message'];
}

Zwischen den Eigenschaften, die hook_libraries_info() zurückgeben kann, gibt es auch 'download url', Das nicht einmal in der Verzweigung 3.x tatsächlich verwendet wird. Wahrscheinlich wird es in Zukunft verwendet, oder Module von Drittanbietern können sich in das Bibliotheks-API-Modul einbinden und die angeforderten, aber fehlenden Bibliotheken herunterladen.

7
kiamlaluno

Nach einigem Graben bin ich immer noch nicht davon überzeugt, was die beste Vorgehensweise ist. Inspiriert vom Modul PHPMailer biete ich dies für klassenbasierte PHP Bibliotheken) an:

function foo_registry_files_alter (&$files, $modules)
{
  if (!class_exists('Foo')) {
    $library_path = function_exists('libraries_get_path') ?
      libraries_get_path('foo') : 'sites/all/libraries/foo';

    $files[$library_path . '/Foo.php'] = array(
      'module' => 'foo',
      'weight' => 0,
    );
  }
}

Dies verwendet hook_registry_files_alter , um die Existenz einer Klasse zu überprüfen und, falls nicht gefunden, eine Datei zur Klassenregistrierung hinzuzufügen (das Äquivalent zu einem files[] = ... Zeile in einer Modul-Info-Datei). Dann sind die in foo.php definierten Klassen mit dem Autoloader verfügbar, sodass die Datei vor der Verwendung der Klasse nicht explizit geladen werden muss.

Dadurch wird auch eine weiche Anforderung an die Bibliotheks-API erstellt, die, sofern verfügbar, verwendet wird. Andernfalls wird ein angemessener Standardwert verwendet.

Es ist auch eine gute Idee, einige Überprüfungen über ein hook_requirements hinzuzufügen, um sicherzustellen, dass die Datei vorhanden ist und der Autoloader die Klasse, die Versionsprüfung usw. findet.

Es ist auch erwähnenswert, dass ein Autoload-Ansatz für die Bibliotheks-API wird diskutiert in der Problemwarteschlange ist.

5
mpdonadio

Kurz gesagt: Wenn Sie vorhaben, das Modul für die Öffentlichkeit freizugeben und die Bibliothek (von Drittanbietern) nicht über eine GPL verfügt, müssen Sie Libraries as verwenden eine Abhängigkeit oder fordern Sie Benutzer auf, diese Dateien manuell herunterzuladen (Sie können sie jedoch nicht automatisch aus der INFO-Datei laden).

In etwas länger:

Der Grund, warum wir das Bibliotheksmodul benötigen, ist im Grunde die Lizenzierung. Unabhängig davon, ob Sie dieses Modul verwenden oder nicht, schließen Sie diese Datei auf irgendeine Weise ein.

Nun, ich denke, Sie haben keine guten Beispiele für solche Bibliotheken gefunden, die mit dem Modul geliefert wurden. Check out SMTP-Modul und es kommt mit den erforderlichen Klassen, wie es in der GPL ist. ( . info file blob ).

Siehe auch simplehtmldom Modul, das nur die Datei enthält, aber sonst nichts.

Das Bibliotheksmodul ist praktisch, da Sie Benutzer bitten können, die Datei an einer beliebigen Stelle hochzuladen. Es ist nicht offensichtlich, dass Benutzer es in den Ordner sites/all/library hochladen. Es können Websites/example.com/Bibliotheken oder ähnliches sein. Das Bibliotheksmodul kann Ihnen helfen, sich auf Ihre eigentliche Arbeit zu konzentrieren, indem Sie die Verzeichniserkennung für Sie durchführen.

Für benutzerdefinierte Module, die ich für meine Clients entwickle, füge ich normalerweise Dateien in den Modulordner ein und verwende je nach Verwendung der Bibliothek den Dateieintrag require_once oder .info.

Lizenzprobleme sind nicht der einzige Grund, das Bibliotheksmodul zu verwenden. Was ist, wenn die Bibliothek eines Drittanbieters schnelle Release-Zyklen aufweist und Ihr Modul nur minimal entwickelt ist? Wenn Sie es in das Modul aufnehmen, müssen Sie jedes Mal eine neue Version erstellen. Sie werden keine Version 7.x-1.99 haben wollen, die 7.x-1.0 sehr ähnlich ist, denke ich.

2
AyeshK

Es scheint, dass das Hauptproblem das automatische Laden ist.

Sie können das Modul Bibliotheken plus xautoload verwenden.

Dann tun Sie es in Ihrem eigenen Modul

function mymodule_libraries_info() {

  return array(
    'mymodule-test-lib' => array(
      'name' => 'My test library',
      ..
      'xautoload' => function($api) {
        // Register a namespace with PSR-0 root in <library dir>/lib/
        // Note: $api already knows the library directory.
        // Note: We could omit the 'lib', as this is the default value.
        $api->namespaceRoot('XALib\TestNamespace', 'lib');
      },
    ),
  );
}

Dies wird hier näher erläutert:
xautoload.api.php
Mehr zum $ api-Argument.

Hinweis: Sie können auch Ihre eigenen "Handler" schreiben, um exotischere Old-School-Muster jenseits von PSR-0 oder PEAR zu implementieren. Wenn Sie dabei Hilfe benötigen, stellen Sie ein Problem in die xautoload-Warteschlange.

Hinweis: Es gibt mehrere Möglichkeiten, Ihre Bibliotheksnamespaces zu registrieren. Dieser ist am einfachsten, wenn Sie möchten, dass die Namespaces in jeder Anfrage registriert werden.

2
donquixote