フックの背後にある基本的な概念は何ですか?


120

私はPHPの中級です。スキルを磨くために、Drupal 7の学習を開始しました。Drupalアーキテクチャの概念を学習している間、フックブートストラップという用語は非常に困惑しました。「Pro Drupal開発」本とdrupal.orgのドキュメントを読みましたが、Webページを表示するためにDrupalでフックがどのように機能するかを学ぶことは非常に高度です。

フックとは簡単な言葉で誰でも教えてもらえますか?

回答:


107

他の答えは素晴らしく、正確で、詳細ですが、質問者が探していた概念の骨を説明する「単純な言葉」かどうかはわかりません。

フックは、コードが一時停止して「他に誰かがここに追加するものがありますか?」と叫ぶポイントだと思います。すべてのモジュールはこれに応答する関数を持つことができ、コードのその時点で適切なデータが渡されてトリガーされます。

わかりやすい簡単な例はhook_node_delete()です。ノードが削除されるたびに、どのモジュールでもそれを使用して物事を発生させることができます。ドキュメントは、このフックが削除されたノードのオブジェクトを処理するモジュールに渡し、呼び出された正確なタイミングに関するその他の有用な情報を概説します(たとえば、ノードデータがデータベースから実際に削除される前) 、Drupalのコードのどこでフックが呼び出されるか(複数の場所になります)。

Drupal apiで「hook_」で始まるものを調べることにより、フックが存在するものを探索し、それらに渡されるデータを見つけることができます。

フックは名前の規則によって機能しhook_node_deleteます。例として、ノードの削除プロセスがフックが呼び出されるポイントに達すると、[modulename]_node_delete()フックの名前の単語hookがモジュールの名前に置き換えられるこのような機能を持つすべてのモジュールについてmy_amazing_module_node_delete())、これらの関数が呼び出されます。

どうして?したがって、どのモジュールでもこれらの重要なポイントで何でもできます。たとえば、削除されたノードを見て、特定の条件(管理者にメールを送信したり、いくつかの長いプロセスを起動したり)を満たせば何かを実行できます。

一部のフックでは、処理される直前に生成されたものを変更できます。たとえば、hook_menu_alter()は、システムが生成した現在のメニュー項目を渡します。どのモジュールでも関数some_modulename_menu_alter()を定義し、それらを見て、オプションでそれらを変更(いくつかを削除、いくつかを追加、ソート...)し、新しく変更されたメニューを戻すことができます。

シンプルで非常に強力であり、Drupalがモジュラーシステムとして機能する方法の中心にあります。フックの実装は、ほとんどのDrupalモジュールの中心です。

Drupalコミュニティは、フックの各実装が持つ規約を実施するため、Drupalモジュールのコードを調べると、(モジュールコード自体から単純に呼び出される関数とは対照的に)フックからの関数を見つけることができますその前に次のようにコメントします(「Implements hook _...」ビットに注意してください):

/**
 * Implements hook_some_hook().
 *
 * Some descriptive summary of what this does
 */
function my_amazing_module_some_hook() {

APIとして機能する一部のモジュールは、独自のフックを定義します。たとえば、ビューは、ビューの作成または表示プロセスのさまざまな時点でデータの追加、読み取り、編集を可能にする多くのフックを定義します。カスタムモジュールで作成されたフックに関する情報は、2つの場所から見つけることができます(モジュールが規則に従っていると仮定すると)。

他の人が説明したように、ブートストラップは基本的に起動します-他の明確な説明を複製しません。


53

フックは、ほとんどがVisitorパターンとObserverパターンの実装です。

最も一般的なフック実装の1つはhook_menuで、これによりモジュールはDrupalシステム内の新しいパスを登録できます。

function my_module_menu() {
  return array('myawesomefrontpage' => array(
    'page callback' => 'function_that_will_render_frontpage'
  ));
}

Drupalで非常によくあるパターンは、[DATATYPE]_infoフックと[DATATYPE]_info_alterフックです。新しいフィールドタイプを作成する場合は、関連するfield_info -hook を実装し、既存のフィールドタイプを操作する場合は、対応するfield_info_alter -hook を実装します。

編集: Chxがコメントで指摘しているように、オブザーバーパターンはオブジェクト指向であり、Drupal 7はまだほとんどではありません。ただし、Wikiページ、オブジェクト指向の観点からのDrupalプログラミング(2005年4月4日にJonBobによって作成)があり、これにもかかわらずDrupalがオブジェクト指向のコードパターンを使用する方法を説明しています。興味深いのは、オブザーバーに言及しているが訪問者には言及していないことです。

Drupal 8に関する注意これはまだかなり早く、変更される可能性がありますが、フックはかなり長い間、Drupalに機能を追加する際の事実上の標準でしたが、プラグインの概念ははるかに明らかになりますDrupal 8では、Coreと対話する新しい方法を提供します。関連する問題、およびドキュメント


2
OOPデザインパターンに縛られないでください。これは1つではありません。DrupalフックはAOPです。下記参照。

@chx、あなたは私よりもよく知っていることを自由に認めていますが:)、あなたの答えは正しいです(私はそれを投票しました)私はそれが私の答えが間違っていると解釈しません。:)あなたが同意しない場合、私はどのようにそれらの実装のパターンを誤解したかを学びたいです。
レサリオン

