Drupal

テーマレイヤでのレンダリング配列の操作 [D7]

レンダリング配列イメージDrupalのテーマシステムは、「レンダリング配列」と呼ばれる強力な仕組みを持っています。このレンダリング配列を操作変更することで複雑な表示制御に対応することが可能になります。その方法について簡単に説明をします。

Drupal

Drupalのテーマカスタマイズはスタイルシートやテンプレートを変更することで行います。しかしプロジェクトによっては、複雑な表示制御をしたいこともあるでしょう。たとえば特定のページにコンテンツを追加したり、別のページでは特別なクラス名を追加したいなどです。
これらの操作をテンプレートで行うことも可能です。しかし操作が複雑になると必要なプログラムも複雑になり、テンプレートをデザイナーレベルで扱うことが困難になってしまいます。これではプレゼンテーションレイヤであるテーマをロジックレイヤから分離している意味がありません。
このような場合には表示データの操作を表示するよりも前の段階で行うことができます。具体的にはテンプレートの前に呼び出されるフックが用意されています。その使い方をここで簡単に説明します。
説明はDrupalコアに付属するBartikのサブテーマを使って行います。サブテーマの作り方は「テーマのスタイルシートをカスタマイズ」で説明しているので参照してください。

レンダリング配列とは

レンダリング配列とはどのようなものかを確認してみましょう。

  1. Drupal.orgから「Devel」モジュールをダウンロードしてインストール・有効化してください。
    (https://www.drupal.org/project/devel)
  2. 次に admin/structure/block へアクセスして「Development」(開発)ブロックをサイドバーなどに配置してください。これによりさまざまなデバッグ用の機能を使うことができます。
  3. sites/all/themes/my_theme/template.php を編集して、以下の内容を加えてください。
    function my_theme_page_alter(&$variables) {
      dpm($variables);
    }
  4. このコードはhook_page_alter() フックの実装です。pageレベルの前処理関数へのフックで、ページ表示用のデータ(レンダリング配列)を、テンプレートに渡す前に変更することができます。
    このコードでデータの変更はしていませんが、dpm() というデバッグ用の関数を呼び出しています。この関数は渡された変数の内容をDrupalのメッセージエリアに表示します。
  5. サイドバーに表示された「開発メニュー」から「Clear cache」をクリックしてください。以下のような画面が表示されるはずです。

 dpm()の出力

これは$variablesの内容をグラフィックに表示したものです。

この$variables がレンダリング配列です。多くの要素がありますが、「#」のついた要素(#show_message や #theme)はプロパティ(付加データ)で、ついていないもの(content やsidebar_first)が表示データです。表示データは基本的には階層的な配列構造になっていて、その中はさらにプロパティや表示データで構成されています。
第一階層の表示データの多くが、リージョンに対応しているのがわかるでしょう。リージョンの中はさらにブロックで構成されている、という風に、基本的にはDrupalのコンテンツ構造がレンダリング配列に反映されています。
このレンダリング配列を操作して、リージョンを丸ごと削除したり、リージョンの中に新しいブロックを追加したりすることができます。またプロパティを操作してラッパーのHTMLコードを追加したり、本来とは異なるテーマ関数でレンダリングしたりすることも可能です。

レンダリング配列の操作の例

それでは実際にレンダリング配列を操作してみましょう。
sites/all/themes/my_theme/template.php を編集して、my_theme_page_alter() の内容を次のように変更してください。

function my_theme_page_alter(&$variables) {
  if (drupal_is_frontpage()) {
    $variables['sidebar_first'] = array();
  }
}

Drupalのキャッシュをクリアしてフロントページにアクセスすると、第一サイドバーが消えているはずです。フロントページ以外のページでは第一サイドバーが表示されます。
引数の$variables の頭に& がついて参照渡しになっていることに注意してください。$variablesの内容を変更して呼び出し元に渡すため、このようになっています。
また$variables[‘sidebar_first’] の内容をクリアするのに、unset() ではなく空の配列を代入しています。これはテンプレートの中で$variables[‘page’][‘sidebar_first’] が存在すると仮定した処理をしているため、unset() してしまうとエラーが発生するためです。

このようにhook_page_alter フックを利用すると、あるモジュールの出力を別のテーマから変更できるようになります。とても強力な機能である反面、不用意な変更はエラーの原因になってしまうため注意が必要です。

 同様の操作をtemplate_preprocess_hook (&$variables) でも行うことができます。(my_theme_preprocess_page() など)ただし引数やレンダリング結果に違いがありますので注意してください。

その他のエントリー