0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

子ブログの一覧

0
Last updated at Posted at 2025-12-02

子ブログ毎の記事一覧を親サイトに表示したい
子ブログの可変に合わせて一覧ページを出したい

「子ブログの記事一覧を親サイトに出す」+「子ブログは増減してもテンプレは触りたくない」
→ 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, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;')
      .replace(/'/g, '&#39;');
  }

  // 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_sitesGetVar の制限を回避できます

結論から言うと、
• 「親サイト側の URL で、子サイトの記事の“詳細ページ”を MT の機能だけ(静的再構築だけ)で出す」はほぼ無理 ❌
• ただし、
• 子サイトで詳細ページを普通に作っておいて、親サイトからリンクする ✅
• もしくは 親サイトに 1 枚だけ「詳細用ページ」を作り、JS+Data API(JSON)で子サイトの記事を読み込んで表示する ✅

というやり方なら、**「見た目上は親サイトで子サイト詳細を表示」**ができます。
あなたが前から言っている **「js経由で json」**の方が現実解です。

  1. なぜ MT だけで「親URLの詳細」を作れないか

MT は基本的に、
• 「そのブログ(サイト)のデータだけ」を使って
• 「そのブログのテンプレート」で
• 「静的にファイルを再構築」

します。

みたいに
テンプレ内で複数ブログの記事を“参照”することはできますが、

「親サイトのアーカイブ用テンプレートから、子ブログの記事ごとの詳細 HTML を量産する」

ということはできません。
アーカイブファイルが作られるのは そのブログ自身のエントリー/コンテンツだけ です。

なので、
• 「/parent/detail/123.html は子ブログAの記事」
• 「/parent/detail/456.html は子ブログBの記事」

みたいな 静的ファイルを、親サイトだけで自動生成するのは NG になります。

  1. 現実解:親サイトに「詳細ページ用テンプレ」を1枚作って、JS+Data API で表示

URLイメージ

親サイトにこんな URL を用意するとします:

•	site_id…子ブログの ID
•	entry_id…その子ブログの記事 ID

これを元に、JS で Data API から詳細データを取ってきて、親サイトの HTML に流し込みます。

  1. 親サイト側のテンプレ(ブログ記事の詳細を出す版)

親サイトにインデックステンプレートかウェブページテンプレートを 1つ作って、
中身を丸ごとこれにしてください。

記事詳細
読み込み中…

使い方
• 子ブログ側の一覧や、親サイトの一覧から
detail.html?site_id=3&entry_id=10 のようなリンクを張る
• そうすると、親サイトの detail.html が Data API で子ブログのエントリーを取って来て表示します

  1. コンテンツタイプ(mt:Contents)の詳細を出したい場合

医師データ・class_list・求人など、コンテンツタイプの詳細を親サイトで表示したい場合は:

URL例:

detail.html?site_id=3&ct_id=2&content_id=15

テンプレの JS 部分だけ、こんな感じに差し替えます。

フィールド名(title, body など)は、
実際のコンテンツタイプのフィールドIDに合わせて書き換えてください。

  1. まとめ
    • MTの再構築だけで「親サイトのURLで子サイト詳細ページを量産」は不可
    • アーカイブは「そのサイト自身のデータ」しか対象にできないため
    • 代わりに:
    • 子サイトで普通に詳細を作って、親サイトからリンク → 一番素直
    • もしくは 親サイトに「詳細用ページ」を 1 枚だけ作って、
    URLパラメータ(site_id / entry_id / content_id)+ JS+Data API で中身を差し替える

結論から言うと、
• 「親サイト側の URL で、子サイトの記事の“詳細ページ”を MT の機能だけ(静的再構築だけ)で出す」はほぼ無理 ❌
• ただし、
• 子サイトで詳細ページを普通に作っておいて、親サイトからリンクする ✅
• もしくは 親サイトに 1 枚だけ「詳細用ページ」を作り、JS+Data API(JSON)で子サイトの記事を読み込んで表示する ✅

というやり方なら、**「見た目上は親サイトで子サイト詳細を表示」**ができます。
あなたが前から言っている **「js経由で json」**の方が現実解です。

  1. なぜ MT だけで「親URLの詳細」を作れないか

MT は基本的に、
• 「そのブログ(サイト)のデータだけ」を使って
• 「そのブログのテンプレート」で
• 「静的にファイルを再構築」

します。

みたいに
テンプレ内で複数ブログの記事を“参照”することはできますが、

「親サイトのアーカイブ用テンプレートから、子ブログの記事ごとの詳細 HTML を量産する」

ということはできません。
アーカイブファイルが作られるのは そのブログ自身のエントリー/コンテンツだけ です。

なので、
• 「/parent/detail/123.html は子ブログAの記事」
• 「/parent/detail/456.html は子ブログBの記事」

みたいな 静的ファイルを、親サイトだけで自動生成するのは NG になります。

  1. 現実解:親サイトに「詳細ページ用テンプレ」を1枚作って、JS+Data API で表示

URLイメージ

親サイトにこんな URL を用意するとします:

•	site_id…子ブログの ID
•	entry_id…その子ブログの記事 ID

これを元に、JS で Data API から詳細データを取ってきて、親サイトの HTML に流し込みます。

  1. 親サイト側のテンプレ(ブログ記事の詳細を出す版)

親サイトにインデックステンプレートかウェブページテンプレートを 1つ作って、
中身を丸ごとこれにしてください。

記事詳細
読み込み中…

使い方
• 子ブログ側の一覧や、親サイトの一覧から
detail.html?site_id=3&entry_id=10 のようなリンクを張る
• そうすると、親サイトの detail.html が Data API で子ブログのエントリーを取って来て表示します

  1. コンテンツタイプ(mt:Contents)の詳細を出したい場合

