子ブログ毎の記事一覧を親サイトに表示したい
子ブログの可変に合わせて一覧ページを出したい
「子ブログの記事一覧を親サイトに出す」+「子ブログは増減してもテンプレは触りたくない」
→ MTタグの include_sites ではなく、JS+Data API(JSON)でやるのが現実的
です。
include_sites は再構築時にしか効かないので、JSで受け取った id を代入して動的に切り替える、という使い方はできません。
なので、
• 親サイトのテンプレは「空の入れ物」だけ作る
• JS が URLパラメータや何かで「どの子ブログか(=site_id)」を受け取る
• JS が MT Data API を叩いて、その site_id の記事一覧(entries / contents)をJSONで取得して描画
という流れにします。
⸻
① 親サイトのテンプレ:器だけ用意(JSで子ブログIDを受け取って一覧出力)
URLイメージ
site_id に子ブログIDが入っている前提。
親サイトのテンプレ(child-list.html 例)
これでできること
• ?site_id=3 → ID=3 の子ブログの記事一覧
• ?site_id=5 → ID=5 の子ブログの記事一覧
• 子ブログが増えても、URLに新しい ID を付ければテンプレはそのまま再利用できます
⸻
② 子ブログの増減にも自動対応したい(子ブログを全部拾うパターン)
「URLで指定するんじゃなくて、親サイトが持っている子ブログを自動で全部出したい」なら、
Data APIの /sites をまず叩いて、そこから子ブログ一覧を拾います。
流れ
1. 親サイトID(Website)を MT側で埋め込む(例:<$mt:BlogID$>)
2. Data API /v6/sites?parent_id=親ID で子ブログ一覧を取得
3. その site.id ごとに /v6/sites/{id}/entries を叩いて記事一覧を作る
ざっくりコード例:
これでできること
• 親サイトの配下に 子ブログがいくつ増えても/減っても
→ sites?parent_id=親ID で毎回取り直すので、テンプレ修正なしで追従
• 各子ブログごとに「見出し+記事一覧」をまとめて表示できる
⸻
③ ざっくりまとめ
• include_sites は MTタグの評価時だけ効く ので、
JSで「idを受け取って代入」はできない
• 代わりに、JS+Data API(JSON)で site_id ごとの記事一覧を取得すれば、
• 親サイト上に「任意の子ブログの記事一覧」を出せる
• 子ブログIDをURLパラメータで可変にできる
• 子ブログそのものも /sites?parent_id= で自動取得できる
⸻
もし、
• 記事ではなく「コンテンツタイプ(class_list や求人)」を出したい
• Data APIのURLが mt/mt-data-api.cgi 以外
• 認証が必要な非公開ブログを扱いたい
OK、じゃあ「親サイトに、子ブログごとの記事一覧を自動でズラッと出す」用の コピペ用テンプレ+JS 書きますね。
🧱 前提
- 親サイト=Website(親ブログ)
- その配下に 複数の子ブログ がぶら下がっている
- 親サイト側に「子ブログ一覧+各子ブログの記事一覧」を出すページを作りたい
- 子ブログは増減するので、テンプレには子ブログIDを書きたくない(自動で拾いたい)
- 表示したいのは「通常のブログ記事(entries)」想定
(カスタムコンテンツの場合の書き換えも下に書きます)
✅ 親サイトのテンプレ(そのまま貼ってOK)
親サイトに「インデックステンプレート」か「ウェブページテンプレート」を1つ作って、
中身をまるっとこれにしてください。
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>子ブログ一覧+記事一覧</title>
<style>
.child-blog-section {
margin: 2rem 0;
border-top: 1px solid #ccc;
padding-top: 1rem;
}
.child-blog-section h2 {
font-size: 1.2rem;
margin-bottom: .5rem;
}
.child-blog-section ul {
margin: 0;
padding-left: 1.2rem;
}
.child-blog-section li {
margin-bottom: .25rem;
}
</style>
</head>
<body>
<h1>子ブログ毎の記事一覧</h1>
<div id="blogs-wrapper">読み込み中...</div>
<script>
(function () {
// ★ MTのData APIのベースURLをテンプレートから埋め込む
// 例: /mt/mt-data-api.cgi/v6
const DATA_API_BASE = '<$MTCGIPath encode_js="1"$><$MTDataAPIScript encode_js="1"$>/v6';
// ★ 親のWebsite(このテンプレートを置いているブログ)のID
const PARENT_ID = '<$mt:BlogID encode_js="1"$>';
// 子ブログの一覧を取得するURL
const sitesUrl = DATA_API_BASE + '/sites?parent_id=' + encodeURIComponent(PARENT_ID);
const wrapper = document.getElementById('blogs-wrapper');
wrapper.textContent = '子ブログを取得中…';
// HTMLエスケープ用ユーティリティ
function escapeHtml(str) {
return String(str || '')
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
// 1. 親IDにぶら下がっている子ブログ一覧を取得
fetch(sitesUrl)
.then(function (res) {
if (!res.ok) throw new Error('sites HTTP Error ' + res.status);
return res.json();
})
.then(function (json) {
if (json.error) throw new Error(json.error.message || 'sites 取得エラー');
const sites = json.items || [];
if (!sites.length) {
wrapper.innerHTML = '<p>子ブログがありません。</p>';
return;
}
// 子ブログごとの記事一覧を取得する Promise を配列で用意
const promises = sites.map(function (site) {
return loadEntriesForSite(site);
});
// 全子ブログ分の一覧HTMLを結合して表示
Promise.all(promises).then(function (htmlArray) {
wrapper.innerHTML = htmlArray.join('');
});
})
.catch(function (err) {
console.error(err);
wrapper.innerHTML = '<p>ブログ情報を取得できませんでした。</p>';
});
// 2. 各子ブログの「記事一覧」を Data API から取得して HTML 文字列を返す関数
function loadEntriesForSite(site) {
// ★ ここで entries を取っている(ブログ記事)
// カスタムコンテンツの場合は /contents に後で差し替えできます。
const url = DATA_API_BASE +
'/sites/' + encodeURIComponent(site.id) +
'/entries?limit=10&sortBy=authored_on&sortOrder=desc';
return fetch(url)
.then(function (res) {
if (!res.ok) throw new Error('entries HTTP Error ' + res.status);
return res.json();
})
.then(function (json) {
if (json.error) {
console.error('site ' + site.id + ':', json.error);
// エラーのサイトは飛ばして空文字を返す
return '';
}
const items = json.items || [];
// 各子ブログごとのブロック
let html = '<section class="child-blog-section">';
// 子ブログ名&リンク(blogUrl があれば使う)
const siteName = escapeHtml(site.name);
const siteUrl = site.url ? site.url : '';
if (siteUrl) {
html += '<h2><a href="' + siteUrl + '">' + siteName + '</a></h2>';
} else {
html += '<h2>' + siteName + '</h2>';
}
if (!items.length) {
html += '<p>記事はありません。</p></section>';
return html;
}
html += '<ul>';
items.forEach(function (item) {
// item.title / item.permalink / item.date などが使えます
const title = escapeHtml(item.title);
const link = item.permalink || '#';
const date = item.date ? item.date.substr(0, 10) : '';
html += '<li><a href="' + link + '">' + title + '</a>';
if (date) {
html += ' <span>(' + date + ')</span>';
}
html += '</li>';
});
html += '</ul></section>';
return html;
})
.catch(function (err) {
console.error('site ' + site.id + ':', err);
// エラーがあったサイトもとりあえずセクションだけ出す
let html = '<section class="child-blog-section">';
html += '<h2>' + escapeHtml(site.name) + '</h2>';
html += '<p>記事一覧を読み込めませんでした。</p></section>';
return html;
});
}
})();
</script>
</body>
</html>
🔁 カスタムコンテンツ(コンテンツタイプ)の場合
もし「記事」ではなく コンテンツタイプ(例:class_list や求人) を出したい場合は、
上のコードの loadEntriesForSite の中だけ 次のように変えてください。
function loadEntriesForSite(site) {
// ★ コンテンツタイプ名を指定(識別子)
const contentType = 'class_list'; // ここを実際のコンテンツタイプIDに変更
const url = DATA_API_BASE +
'/sites/' + encodeURIComponent(site.id) +
'/contentTypes/' + encodeURIComponent(contentType) +
'/contents?limit=10&sortBy=authored_on&sortOrder=desc';
return fetch(url)
.then(function (res) {
if (!res.ok) throw new Error('contents HTTP Error ' + res.status);
return res.json();
})
.then(function (json) {
if (json.error) {
console.error('site ' + site.id + ':', json.error);
return '';
}
const items = json.items || [];
let html = '<section class="child-blog-section">';
const siteName = escapeHtml(site.name);
const siteUrl = site.url ? site.url : '';
if (siteUrl) {
html += '<h2><a href="' + siteUrl + '">' + siteName + '</a></h2>';
} else {
html += '<h2>' + siteName + '</h2>';
}
if (!items.length) {
html += '<p>コンテンツはありません。</p></section>';
return html;
}
html += '<ul>';
items.forEach(function (item) {
// コンテンツのタイトルは item.label or item.title
const title = escapeHtml(item.label || item.title || '');
const link = item.permalink || '#';
html += '<li><a href="' + link + '">' + title + '</a></li>';
});
html += '</ul></section>';
return html;
})
.catch(function (err) {
console.error('site ' + site.id + ':', err);
let html = '<section class="child-blog-section">';
html += '<h2>' + escapeHtml(site.name) + '</h2>';
html += '<p>コンテンツ一覧を読み込めませんでした。</p></section>';
return html;
});
}
🎯 これでできること
- 親サイト1ページだけで
👉 配下の子ブログを全部自動取得
👉 各子ブログごとに「見出し+最新10件一覧」を表示 - 子ブログを追加・削除しても、
👉 親サイトのテンプレートは一切いじらなくてOK - すべて JS+JSON(Data API)経由 なので、
👉include_sitesやGetVarの制限を回避できます
結論から言うと、
• 「親サイト側の URL で、子サイトの記事の“詳細ページ”を MT の機能だけ(静的再構築だけ)で出す」はほぼ無理 ❌
• ただし、
• 子サイトで詳細ページを普通に作っておいて、親サイトからリンクする ✅
• もしくは 親サイトに 1 枚だけ「詳細用ページ」を作り、JS+Data API(JSON)で子サイトの記事を読み込んで表示する ✅
というやり方なら、**「見た目上は親サイトで子サイト詳細を表示」**ができます。
あなたが前から言っている **「js経由で json」**の方が現実解です。
⸻
- なぜ MT だけで「親URLの詳細」を作れないか
MT は基本的に、
• 「そのブログ(サイト)のデータだけ」を使って
• 「そのブログのテンプレート」で
• 「静的にファイルを再構築」
します。
みたいに
テンプレ内で複数ブログの記事を“参照”することはできますが、
「親サイトのアーカイブ用テンプレートから、子ブログの記事ごとの詳細 HTML を量産する」
ということはできません。
アーカイブファイルが作られるのは そのブログ自身のエントリー/コンテンツだけ です。
なので、
• 「/parent/detail/123.html は子ブログAの記事」
• 「/parent/detail/456.html は子ブログBの記事」
みたいな 静的ファイルを、親サイトだけで自動生成するのは NG になります。
⸻
- 現実解:親サイトに「詳細ページ用テンプレ」を1枚作って、JS+Data API で表示
URLイメージ
親サイトにこんな URL を用意するとします:
• site_id…子ブログの ID
• entry_id…その子ブログの記事 ID
これを元に、JS で Data API から詳細データを取ってきて、親サイトの HTML に流し込みます。
⸻
- 親サイト側のテンプレ(ブログ記事の詳細を出す版)
親サイトにインデックステンプレートかウェブページテンプレートを 1つ作って、
中身を丸ごとこれにしてください。
使い方
• 子ブログ側の一覧や、親サイトの一覧から
detail.html?site_id=3&entry_id=10 のようなリンクを張る
• そうすると、親サイトの detail.html が Data API で子ブログのエントリーを取って来て表示します
⸻
- コンテンツタイプ(mt:Contents)の詳細を出したい場合
医師データ・class_list・求人など、コンテンツタイプの詳細を親サイトで表示したい場合は:
URL例:
detail.html?site_id=3&ct_id=2&content_id=15
テンプレの JS 部分だけ、こんな感じに差し替えます。
フィールド名(title, body など)は、
実際のコンテンツタイプのフィールドIDに合わせて書き換えてください。
⸻
- まとめ
• MTの再構築だけで「親サイトのURLで子サイト詳細ページを量産」は不可
• アーカイブは「そのサイト自身のデータ」しか対象にできないため
• 代わりに:
• 子サイトで普通に詳細を作って、親サイトからリンク → 一番素直
• もしくは 親サイトに「詳細用ページ」を 1 枚だけ作って、
URLパラメータ(site_id / entry_id / content_id)+ JS+Data API で中身を差し替える
⸻
結論から言うと、
• 「親サイト側の URL で、子サイトの記事の“詳細ページ”を MT の機能だけ(静的再構築だけ)で出す」はほぼ無理 ❌
• ただし、
• 子サイトで詳細ページを普通に作っておいて、親サイトからリンクする ✅
• もしくは 親サイトに 1 枚だけ「詳細用ページ」を作り、JS+Data API(JSON)で子サイトの記事を読み込んで表示する ✅
というやり方なら、**「見た目上は親サイトで子サイト詳細を表示」**ができます。
あなたが前から言っている **「js経由で json」**の方が現実解です。
⸻
- なぜ MT だけで「親URLの詳細」を作れないか
MT は基本的に、
• 「そのブログ(サイト)のデータだけ」を使って
• 「そのブログのテンプレート」で
• 「静的にファイルを再構築」
します。
みたいに
テンプレ内で複数ブログの記事を“参照”することはできますが、
「親サイトのアーカイブ用テンプレートから、子ブログの記事ごとの詳細 HTML を量産する」
ということはできません。
アーカイブファイルが作られるのは そのブログ自身のエントリー/コンテンツだけ です。
なので、
• 「/parent/detail/123.html は子ブログAの記事」
• 「/parent/detail/456.html は子ブログBの記事」
みたいな 静的ファイルを、親サイトだけで自動生成するのは NG になります。
⸻
- 現実解:親サイトに「詳細ページ用テンプレ」を1枚作って、JS+Data API で表示
URLイメージ
親サイトにこんな URL を用意するとします:
• site_id…子ブログの ID
• entry_id…その子ブログの記事 ID
これを元に、JS で Data API から詳細データを取ってきて、親サイトの HTML に流し込みます。
⸻
- 親サイト側のテンプレ(ブログ記事の詳細を出す版)
親サイトにインデックステンプレートかウェブページテンプレートを 1つ作って、
中身を丸ごとこれにしてください。
使い方
• 子ブログ側の一覧や、親サイトの一覧から
detail.html?site_id=3&entry_id=10 のようなリンクを張る
• そうすると、親サイトの detail.html が Data API で子ブログのエントリーを取って来て表示します
⸻
- コンテンツタイプ(mt:Contents)の詳細を出したい場合
医師データ・class_list・求人など、コンテンツタイプの詳細を親サイトで表示したい場合は:
URL例:
detail.html?site_id=3&ct_id=2&content_id=15
テンプレの JS 部分だけ、こんな感じに差し替えます。
フィールド名(title, body など)は、
実際のコンテンツタイプのフィールドIDに合わせて書き換えてください。
⸻
- まとめ
• MTの再構築だけで「親サイトのURLで子サイト詳細ページを量産」は不可
• アーカイブは「そのサイト自身のデータ」しか対象にできないため
• 代わりに:
• 子サイトで普通に詳細を作って、親サイトからリンク → 一番素直
• もしくは 親サイトに「詳細用ページ」を 1 枚だけ作って、
URLパラメータ(site_id / entry_id / content_id)+ JS+Data API で中身を差し替える
⸻
結論から言うと、
• 「親サイト側の URL で、子サイトの記事の“詳細ページ”を MT の機能だけ(静的再構築だけ)で出す」はほぼ無理 ❌
• ただし、
• 子サイトで詳細ページを普通に作っておいて、親サイトからリンクする ✅
• もしくは 親サイトに 1 枚だけ「詳細用ページ」を作り、JS+Data API(JSON)で子サイトの記事を読み込んで表示する ✅
というやり方なら、**「見た目上は親サイトで子サイト詳細を表示」**ができます。
あなたが前から言っている **「js経由で json」**の方が現実解です。
⸻
- なぜ MT だけで「親URLの詳細」を作れないか
MT は基本的に、
• 「そのブログ(サイト)のデータだけ」を使って
• 「そのブログのテンプレート」で
• 「静的にファイルを再構築」
します。
みたいに
テンプレ内で複数ブログの記事を“参照”することはできますが、
「親サイトのアーカイブ用テンプレートから、子ブログの記事ごとの詳細 HTML を量産する」
ということはできません。
アーカイブファイルが作られるのは そのブログ自身のエントリー/コンテンツだけ です。
なので、
• 「/parent/detail/123.html は子ブログAの記事」
• 「/parent/detail/456.html は子ブログBの記事」
みたいな 静的ファイルを、親サイトだけで自動生成するのは NG になります。
⸻
- 現実解:親サイトに「詳細ページ用テンプレ」を1枚作って、JS+Data API で表示
URLイメージ
親サイトにこんな URL を用意するとします:
• site_id…子ブログの ID
• entry_id…その子ブログの記事 ID
これを元に、JS で Data API から詳細データを取ってきて、親サイトの HTML に流し込みます。
⸻
- 親サイト側のテンプレ(ブログ記事の詳細を出す版)
親サイトにインデックステンプレートかウェブページテンプレートを 1つ作って、
中身を丸ごとこれにしてください。
使い方
• 子ブログ側の一覧や、親サイトの一覧から
detail.html?site_id=3&entry_id=10 のようなリンクを張る
• そうすると、親サイトの detail.html が Data API で子ブログのエントリーを取って来て表示します
⸻
- コンテンツタイプ(mt:Contents)の詳細を出したい場合
医師データ・class_list・求人など、コンテンツタイプの詳細を親サイトで表示したい場合は:
URL例:
detail.html?site_id=3&ct_id=2&content_id=15
テンプレの JS 部分だけ、こんな感じに差し替えます。
フィールド名(title, body など)は、
実際のコンテンツタイプのフィールドIDに合わせて書き換えてください。
⸻
- まとめ
• MTの再構築だけで「親サイトのURLで子サイト詳細ページを量産」は不可
• アーカイブは「そのサイト自身のデータ」しか対象にできないため
• 代わりに:
• 子サイトで普通に詳細を作って、親サイトからリンク → 一番素直
• もしくは 親サイトに「詳細用ページ」を 1 枚だけ作って、
URLパラメータ(site_id / entry_id / content_id)+ JS+Data API で中身を差し替える
⸻
うん、「一覧から親サイト側の詳細ページ用URLを自動生成する」は MT の機能だけでできます 👍
JS は「詳細画面の中身を取ってくるとき」にだけ使って、
「一覧からのリンク」は MT のタグで組み立てればOKです。
⸻
① 親サイトに「一覧ページ」がある場合(ChildSites + Entries)
親サイト側で子ブログの記事一覧を出していて、
そこから 親サイトの detail.html に飛ばしたい 例です。
イメージURL
親サイトの詳細URL: /detail.html?site_id=子ブログID&entry_id=記事ID
親サイトの一覧テンプレ例(インデックス/ウェブページ)
子ブログの記事一覧(親サイト)
<$mt:BlogURL$>detail.html
<$mt:SiteName$>
<mt:Entries lastn="10">
<mt:EntriesHeader><ul></mt:EntriesHeader>
<li>
<a href="<$mt:Var name='detail_base'$>?site_id=<$mt:BlogID$>&entry_id=<$mt:EntryID$>">
<$mt:EntryTitle$>
</a>
(<$mt:EntryDate format="%Y-%m-%d"$>)
</li>
<mt:EntriesFooter></ul></mt:EntriesFooter>
</mt:Entries>
ポイント
• detail_base に 親サイトの detail.html のURL をセット
→ <$mt:BlogURL$>detail.html
• mt:ChildSites の中で
• <$mt:BlogID$> … その子ブログのID(→ site_id に使う)
• <$mt:EntryID$> … 記事ID(→ entry_id に使う)
• これで 各記事ごとに自動でクエリ付きURLが生成されます。
あとは、前に書いた 親サイト側 detail.html の JS が
site_id と entry_id を受け取って Data API から本文を取得して表示、という流れになります。
⸻
② 一覧が「子ブログ側」にあって、親サイトの詳細に飛ばしたい場合
子ブログの記事一覧テンプレ(アーカイブ/インデックスなど)から、
親サイト detail.html に飛ばしたいときも同じです。
子ブログ側テンプレ
https://example.com/parent/detail.html
• 親サイトのURLが決まっているなら、detail_base は直書きでOKです。
⸻
③ コンテンツタイプ(Contents)の場合
医師データ/class_list/求人など、コンテンツタイプの詳細を親サイトで表示する場合は、
クエリに ct_id と content_id を追加すればOKです。
URLイメージ
/detail.html?site_id=3&ct_id=class_list&content_id=15
親サイトの一覧が の場合
<$mt:BlogURL$>detail.html
<$mt:SiteName$>
<mt:Contents content_type="class_list">
<mt:ContentsHeader><ul></mt:ContentsHeader>
<li>
<a href="<$mt:Var name='detail_base'$>?site_id=<$mt:BlogID$>&ct_id=class_list&content_id=<$mt:ContentID$>">
<$mt:ContentField name="title"$>
</a>
</li>
<mt:ContentsFooter></ul></mt:ContentsFooter>
</mt:Contents>
• ct_id=class_list の部分は、JS 側で Data API を叩くときに使う値に合わせてください
(数値IDでも識別子でもOK)
⸻
④ まとめ
• ✅ 一覧から親サイト側の詳細URL(?site_id=…&entry_id=… 等)は MT のタグだけで自動生成できる
• BlogURL + BlogID + EntryID / ContentID を組み合わせるだけ
• ✅ JS が必要なのは 詳細ページの中身を Data API で取る部分だけ
• ✅ 一覧側は完全に静的MTテンプレートでOK
⸻
結論から言うと、
• 「親サイト側の URL で、子サイトの記事の“詳細ページ”を MT の機能だけ(静的再構築だけ)で出す」はほぼ無理 ❌
• ただし、
• 子サイトで詳細ページを普通に作っておいて、親サイトからリンクする ✅
• もしくは 親サイトに 1 枚だけ「詳細用ページ」を作り、JS+Data API(JSON)で子サイトの記事を読み込んで表示する ✅
というやり方なら、**「見た目上は親サイトで子サイト詳細を表示」**ができます。
あなたが前から言っている **「js経由で json」**の方が現実解です。
⸻
- なぜ MT だけで「親URLの詳細」を作れないか
MT は基本的に、
• 「そのブログ(サイト)のデータだけ」を使って
• 「そのブログのテンプレート」で
• 「静的にファイルを再構築」
します。
みたいに
テンプレ内で複数ブログの記事を“参照”することはできますが、
「親サイトのアーカイブ用テンプレートから、子ブログの記事ごとの詳細 HTML を量産する」
ということはできません。
アーカイブファイルが作られるのは そのブログ自身のエントリー/コンテンツだけ です。
なので、
• 「/parent/detail/123.html は子ブログAの記事」
• 「/parent/detail/456.html は子ブログBの記事」
みたいな 静的ファイルを、親サイトだけで自動生成するのは NG になります。
⸻
- 現実解:親サイトに「詳細ページ用テンプレ」を1枚作って、JS+Data API で表示
URLイメージ
親サイトにこんな URL を用意するとします:
• site_id…子ブログの ID
• entry_id…その子ブログの記事 ID
これを元に、JS で Data API から詳細データを取ってきて、親サイトの HTML に流し込みます。
⸻
- 親サイト側のテンプレ(ブログ記事の詳細を出す版)
親サイトにインデックステンプレートかウェブページテンプレートを 1つ作って、
中身を丸ごとこれにしてください。
使い方
• 子ブログ側の一覧や、親サイトの一覧から
detail.html?site_id=3&entry_id=10 のようなリンクを張る
• そうすると、親サイトの detail.html が Data API で子ブログのエントリーを取って来て表示します
⸻
- コンテンツタイプ(mt:Contents)の詳細を出したい場合
医師データ・class_list・求人など、コンテンツタイプの詳細を親サイトで表示したい場合は:
URL例:
detail.html?site_id=3&ct_id=2&content_id=15
テンプレの JS 部分だけ、こんな感じに差し替えます。
<script>
(function () {
const DATA_API_BASE = '<$MTCGIPath encode_js="1"$><$MTDataAPIScript encode_js="1"$>/v6';
const params = new URLSearchParams(location.search);
const siteId = params.get('site_id');
const ctId = params.get('ct_id'); // コンテンツタイプID(数値 or 識別子)
const contentId = params.get('content_id'); // コンテンツID
const container = document.getElementById('post-detail');
if (!siteId || !ctId || !contentId) {
container.innerHTML = '<p>site_id / ct_id / content_id が足りません。</p>';
return;
}
const url = DATA_API_BASE +
'/sites/' + encodeURIComponent(siteId) +
'/contentTypes/' + encodeURIComponent(ctId) +
'/contents/' + encodeURIComponent(contentId);
function escapeHtml(str) {
return String(str || '')
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
fetch(url)
.then(res => {
if (!res.ok) throw new Error('HTTP Error ' + res.status);
return res.json();
})
.then(json => {
if (json.error) throw new Error(json.error.message || 'Data API エラー');
const item = json;
// 例:title フィールドと body フィールドを使う想定
const title = escapeHtml(item.label || (item.fields && item.fields.title));
const body = (item.fields && item.fields.body) || '';
let html = '';
html += '<h1>' + title + '</h1>';
html += '<div class="post-body">' + body + '</div>';
container.innerHTML = html;
})
.catch(err => {
console.error(err);
container.innerHTML = '<p>詳細を読み込めませんでした。</p>';
});
})();
</script>
フィールド名(title, body など)は、
実際のコンテンツタイプのフィールドIDに合わせて書き換えてください。
⸻
- まとめ
• MTの再構築だけで「親サイトのURLで子サイト詳細ページを量産」は不可
• アーカイブは「そのサイト自身のデータ」しか対象にできないため
• 代わりに:
• 子サイトで普通に詳細を作って、親サイトからリンク → 一番素直
• もしくは 親サイトに「詳細用ページ」を 1 枚だけ作って、
URLパラメータ(site_id / entry_id / content_id)+ JS+Data API で中身を差し替える
⸻
OK!
「Entries(記事)」版で、“親サイト一覧 → 親サイト詳細(中身は子ブログの記事)」の一連セット を、コピペで試せる形で作ってみますね。
⸻
前提イメージ
• 親サイト(Website)…parent
• 一覧ページ:/parent/list.html
• 詳細ページ:/parent/detail.html
• 子ブログA, 子ブログB … 親サイト配下のブログ
• 子ブログの記事を「親サイトのURL」で見せたい
→ 一覧ページから detail.html?site_id=○&entry_id=△ へリンク
→ detail.html 側で JS + Data API で本文を取ってくる
⸻
① 親サイト:記事一覧テンプレ(list.html)
親サイトに「インデックステンプレート」か「ウェブページテンプレート」を作って、
出力ファイル名を list.html にして、中身をこれにします。
子ブログの記事一覧(親サイト)
<$mt:BlogURL$>detail.html
<$mt:SiteName$>
<mt:Entries lastn="10">
<mt:EntriesHeader><ul></mt:EntriesHeader>
<li>
<a href="<$mt:Var name='detail_base'$>?site_id=<$mt:BlogID$>&entry_id=<$mt:EntryID$>">
<$mt:EntryTitle$>
</a>
(<$mt:EntryDate format="%Y-%m-%d"$>)
</li>
<mt:EntriesFooter></ul></mt:EntriesFooter>
</mt:Entries>
ここでやっていること
• mt:ChildSites … 親サイト配下の子ブログをループ
• ループ内で mt:Entries … その子ブログの記事一覧(最新10件)
• リンクURL:
<a href="<$mt:Var name='detail_base'$>?site_id=<$mt:BlogID$>&entry_id=<$mt:EntryID$>">
• detail_base … 親サイトの detail.html のURL(BlogURL + "detail.html")
• BlogID … その子ブログのID → site_id として渡す
• EntryID … 記事ID → entry_id として渡す
→ 記事・ブログが増えても全部自動でURLが生成されます。
⸻
② 親サイト:詳細テンプレ(detail.html)
同じ親サイトに、もうひとつテンプレートを作って、
出力ファイル名を detail.html にします。
中身をこれにします。
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>記事詳細</title>
<style>
body { font-family: sans-serif; }
.post-detail { max-width: 800px; margin: 2rem auto; }
.post-detail h1 { font-size: 1.6rem; margin-bottom: .5rem; }
.post-meta { color: #666; font-size: .9rem; margin-bottom: 1rem; }
.post-body { line-height: 1.8; }
</style>
</head>
<body>
<div class="post-detail" id="post-detail">
読み込み中…
</div>
<script>
(function () {
// ★ MT Data API のベースURL(/v6 まで含める)
const DATA_API_BASE = '<$MTCGIPath encode_js="1"$><$MTDataAPIScript encode_js="1"$>/v6';
// URLクエリから site_id と entry_id を取得
const params = new URLSearchParams(location.search);
const siteId = params.get('site_id');
const entryId = params.get('entry_id');
const container = document.getElementById('post-detail');
if (!siteId || !entryId) {
container.innerHTML = '<p>site_id と entry_id が指定されていません。</p>';
return;
}
// 単一エントリ取得用の Data API エンドポイント
const url = DATA_API_BASE +
'/sites/' + encodeURIComponent(siteId) +
'/entries/' + encodeURIComponent(entryId);
function escapeHtml(str) {
return String(str || '')
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
fetch(url)
.then(function (res) {
if (!res.ok) throw new Error('HTTP Error ' + res.status);
return res.json();
})
.then(function (json) {
if (json.error) throw new Error(json.error.message || 'Data API エラー');
const item = json; // 単一の記事データ
const title = escapeHtml(item.title);
const date = item.date ? item.date.substr(0, 10) : '';
const body = item.body || item.text || '';
let html = '';
html += '<h1>' + title + '</h1>';
if (date) {
html += '<div class="post-meta">投稿日:' + date + '</div>';
}
html += '<div class="post-body">' + body + '</div>';
container.innerHTML = html;
})
.catch(function (err) {
console.error(err);
container.innerHTML = '<p>記事詳細を読み込めませんでした。</p>';
});
})();
</script>
</body>
</html>
ポイント
• detail.html?site_id=3&entry_id=10 のようにアクセスされる前提
• JS が site_id と entry_id を読み取って、
/v6/sites/{site_id}/entries/{entry_id} を Data API で叩く
• 返ってきた item.title, item.date, item.body を HTML に埋め込む
⸻
③(おまけ)子ブログ側の一覧から親サイト詳細へ飛ばす場合
もし、子ブログ側にも通常の一覧(サイドバー、アーカイブなど)があって、
そこから親サイトの detail.html に飛ばしたい場合は、
子ブログ側テンプレにこう書けばOKです。
<mt:SetVarBlock name="parent_detail_base">
https://example.com/parent/detail.html
</mt:SetVarBlock>
<mt:Entries>
<li>
<a href="<$mt:Var name='parent_detail_base'$>?site_id=<$mt:BlogID$>&entry_id=<$mt:EntryID$>">
<$mt:EntryTitle$>
</a>
</li>
</mt:Entries>
• https://example.com/parent/detail.html の部分は実際の親サイトURLに変更
• これで、子ブログからも 親サイトのURLで詳細を表示 できるようになります。
⸻
④ ざっくり流れの確認
1. 親の list.html を開く
→ 子ブログごとの記事一覧が出る
→ 各行のリンクが detail.html?site_id=○&entry_id=△
2. そのリンクをクリック
→ 親の detail.html に遷移
→ JS が Data API から子ブログの記事を取得して詳細表示
⸻