レベル: 中級 Alister Lewis-Bowen (alister.lewisbowen@gmail.com), Senior Software Engineer, FIT Team, IBM China Development Lab Stephen Evanchik (evanchsa@clarkson.edu), Student, Clarkson University Louis Weitzman (louis.weitzman@gmail.com ), Senior Software Engineer, FIT Team, IBM China Development Lab
2006年 10月 03日 この連載では、IBM Internet Technology Group が無料で入手可能なソフトウェア・パッケージを使って、閉鎖的コミュニティーの Web サイトを設計、開発、およびデプロイメントします。これまでの記事では、新しい Web サイトのニーズに合わせて Drupal を拡張し、構成する方法を説明してきました。コンテンツを追加するにつれ、情報の構造が具体的な形になってきます。今回の記事では、Internet Technology Group チームが Drupal が提供するコンテンツを構成する際に採ったアプローチそしてその主要な方法を説明します。
はじめに
連載第 2 回では、架空の会社、IBC (International Business Council) の Web サイトが対象とする読者の性質を理解するために Internet Technology Group チームが採った手法について説明しました。書類のプロトタイプなど、さまざまな手法を使ってページ・レイアウトとユーザー操作をテストしました。私たちは、この段階の作業で用意した視覚的要素と汎用レイアウトを組み合わせるための基盤を使用して、情報を表示するための基本スタイルの作成に着手しました。今回と次回の 2 回にわたる記事で、IBC Web サイトのカスタム・テーマを構成する手法について説明します。
 | |
