hook_module_implements_alter()でフックの実装を別のファイルに配置-悪い習慣?


7

私が書いたいくつかのモジュールでは、hook_module_implements_alter()を使用して* .moduleファイルを分割し、フックの実装を個別のファイルに移動しています。

主な理由は、長いファイルが嫌いだからです。(そして、はい、これは私がDrupal 7の多くのファイルについて不満に思って、貢献しています)

例:

考慮すべきことがいくつかあります。

  1. すべてのフックで機能しない場合があります。たとえば、bootまたはinstall、またはmodule_implements()経由で呼び出されないフック。
  2. module_implements()の動作方法により、hook_module_implements_alter()実装内からそれぞれのファイルを含めることが重要です。

今、私は長い間、よく知られたDrupal開発者から、この方法には問題があると聞きました。https://drupal.org/node/2230319(トピックスターター、コメント#5および#11)。

機能の移動を始める前に、技術的にも審美的にも、これが悪いかどうか、なぜ悪いのかを他の人から聞きたいと思います。

編集:これは2つの質問に分けられると思います:

  1. * .moduleファイルを分割して、フック実装が別の場所に存在するようにするのは良いことですか、悪いことですか?
  2. hook_module_implements_alter()の信頼性は十分include_once __DIR__ . '/MYMODULE.filename.inc'ですか、それとも* .moduleファイルで直接使用する必要がありますか?このためにhook_module_implements_alter()を使用すると、何が問題になる可能性がありますか?

スプリットについては他の人に検討してもらいたいのですが、良いと思います。私は#2の理由に本当に入っています。
mpdonadio

(ところで、答えの一部は私がすでに知っているものですが、それでも他の人に役立つようにするために関連性があり、不可欠です。そして、彼らは分割が一般的な慣行であることを確認します。したがって、両方とも私から+1を受け取ります。 )
ドンキホーテ2014

回答:


4

欠けていた情報を見つけました。
編集:そしてもう一つ。

module_invoke()の問題

module_invoke_all()は常にを呼び出しますmodule_implements()。これにより、hook_hook_info()およびの両方がチェックされ、モジュールインクルードファイルがチェックされますhook_module_implements_alter()

ただし、module_invoke()チェックのみであり、チェックはhook_hook_info()行いません hook_module_implements_alter()

module_invoke()たとえば_block_render_blocks()forで呼び出されhook_block_view()ます。これはhook_module_implements_alter()hook_block_view()実装を個別のファイルに分割するための適切なソリューションではないことを意味します。

これはCrumbsの問題でした。https: //www.drupal.org/node/2328535を参照してください

他のフックの場合、通常は問題なく動作しますが、特定のモジュールがのmodule_invoke()代わりに使用したいかどうかはわかりませんmodule_invoke_all()

ブートストラップで汚染されたmodule_implements()キャッシュ。

別の問題は、ここで報告されているコアの問題が原因です
。module_implements_cache()は、module_invoke_all()を直接または間接的に呼び出すhook_boot()実装によって汚染される可能性があります

これは、の実装が検出されないことがある非ブートモジュールにのみ適用hook_module_implements_alter()されます。

  1. 予期しない一連のイベントにより、module_implements($hook)から呼び出されhook_boot()ます。任意のランダムなフックすることができ、それは我々が取り組んでいるモジュールに関連する必要はありません。
    $hook
  2. これmodule_implements('module_implements_alter')が呼び出されます。
  3. Drupalはのすべての実装を探しますhook_module_implements_alter()。現時点でMODULENAME.moduleは、まだ含まれていません。
    したがって、残りのリクエストでは、Drupalは実装MODULENAME_module_implements_alter()が存在しないと想定します。
  4. リクエストの後半で、他のフックの実装が発見されていますが、MODULENAMEによる実装は実行されていないため、見つかりMODULENAME_module_implements_alter()ません。

代替案

require_once

代替案はすでに言及されています。これらのトリックの代わりに、ファイルを直接含めることができます。小さなパフォーマンスへの影響があるかもしれませんが、これは恐らくDrupalの他の多くの事柄によって影に隠れています。

しかし、を使用する代わりにmodule_load_include()、より直接的な解決策を提案します。

require_once __DIR__ . '/crumbs.block.inc';

または、PHP 5.2互換にするには:

require_once dirname(__FILE__) . '/crumbs.block.inc';

なぜmodule_load_include()をしないのですか?

module_load_include()* .moduleファイルがyou-dont-know-where(例:からsettings.php)からインクルードされていて、それmodule_load_include()が利用可能かどうかわからない場合、通常はを呼び出す必要はありません。

この関数は主に、他のモジュールの場所を特定するのに役立ちます。ただし、同じモジュール内に含める場合は、相対ファイルパスと明示的なファイルを使用する方が一般に安全かつ簡単で高速require_onceです。

ヘルパー関数の呼び出し

Jimajammaで述べたように、メイン*.moduleファイルにフックを実装し、別のファイルをインクルードして、そこからヘルパー関数を呼び出すこともできます。これは、たとえばDisplay suiteで行われます。

