サードパーティのPHPクラスベースライブラリのベストプラクティス


17

私は現在、サードパーティのPHPライブラリを必要とするモジュールに取り組んでいます。これは基本的に単一のPHPクラスです。通常、includes /サブディレクトリに配置して追加します

files[] = includes/Foo.php

.infoファイルに追加して、を実行するときにDrupal 7クラスのオートローダーにその処理を実行させ $foo = new Foo()ます。

ただし、このモジュールを公開する許可はありますが、ライブラリをモジュールに含めることは避けます。ライセンスに関する複雑さについてはよく知っていますが、この質問のために無視したいと思います。

同様の質問があります。PHPライブラリを含めるにはどうすればよいですか?、しかし、これが私のジレンマに答えるとは思わない。

この質問にこの答えは、基本的に使用するように言うライブラリAPIを、私は用途が、これは単にないことを発見したことを、すべて単一のモジュールlibraries_get_path()はBasePathを取得(そして、それは利用できない場合にフォールバックパスを含みます)し、その後、ないrequireまたはinclude一部とエラーチェック(またはそうでない)。すべてのような何かをします:

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
  }
}

この場合、ライブラリAPIは実際には何もしていません。ユーザーにコピーをダウンロードしてモジュールフォルダー自体に配置するよう求める古い方法に比べて、これを使用する利点はありません。また、モジュール開発者が/ を使用して手動でロードを行う必要があるという問題がまだあります。たとえば、Facebookモジュールはライブラリをaにロードするだけで、HTML Purifierモジュールには、ライブラリが必要になるたびにチェックアンドロードする内部関数があります。includerequirehook_init

これは広く行われているプラクティスかもしれませんが、ベストプラクティスとは思えません。

私のモジュールがイニシアチブを取り、hook_libraries_info使用できるように宣言する必要がありますlibraries_load('foo')か?これも奇妙に思えます。


別の問題は、サードパーティのライブラリのライセンスがdrupalのライセンスと一致するかどうかです。それがあり、それが巨大でなければ、私はそれを含めるだけです。含まれていない場合、最初から含めることはできません/含めるべきではありません。したがって、ライブラリのアプローチのほうが優れているようで、最終的にエンドユーザーに自分でダウンロードしてもらいます。
ジマジャマ

1つの目的はif (libraries_load($name)) {..}、ライブラリが存在しない場合にWSODを回避することです。
ドンキホーテ14年

回答:


7

ライブラリのAPIモジュールのブランチ2.xではを通じて、開発者が定義することができます)(hook_libraries_info、またはライブラリ用の.infoファイルは、以下の情報(参照libraries.apiを):

  • ライブラリの依存関係
  • 依存関係ごとに、ライブラリと互換性のあるバージョン
  • ロードする必要があるファイルのリスト(CSS、JavaScript、またはPHPファイル)

ライブラリが必要な場合、ロードする必要があるファイルのリストは、それらのファイルをロードするために使用されます。これは、ライブラリAPIモジュールから既に行われているように、モジュールがCSSやJavaScriptファイルをdrupal_add_css()、またはdrupal_add_js()で読み込む必要がないことを意味します。依存関係の読み込みは、呼び出し側モジュールが何も実行せずに、ライブラリAPIモジュールから実行されるタスクです。

モジュールは、ライブラリをロードするために次のコードを使用しています。(ライブラリAPI 2.xの使用(モジュール開発者として)を参照してください。)

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

ライブラリが存在するかどうかを検出する必要がある場合、モジュールは次のようなコードを使用する必要があります。

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

hook_libraries_info()返すことができるプロパティの間には'download url'、ブランチ3.xでも実際には使用されていないがあります。おそらく今後使用されるか、サードパーティのモジュールがライブラリAPIモジュールにフックし、要求されているが欠落しているライブラリをダウンロードする可能性があります。


PHPライブラリでこれを行う一般的なモジュールを指摘できますか?質問の動機の一部は、パブリックモジュールのベストプラクティスに従うことができるようにすることでした。そのため、ライブラリAPIを使用するものを探し始めました。hook_libraries_info()を実装し、library_load()を内部で使用するものは見つかりませんでした。
mpdonadio

zencorderapiモジュール(ビデオモジュールの一部)はhook_libraries_info()を使用します
AyeshK


@kiamlaluno、ありがとう、私が最初に見た場所でした。6つのうち、hook_libraries_infoを実装しているライブラリは2つだけです。私はあなたの答えが間違っているとは思いませんが、これが現在広く普及しているベストプラクティスであるとは確信していません。ライブラリの1つに興味深いテクニックがありましたが、これをテストし、後で投稿することもあります。
mpdonadio

@MPDバージョン7.x-2.0は7月29日にリリースされました。ほとんどのモジュールがまだ7.x-1アプローチを使用している可能性があります。
キアムルノ

5

十分な量の掘り下げを行った後、ベストプラクティスが何であるかについてはまだ確信が持てません。PHPMailerモジュールに触発され、クラスベースのPHPライブラリ向けにこれを提供しています。

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,
    );
  }
}

