2012年02月12日

Movable Typeでのログイン機能実装

MovableTypeでログイン機能を実装する方法を考える。
ブログ記事管理を通常の MT 管理画面上でいつもどおりに行えるようにしたい。
つまり、MT 管理画面上での:
  • ブログ記事の投稿や変更
  • テンプレートの改変
が公開される記事に反映されるようにしたい。

いろいろな方法があると思うが、以下のような仕組みを考えた:
  • ログインが必要なコンテンツは、別ブログに分ける。
  • ブログ記事、ウェブページはウェブ上に公開されない場所に保存させる。
  • ブログ記事は PHP スクリプトから読み出して表示させる。
     (PHP スクリプト上でユーザー認証を行うことで、ログイン機能を実現)
  • PHP 用のテンプレートはウェブページで作成する。
     (ウェブページのデザインテンプレートでデザインを変更できる)

以下、具体的な方法を説明する。

使用した MT バージョンは 5.12-ja。

ブログの作成

ログインを必要とするコンテンツ用のブログを作成する。
その際、[ブログパス] は [絶対パス] にチェックを入れ、ウェブ上に公開されないパスを指定する。

ブログの設定で、
「全般設定」
  • 「アーカイブ設定」-> [ファイルの拡張子] を "tpl" に変更 (これは好みに応じて)
「投稿設定」
  • 「作成の既定値」-> [テキストフォーマット] を "なし" に変更
とする。

デザインテンプレート整備

デザインの「ブログテンプレートの管理」画面で、以下のような設定を行う。
ウェブページテンプレート改変
アーカイブテンプレートの「ウェブページ」テンプレートを改変する。

ウェブページは PHP のデザインテンプレートとして使用するため、ところどころ PHP コードに置き換える必要がある。
ページタイトル
<title><$mt:PageTitle encode_html="1"$> - <$mt:BlogName encode_html="1"$></title>
の部分は記事ごとに変える必要があるので、たとえば
<title><?php echo htmlspecialchars($page_title); ?> - <$mt:BlogName encode_html="1"$></title>
のようにする。

PHP のデザインテンプレートは「ブログ記事」「カテゴリページ」など複数用意することになるので、「ウェブページ」テンプレートはそれらに共通して使えるようにする。
ブログ記事テンプレート改変
アーカイブテンプレートの「ブログ記事」テンプレートを改変する。

ブログ記事は PHP スクリプトから読み出される記事データベース的役割をする。
そのため、読み出しに適した単純な書式で各記事詳細を書き込むようにする。
たとえば:
<$mt:CategoryLabel$>
<$mt:EntryTitle$>
<$mt:EntryDate$>
<$mt:EntryBody$>
など。
今回は議論しないがコメントとタグもブログ記事に書き出すようにする。

また、ブログ記事の URL から記事 ID がわかるように、アーカイブマッピングで [パス] のファイル名部分を %-f から <$MTEntryID$>.html に変更する。
ブログ記事リストテンプレート改変
カテゴリ別や月別のブログ記事リストのテンプレートを改変する。

ブログ記事リストも PHP から読み出されるので、読み出しに適した書式にする。
たとえば:
<mt:Entries limit="$limit">
<$MTEntryDate format="%Y/%m"$>/<$MTEntryID$>:<$MTEntryTitle$>
</mt:Entries>
などとする。

また、アーカイブマッピングの [パス] で、
  • %iindex.html に、
  • %-c%c に、
  • 拡張子を .tpl から .html に、
変更する。
カテゴリリストテンプレート追加
アーカイブテンプレートに、カテゴリリストを出力する「ブログ記事リスト」を追加する。

たとえば、
<MTCategories>
<$MTCategoryBasename$>:<$MTCategoryLabel$>
</MTCategories>
など。

これは、メインインデックスを出力する際に使用する。
インデックステンプレート変更
メインインデックスは直接アクセスしないので削除する。
JavaScript、CSS は [パス] に絶対パスを指定する。
ほか、不要な物は削除。

ウェブページで PHP テンプレート作成

たとえば、以下のようなテンプレートをウェブページとして作成する。
ログイン画面用テンプレート
ファイル名: login.tpl
<h2>ログイン</h2>
<form name="form1" action="/members/index.html" method="post">
<table>
<tr>
<td>メールアドレス</td>
<td><input type="text" name="li_mail" value="<?php echo htmlspecialchars($mail); ?>"/></td>
</tr>
<tr>
<td>パスワード</td>
<td><input type="password" name="li_passwd" value=""/></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="ログイン" /></td>
</tr>
</table>
</form>
メインインデックス用テンプレート
ファイル名: index.tpl
<h2>会員用ページ</h2>
<div class="members">
<?php
foreach ($categories as $category) {
?>
<div><a href="<?php echo htmlspecialchars($category['basename']); ?>/"><?php echo htmlspecialchars($category['label']); ?></a></div>
<?php
}
?>
</div>
カテゴリ別ブログ記事リスト用テンプレート
ファイル名: category.tpl
<h2><?php echo htmlspecialchars($category_label); ?></h2>
<div class="members">
<?php
foreach ($entries as $entry) {
?>
<div><a href="<?php echo htmlspecialchars($entry['path']); ?>.html"><?php echo htmlspecialchars($entry['title']); ?></a></div>
<?php
}
?>
</div>

