hook_menu()を実装するにはどうすればよいですか?


103

実装の基本は何hook_menu()ですか?

同じような、しかし異なる質問に何度も答えなければならないことを避けるために、1つの質問で基本をカバーしたいと思います。

回答:


148

この情報は、Drupal 6および7で有効です。Drupal8では、新しいルーティングシステムにhook_menu()置き換えられました。以下に、3つの簡単な手順で実装します。hook_menu()

第一歩

空のモジュールを作成する方法の手順に従って空のモジュールを作成します。ここに示すコードでは、モジュールの名前がhelloworldであると想定しています。

ステップ2

モジュールファイルに次のコードを追加します。

/**
 * Implements hook_menu().
 */
function helloworld_menu() {
  $items['hello'] = array(
    'title' => 'Hello world!',
    'page callback' => 'helloworld_page',
    'access callback' => TRUE,
  );

  return $items;
}

/**
 * Page callback for /hello.
 */
function helloworld_page() {
  return 'Hello world!';
}

ステップ3

モジュールを有効にして、http://example.com/helloにアクセスします。(example.comをサーバーのドメイン名に置き換えます。)
「Hello world!」というメッセージが表示されます。それでおしまい!完全に機能するhook_menu()実装があります。以下は、に関してより高度なさまざまなトピックですhook_menu()。特に、上記のページは誰でも閲覧できるため、権限について読む必要があります。

引数

より多くのデータをページコールバックに渡したい場合は、ページ引数を使用してこれを実現できます。ページ引数は、ページコールバックに渡す引数の配列である必要があります。整数が引数として使用される場合、URLの一部を表し、0から始まり、スラッシュ(/)ごとに1つずつ増加します。次の例では、これは0が「hello」に変わることを意味します。

function helloworld_menu() {
  $items['hello'] = array(
    'page callback' => 'helloworld_page',
    'page arguments' => array(0),
  );

  return $items;
}

function helloworld_page($argument1) {
  return $argument1;
}

文字列は逐語的に送信されるので、再びarray(0, 'world')使用するために使用できますhello world

function helloworld_page($argument1, $argument2) {
  return $argument1 . ' ' . $argument2;
}

「ワイルドカード」を使用して、URLから任意のデータを受け入れることができます。

function helloworld_menu() {
  $items['hello/%'] = array(
    'page callback' => 'helloworld_page',
    'page arguments' => array(1),
  );

  return $items;
}

function helloworld_page($argument1) {
  return $argument1;
}

hello / worldにアクセス$argument1すると、に等しくなりworldます。

引数の自動読み込み

多くの場合、URL引数は、たとえばエンティティを識別する番号になります。このIDを対応するオブジェクトに変換するコードの重複を避けるために、Drupalは「名前付き」ワイルドカードの自動ロードをサポートしています。名前付きワイルドカードを使用すると、Drupalは、ワイルドカードと同じ名前に接尾辞が付いた関数をチェックし_loadます。そのような関数が見つかった場合、URLの値の値で呼び出され、ローダー関数によって返されるものはすべて、元の値の代わりにページコールバックに渡されます。Drupalにはノードをロードするためのそのような関数が既にあるnode_load()ため、ノードを自動ロードしてページコールバックに渡すことができます。

function helloworld_menu() {
  $items['hello/%node'] = array(
    'page callback' => 'helloworld_page',
    'page arguments' => array(1),
  );

  return $items;
}

function helloworld_page($node) {
  return t('Hello node (ID = !nid)', array('!nid' => $node->nid));
}

高度な自動読み込み

時には、複数の引数に基づいてより多くを自動ロードする必要があります。デフォルトでは名前付き引数のみがローダーに渡されるため、Drupalにどの追加の引数をローダーに渡すかを明示的に伝える必要があります。たとえば、ノードの特定のリビジョンをロードするにはnode_load()、ノードIDとリビジョンID を渡す必要があります。これは、次のコードで実現できます。

function helloworld_menu() {
  $items['hello/%node/revision/%'] = array(
    'page callback' => 'helloworld_page',
    'page arguments' => array(1),
    'load arguments' => array(3),
  );

  return $items;
}

function helloworld_page($node) {
  return t('Hello node (ID = !nid, revision ID = !rid)', array('!nid' => $node->nid, '!rid' => $node->vid));
}

許可

'access callback' => TRUE,上記の簡単な例を表示できるようにする必要がありますが、これまでのところ何も制御できないため、理想的とは言えません。/ helloにアクセスしようとすると、アクセスが許可されます。制御の尺度を提供する最も簡単な方法は、上記のページコールバックによく似たアクセスコールバックを提供することです。次のコードは、だれでもアクセスできますが、アクセス時に呼び出される関数にロジックを移動して、より複雑なロジックを許可する方法を示しています。

/**
 * Implements hook_menu().
 */
function helloworld_menu() {
  $items['hello'] = array(
    'page callback' => 'helloworld_page',
    'access callback' => 'helloworld_access',
  );

  return $items;
}

/**
 * Access callback for /hello.
 */
function helloworld_access() {
  return TRUE;
}

カスタム関数を使用するとコードが不必要に重複することが多いため、これは必ずしも最良の方法ではありません。より良い方法は、ほとんどの場合、を使用することuser_access()です。アクセスコールバックと一緒に、アクセス引数を設定できます。次のコードを使用して、ユーザープロファイルへのアクセス許可を持つユーザーからページを表示できるように要求することができます。

/**
 * Implements hook_menu().
 */
function helloworld_menu() {
  $items['hello'] = array(
    'page callback' => 'helloworld_page',
    'access callback' => 'user_access',
    'access arguments' => array('access user profiles'),
  );

  return $items;
}

デフォルトではアクセスコールバックはuser_accessであるため、上記のコードのように省略することができます。

より高度なトピック

公式hook_menu()ドキュメントには、フックの最も複雑な使用例に関する詳細情報が記載されています。


3
驚くばかり!完全を期すために、titleプロパティは、以下から返されるすべてのアイテムに必要ですhook_menu()
Clive

1
ドキュメントがそう言っていることは知っていますが、D7でテストしたときはそうではありませんでした。私が推測する最初の例にそれを追加することはできましたが、できる限り簡単にするために、絶対に最小限に抑えたいと思いました。
レサリオン

1
ページにタイトルを追加することは、hook_menu()でできる最低限のことの1つですが、それはあなたの投稿です:P構文エラーを修正する価値があるかもしれません6)、人々がコピー&ペーストできるように
クライブ

1
Argh、私は最初は実際にコードを実行することに熱心でしたが、時間が経つにつれて、私はだらしないようになり、コピー貼り付けを開始しました。少なくとも、私が見たものの構文エラーを修正しました;)まあ、もちろんタイトルがあるべきだということは正しいので、最初の例に追加しました。
レサリオン

1
hook_menuを使用してphpファイルをパスに登録するにはどうすればよいですか?これは、drupalブートストラップを含むカスタム記述されたphpファイルであり、drupalセッション変数を使用し、ユーザーIDである引数を受け入れます。
ЕлинЙ.
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.