P.276の「hook_form_FORM_ID_alter」についてP.276の「hook_form_FORM_ID_alter」について

度々、申し訳ありません。
タイトルの掲題の件で、教えて頂きたい事があります。
P.276の「hook_form_alter」と「hook_form_FORM_ID_alter」の例題に関してですが
「formexample_form_alter」に関しては問題なく動作しました。
しかし、「formexample_form_user_login_alter」に関してはDrupal側からこのメソッドがコールされません。

ちなみに、フォーム要素の変更対象フォームを「ログインフォーム」ではなく
自分で作った、任意のフォームに対して「hook_form_FORM_ID_alter」を実装し
フォーム要素の変更対象フォームを「formexample」にしたところ、問題無く動作しました。

教えて頂きたいのは、「ログインフォーム」に対する変更を「hook_form_FORM_ID_alter」実装する場合は
P.276の例題に記述してある事以外にも「何が」必要なのかという事です。
多分、また読み落としているとは思いますが
宜しくお願い致します。

hook_form_FORM_ID_alter

Takafumiさんのユーザアバター

hook_form_FORM_ID_alter() の実装に必要なのは、関数名を『モジュール名 + 'form' + フォームID + 'alter'』で命名するということ以外にはありません。
コールされないのであれば、0829さんのコメントにもあるように、フォームID「user_login」と「user_login_block」を混同されているのではと思います。

以下、非常に簡単なコードですが、formexample.module に実装すれば、「どのページ」で「どの関数」が「どの順序」でコールされるかがわかると思いますので参考にしてください。

function formexample_form_alter(&$form, &$form_state, $form_id) {
  switch ($form_id) {
    case 'user_login':       // ?q=user
    case 'user_login_block': // 
    case 'user_pass':        // ?q=user/password
    case 'user_register':    // ?q=user/register
      drupal_set_message('formexample_form_alter()');
  }
}

function formexample_form_user_login_alter(&$form, &$form_state) {
  drupal_set_message('formexample_form_user_login_alter()');
}

function formexample_form_user_login_block_alter(&$form, &$form_state) {
  drupal_set_message('formexample_form_user_login_block_alter()');
}

function formexample_form_user_pass_alter(&$form, &$form_state) {
  drupal_set_message('formexample_form_user_pass_alter()');
}

function formexample_form_user_register_alter(&$form, &$form_state) {
  drupal_set_message('formexample_form_user_register_alter()');
}

ありがとうございます

Drupal「user」パスの件も含めて、大変参考になりました。
そこで、もう一つお尋ねしたいのですが
P.276の上から6行目に記述される
「この特定のケースでは、hook_form_alter()の最初の形式が優先されます。」とありますが
「hook_form_alter()の最初の形式」とは何を指しているのですか?

form_alter() の優先順位

Takafumiさんのユーザアバター

確かに、書籍の文章は少々わかりづらいかもしれませんね。

特定のケース == hook_form_alter() と hook_form_FORM_ID_alter() の両方で'user_login'を処理した場合

hook_form_alter()の最初の形式が優先 == hook_form_FORM_ID_alter() ではなく hook_form_alter() での処理が優先される

という認識でよいと思います。
つまり、先に挙げたサンプルを実行するとわかるように、はじめに hook_form_FORM_ID_alter() が、次に hook_form_alter() がコールされるため、どちらでも同じフォームIDに対して処理を行えば必然的に後者の処理が反映されるということです。

ご回答ありがとうございます

Takafumiさんに提示して頂いたサンプルソースの動作確認をすれば理解出来る事なのですが
「やらかし」を連発している私なので
テーマの章で同じような解説がありましたが
まだ、読み落としている箇所があるかと思い
ご確認させて頂いた次第です。
ご丁寧な回答ありがとうございました。

もしかすると……

Takafumiさんのユーザアバター

もしかすると私の認識が間違っていて、著者は単に「このケースのように2つのフォームIDを処理する場合は hook_form_alter() の方を実装するのがよい」と言っているような気もしてきました……。どちらにしても全体には影響を与えない部分なのでご容赦ください。

Re: P.276の「hook_form_FORM_ID_alter」について

「ログインフォーム」に対する変更は「hook_form_FORM_ID_alter」で実装可能です。
例えば、P.275 の「特定のフォームの変更」に記載されている「hook_form_FORM_ID_alter」の使用例(コード)は、正しく動作します。

※ P.276 でも少し触れられていますが、「http://example.com/?q=user ページのログインフォーム(user_login)」と「ユーザブロックに表示されるログインフォーム(user_login_block)」は別のものですので、ご注意ください。

解りました

つまり、トップページに紐付くログインブロック(ログインフォーム)ではなく
匿名ユーザーが閲覧できるトップページに掲載されるコンテンツに対して
投稿する場合にログインする、フォームを変更対象にしているという事だったんですね。
ホントに毎回、申し訳ないです。
でも、物凄く勉強になります。
有難うございます、お世話をかけました。

補足

Takafumiさんのユーザアバター

現象的にはその理解もあながち間違ってはいないのですが、より正しく理解してもらうために補足します。

「user_login」は、Drupalパス'user'(つまり、uriが http://example.com/?q=user や http://example.com/user)にアクセスした場合に表示されるフォームのIDであり、「user_login_block」はどのページにでも表示可能なユーザログイン用のブロックに使用されるフォームIDです。