Midgardは、その資料の中では、"動的に生成されるWebアプリケーションの開発とサービス提供のための" アプリケーションである、と記されています。Midgardは、いわゆるコンテンツ・マネージメント・システムのようですが、配布コンテンツの所有権の提供、コンテンツとルック・アンド・フィールの切り離し、サイトへのサービス提供、そしてWebベースの管理といった機能を備えてます。
PHPを起動して実行状態にし、MySQL接続を済ませたら、次のステップとして、データベース駆動型コンテンツを作動させることになります。多くのプログラミング作業の結果、データベースから取り出したニュース・アーティクルを編集、作成するためのWebフロントエンドを備えたニュース・ページができることになるかもしれません。もし筆者と同じようなコードを書く人がいるとしたら、そのコードは素直で管理しやすいなどとはとても言えないものでしょう。おそらくはSQLステートメントと配列操作が、所狭しとごった返しているといったところでしょう。しかし、頼りになるのは自分しかいないのです。
Midgardは、そのようなアーティクルの管理をずっと簡単でわけのないものにする、PHP用のコンテンツ・マネージメントAPI を非常に基本的な技術レベルにおいて実現しています。Midgardでは、その独自のコンテンツ・マネージメント概念の一部を実際に取り入れることにより、より論理的にアーティクルを編成したり、簡単にアーティクルが取り扱えるようにしたりしています。また、セキュリティーをインプリメントして、許可ユーザーだけがコンテンツの更新や閲覧をできるようにしたり、ユーザーの個人情報を記録したりすることもできます。
Midgardは、2つのWebサイト (サンプルのMySQLデータベースにあるレコードです) を パッケージの中に含んでいます。つまり "Virtual Midgard Using Company" の見本サイトと、Webサイトの管理に効果的に使用できる完全なWebベース・コンテンツ・マネージメント・システムである その管理サイトです。
筆者がMidgardを使い始めたのは、筆者が属するネットワーク・ゲーム・クラブのWebサイトを開設しようとしていたときです。そのとき欲しかったのは、Webサイトのコンテンツを更新 (ニュース、ファイル、FAQ項目などの追加) でき、なおかつ簡単な方法でコンテンツを動的に生成できるような、1つの委員会のようなものです。そのときは、既に別プロジェクトのサイトの大まかな原型プログラムをPHPでプログラミングした後でしたが、そこで (希望のクオリティーに達するには) 一からすべてを書き直すか、別の何かを試すかしかないという二者択一に迫られていました。Midgardがその別の何かだったのです。
Midgardをインストールする最も簡単な方法は、www.midgard-project.orgからApache-Midgardパッケージを入手して、そのインストール・ガイドに従うことです。これらのパッケージには、Apache WebserverとMidgardを拡張したPHPが含まれています。また、www.mysql.orgからMySQLサーバーも入手する必要があります。(これらのサイトへのリンクは、参考文献を参照してください。)
Midgardは、その独自のコンテンツ概念により、通常のWebサイトを幾つかの部分に分割します。その幾つかの部分とは、トピック、アーティクル、ホスト、ページ、スタイル です。各コンテンツ・タイプは、管理サイトを使って管理することができます。各コンテンツ・タイプの定義には、そのコンテンツ・タイプを参照するための固有IDがあります。
配布コンテンツの所有権は、Midgardデータベースの個人レコードおよびグループ・レコードを使ってインプリメントできます。個人レコードおよびグループ・レコードは、Midgard Administrator (Midgardのセットアップ時に作成されるデフォルトのユーザー・アカウントです) が管理サイトから作成することができます。個人レコードには、名前、住所、電子メール・アドレス、ホーム・ページ、説明など多数の属性があります。また、個人レコードにMidgardログオン・ユーザー・アカウントを割り当てる (管理サイトで個人レコードを変更します) こともできるため、各個人がWeb上でコンテンツを管理したり、自身の詳細を変更したりすることができます。グループ・レコードにも、名前、説明など多くの詳細があり、システム上にリストされた個人をグループに編成する (管理サイトでグループを変更します) ことができます。通常、システム内の他の項目 (ホスト、アーティクル、その他のグループ) は特定のグループが所有しているため、このことは重要な意味を持っています。所有グループのメンバーは、分散コンテンツの所有権システムを提供している管理Webサイトを通して、これらの項目を変更することができます。
筆者のクラブのWebサイトの場合、クラブの委員会 ("NGS Committee") に対して1つのグループを、委員会のメンバーそれぞれに対して1つずつの個人レコードを、作成しました。そしてこれらのレコードを委員会グループに追加し、最後にそれぞれの個人にユーザー・アカウントを与えて、Web上でコンテンツへのログオンと変更ができるようにしました。また、Webサイトの管理に携わるメンバー用にもグループ ("NGS Admins") を1つ作成し、自分の個人レコードをそこに加えました。
スタイルは、Webサイトの外観とそのコンテンツの配置の仕方を定義するものです。他のMidgardエレメントと同様、スタイルもまたグループが所有しています。したがって、そのグループのメンバーだけがスタイルを更新する権限を持ちます。スタイルは複数のスタイル・エレメントから構成され、それぞれに固有の名前と何らかのコンテンツがあります。スタイルのコンテンツとは、他のエレメントを参照し、そのエレメントのPHPコマンド、PHP Midgardコマンドおよび HTMLを取り込むことのできる (サーバー・サイド・インクルードに近いものです) 断片的HTMLのことです。重要なスタイル・エレメントは「ルート」と呼ばれ、MidgardがWebサイト・ページを作成する際に最初に使用されます。"新規の子スタイル" として定義されるスタイル・レコードは、その親レコードからスタイル・エレメントを継承します。
スタイル・レコードは、管理サイトのLayout Administrationセクションから操作することができます。筆者のクラブのWebサイトでは、"NGS Style" という最上位のスタイルを新たに定義し、その所有者をNGS Adminsグループにしました (以上の作業を行うにはMidgard Administratorとしてログインする必要があります)。
図1
スタイルの定義後は、筆者自身がこのスタイルの所有者である "NGS Admins" グループのメンバーであるため、自分の名前でログインして作業を継続することができるようになりました。最初に行ったのは、以下のコードを使用して「ルート」スタイル・エレメントを定義することでした。
<html> <head> <title><(title)></title> </head> <body bgcolor="black" text="white"> <table border=0> <tr> <td><[navigator]></td> <td><[content]></td> </tr> </table> </body> </html> |
<title> タグの内側に<(title)> とあることに注意してください。これは、表示されるページのtitleフィールドを取り出してきて、そのコンテンツをHTMLタイトルに使用するためのものです。<td> とあるタグは、それぞれnavigator、content と呼ばれる他のスタイル・エレメントを参照するためのものです。navigatorスタイル・エレメントの例を示しましょう。
<a href="/">Home page</a> <a href="/news/">News</a> <a href="/about/">About the club</a> |
また、navigatorに他のスタイル・エレメントへの参照を加えることも、必要なだけこの手のエレメントを作成することもできます。
「ルート」スタイル・エレメントでのコンテンツ参照は特殊なものです。これはMidgardにある実際のWebサイト・コンテンツ、この場合NGS Committeeのメンバーが持つコンテンツです。これ以上、コンテンツ・スタイル・エレメントを定義する必要はありません。
かなりシンプルなスタイルをさらに拡張して、ページ・ヘッダー、ページ・フッター、検索フィールド、その他希望のものを組み込むことができます。それぞれを固有のスタイル・エレメントに入れれば、HTMLの編集が単純化され、プロセスにある程度の論理的な構造を持たせることができます。
複数のスタイル・エレメントを使えば、子スタイルでスタイル・エレメントをオーバーライドすることができるようになります。たとえば、オリジナル・スタイルの子に親のフッター・エレメントと同じ名前のスタイル・エレメントを追加し、新しいフッターをそこにコーディングすれば、異なるフッターを持ったWebサイトの別バージョンを簡単に作ることができます。
コンテンツ・マネージメントは、アーティクル・レコードおよびトピックを使って実行します。アーティクル・レコードには、タイトル、名前、要約、コンテンツ、作成者、その他のフィールドがあります。アーティクルは自分に行われた変更を追跡します。また、作成者が他のユーザーが更新しないようにロックをかけることができます。アーティクルはトピック・レコードの下に編成され、それぞれ1つのトピックに属します。また、固有のIDによってプログラムによる検索が可能になっています。
各トピックには、名前、説明、その他のフィールドがあります。またトピックを所有するのはグループです。このグループは、トピックそのものに対する変更や、トピックに関連付けられたアーティクルへの追加や変更を行えるユーザーが誰であるのかを制御します。トピックを他のトピックの下に編成することもできます。最上位のトピックがWebサイトのトピック・ツリーのルートとなり、さまざまなトピックを使用して収集したサブトピックやアーティクルがその下にきます。
トピックの詳細は、そのトピックの固有のIDを使って検索することができます。トピックの下のアーティクルは、1つ1つ取り出すことができます。
アーティクルに対する許可は、サブトピックに対して累積的に働きます。つまり、すべての親トピックを所有するグループが、トピックに対する許可を受けます。特定のトピックをあるグループのところまでロックする場合、他のグループが親トピックを所有することがないようにすることが重要です。
コンテンツは、管理サイトのContent Administrationセクションから管理することができます。
筆者のクラブのサイトでは、"NGS" という最上位トピックを新たに定義して、NGS Adminsにその所有権を与え、若干の記述ワードを入力しました (Midgard Administratorとしてログインする必要があります)。
図2
サイト・アドミニストレーターが更新できるフロントページに記述テキストを入れるため、このトピックの下に新規のアーティクルを作成して、タイトル "Home page"、名前 "Home"、要約、そして記述フィールドへの記入内容などを入力しました。
図3
これに割り当てられた固有のIDが33 であることに注意してください。ただし、IDはその時点でいくつのアーティクルが定義されているかによって決まり、別のシステムでは異なる内容になる場合がよくあります。
委員会のメンバーが管理する動的ニュースを追加するため、"News" というサブトピックを新たに作成し、NGS Committeeに所有権を与えました。これにより、委員会グループのメンバーは自分でニュースを更新または定義できるようになり、うまくいけば、スムーズな情報交換が行えるはずです。このシステムでのトピックIDは23です。
最後に、テスト用のニュース・アーティクルとして、覚えやすいタイトルと、短い要約、コンテンツとしてのアーティクル全文を定義しました。
図4
トピックおよびアーティクルは、Webサイトの動的コンテンツを編成する際に便利なものですが、それぞれの情報をどうリンクするかということは定義しません。それを行うのは、ホスト・レコードとページ・レコードの役目です。
ホストには、WebサイトのWeb上のかなめとなるツールともいうべき、ホスト、実行ポート、サイトの所有者グループ、サイトのスタイル、ホーム・ページ ("ルート・ページ") などを記述します。ホスト・レコードは、管理サイトのHost Administrationセクションから操作できます。
筆者のクラブのサイトの場合、ポート8090、NGS Webサイトのスタイル、そして所有者としてNGS Adminsをリストしました。名前 (Name) とあるのは、ホスト名およびWebサーバーのドメインのことです。この場合、最初から始めたかったので、ルート・ページの設定は[new root page] にしました。
図5
ホスト定義とポート情報は、Apache Webサーバーの構成ファイルhttpd.confの項目と密接に関連付けられています。ホストを動かすには、httpd.confに
VirtualHost 項目がなければいけません。このテスト用サイトの場合、これらの項目は以下のようになりました。
Listen 8090 NameVirtualHost 127.0.0.1:8090 <VirtualHost 127.0.0.1:8090> ServerName ngs.domain.com DocumentRoot "/home/djs/ngs" Port 8090 </VirtualHost> |
ヒント: コンテンツの大半は、最初からMidgardに用意されていますが、イメージやダウンロード用ファイルなどを従来のファイル・システムに保管したいというユーザーもいるでしょう。
VirtualHost のDocumentRoot 定義で、Midgardの認識外のURLがどこにあるかを判別します。たとえば、このサイトのイメージはすべて/home/djs/ngs/images にあるため、http://ngs.domain.com/images/ というURLを使ってアクセスできることになります。
Midgard管理サイトからホストを定義すると、以下のように、midgard データベースのhost テーブルに項目が1つ作成されます。
mysql> USE midgard; SELECT * FROM host WHERE port='8090'; | id | name | root | style | info | owner | port | online | prefix | | 5 | ngs.domain.com | 41 | 3 | | 3 | 8090 | 0 | | |
管理サイトのHost Adminパートで、Webサイトをオフライン (サイトにアクセスしようとしたユーザーは403 Forbidden応答を受け取ります) にしたり、オンラインにしたりすることができます。Webサイトおよびルート・ページは使用可能な他のスタイルに変えることができるため、サイトのルック・アンド・フィールを必要に応じて簡単に変更することができます。
新規ホストを作成したところ、Midgardにより新規ページが作成されました。このページは管理サイトのPage Adminセクションから管理できます。ホスト・レコードを表示するときは、このページにリンクします。
ページ・レコードは、Webサイトの構造、特に、サイトの各部にアクセスする際に使用するURLや それぞれのサイトのコンテンツ、そしてサイトのどの部分が静的であるか動的であるかを定義するためのものです。それぞれのページには、名前、タイトル、スタイル (スタイルは継承されるため、Webサイトの全ページで同じホスト・スタイルが保たれます)、作成者、コンテンツが含まれます。認証が必要であるかどうかはページごとに設定可能で、設定しない場合には、継承されます。各ページにはタイプがあり、これによって、ロケーションの後ろに指定されたURLの残りの部分を、入力パラメーターとして読み取るか (たとえば "news" の場合、/news/10.html を読み取ったときに、
10.html ビットをスクリプトに対するパラメーターとして使用します)、ただのプレーン・ページとして読み取るかが決まります。前者が動的ページで、後者が静的ページですが、静的ページでもPHPを使用することができ、かなり動的です。
ページは、サブページおよびページ・エレメントを持つことができます。サブページを作成すると、URL/<parent page name>/<subpage name>/ でアクセス可能なページが作成されます。たとえば、ルート・ページの下に置く場合、/<subpage name>/ でサブページにアクセスできます。/news/extra/ というURLであれば、"extra" というニュース・サブページの下にサブページを作成することになります。ページ・エレメントは、スタイル・エレメントに非常によく似たもので、<[element name]> 構文を使って、ページのコンテンツに組み込むことができる断片的HTMLです。
ページのコンテンツには通常、アーティクルを取り出し、そのコンテンツを使用してHTMLを表示するためのPHPコードや、トピックの下にある一連のアーティクルを取り出し、閲覧者が選択できるような項目リスト (ニュース・アーティクルなど) を作成するためのPHPコードが含まれます。ルート・ページとは、Webサイトのルート (/ など) として使用されるページのことです。
今回のクラブのルート・ページでは、名前を "NGS"、タイトルを "Network Gaming Subsection" とし、これを静的なものとして定義した後で、ホーム・ページ・テキストとして使うアーティクルを取り出すためのPHPコードをコンテンツに加えました。
<? $article = mgd_get_article(33); ?> <h2>&(article.title);</h2> <p> &(article.abstract); &(article.content:h); |
この例には、Midgardコードを作成する際に役立つ2つの概念が含まれています。1つ目は、アーティクルの固有IDを取得し、そのアーティクルへハンドルを戻す
mgd_get_article 関数を使用していることです。他のMidgard PHP関数と同様、この関数もmgd_ で始まっています。2つ目は、実際にアーティクルのフィールドを表示するのに、通常のHTMLのフォーマット&(<article handle>.<field>); を使用していることです。たとえば&(article.title); は、アーティクルのタイトル・フィールドを表示します。また、フィールド・コンテンツの表示方法を指定することもできます。&(article.content:h); の:h は、Midgardにそのコンテンツ・フィールドをHTMLとして、つまり、<br> タグや <p> タグを入れたり、リスト状の構造をHTMLリストに置き換えるなどの操作をするものとして、レンダーするように指示します。
フォーマット修飾子の全リストは、"Formatting Engine" (参考文献のリンクを参照) にあるMidgard資料に記載されています。
上記のコードの下に、ニュース・トピックからアーティクルを検索し、最初の3つのタイトルおよび要約と、ニュース・ページを開いて全文表示を行うリンクを表示するためのコードを追加しました。
<? $article = mgd_list_topic_articles_all(23);
if($article)
{
// show first 3 news articles
for($i = 0; $i < 3 && $article->fetch(); $i++)
{ ?>
<p>
<strong><a href="/news/&(article.id);.html">&(article.title);</a></strong>
<br>&(article.abstract);<br>
</p>
<? } }
?>
|
最初の行ではニュース・トピックの固有IDを使用してcursor object を検索し、そのハンドルを$article 変数に保管しています。この結果、指定トピックの下にアーティクルが表示されます。これが設定されている (つまり、最低1つのニュース・アーティクルがあるということ) 場合、メソッドfetch() が最初のアーティクルを、そして呼び出されるごとに以降のアーティクルを取り出します。アーティクルの数を最初の3つに制限するため、このコードではfetch() をfor ループの中に置いています。デフォルトでは、mgd_list_topic_articles_all 関数が作成日をもとに、こちらがニュースとして必要としている最新のアーティクルから順にソートします。しかし、アーティクル名、スコア、逆引きなどの検索オプションを使用することもできます。
コードはアーティクルを取り出すと、再度&(<handle>.<field>); 構文を使用して、アーティクルのタイトルおよび要約を表示します。また、アーティクルのタイトルをURL/news/<article ID>.html にリンクします。これによってリンクは "news" という動的サブページ (アーティクルIDをパラメーターとして使用します) を参照します。
このニュース・サブページをURL/news/ に作成するために、NGSルート・ページである "news" から管理サイトを使用して、適切なタイトルおよびタイプactive を指定したサブページを作成しました。コンテンツのコードの最初の部分は、以下のようなものです。
<? if($argc == 1) { $id = $argv[0]; } if($id) { $article = mgd_get_article($id); } if($article) {
?> <[article]> <? }
|
動的ページの場合、URLの末尾部分から取得するパラメーターは、おなじみの$argv 配列に、長さを指定する
$argc 変数を指定して渡されます。ただし、これらのパラメーターを取得するに当たって、Midgardは多少優れた振る舞いをします。Midgardは最後の.html を省くので、URL/news/10.html は
argv 配列において値10 を持つ単一パラメーターになります。パラメーターをスラッシュで区切って (たとえば、/news/sports/10/)、さらにパラメーターを指定することもできますが、ここでは、表示されるアーティクルの固有IDを表すパラメーターだけを使用しています。アーティクルが指定されると、コードはこれを取り出して、アーティクル・ページ・エレメントを使ってレンダーします。
上記のようにしない場合、ホーム・ページの場合と同様、タイトルを表示し、ニュース・アーティクルのリストを取り出しますが、この場合は、すべてのニュース・アーティクルをその日付と一緒に表示します。
else {
?>
<h3>News</h3>
<? $article = mgd_list_topic_articles_all(23); if($article) { while($article->fetch()) { ?>
<p>
<strong><a href="&(article.id);.html">&(article.title);</a></strong> <font size=-1>&(article.adate);</font>
&(article.abstract);
</p>
<? } } }
?>
|
最後に、ニュース・アーティクルのコンテンツをレンダーする "アーティクル" というページ・エレメントを定義しました。
<h3>&(article.title);</h3> <p><font size=-1>&(article.aldate);</font></p> <p> &(article.content:h); <p> <a href="/news/" class="navi">More news</a> </p> |
以上のコードは、アーティクル・タイトルを正式な形式のヘッダーとして、日付を小さなフォントで、そしてアーティクルのコンテンツをHTMLで出力します。また、アーティクルの一番下の部分に、ニュース・ページへ戻る小さなリンクも表示します。もちろん、そうしようと思えば、アーティクル・ページ・エレメントのコンテンツをニュース・ページに組み込むこともできますが、これらを分けておくことで、分かりやすくきちんと整理された状態に保つことができます。
注意: 実際のページそのものやスタイルなどを含め、他のどんなエレメントよりも先に自動的に組み込まれるcode-init という特殊なページ・エレメントがあります。これを使用することによって、argv配列からの$id の取得や適切なアーティクルの取り出しなどの初期設定を、そのような基本コードをメイン・ページと切り離したまま行うことができます。
'code-init' page element content:
<? if($argc == 1) { $id = $argv[0]; } if($id) { $article = mgd_get_article($id); }
?>
|
これはスタイルよりも前に実行されるため、上の例ではスタイルがレンダーされるときに、$article 変数が設定されます。その結果、スタイルがアーティクルのタイトルを読み取って、HTMLヘッダーに表示することができるようになります。
<P>Partial style element content:
<title><?
if($article)
{ ?>NGS - &(article.title);<?
}
else
{ ?><(title)><?
}
?></title>
|
サイトの最後の締めくくりとして、"about" というルート・ページに静的サブページを作成して /aboutページを追加し、参考コンテンツを書き込みました。
トピックIDからアーティクル・レコードを取り出すことができるように、グループIDから個人レコードにアクセスすることもできます。
これは、委員会メンバーのページを作成する場合に役に立ちます。筆者の場合、NGS CommitteeグループのID (3) と関数mgd_list_members を使用して、グループのカーソル・オブジェクトを取得しました。個人の全詳細を知るには、そのメンバーの ($person 変数のuid フィールドにある) IDを入手し、それを使って
mgd_get_person を実行する必要があります。なぜならば、mgd_list_members が戻す個人レコードでは、多くのフィールドが抜けているからです (たとえば電子メール)。
<?
$person = mgd_list_members(3);
if($person)
{
while($person->fetch())
{
$persondetails = mgd_get_person($person->uid);
?>
<p>
<strong>&(persondetails.name);</strong>
&(persondetails.extra);
<? if($persondetails->email) {
?>
<a href="mailto:&(persondetails.email);"><font size=-1>&(persondetails.email);</font></a>
<? }
?>
</p>
<? } } else {
?>
There are no committee members! =)
<? }
?>
|
このコードでは、アーティクルで使用したのと同じ&(<variable> .<field> ); 構文を使用して、個人レコードの名前、その他、電子メールの各フィールドを出力しますが、電子メール・フィールドでは記載があるかどうかチェックしています (フィールドに記載がなかった場合には、コードは電子メール・リンクを出力しません)。
今回作成したサイトは、Midgardでできることのほんの簡単な一例を示しているに過ぎません。われわれNGS Committeeのメンバーは、こうしてサーバーにログオンしてニュース・アーティクルを作成することができるようになりました。NGS Adminsのメンバーとして、筆者もスタイルやページと同様、ホーム・ページの記述テキストを更新することができます。Midgardは、Webサイトの機能を拡張できる数多くのPHP機能を備えています。Midgardの管理サイトは言うまでもなくMidgardサイトであり、例としてはうってつけです。ぜひソースをチェックしてみてください。
- Midgard全般に関しては、MidgardプロジェクトのWebサイトをご覧ください。
-
MySQLデータベース・サーバーはここからダウンロードしてください。
- PHPに関する詳細は、php.net をご覧ください。
- PHPの基本事項に関しては、このdeveloperWorksの記事をご覧ください。