PHPスクリプトの作成

ページを表示するための PHP スクリプトを用意する。
PHP スクリプトは、記事IDまたはカテゴリIDからブログ記事ファイルのパスを決定し、ファイルの内容を読み出し、デザインテンプレートを選んで表示する処理を行う。

以下の PHP コードはその一例で、view.php というファイル名で対象パス (DocumentRoot/members など) に置く。
<?php
/**
* ページ表示
*
* 入力パラメータ
* c -- 'index' / カテゴリのベースネーム
* y -- 記事年
* m -- 記事月
* e -- 記事番号
* 組み合わせは以下のいずれか
* view.php?c=index
* view.php?c=cat
* view.php?y=2012&m=01&e=00123
*/
// ブログの [ブログパス] で設定したパスを指定
define('MEMBERS_BASEDIR', '/var/www/members');
if (!auth()) {
require MEMBERS_BASEDIR . '/login.tpl';
exit;
}
// 表示ページの決定
if (isset($_REQUEST['c']) && $_REQUEST['c'] != '') {
$category_basename = $_REQUEST['c'];
}
if (isset($_REQUEST['e']) && $_REQUEST['e'] != ''
&& isset($_REQUEST['m']) && $_REQUEST['m'] != ''
&& isset($_REQUEST['y']) && $_REQUEST['y'] != '') {
$entry_year = $_REQUEST['y'];
$entry_month = $_REQUEST['m'];
$entry_id = $_REQUEST['e'];
if (!preg_match('/^\d{4}$/', $entry_year)) {
echo "ERR(1)";
exit;
}
if (!preg_match('/^\d{2}$/', $entry_month)) {
echo "ERR(1)";
exit;
}
} else {
$entry_year = '';
$entry_month = '';
$entry_id = '';
}
} else {
echo "ERR(2)";
exit;
}
// 記事の内容
if ($entry_id != '') {
// 個別の記事
$entry_fname
= MEMBERS_BASEDIR . "/$entry_year/$entry_month/$entry_id.html";
if (!file_exists($entry_fname)) {
echo "ERR(3)";
exit;
}
if (($fh = fopen($entry_fname, 'r')) === FALSE) {
echo "ERR(4)";
exit;
}
flock($fh, LOCK_SH);
$category_label = trim(fgets($fh));
$entry_title = trim(fgets($fh));
$entry_date = trim(fgets($fh));
$entry_contents = '';
while ($row = fgets($fh)) {
$entry_contents .= $row;
}
fclose($fh);
$page_title = $entry_title;
} else if ($category_basename == 'index') {
// インデックス
$categireis = array();
if (($fh = fopen(MEMBERS_BASEDIR . '/categories', 'r')) === FALSE) {
echo "ERR(5)";
exit;
}
flock($fh, LOCK_SH);
while ($row = fgets($fh)) {
$row = trim($row);
if ($row != '') {
list($cbn, $cl) = explode(':', $row, 2);
$categories[] = array('basename' => $cbn,
'label' => $cl);
}
}
fclose($fh);
$page_title = '会員用ページ';
} else {
// カテゴリ
$categirey_label = '';
if (($fh = fopen(MEMBERS_BASEDIR . '/categories', 'r')) === FALSE) {
echo "ERR(5)";
exit;
}
flock($fh, LOCK_SH);
while ($row = fgets($fh)) {
if (preg_match("/^$category_basename:(.+)$/", $row, $matches)) {
$category_label = $matches[1];
break;
}
}
fclose($fh);
if ($category_label == '') {
echo "ERR(6)";
exit;
}
$entries = array();
if (($fh = fopen(MEMBERS_BASEDIR . "/$category_basename/entries", 'r'))
=== FALSE) {
echo "ERR(7)";
exit;
}
flock($fh, LOCK_SH);
while ($row = fgets($fh)) {
$row = trim($row);
if ($row != '') {
list($p, $t) = explode(':', $row, 2);
$entries[] = array('path' => $p,
'title' => $t);
}
}
fclose($fh);
$page_title = $category_label;
}
if ($entry_id != '') {
require MEMBERS_BASEDIR . '/entry.tpl';
} else if ($category_basename == 'index') {
require MEMBERS_BASEDIR . '/index.tpl';
} else {
require MEMBERS_BASEDIR . '/category.tpl';
}
function auth()
{
// ここで認証処理行う
return TRUE;
}
?>

Rewrite設定

Apache の Rewrite エンジンを利用して、ブログ記事や記事リストへのアクセスを view.php にパラメータをつけて転送する。

設定例:
RewriteEngine On
RewriteRule ^index\.html view.php?c=index [L]
RewriteRule ^([^/]+)/([^/]+)/([^/]+)\.html view.php?y=$1&m=$2&e=$3 [L]
RewriteRule ^([^/]+)/index\.html view.php?c=$1 [L]

以上で設定は完了。
タグ:MovableType PHP
posted by K/I at 08:55 | 東京 ☀ | Comment(0) | TrackBack(0) | 技術メモ | このブログの読者になる | 更新情報をチェックする