4
ウィキペディア:「オブザーバーパターンは、サブジェクトと呼ばれるオブジェクトがオブザーバーと呼ばれるその従属物のリストを保持するソフトウェア設計パターンです」オブザーバーを保持するオブジェクトはありません。訪問者はより暗くなりますが、同じ一般的な原則が適用されます:OOPではないものはOOPパターンを持つことができません。

33

素人の言葉で言うと、フックとは、モジュールが相互にやり取りし、互いの構造とデータを変更し、新しいデータを提供する方法を提供する一種のブリッジです。

ほとんどの場合、hook_関数名の単語はモジュールの名前に置き換えられ、モジュールが別のモジュールの操作を利用する方法を提供します。たとえば、「ノード」と呼ばれるdrupalコアモジュールは、さまざまなフックを呼び出します。それらの1つはhook_node_update、既存のノードが更新されるたびに呼び出されるものです。このフックが呼び出されると、モジュールの(たとえば、呼び出すmymodule)実装が呼び出されます。hook_node_updateこの場合、モジュールの.moduleファイル内の関数になりますmymodule_node_update(明らかに、この関数は、モジュールのフォルダー内の任意のファイルにあります。 .moduleファイルにも含まれています)。このフックには、使用、変更、および/またはフックを呼び出した関数に戻ることができる必要なパラメーター(変数)も渡されます。

最初にDrupalを学び始めたとき、私はあなたと同じ船に乗っていました。最初はつかむのが少し難しいですが、一度理解すると、とてもシンプルで直感的です。幸運を。


1
answer.itに感謝します。前の答えを説明する際に、drupalのブートストラップの概念とブートストラップでのフックの扱い方を簡単な言葉で教えてください
。– GiLL

@Bayasa、自分の考えをここに入力してください。私は自分自身を追加しています。boostrtappingは、コンピューターの起動と考えることができます。Drupalには、データベース、ファイル、フォームなど、多くのAPIがあります。これらは「プラットフォーム」に基づいています。ブートストラップ中に、Drupalはこれらの機能とその他の設定(データベース接続、ファイルフォルダーなど)を定義するため、システムの残りの部分は残りの部分から続行できます。
AyeshK

32

コア開発者の1人が「オブジェクト指向の観点からのDrupalプログラミング」という記事を少し前に書きました。フックが一般的なデザインパターンの多くを実装すると考えられる方法を説明する良い仕事をします。フックの最良の説明は、記事から来ています。

Drupalのフックシステムは、インターフェイスの抽象化の基礎です。フックは、モジュール上またはモジュールによって実行できる操作を定義します。モジュールがフックを実装すると、フックが呼び出されたときに特定のタスクを実行したり、特定の種類の情報を返したりする契約が締結されます。フックを呼び出すことで有用な作業を行うために、呼び出し元のコードはモジュールやフックの実装方法について何も知る必要はありません。


1
私は、あたりとしてその記事の著者を固定drupal.org/node/19964

@chx、ありがとう。現在、この回答を削除することを検討しています。私はプレーンCで多くのオブジェクト指向の作業を行っていたb / cに投稿し、実際のオブジェクトのないオブジェクト指向の概念に慣れました。ただし、ポイントカット/ウィーバーの関係については正しいです。ただし、引用がアスペクトの正確な説明であるかどうかはわかりません(「インターフェースの抽象化」の部分は無視します)。
mpdonadio

21

ブートストラップは、Drupalがページを構築するプロセスであり、基本的にすべてのコア、テーマ、およびモジュールコードを順番に実行します。
基本的には、Drupalが起動し、CMSとしての仕事を準備する方法です。