これはhook_registry_files_alterを使用してクラスの存在を確認し、見つからない場合はファイルをクラスレジストリに追加します(files[] = ...モジュールの.infoファイルの行に相当)。そうすると、foo.phpで定義されたクラスがオートローダーで利用できるようになるため、クラスを使用する前にファイルを明示的にロードする必要はありません。

また、これによりライブラリAPIにソフト要件が作成され、使用可能な場合はそれが使用され、それ以外の場合は妥当なデフォルトが使用されます。

ファイルが存在すること、オートローダーがクラス、バージョンチェックなどを見つけることを確認するために、hook_requirementsを介していくつかのチェックを追加することも良い考えです。

また、ライブラリAPIの自動ロードアプローチが課題キューで議論されていることも注目に値します。


いけないが、それ以外の場合文句を言わないトリガー、hook_registry_files_alterを実施した後、あなたのキャッシュをクリアすることを忘れ;)
saadlulu

2

要するに、 モジュールを公開する予定で、(サードパーティの)ライブラリがGPLになっていない場合、ライブラリを依存関係として使用するか、ユーザーにこれらのファイルを手動でダウンロードするように依頼する必要があります(ただし、 .infoファイルから自動ロードします)

もう少しで:

ライブラリモジュールが必要な理由は、基本的にライセンスです。そのモジュールを使用するかどうかに関係なく、何らかの方法でそのファイルを含めます。

さて、あなたはそのようなモジュール付きのライブラリのケースの良い例を見つけられなかったと思います。SMTPモジュールを確認してください。GPLにあるように、必要なクラスが付属しています。(.infoファイルblob)。

また、ファイルだけをインクルードするsimplehtmldomモジュールも参照してください。

Librariesモジュールが便利なのは、ユーザーにファイルを好きな場所にアップロードするように依頼できることです。ユーザーがそれをsites / all / librariesフォルダーにアップロードするかどうかは明らかではありません。sites / example.com / librariesまたはそのようなものである可能性があります。ライブラリモジュールは、ディレクトリディスカバリーを行うことにより、実際の作業に集中するのに役立ちます。

クライアント用に開発したカスタムモジュールの場合、通常はモジュールフォルダーにファイルを含め、ライブラリの使用に応じてrequire_onceまたは.infoファイルエントリを使用します。

また、ライブラリモジュールを使用する理由は、ライセンスの問題だけではありません。サードパーティのライブラリのリリースサイクルが急速で、モジュールの開発が最小限の場合 モジュールに含めると、毎回新しいリリースを作成する必要があります。7.x-1.0と非常によく似たリリース7.x-1.99は必要ないでしょう。


答えてくれてありがとう。明確にするために質問を少し編集しました。問題は、ライセンスとリリーススケジュールの複雑さ、およびライブラリAPIがこれにどのように役立つかについてではありません。サードパーティのライブラリを実際にロードするためのベストプラクティスに興味があります。
mpdonadio

2

主な問題は自動ロードのようです。

ライブラリモジュールとxautoloadモジュールを使用できます。

次に、独自のモジュールで、あなたは

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');
      },
    ),
  );
}

これについては、
xautoload.api.phpで詳しく説明してい
ます。$ api引数の詳細。

注:また、独自の「ハンドラー」を作成して、PSR-0またはPEARを超えた、よりエキゾチックな旧式のパターンを実装することもできます。それに関して助けが必要な場合は、xautoloadキューに問題を投稿してください。

注:ライブラリの名前空間を登録する方法は複数あります。名前空間をすべてのリクエストに登録する場合、これが最も簡単です。


1
追加する必要がありますが、これは手続き型ファイルの読み込みには役立ちません。これは、リクエストでライブラリが必要になったらすぐに、手動で行う必要があります。
ドンキホーテ

また、一部のライブラリには独自のクラス読み込みソリューションがあります。それでも、Drupal / contribで既に利用可能なローダーを使用する方が便利です。
ドンキホーテ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.