Movable Typeで作成されたとあるサイトにて、特定のカテゴリに含まれている記事の総数を表示できるようにしてほしいと頼まれました。
その総数は、サイト内の全ページにあるヘッダーに表示させる予定です。
しかし、Wordpressと違ってMovable Typeは静的ページが表示される形式です。
すでに千ページ以上に渡る大規模サイトであったため、1つの更新があるだけでサイト全体の再構築が30分以上もかかってしまいます。
1つ記事を作成するたびに、サイト全体に再構築をかけるのはあまりにも手間なので、もっと手間なくできる方法を探すことになりました。
通常のMovable Typeの関数で取得する場合
1 2 3 4 5 6 7 8 9 10 11 12 |
<mt:setvar name="count" value="0"> <mt:categories> <mt:if tag="CategoryLabel" like="^(カテゴリ名)"> <mt:setvarblock name="add"><$mt:CategoryCount$></mt:setvarblock> <$MTSetVar name="count" value="$add" op="+" $> </mt:if> </mt:categories> <mt:entries lastn="1" sort_order="descend" category="カテゴリ名"> <mt:setvarblock name="date"><$MTEntryDate format="%y年%m月%d日"$></mt:setvarblock> </mt:entries> <span class="title">記事総数</span> <span class="count"><$MTGetVar name="count"$></span>件(<$MTGetVar name="date"$>現在) |
冒頭の画像のような表示を出すためのコードです。
ついでに、最新の投稿だけ抜き出して、更新日の取得も行っています。
ただ、Movable Typeはリアルタイムでないため、実際に新しい記事を作っても、再構築をしなければ総数が更新されません。
PHPを使って取得する場合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
<?php //$DocRoot = $_SERVER['DOCUMENT_ROOT']; $DocRoot = "/home/xxxxx.com/public_html"; require_once $DocRoot.'/mt/php/mt.php'; require_once $DocRoot.'/mt/php/lib/MTUtil.php'; $blog_id = 1; $mt = MT::get_instance($blog_id, $DocRoot.'/mt/mt-config.cgi'); $ctx =& $mt->context(); $ctx->caching = FALSE; $blog = $mt->db()->fetch_blog( $blog_id ); $ctx->stash( 'blog', $blog ); $ctx->stash( 'blog_id', $blog->id ); $offset = 0; $count = 0; do { $args = [ "blog_id" => $blog_id, "category" => "カテゴリ名", "limit" => 100, "offset" => $offset, ]; $entries = $mt->db()->fetch_entries( $args ); $count += count($entries); $offset += 100; } while(count($entries) > 0); $file = $DocRoot.'/count.txt'; file_put_contents($file, $count); $args = [ "blog_id" => $blog_id, "category" => "カテゴリ名", "limit" => 1, ]; $entries = $mt->db()->fetch_entries( $args ); $date = $entries[0]->entry_modified_on; $args = [ substr($date, 0, 4), substr($date, 4, 2), substr($date, 6, 2), ]; $date = vsprintf("%d年%d月%d日", $args); $file = $DocRoot.'/date.txt'; file_put_contents($file, $date); |
Movable Typeだとたいていは専用の関数を用いることになるのですが、いつものPHPの関数を使ってリアルタイムに記事の情報を取得することもできます。
そして上記のコードで、特定のカテゴリのみに含まれている記事だけを取得しています。
なお、記事を取得する際、一括ですべて取得するのではなく、do whileで100件ずつ行っています。
今回のサイトの場合、一括で取得すると負荷がかかりすぎてエラーになってしまうためです。
サーバーによっては一括でも大丈夫かもしれませんが、念の為。
また、このコードをヘッダーに置いてしまうと、ページを開くたびに取得処理が作動してしまい、開くのが非常に遅くなってしまいます。
せっかくの静的ページで開くMovable Typeの意味がありません。
よってこれを別のphpファイルとして作成し、サーバーのcronで1日1回の実行としています。
そして総数と更新時間はtxtファイルとして出力されるので、そのtxtをヘッダーで読み込みすれば、表示の遅さは大幅に軽減されます。
1 2 3 4 5 6 7 8 9 |
<?php $DocRoot = $_SERVER['DOCUMENT_ROOT']; $file = $DocRoot . "/count.txt"; $count = file_get_contents($file); $file = $DocRoot . "/date.txt"; $date = file_get_contents($file); ?> <span class="title">記事総数</span> <span class="count"><?php echo $count; ?></span>件(<?php echo $date; ?>現在) |
1日1回の自動更新のため、厳密にはリアルタイムではありませんが、毎日何個も記事が作成されるわけではないですし、長時間かかる無駄な手動再構築の手間はなくなりました。
できれば直したかったところ。
1 2 |
//$DocRoot = $_SERVER['DOCUMENT_ROOT']; $DocRoot = "/home/xxxxx.com/public_html"; |
上記コードでMovable Typeのルートのディレクトリを取得したかったのですが、外部のphpファイルではうまく動作しませんでした。
よって、ディレクトリのパスを直で入力せざるを得ませんでした。
また、総数を出力するphpを1日1回のcron実行にするのではなく、サイトの再構築をcronにする手もあったのですが、これもうまく動作しなかったため、今回のようなやり方となってしまいました。
そもそも、記事追加のたびに再構築が必要という、Movable Typeの存在そのものがめんどくさい…。
情報も少なすぎて、トラブルがあってもなかなか解決できない。
WordPressで作り直しさせてほしい。
つい最近、普通二輪MTの免許取りました。夏が終われば大型も取りに行きたい。
いちおう、四輪MTの免許も持っています。クルマがないけど。
5年ほど岡山の田舎に、単身で生活していたこともありました。今は実家の事情で大阪に戻っていますが、将来はまた人混みのない生活に戻りたい。