モジュールやテーマの任意の場所にフックを配置できるという点で賢明であり、ブートストラッププロセスにより、それらが適切なポイントで実行されるようになります。
たとえば、「hook_form_alter」を使用してカスタムチェックボックスをフォームに追加すると、Drupalのブートストラップは、フォームをレンダリングする直前にそのコードを実行するようにします。

ブートストラップの問題の1つは、たとえ少量のデータしか返さない場合でも、プロセス全体の実行に時間がかかることです。DrupalをサービスモジュールでAPIとして使用し、多くの小さなXHTMLまたはJSON応答を返す場合、ブートストラップ全体を実行することはあまりパフォーマンスがありません。一部の賢い人々は、Drupal 8についてこれに関する賢い方法を検討しています。

しかし、通常のDrupalページをレンダリングする場合、ブートストラッププロセスはうまく機能し、Drupalキャッシングシステムを使用して処理を高速化し、サイトのすべての部分を完全に制御できます。サイトの速度が遅い場合は、APCやMemCachedなどを使用して、速度を上げることができます。

私の答えが正確で、あなたのために物事を簡単に説明してくれることを望みます、私は専門家ではありませんが、それがどのように機能するかと思います。


15

ブートストラップは、Drupalが自身を初期化するプロセスです。プロセスには実際に以下が含まれます。

  • エラーと例外ハンドラーの設定
  • に含まれるいくつかの仕様グローバル変数の値を初期化する $_SERVER
  • いくつかの変数を初期化する init_set()
  • 提供するページのキャッシュバージョンを見つける
  • データベースの初期化
  • クラスまたはインターフェースが見つからない場合にファイルをロードするハンドラーを設定する
  • Drupal変数の初期化
  • PHPセッションの初期化
  • 言語変数の初期化
  • 有効なモジュールをロードする

説明した操作の一部は、Drupal 7以降に固有のものですが、ほとんどの操作はDrupalバージョンから独立しています。

フックは、タスクを実行する必要があるときにDrupalまたはサードパーティのモジュールから呼び出すことができるPHP関数です。呼び出す関数のプレフィックスリストを使用する代わりに、リストは有効なモジュールとそれらが実装する関数をチェックしてビルドされます。
たとえば、Drupalはhook_node_update();を使用します。node_save()使用してノードを保存すると、次のコードが実行されます。

// Call the node specific callback (if any). This can be
// node_invoke($node, 'insert') or
// node_invoke($node, 'update').
node_invoke($node, $op);

node_invoke()ん以下の通りです:

  • 有効なすべてのモジュールのリストを取得する
  • 有効なモジュールに、名前が「_node_update」で終わり、モジュールの短縮名で始まる関数があるかどうかを確認します
  • その関数を呼び出し、$nodeパラメーターとして渡す

フックは、独自のデータをデータベースに保存したり、関数から返される値を変更したりできます。最後のケースは、例えば、drupal_prepare_form()への参照として渡される値を変更するhook_form_alter()で起こることです。$form

Drupalフックは通常、3つの関数を使用して呼び出されます。

drupal_alter()その目的は、データを変更することであるような参照としてそれらを渡す特定フック呼び出すために使用される機能であるhook_form_alter() hook_hook_info_alter() 、及び)hook_tokens_alterは(

フックなど、フックを呼び出すために使用される関数は他にもありますがnode_invoke()、これらの関数は基本的に、前にリストした関数の1つを使用します。


12

フックはポイントカットmodule_invoke_allあり、ウィーバーです(実装には明確ではなく、他のウィービング関数があります)。私の知る限り、DrupalはPHP関数でAOPを実装する唯一のシステムです。

DrupalでのAOPの動作に関する別の説明をご覧ください


jhodgdonの記事(私の回答で述べた)は正確だと思いますか?
mpdonadio

2
これは、属性が間違っている2005年のjonbobの記事です。私はそれを議論します、はい。

6

Drupalで呼び出すことができるフックを表示するには、api.drupal.orgに移動し、検索ボックスにタブで移動して、「hook_」と入力します。これにより、Drupalで定義されているほとんどのフックの大きなリストが得られます。'_alter'についても同じことを行い、さらに多くを確認します。

ノードAPIフックのページには、ノードの操作中に呼び出されたすべてのフックの時系列リストを提供しています。Nodeモジュールと、EntityシステムとFieldシステムがフックの呼び出しで互いに交代することを確認できます。

たとえば、下にスクロールして次のセクションを見ると、node_load()Nodeモジュールはhook_load()を提供し、いくつかのフィールドをロードするエンティティシステムに制御を渡します。リストされていないフィールドフックのホスト全体があり、それがエンティティシステムを呼び出すとhook_entity_load()、を呼び出すNodeに制御を戻す前に呼び出しますhook_node_load()

これにより、コードは、問題のノードが1つずつロードされるときに、そのノードで動作する機会を与えます。これらのフックとそれらが呼び出されるタイミングと理由を学習することは、Drupalコーディングの冒険の一部です。:-)