スタイル設定を適用して Web サイトのテーマ設定を完成させる方法については、連載第 8 回で説明します。 |
|
この記事に記載する情報は絶対的な開発ガイドラインとしてではなく、独自の Web サイトをスタイル設定する際の手掛かりとして使ってください。
この記事では、Drupal でテーマを作成する手順を紹介し、以下を使用できるようにするための方法に焦点を当てます。
- コンテンツ・フラグメントのテンプレート
- 独立したホーム・ページ・レイアウト
- Web サイトのセクション識別
- 動的に更新するナビゲーション
- 非従来型ブラウザーへの対応
- 内容に従って配置されるアクション
- 強調表示されたコンテンツ・エリア
上記の多くの概念は既存のプラクティスと現在の標準ベースの Web 設計に基づくものですが、この記事が、Drupal のコンテキスト内でコンテンツ構造に対処する方法を強化するためのヒントとなることを期待しています。
経験から生まれる進化
私たちがカスタム・テーマの作成に着手した時点では、使用可能な機能の多くを認識していませんでした。まにあわせのソリューションから始めて、後になってから同じことを遥かに優れた方法で行えることに気付いたという経験はよくあります。私たちはまだ学習している最中だからです。この考え方は心強いもので、通常は Web サイトの「外観」を短時間で組み立て、Drupal を使い慣れていくにつれ、改良することができます。
この記事では私たちが採った方法を説明した後、最初のソリューションから、より有効で体系的な手法に移行した過程に従って、その論理的根拠を説明していきます。
標準ベースの Web 設計
多くの著作物や Web サイトは、標準ベース Web 設計の現在の傾向を物語っています。この考え方に不可欠なのは、XHTML とカスケーディング・スタイル・シート (CSS) を適切に適用することです。その柔軟な性質により、Drumal テーマ設定システムでは Web サイトの設計者がこれらの標準を簡単に採用できます。
IBC Web サイトの構造とスタイルに標準ベースの手法を用いることによって、以下のような頑強な設計を実現できます。
- 現代の Web ブラウザー、スクリーン・リーダー、ワイヤレス・デバイスで機能します。
- ブラウザーによるページのダウンロードおよびレンダリング時間が短縮されます。
- ユーザーがブラウザーのウィンドウ・サイズやフォント・サイズを拡大縮小できる柔軟なレイアウトを作成できます。
- Web サイト上の任意のコンテンツで満足できる印刷表現を作成できます。
- 古いブラウザーで表示する際にコンテンツを正常にデグレードできます。
IBC Web サイトの作成手法には、標準ベースの Web 設計を採用していますが、これらの標準について説明することがこの記事の目的ではありません。ここからは、新しいカスタム・テーマの作成に取り掛かります。
新規テーマの作成
新しいテーマを作成するため、チームはまず themes ディレクトリー内にある Bluemarine ディレクトリーをコピーして、ディレクトリー名を ibc に変更しました。これは Drupal 付属のデフォルト phptemplate エンジン・テーマで、ここに含まれる基盤を使って独自のカスタム・テーマを作成できます。図 1 に、Eclipse 環境での新しいディレクトリーを示します。
図 1. Navigator ビューの新規 IBC テーマ・ディレクトリー
その他にもテーマ・エンジンは用意されています。Drupal が使用するように定義されているエンジンは、テーマ・ディレクトリーにある .tpl.php ファイルを使用した場合は phptemplate で、.xtmpl ファイルを使用した場合は xtemplate です。また、.theme ファイルを使用して、このファイル内で PHP テーマ関数をオーバーライドすることもできます。詳細については、Drupal の「Theming overview」を参照してください。
この ibc テーマを Web サイトのアクティブ・テーマにするには、admin/themes ページでこのテーマを有効に設定します。このページには、Drupal が themes ディレクトリー内にあるすべてのテーマをリストします。図 2 に示すように、このページで ibc テーマを有効に設定し、デフォルトとして選択できます。
図 2. IBC テーマの選択
テーマの外観をスクリーン・ショットで表示するサムネール画像は、themes ディレクトリー内にある screenshot.png ファイルに設定されています。テーマに独自の画像を作成することもできますが、この作業を行うのはおそらく、表示する外観が決まっている場合だけです。
図 2 の configure タブでは、管理者が全体的なテーマ、あるいは特定のテーマの設定値を変更できます。特定のテーマについては、Drupal が提供するテーマごとの一定のコンテンツ要素を有効または無効に設定できます。
図 3 のCONFIGURE タブには、Toggle display グループで有効または無効にできる多数のコンテンツ要素がリストされています。Mission statement は、管理者が admin/settings ページの General Settings で定義した要素です。このテキスト・ストリングを有効にすると、テーマ・エンジンはこのストリングを変数 ($mission) としてページ・テンプレート (リスト 1 で説明) に渡します。テーマ設計者はカスタム・テーマを作成するときに、これらのページ要素をレンダリングする方法を決定したり、あるいはレンダリングしないことを決定できます。
図 3. IBC テーマの構成ページ
コンテンツ構造
部屋の壁をペンキで塗るときと同じように、作業のほどんとは準備に費やされます。壁の穴やひび割れを塞ぎ、やすりで表面を滑らかにする作業をしっかりやっておけばおくほどペンキは塗りやすくなり、部屋の見映えも一層よくなります。それと同じことで、Web サイトのスタイルを設定する前には、コンテンツをしっかりと構成しておく必要があります。ここからは、テーマに XHTML を構成し、CSS でのスタイル設定を比較的簡単にする方法について説明していきます。
基本レイアウト
Web サイトの基本レイアウトは、図 1 で作成したテーマ・ディレクトリー内にある page.tpl.php ファイルによって制御されます。このファイルで、まず始めに骨組みとなる構造を定義します。この構造が、後で説明するノード・テンプレート・ファイルで定義されたコンテンツ・フラグメントをラップすることになります。リスト 1 に、私たちが page.tpl.php ファイルでどのようにレイアウトに取り掛かったかを示します。このリストは、IBC テーマの基本コンテンツ構造について詳しく説明するときにもう一度参照します。
リスト 1. page.tpl.php での基本ページ・レイアウト
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
lang="<?php print $language ?>;"
xml:lang="<?php print $language ?>">
<head>
<title><?php print ( $is_front ? "Home | International Business Council (IBC)"
: $head_title ); ?></title>
<?php print $head ?>
<link rel="stylesheet" type="text/css" media="screen"
href="themes/ibc/c/screen.css" />
</head>
<body>
<div id="wrap">
<div id="header">
<div id="banner">
<h1>International Business Council</h1>
</div>
<div id="nav_bar">
</div>
</div>
<div id="content">
<div class="tabs"><?php print $tabs ?></div>
<?php print $help ?>
<?php print $messages ?>
<?php if ($is_front) { : ?>
<?php print announcement_all(); ?>
<?php print discussions_all(); ?>
<?php else : ?>
<?php print $content; ?>
<?php endif; ?>
</div>
<div id="sidebar">
<?php print $sidebar_right; ?>
</div>
<div id="footer">
</div>
</div>
<?php print $closure;?>
</body>
</html>
|
有効コンテナー
準備作業として効果的なのは、スタイルを設定するすべての要素に CSS セレクターを使ってアクセスできるように XHTML を構成することです。もちろん、すべてのものを DIV 要素や SPAN 要素にラップしなければならないと言っているわけではありません。私たちはセマンティック・マークアップの概念を採り入れて、適切なXHTML 要素をその目的に合わせてコンテンツに使用するようにしました。DIV 要素と SPAN 要素は、コンテンツ内で論理的区切りを定義しなければならない場合にだけ使用しました。リスト 1 を見ると、どのコンテナーがそれぞれヘッダー、コンテンツ、サイドバー、フッターに対応しているかがわかるはずです。
識別子とクラス
ID 属性は主に、レイアウトおよびクラス属性、繰り返し要素、あるいは CSS セレクターでは識別しにくいことがわかっている要素に使用します。リスト 1 では、コンテンツの主要な論理ブロックでは、<div id="content"> のように、識別子によってレイアウト内でのそれぞれの目的を分類していることに注目してください。<div class="tab"> は、ID 属性として考えられる場所にクラス属性を使用しています。これは Bluemarine テーマの既存のスタイル値で、私たちはこれを維持することにしました。
特定のテンプレート・ファイルで生成されたコンテンツのブロックを識別するため、クラス属性値を使って収容要素のコンテンツ・フラグメントを記述しています。例えば、クラス属性値が announcement_summary の announcement_compact.tpl.php で定義されたコンテンツは DIV にラップすることにしました。この手法は結果として、どのテンプレートがどのコンテンツを制御しているかを追跡する際のデバッグに役立っています。これについては、テーマ内の特定のテンプレートを取り上げるときに説明します。
変数と領域
リスト 1 を見ると、$language、$is_front、$title_head などの名前を持つ変数が使用されていることがわかります。phptemplate エンジンはテンプレート・ファイルを呼び出すときに変数をこのテンプレートに渡します。これらの変数は、Drupal 設定ページ内で定義して、前に示したようにテーマ構成で有効/無効に設定できます。有効な変数は、テンプレート内の適切な場所に挿入することができます。
領域とは、テーマ設定されたブロックおよびノード・コンテンツを Drupal がレンダリングする領域のことです。$sidebar_$left、$sidebar_right、$content、$header、および $footer_message は、標準領域のコンテンツが含まれる変数です。_regions hook テーマを使用してカスタム領域を定義することもできます。これらのテーマ設定されたコンテンツの集合は、テーマ設計者がページ・レイアウト内に配置できる便利なコンテナーを提供してくれます。
ホーム・ページの構造
ほとんどの Web サイトと同様、ホーム・ページ (フロント・ページ) は通常、他のページとは異なるレイアウトを表示します。表示される各種の要素を決定するには、page.tpl.php ファイル内の $is_front 変数を使用します。例えばリスト 2 のように、タイトル要素を多少変更して表示することができます。
リスト 2. $is_front 変数に基づくページ・タイトルの変更
<title><?php print ( $is_front ? "Home | International Business Council (IBC)"
: $head_title ); ?></title>
|
IBC Web サイトの場合は、アナウンスメントのサマリー・リストと、フォーラムの最新エントリーを表示する必要がありました。このコンテンツのレイアウトを他のページのレイアウトから区別するため、リスト 3 のような条件ステートメントをページの本文内で使用しました。
リスト 3. $is_front 変数に基づくページ・コンテンツの変更
<?php if ($is_front) { : ?>
<?php print announcement_all(); ?>
<?php print discussions_all (); ?>
<?php else : ?>
<?php print $content ?>
<?php endif; ?>
|
このように、ページ・テンプレートがホーム・ページに使用されていたかどうかによって、どのコンテンツを表示するかを制御しています。$is_front が true の場合、適切なモジュール関数 (アナウンスメント・モジュールに含まれる関数など) を呼び出して、アナウンスメントのサマリー・リストを表示します。一方、$is_front が false の場合には、$content 変数が表示されます。この変数には、以前の記事で説明したノード作成シーケンスに基づいて Drupal が組み立てた、テーマ設定されたノードの集合が含まれます。
ログイン・ページ
IBC サイトの要件の 1 つは、ユーザーが認証されるまでは、コンテンツを表示できないようにすることです。通常、このような閉鎖的コミュニティーのサイトやエクストラネットのサイトは、認証前のユーザーにはホーム・ページではなくログイン・ページを表示します。
page.tpl.php ファイルについて説明しているところなので、参考のため、この問題に対する私たちの初期のソリューションを説明しておきましょう。初期のソリューションは、セッションの有効期限を考慮したものでも、とりわけ洗練されているものでもありませんが、その役目は果します。(今後の記事ではこれより優れた方法を説明しますが、初期のソリューションをここで紹介しておくのも興味深いと思います。)
リスト 4 のコードは、page.tpl.php ファイル内のリスト 1 で示した DOCTYPE 要素の前に配置されます。$user->uid 変数は、現行ユーザーが認証されている場合にのみ設定されます。この変数を使用して、別のテンプレート・ファイルを組み込んでログイン・ページをレンダリングした後に page.tpl.php ファイルからジャンプするかどうかを決定しています。この login.tpl.php ファイルがレンダリングするログイン・ページには、ユーザー・ログイン・ブロックからコピーしたログイン・フォームが表示されます。
リスト 4. ユーザーが認証されているか、またはログイン・ページを表示するかどうかのチェック
<?php
global $user;
if (!$user->uid) {
include('login.tpl.php');
return;
}
?>
|
場所の検知
Web サイトのページの基本レイアウトを 1 つのファイルで保守できると便利ですが、Web サイトのさまざまなセクションを識別する必要がある場合はどうなるでしょう。例えば、ユーザーに現行セクションの視覚的な手がかりを与えるといった場合が考えられます。そのため、私たちは URL を使用して body 要素にクラスの値を設定し、この値に応じて適切にページをスタイル設定できるようにしました。リスト 5 のように Drupal の arg 関数を直接クラス属性の値に指定することも 1 つの方法ですが、それでは十分に制御できなかったからです。
リスト 5. body 要素に追加したクラス値
<body class="<?php print arg(0); ?>" > |
代わりの方法として使用したのは、単純な switch ステートメントです。この方法では、クラス値の定義をより柔軟に制御できます。リスト 6 の switch ステートメントは、URL パスの最初の部分に基づいて使用する値を決定しています。これによって指定された CSS クラスを使用して、表示対象の Web サイトのセクションに応じてページの表示を変えています。
リスト 6. body 要素への定義済みクラス値の追加
<?php
switch(arg(0)) {
case 'workgroups':
$page_type = 'workgroups';
break;
case 'action_items':
$page_type = 'workgroups';
break;
case 'conferences':
$page_type = 'conferences';
break;
case 'agenda_items':
$page_type = 'conferences';
break;
case 'members':
$page_type = 'members';
break;
default:
$page_type = 'home';
}
?>
<body class="<?php print $page_type; ?> <?php print arg(0); ?>" >
|
当然のことながら、URL からサイトのセクションを確実に検出できるように、admin/settings ページで新しい URL を構成し、Web サイトのセクションごとのモジュールで URL を Drupal メニュー・システムに登録しました。今後の記事で紹介する予定ですが、表示中のセクションを判別するもう 1 つの方法として、タクソノミー・モジュールを使用することもできます。
動的ナビゲーション
基本ナビゲーションの構造は、Web サイトのデータベース・コンテンツに応じて変更する必要がありました。例えば、Workgroups セクションでは、活動中のワークグループのみをリストし、Conferences セクションでは過去 2 年間のコンファレンスのみをリストするといった具合です。リスト 7 に、このような要件に基づく基本ナビゲーションのコンテンツを構成するために作成した順不同リストを示します。これは、リスト 1 の nav_bar DIV 内で使用します。リスト 7 では、Workgroups セクションと Conferences セクションに対して、ワークグループ・モジュールとコンファレンス・モジュールの関数が、リスト項目としてレンダリングする項目をリストしています。
リスト 7. 基本ナビゲーションの構成
<ul id="pri_nav">
<li id="t_home"><a href=" accesskey="1"
title="The IBC home page">Home</a></li>
<li id="t_workgroups"><a href="workgroups"
title="IBC Workgroups and status">Workgroups</a>
<ul>
<li><a href="workgroups" title="View all Workgroups">All Workgroups</a></li>
<?php
$workgroups = workgroup_nav_list();
foreach ($workgroups as $wg) : ?>
<li><a href="workgroups/<?php print $wg->nid; ?>"
title="Jump to $wg->title"><?php print $wg->title; ?></a></li>
<?php endforeach; ?>
</ul>
</li>
<li id="t_conferences"><a href="conferences/" title="IBC Conference
information">Conferences</a>
<ul>
<li><a href="conferences/" title="View all Conferences">All Conferences</a></li>
<?php
$conferences = conference_nav_list();
foreach ($conferences as $c) : ?>
<li><a href="conferences/<?php print $c->nid; ?>"
title="Jump to $c->title"><?php print $c->title; ?></a></li>
<?php endforeach; ?>
</ul>
</li>
<li id="t_members"><a href="members" title="IBC Members and contact
information">Members</a>
<ul>
<li><a href="members" title="All Members">All Members</a></li>
<li><a href="members/bycompany" title="By Company">By Company</a></li>
<li><a href="members/byconference" title="By Conference">By Conference</a></li>
<li><a href="members/byworkgroup" title="By Workgroup">By Workgroup</a></li>
<li><a href="members/workgroupleaders" title="Workgroup Leaders">Workgroup
Leaders</a></li>
<li><a href="members/abcstaff" title="IBC Staff">IBC Staff</a></li>
</ul>
</li>
</ul>
|
リスト 7 を見るとわかるように、Workgroups および Conferencesのリスト項目の要素には、さらにネストされたリストが組み込まれています。これらのリストには、PHP を使って生成される動的コンテンツが含まれます。次回の記事では、この構造をスタイル設定して、基本ナビゲーションのドロップダウン・メニューを作成する方法について説明します。
非従来型ブラウザー用のコンテンツ
従来のブラウザーでは IBC コンテンツを表示できない場合に備え、追加コンテンツ構造を組み込んでアクセシビリティーを向上させています。追加したのは、アクセス・キー、コンテンツ・レイアウトに含まれる特定の主要セクションへのリンク、そしてこれらのセクションを識別するための見出しです。
Web サイトのページ・レイアウト内で使用するアクセス・キーを文書化するため、ページ先頭の BODY 要素 (リスト 1) の直後に説明文のコンテナーを追加しました。以下のリスト 8 に、このブロックの追加コンテンツ構造を示します。
リスト 8. BODY 要素の直後に配置した ALT キーの説明文
<div id="access-info">
<p class="access" >The access keys for this page are:</p>
<ul class="access">
<li>ALT plus 1 links to the IBC home page.</li>
<li>ALT plus 2 links to the site map for the IBC web site.</li>
<li>ALT plus 3 skips to the start of the content on this page.</li>
<li>ALT plus 9 links to the contact page.</li>
</ul>
</div>
|
アクセス・キーのインプリメンテーションは、accesskey 属性を持たせて関連リンクに追加しました。リスト 9 は、アクセス・キーの使用方法の例です。
リスト 9. ページ・テンプレートでのアクセス・キーの例
<li><a href="sitemap" accesskey="2"
title="An index to the whole of this web site">Site map</a></li>
<li><a href="contact" accesskey="9"
title="Contact information for the IBC web site">Contact</a></li>
|
リスト 10 は、ページ・レイアウトの主要セクションを識別し、ページ・コンテンツの先頭へのリンクを追加するコンテンツ構造を追加で挿入する例です。クラス値 access によって、CSS が従来のブラウザー用の追加コンテンツ構造を非表示にできることに注目してください。
リスト 10. ページ・テンプレート内でセクションを識別できるようにするための見出しの例
<div class="access">
<p><a href="<?php print request_uri(); ?>#page-content"
accesskey="3">Jump to the start of the content on this page</a></p>
</div>
.
.
.
<h2 class="access">Start of main page navigation</h2>
.
.
.
<div id="content">
<h2 id="page-content" class="access">Start of the main page content</h2>
.
.
.
|
もちろん使用しなければならない構成手法は他にもあります。例えば、IMG 要素に att 属性を組み込んで、画像の使用方法を説明できるようにするなどです。Drupal で title 属性をアンカー要素 (<A>) 内に配置するには、リスト 11 のように、この属性を l 関数の属性配列内に組み込みます。
リスト 11. リンクに追加した title 属性
$links[] = l(t('Edit'),
"announcement/$node->nid/edit",
array('title' => t('Display the edit form for this announcement')));
|
フォーム内でのアクセシビリティーについては、Drupal が、フォームの API を使用する際にフォーム要素の前に LABEL 要素が確実に置かれるようにします。
このように、ページ・テンプレートにはさまざまなコンテンツの部分が挿入されていますが、これに対してレンダリングされるコンテンツの構造はどのようにカスタマイズするのでしょう。それにはコンテンツ・フラグメントのテンプレートを使用します。
コンテンツ・フラグメントのテンプレート
phptemplate エンジンは、生成されたノード・データをテーマ設計者がコンテンツ・フラグメントの形に当てはめるための汎用テンプレートとして、node.tpl.php を使用します。複数のノード・タイプを使用するサイトの場合には、テーマ設計者は node-<node-type>.tpl.php テンプレート・ファイルを使って、特定ノード・タイプに対するデータのレンダリングを制御できます。
連載第 6 回では、どのようにして IBC Web サイトのカスタム・モジュールが、詳細レイアウト、サマリー表示、そしてブロックという 3 通りのコンテキストでデータをレンダリングするパターンに従うかを説明しました。図 4 と図 5 に、これらのコンテキストがページ・テンプレートに挿入された例を示します。ノード作成シーケンスが URL からアナウンスメント・ページを作成することを認識すると、図 4 に示すように、Drupal はそのページに必要な各種のノード・フラグメントを組み立て、テーマ設定してからページ・テンプレート内に配置します。
図 4 の A で示した枠内は、ノード・システムがアナウンスメント・データを構成するための node-announcement.tpl.php テンプレート (リスト 14 で説明したテンプレート) を使用して作成したコンテンツ・フラグメントです。C の枠内は、アナウンスメント・モジュールのブロック・フックがブロック・データを構成するための announcement_block_list.tpl.php テンプレートを使用して作成したコンテンツです。
図 4. 詳細レイアウトとアナウンスメント・ブロック・レイアウトが含まれるアナウンスメント・ページのコンテキスト
図 5 の B で示した枠内のコンテンツ・エリアは、アナウンスメント・サマリーのコンテンツ・フラグメントです。これは、アナウンスメント・モジュールに含まれる announcement_all 関数が announcement_compact.tpl.php テンプレートを使用して作成したものです。
図 5. サマリー・レイアウトとアナウンスメント・ブロック・レイアウトが含まれるホーム・ページのコンテキスト
図 5 に示されているように、私たちはテンプレートを使用して、これらのコンテキストの構造とスタイル設定を、データを作成するモジュールから切り離しています。詳細ビューのレンダリングには、node-<node-type>.tpl.php テンプレート・ファイルを使用しました。ただし、サマリーおよびブロック・コンテキストをノード・タイプごとの独自のテンプレート・ファイルでテーマ設定するためのテンプレートは、第 6 回で説明した方法で作成しました。
Drupal でデータにテーマを設定するときには、theme(<theme_function_name>, <data>) 関数を使用します。ここで、theme_function_name はテーマ関数を識別するためのストリングです。Drupal は排除のプロセスによって、どの関数を使用してデータを渡すかを決定し、テーマ設定した出力を生成します。図 6 で、このプロセスを説明します。
図 6. Drupal がテーマ関数を見つける方法
上記のプロセスにより、モジュール開発者は phptemplate エンジン固有のテーマ関数を使ってデフォルト・テーマ関数をオーバーライドできます。この phptemplate テーマ関数内で _phptemplate_callback 関数を使用して、Drupal テーマ・システムに theme_function_name で構成されたテンプレート・ファイルを使用するように指示します。したがって、リスト 12 のようなテーマ呼び出しでは announcement_compact.tpl.php テンプレート・ファイルを使用することになります。
リスト 12. announcement.module でのアナウンスメント・サマリーのテーマ設定
$page_content[] = theme('announcement_compact', $announcement);
|
第 6 回の hook_nodeapi セクションでは、モジュール開発者が任意の theme_function_name に <theme_function_name>-<node-type>.tpl.php を作成できるようにする方法を説明しました。この方法を使用すれば、必要に応じて block-<node-type>.tpl.php ファイルを作成することができます。
アナウンスメント用のテンプレート
第 6 回で説明したアナウンスメント・モジュールを使って、これらのテンプレートが 3 つのコンテキストでどのように表示されるかを見てみましょう。
アナウンスメント詳細
完全なアナウンスメントのコンテンツ・フラグメントは、node-announcement.tpl.php テンプレート・ファイルを使用して構成しています。このコンテンツ・フラグメントは、単一のアナウンスメント (図 4 のセクション A) を表示するページに現れます。Drupal ノード作成システムは、XHTML 構造に挿入可能な変数を指定して、ノード・オブジェクトをこのテンプレートに渡します。
XHTML に挿入可能な変数を調べるには、リスト 13 のようにテンプレートで print_r 関数を使用します。テンプレート・ファイルを保管してから、このテンプレートが含まれる Web ページを表示すると、$node のコンテンツが表示されます。この関数は初歩的なものですが、PHP を使うときには便利なデバッグ・ツールとなります。
リスト 13. ノード・オブジェクトのコンテンツの表示
<?php print print_r($node); ?> |
リスト 14 を見ると、完全なアナウンスメントの作成方法がわかります。テンプレート内の PHP コードは、データを完全に構造化された XHTML コンテンツ・フラグメントに変換するためだけに使用されています。このようなコンテンツ・フラグメントは、CSS で簡単にスタイル設定できます。(スタイル設定についての詳細は、この連載の次回の記事で説明します。)
リスト 14. node-announcement.tpl.php テンプレート
<?php
global $user;
$published = format_date($node->publish_date,'custom','j M, Y');
$expires = format_date($node->expiration_date,'custom','j M, Y');
?>
<?php if ($page or $page == 0): ?>
<h2 class='category'>Announcement</h2>
<?php endif; ?>
<div class="announcement_detail">
<h3><?php print $title ?><?php print $links ?></h3>
<p class="date">Posted on <?php print $published; ?>
<?php
if ($user->uid == $node->uid or user_access('edit announcement')) {
if ($node->expiration_date < time()) print " and expired on ".$expires;
else print " and going to expire on ".$expires;
}
?>
</p>
<?php if ($node->abstract) : ?>
<div class="abstract"><?php print $node->abstract ?></div>
<?php endif; ?>
<?php if ($node->body) : ?>
<div><?php print $node->body ?></div>
<?php endif; ?>
<?php
if ($node->attachments != NULL) {
print filegallery_attachments_display($node);
}
?>
</div>
|
上記のリストでは、先頭で公開日と有効期限を変換しています。この公開日と有効期限は、後からテンプレート内で使用されます。続いてプリントアウトされている <h2 class='category'>Announcement</h2> は、コンテンツのこの部分を紹介する短いタイトルです。
次に、DIV 要素がフラグメントに有効なコンテナーとして示され、前に述べたように announcement_detail というクラス属性値によって識別されています。これにより、フラグメント内のコンテンツをスタイル設定するために使用するクラス名がわかります。
 | |
drupal.org では、user_load() 関数を使用して、$user object を完全にデータ設定することを推奨しています。 |
|
続いて、タイトルが announcement_link 関数によって生成された $links コンテンツと一緒に出力されています。これはいわゆる「アクション・リンク」で、アナウンスメントの見出しの横に表示されます。デフォルトの Drupal タブ付きインターフェースは、ユーザーがアクションをノードに適用する方法になりますが、私たちはこのインターフェースに頼らずに、図 7 の赤字で示すアクション (Add、Edit、および Delete) を対象コンテンツの横に配置する方法を採ることにしました。
図 7. アナウンスメント見出しの横に表示されたアクション・リンク
お気付きかもしれませんが、Posted on (投稿日) の行には、追加情報を表示しています。これはリスト 14 で条件ステートメントを使用して、この有効期限情報を追加表示しているためです。この条件ステートメントは、現行ユーザーがアナウンスメントの作成者であるか、あるいは編集アクセス権があるかどうかをテストします。これを可能にしているのは、グローバル・ユーザー・データ・オブジェクト ($user) と user_access 関数です。この条件ステートメントは、1 つのテンプレート・ファイル内で異なるデータ・オブジェクトとヘルパー関数を使用する例として組み込んでいます。
リストの残りの部分には、要約、本文、そしてアナウンスメントの添付が表示されています。この XHTML は意味的にも構造的にも有効になるように構成されています。つまり、一部のデータが使用できない場合は、これを収容する XHTML 要素全体がコンテンツ・フラグメントから除外されます。例えば、要約文が含まれる DIV 要素を PHP 条件ステートメント内にラップすると (<?php if ($node->abstract) : ?>)、$node->abstract が存在する場合にのみ、このコンテンツが表示されることになります。
アナウンスメント・サマリー
アナウンスメント・サマリーのコンテンツ・フラグメントは、announcement_compact.tpl.php テンプレート・ファイルを使用して構成しています。このコンテンツ・フラグメントは、図 5 のセクション B のように、ホーム・ページやアナウンスメント・ページなどで複数のアナウンスメントをリストするときに使用されます。
リスト 15 には、announcement_summary のクラス属性値で識別されるオブジェクトに有効なコンテナーがあります。ここに含められる可能性があるクラス属性値として、他に sticky と hl_yellow の 2 つがあることがわかります。
リスト 15. announcement_compact.tpl.php テンプレート
<?php global $user; ?>
<div class="announcement_summary<?php print ($node->sticky) ? " sticky" : "; ?>
<?php print ($user->uid == $node->uid) ? " hl_yellow" : "; ?>">
<h3>
<a href="<?php print $node->url ?>"
title="Read more about this announcement"><?php print $title ?></a>
<?php print $links ?>
</h3>
<p class="date">Posted on <?php print $published; ?>
<?php
if ($user->uid == $node->uid or user_access('edit announcement')) {
if ($node->expiration_date < time()) print " and expired on ".$expires;
else print " and going to expire on ".$expires;
}
?>
</p>
<?php if ($abstract) : ?>
<div class="abstract">
<?php print $abstract ?>
<a class="more" href="<?php print request_uri(); ?>/<?php print $node->nid ?>"
title="Read more">more »</a>
</div>
<?php endif; ?>
</div>
|
アナウンスメントを編集する際に、管理者はフォームの Publishing options セクションでノードにスティッキー・フラグを設定できます。これをアナウンスメント・モジュールで使用すると、発生順によるアナウンスメントのリストをオーバーライドして、先頭にスティッキー・アナウンスメントを配置することができます。ここでは、収容 DIV 要素のクラス属性値でスティッキー・アナウンスメントを識別しています。$node->sticky 変数は、phptemplate_announcement_compact 関数 (第 6 回に記載) に組み込まれてテンプレートに渡されます。
hl_yellow クラスは、現行ユーザーの ID がアナウンスメントの関連ユーザー ID と同じ場合に組み込まれます。このクラスによって、現行ユーザーによって作成されたアナウンスメントを強調表示できます。
アナウンスメント・ブロック
アナウンスメント・ブロックのコンテンツ・フラグメントは、announcement_compact.tpl.php テンプレート・ファイルを使用して構成しています。このコンテンツ・フラグメントは、図 4 のセクション C と図 5 のセクション C に示すように、過去のいくつかのアナウンスメントをすべてのページの右側のサイドバーにリストするときに使用されます。
リスト 16 のテンプレートは、announcement_block 関数で作成されたデータをカスタマイズするものです。このテンプレートはアナウンスメント・ブロックのコンテンツ変数で使用するための表形式のアナウンスメント・リストを作成します。アナウンスメント・ブロックはデフォルトのブロック・レイアウトを使用するため、このリストは block.tpl.php テンプレートを使用して変更することもできます。
リスト 16. announcement_block_list.tpl.php テンプレート
<?php global $user; ?>
<?php $i = 1; ?>
<table cellspacing="0">
<tbody>
<?php foreach($announcements as $a): ?>
<tr class="<?php print ($i%2) ? " : " alt"; ?>
<?php print ($a->uid == $user->uid) ? " hl_yellow" : " ; ?>">
<td class="col1"><a href="/announcements/<?php print $a->nid; ?>"
title="Read more about '<?php print $a->title ?>'">
<?php print $a->title; ?></a></td>
<td class="col2">
<?php print format_date($a->publish_date,'custom','j M y'); ?></td>
</tr>
<?php $i++; ?>
<?php endforeach; ?>
</tbody>
</table>
<p class="more"><a href="announcements/">View all the Announcements »</a></p>
|
この表のコードは、アナウンスメントごとに表の行を作成するため少々複雑です。各行には 2 つの列が含まれます。最初の列に記載されるアナウンスメント・タイトルは、アナウンスメントの詳細ページにリンクする XHTML アンカー要素として作成されます。一方、2 番目の列にはアナウンスメントの公開日が記載されます。表の後にはもう 1 つのアンカー要素が作成され、すべてのアナウンスメントをリストするページにユーザーがリンクできるようにします。要約レイアウトと同様、現行ユーザーが所有するアナウンスメントの場合には、クラス属性値 hl_yellow が組み込まれます。
第 6 回では、$announcement_block_max_list_count 変数を使用してブロック内に表示するアナウンスメント数を制御する方法を説明しました。このロジックは announcement_block 関数内に含まれるため、適切な数のアナウンスメントがこのテンプレートに渡されます。
template.php ファイル
template.php ファイルの使用方法については、第 5 回で述べました。このファイルには、特定のノード・タイプだけではなく、テーマ全体に適用される既存のテーマ関数をオーバーライドするテーマ関数が含まれます。このファイルを使用する単純な例としては、アクション・リンク (上記で説明) をコンテナーでラップし、これらのアンカー要素がコンテンツの残りの部分とは視覚的に区別されるようにスタイル設定する必要がある場合が挙げられます。
Drupal 配布に付属する /inc/theme.inc ファイルは、theme_links 関数を定義します。この関数は、phpengine がテンプレート・ファイルに渡す $links 変数にテーマ設定するために使用されます。そのため、図 6 に記載したフローに従えば、phptemplate_links という関数を使用するとこの関数をオーバーライドできます。リスト 17 に、template.php ファイルに配置した phptemplate_links 関数を示します。
リスト 17. template.php ファイルでのデフォルト theme_links 関数のオーバーライド
function phptemplate_links($links, $delimiter = " ") {
return '<span class="action">'.implode($delimiter, $links).'</span>';
}
|
上記のリストを見るとわかるように、この関数は、クラス属性で識別される SPAN 要素でリンクをラップしているだけです。
まとめ
今回の記事では、新規テーマの作成に着手する方法、そしてサンプルの Web サイトのテーマ内に構造化 XHTML を作成する方法を説明しました。また、全体のページ・レイアウト、ホーム・ページのコンテンツ、基本ナビゲーション、Web サイトのセクション識別など、Web サイトのコンテンツを構成するいくつかの方法を紹介しました。
次回の記事では構造化された IBC Web サイトを CSS を使ってスタイル設定する方法を取り上げるので、お見逃しなく。
参考文献 学ぶために
議論するために
著者について  | 
|  | Alister Lewis-Bowen は、IBM Internet Technology Group のシニア・ソフトウェア・エンジニアです。1993年から
IBM 社員としてインターネットおよび Web テクノロジーに取り組んでいます。彼は
IBM 後援のスポーツ・イベントの Web サイトに従事するためにアメリカ合衆国に移り、のちに
ibm.com のシニア・ウェブマスターとなりました。現在は、セマンティック Web プロトタイプの作成を支援しています。 |
 | |  | Stephen Evanchik は、IBM Internet Technology Group のソフトウェア・エンジニアです。多くのオープン・ソース・ソフトウェア・プロジェクトに貢献した経歴を持ち、なかでも
Linux カーネルの IBM TrackPoint は彼の注目に値する功績となっています。現在は、新しいセマンティック
Web テクノロジーに取り組んでいます。 |
 | 
|  | Louis Weitzman は、IBM Internet Technology Group のシニア・ソフトウェア・エンジニアです。30年間、設計とコンピューティングが交わる部分で働いています。彼は
ibm.com で使用する XML、フラグメント・ベースのコンテンツ管理システムの開発を支援し、現在は新しいプロジェクトへの設計プロセスの統合に従事しています。 |
記事の評価
|