医師データ・class_list・求人など、コンテンツタイプの詳細を親サイトで表示したい場合は:

URL例:

detail.html?site_id=3&ct_id=2&content_id=15

テンプレの JS 部分だけ、こんな感じに差し替えます。

フィールド名(title, body など)は、
実際のコンテンツタイプのフィールドIDに合わせて書き換えてください。

  1. まとめ
    • MTの再構築だけで「親サイトのURLで子サイト詳細ページを量産」は不可
    • アーカイブは「そのサイト自身のデータ」しか対象にできないため
    • 代わりに:
    • 子サイトで普通に詳細を作って、親サイトからリンク → 一番素直
    • もしくは 親サイトに「詳細用ページ」を 1 枚だけ作って、
    URLパラメータ(site_id / entry_id / content_id)+ JS+Data API で中身を差し替える

結論から言うと、
• 「親サイト側の URL で、子サイトの記事の“詳細ページ”を MT の機能だけ(静的再構築だけ)で出す」はほぼ無理 ❌
• ただし、
• 子サイトで詳細ページを普通に作っておいて、親サイトからリンクする ✅
• もしくは 親サイトに 1 枚だけ「詳細用ページ」を作り、JS+Data API(JSON)で子サイトの記事を読み込んで表示する ✅

というやり方なら、**「見た目上は親サイトで子サイト詳細を表示」**ができます。
あなたが前から言っている **「js経由で json」**の方が現実解です。

  1. なぜ MT だけで「親URLの詳細」を作れないか

MT は基本的に、
• 「そのブログ(サイト)のデータだけ」を使って
• 「そのブログのテンプレート」で
• 「静的にファイルを再構築」

します。

みたいに
テンプレ内で複数ブログの記事を“参照”することはできますが、

「親サイトのアーカイブ用テンプレートから、子ブログの記事ごとの詳細 HTML を量産する」

ということはできません。
アーカイブファイルが作られるのは そのブログ自身のエントリー/コンテンツだけ です。

なので、
• 「/parent/detail/123.html は子ブログAの記事」
• 「/parent/detail/456.html は子ブログBの記事」

みたいな 静的ファイルを、親サイトだけで自動生成するのは NG になります。

  1. 現実解:親サイトに「詳細ページ用テンプレ」を1枚作って、JS+Data API で表示

URLイメージ

親サイトにこんな URL を用意するとします:

•	site_id…子ブログの ID
•	entry_id…その子ブログの記事 ID

これを元に、JS で Data API から詳細データを取ってきて、親サイトの HTML に流し込みます。

  1. 親サイト側のテンプレ(ブログ記事の詳細を出す版)

親サイトにインデックステンプレートかウェブページテンプレートを 1つ作って、
中身を丸ごとこれにしてください。

記事詳細
読み込み中…

使い方
• 子ブログ側の一覧や、親サイトの一覧から
detail.html?site_id=3&entry_id=10 のようなリンクを張る
• そうすると、親サイトの detail.html が Data API で子ブログのエントリーを取って来て表示します

  1. コンテンツタイプ(mt:Contents)の詳細を出したい場合

医師データ・class_list・求人など、コンテンツタイプの詳細を親サイトで表示したい場合は:

URL例:

detail.html?site_id=3&ct_id=2&content_id=15

テンプレの JS 部分だけ、こんな感じに差し替えます。

フィールド名(title, body など)は、
実際のコンテンツタイプのフィールドIDに合わせて書き換えてください。

  1. まとめ
    • 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:ChildSites

<$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

mt:Entries

<$mt:EntryTitle$>
•	親サイトの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:ChildSites

<$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」**の方が現実解です。

  1. なぜ MT だけで「親URLの詳細」を作れないか

MT は基本的に、
• 「そのブログ(サイト)のデータだけ」を使って
• 「そのブログのテンプレート」で
• 「静的にファイルを再構築」

します。

みたいに
テンプレ内で複数ブログの記事を“参照”することはできますが、

「親サイトのアーカイブ用テンプレートから、子ブログの記事ごとの詳細 HTML を量産する」

ということはできません。
アーカイブファイルが作られるのは そのブログ自身のエントリー/コンテンツだけ です。

なので、
• 「/parent/detail/123.html は子ブログAの記事」
• 「/parent/detail/456.html は子ブログBの記事」

みたいな 静的ファイルを、親サイトだけで自動生成するのは NG になります。

  1. 現実解:親サイトに「詳細ページ用テンプレ」を1枚作って、JS+Data API で表示

URLイメージ

親サイトにこんな URL を用意するとします:

•	site_id…子ブログの ID
•	entry_id…その子ブログの記事 ID

これを元に、JS で Data API から詳細データを取ってきて、親サイトの HTML に流し込みます。

  1. 親サイト側のテンプレ(ブログ記事の詳細を出す版)

親サイトにインデックステンプレートかウェブページテンプレートを 1つ作って、
中身を丸ごとこれにしてください。

記事詳細
読み込み中…

使い方
• 子ブログ側の一覧や、親サイトの一覧から
detail.html?site_id=3&entry_id=10 のようなリンクを張る
• そうすると、親サイトの detail.html が Data API で子ブログのエントリーを取って来て表示します

  1. コンテンツタイプ(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, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;')
      .replace(/'/g, '&#39;');
  }

  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に合わせて書き換えてください。

  1. まとめ
    • 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:ChildSites

<$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, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;')
      .replace(/'/g, '&#39;');
  }

  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 から子ブログの記事を取得して詳細表示

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?