他のシステムにもフックがあります。などhook_init()hook_boot()。これにより、質問のブートストラップ部分に到達します。hook_boot()キャッシングシステムがロードされる前にDrupalによって呼び出されます。したがって、Drupalが実際に起動する前にモジュールで何かを行う必要があり、キャッシュに関係なくコードを実行したい場合は、を実装しhook_boot()ます。それ以外の場合、キャッシュされていないページのみに関心がある場合は、を実装しhook_init()ます。

これにより、Drupalが完全に起動する前に、ロードプロセスの早い段階で何かを実装するオプションが提供され、プロセスのどのポイントをインターセプトするかについてある程度の柔軟性が得られます。

続行する前にDrupalが特定のポイントまで起動したことを確認する必要がある場合は、を呼び出すことができますdrupal_bootstrap()。そのドキュメントをクリックすると、ブートストラップのレベルが何からすべてに至るまで利用できます。

そして最後に、Examplesプロジェクトで、特定のサブシステム用に広範囲に文書化されたコードを見ることができます。


OPは、Drupalが使用するフックのリストではなく、フックの定義を要求しています。
キアムルノ

6

フックはphp関数であり、「yourmodulename_hookname」という命名規則に基づいてブロックを構築し、開発者がモジュールを作成できるようにします

モジュールは、DrupalシステムでCORE機能とカスタム機能の両方を有効にするため、本当に重要です。したがって、モジュールはフックで構成され、Drupalインストールでモジュールがアクティブ化されると、module.inc関数module_invoke_all($ hook)またはmodule_invokeのおかげで、そのフック関数を他のモジュールから呼び出すことができます。

したがって、フックが何であるかを適切に理解するには、実際に手を汚してモジュール開発を試してください。この目的のために、開発者向けDrupalのサンプルをダウンロードして試してみてください。モジュールの作成にも慣れておく必要があります

上記の開発者向けの便利なDrupalの例を次に示します。

block_exampleモジュールのhook_block_view()実装例

/**
 * @file examples/block_example/block_example.module line 127
 *
 * Implements hook_block_view().
 *
 * This hook generates the contents of the blocks themselves.
 */