この解決策は問題ありませんが、メインファイルが雑然としていて、さらに多くの場所を見ることができると思います。

またmodule_load_include()、同じモジュール内にある場合は、の代わりにrequire_onceを使用することもできます。


慎重な内訳をありがとう。私は、クライアント用の関連するが、個別のカスタムモジュールを6つに1つに統合するために役立つ助けが必要でした。require余計なことを考え直すのはやめようと思います。単に余分なファイルだけです。これらのファイルの適切な命名規則も役立ち、全体がはるかに解析可能になります。
チャーリーシュリーサー、2015

なぜ異なるモジュールを1つに組み合わせるのですか?分離がいい!(もちろん依存します)
ドンキホーテ2015

心配事の分離は必須です!そして、抽象的であり続けることができるモジュール(つまり、モジュールであること)はそうすべきです。この特定のプロジェクトで、私はある時点で、アプリ内で展開され進化していたビジネスロジックに同じパラダイムが適用されたと考えていたようです。それは実際には同じケースではなく、いくつかのモジュールは実際にはモジュールではなく、お互いがなければ意味のないPACロジックのコレクションです。
チャーリーシュリー

hook_hook_info_alter()代わりに使用しないのはなぜですか?を使用hook_hook_info_alter()して別のファイルにフック実装を分割する場合、同じ考慮事項/問題が適用されますか?
ЕлинЙ.

hook_hook_info_alter()は、このフックのすべての実装に適用されます。したがって、他のモジュールに意図しない副作用が発生します。
ドンキホーテ2016年

2

私が取り組んだ主なプロジェクトはすべて、物事を扱いやすく、簡単に割り当て可能な部分に分割しました。基本的にここで言及した@tenkenのようにfoo.module終わるか、最終的には次のものが含まれるだけになります。

<?php

module_load_include('inc', 'foo', 'foo.defines');         // bring in our define()s
module_load_include('inc', 'foo', 'foo.HOOK1');           // bring in our HOOK1 functions
module_load_include('inc', 'foo', 'foo.HOOK2');           // bring in our HOOK2 functions

// ...etc

もちろん、私はまた、管理者のみまたはほとんど使用されないフックが次のように含まれている状況を見て、使用しました。

function foo_HOOK(/* $args */) {
  module_load_include('inc', 'foo', 'foo.HOOK');
  return _foo_HOOK(/* $args */);  // _foo_hook() is defined in foo.HOOK.inc
}

はい、それを見て自分でやった。それの両方。私は最近include_once __DIR__を好むが、'/filename.inc'。ですから、質問1についてははっきりしていると思います。2つ目は、hook_module_implements_alter()を使用した場合に問題が発生するかどうかです。または、平均的なリクエストにファイルを含めないことで、パフォーマンスのメリットがどの程度大きくなるか(たとえば、hook_menu()が呼び出されない場合)。
ドンキホーテ2014

ところで、私は個人的に_foo_HOOK(好きではない)...それは私が代わりに1の2つの場所で見えるのです、あまりにも多くのトリック
donquixote

ところで、module_load_include( 'defines.inc'、 'foo')に簡略化できます。しかし、lrfmとは何ですか?
ドンキホーテ2014

笑、lrfmは私がそれを切り取って貼り付けたモジュールで、fooに変更するのを忘れていました:)
Jimajamma

あなたの単純化に関しては、はい、それは確かに機能しますが、最初の引数はファイルのタイプであることになっています、そしてapi.drupal.org/api/drupal/includes%21module.inc/function/…の例によると、私は「ありのままの力」が何を意図していたのか疑わしいが、タイピングは確かに少ない。
ジマジャンマ2014

1

複数のファイルにまたがって.moduleファイルを分割しようとすると、include_once()を使用する「インクルードされた」ファイルに対して、D7の機能で次のことを行う傾向があります。

include_once('MYMODULE.features.inc');

D7の場合も、これらのインクルードファイルには引き続きモジュール名「function namespacing」を使用し、プライベートモジュール関数には通常「_MYMODULE_foo()」というプレフィックスを付けます。

この回答は、コード内で使用しようとしているAutoloadingクラスとOO関連のパターン(コードの依存関係など)の使用を無視します。

あなたのリンクされた問題では、hook_module_implements_alter()を使用して、.moduleファイル内のどのファイルがどの機能を持っているかを示す読み取り可能なインデックスにしたいようです。正しい 'MYMODULE.PURPOSE.inc'ファイル名は、モジュール内でそのインクルードファイルを使用する開発者の手がかりを得るのに十分だと思います。


必要な場合にのみ、それぞれのファイルを含めるという考え方です。そこでパフォーマンスについて考えていますが、実際のパフォーマンスへの影響はわかりません。APCやそれと同様のものでは大きな違いはないと思いますが、測定したことはありません。
ドンキホーテ2014

1
@donquixoteは、パフォーマンスについて考えている場合は、APCまたは他のオペコードキャッシュをインストールします。あまりスプリットする必要はありません。
Mołot
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.