function block_example_block_view($delta = '') {
  //The $delta parameter tells us which block is being requested.
  switch ($delta) {
    case 'example_configurable_text':
      // The subject is displayed at the top of the block. Note that it
      // should be passed through t() for translation. The title configured
      // for the block using Drupal UI supercedes this one.
      $block['subject'] = t('Title of first block (example_configurable_text)');

このフックを使用すると、Drupalのブロック作成にアクセスして、Webサイトにカスタムブロックを表示できます。block.moduleには、すべてのモジュールがhook_blockビューを定義できるようにする_block_render_block関数があるため可能です(module_invokeの最後の行に注意してください):

/**
 * @file modules/block/block.module, line 838
 *
 * Render the content and subject for a set of blocks.
 *
 * @param $region_blocks
 *   An array of block objects such as returned for one region by _block_load_blocks().
 *
 * @return
 *   An array of visible blocks as expected by drupal_render().
 */
function _block_render_blocks($region_blocks) {
  ...
  foreach ($region_blocks as $key => $block) {
    ...
    $array = module_invoke($block->module, 'block_view', $block->delta);

render_exampleモジュールのhook_menu()実装例

/**
 * @file examples/render_example/render_example.module line 22
 * 
 * Implements hook_menu().
 */
function render_example_menu() {
  ...
  $items['examples/render_example/arrays'] = array(
    'title' => 'Render array examples',
    'page callback' => 'render_example_arrays',
    'access callback' => TRUE,
  );

このフックは、DrupalのURLルーティングシステムにリンクされ、モジュールで使用される関連するレンダリングコールバックでURLパターンを定義します。system.moduleから呼び出さます。

ブートストラップについては、基本的に、各ページ要求で実行されることを知る必要があります。このstackoverflowの答えを読むことを本当にお勧めします。ブートストラップとフックがどのように関連しているが分離されているかを説明しています。

Webページの表示に関して、DrupalのWebサイトのHTML表示は、レンダー配列とテーマを使用してほとんど達成されます


3

モジュールがmodule_implements()を呼び出す場所http://api.drupal.org/api/drupal/includes%21module.inc/function/module_implements/7 Drupalは、重みに基づいて、正しい名前の関数をすべて正しい順序で起動します。module_implementsを使用するモジュールのドキュメントではhook_menuのようなものを見るため(メニューがメニュー項目を返すように設計されたすべての関数を呼び出す場合)、これらはフック関数と呼ばれます。「フック」という単語は、それを実装するモジュールの名前に置き換えるだけで、Drupalが残りを行います。

drupal_alter()関数もあります。これは、別のフックによって以前に登録されたものを変更できるように、正しく名前が付けられたすべての変更関数を起動します。

通常、変更は参照によって引数を渡すので、オブジェクトを直接編集できますが、通常の「フック」では通常、新しいものを返すことができます。

アイデアは、Drupalにすべての必要なフック関数を呼び出して、処理するために返すものを取得するように要求することにより、任意のモジュール(独自のものを含む)を簡単に拡張できるということです。フック関数を呼び出すモジュールは、フックを実装するモジュールについて何も知る必要はなく、フックを実装するモジュールは、フックを呼び出すモジュールについて何も知る必要はありません。両方のモジュールが知る必要があるのは、返されるデータまたは変更されるデータの構造だけです。

実際には、フックは次の目的で最も一般的に使用されます。

  • ユーザーがログインしたときにhook_user_loginが呼び出されるなど、イベントに応答する
  • hook_menuのようなシステムを拡張するために使用できる新しいものを登録します
  • テーマ/レンダリングhtmlまたはビルド/検証/送信フォーム

1

上記の多くの答えがありますが、フックの背後にある非常に基本的な概念を理解するために、はるかに簡単な方法で答えを出したいです。フックは実際にはdrupalコアの機能に組み込まれており、さまざまなことを管理し、コアでさまざまなジョブを実行します。独自の機能をこれらの組み込みのdrupalコアの機能と同期させて、さまざまなフックを呼び出すことで独自の機能に機能を追加できます。

あなたがポイントを得ることを願っています!


1

私にとっては、フックとコア(D7)に関しては、module_implements関数がすべてです。理解することが重要だと思うことの1つは、何かを変更するためのフックを作成することで、処理しているデータ構造に何が起こるかについて最後の発言権がまったくないということです。フックは、メニュー、menu_links、ブロック、ノード、ユーザー、エンティティ、レンダー要素など、同じデータ構造に作用する関数の行(キュー)を取得します。

したがって、フックが期待どおりに使用されることを実際に確認するには、自分(フック)が並んでいる場所を知るか、意識する必要があります。これは、小石の重量によって決まります。Drupalコアは、適切な名前のフックを重みの昇順で呼び出すだけで、データに何が起きても起こります。

数時間のヘッドバンギングの後、モジュールの重量が軽すぎて、後続のフックが私がしたことを事実上無効にしたり、すべてをまとめて無視したことを知るためだけに、それは何の効果もないフックを書きました。

よく書かれたフックは、それ自体が最後になるように「人を扱う」ことも「強制する」こともありません。

そして、フックの「ライン」といえば。何年もの間、GoogleでDrupalを検索してきましたが、この画像は可能性のプリプロセスとプロセスフックリストをよく表しているようです。
ここに画像の説明を入力してください


1

より簡単な方法で、フックは、開発者が既存のコードを変更せずに、要件に応じて既存の機能を変更するのに役立ちます。PHPの抽象関数に似ています。

例:バスのチケットを予約するためのモジュールを作成しました。あなたのコードによると、チケットが一度予約された場合、ピックアップ場所はそのプロジェクトの要件であった編集できません。ユーザーがピックアップ場所を変更できることを除いて、友人が同様の要件に同じモジュールを必要とするとします。どういうわけか彼はあなたのモジュールを使わなければならず、あなたは彼にコードの変更をさせたくありません。したがって、モジュールを変更せずに変更を実装できるインターフェース(この場合はフック)を提供します。

drupal〜drupal-7では、テーマと同様にモジュール用のフックがあります。フックがどのように機能するかを確認するには、drupal.orgのフックでカスタムフックを作成し、このリンクを確認してください


0

フック。モジュールがDrupalコアと対話できるようにします。Drupalのモジュールシステムは、「フック」の概念に基づいています。フックはfoo_bar()という名前のPHP関数です。ここで、「foo」はモジュールの名前(ファイル名はfoo.module)であり、「bar」はフックの名前です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.