記事一覧のデータをJSONファイルで管理する

ブログ記事一覧のページは今までHTMLベタ打ちで更新していました。

<li class="list_item" data-category="gadget" data-tag='["レビュー"]'>
  <span class="Gadget">Gadget</span>
  <a href="https://miscnote.com/blog/20240814-entry-01/">GameSir Nova Liteを買いました</a>
  <span class="pr color_red">NEW</span>
  <time class="date">2024-08-14</time>
</li>

このような形の部分をコピーして修正するだけなので、簡単といえば簡単なのですが…

タイトルの前の「ラベル部分」もカテゴリに合わせて変更していたので、その修正が地味に大変…というか修正し忘れて間違えていることが時々ありました。

もう少し管理を楽にしようと思い、今回はこの「タイトル・カテゴリー・タグ・日付・URL」といったデータ部分をJSONファイルで管理できるようにしてみました。

ついでに、更新してから1ヶ月以内の記事にはNEWの文字を付けるようにしました(今まで手打ちで追加/削除してたので😅)

※今回も例によってchatGPTに提案・書いてもらったコードです。

外部ファイルの形式を決める

PHPファイルで読み込むデータ形式はいくつか候補がありました。

  • JSON: 最も一般的で、ほとんどの用途で十分。
  • XML: 階層的なデータを扱う場合に有用。
  • CSV: シンプルなテーブルデータや大量データに適している。
  • INI: 設定データなどの簡単なキー・バリューのペアに使用。
  • PHPファイル: PHPで直接データを使う場合に便利。

chatGPTはすごいですね! PHPでの使用方法や記述例までまとめてくれました。

ひと通り見た結果、一番シンプルで管理しやすそうだったJSONを採用しました。

CSVも悪くないかなと思ったのですが、今回の場合「タグ」にデータが1つ~複数入る形だったので、基本的に1つの項目に1つのデータを管理するCSVには不向きかなーと思い断念しました。

VScodeではCSVデータを編集するためのプラグインもあるみたいなので、別の機会に使ってみたいなと思います。

JSONファイルを作成

JSONファイル(blogs.json)はこのような形にしています。

{
  "_comment": "// ここにメモ書き //",

  "blogs": [
    {
      "category": "gadget",
      "tags": [
        "レビュー"
      ],
      "url": "https://miscnote.com/blog/20240814-entry-01/",
      "title": "GameSir Nova Liteを買いました",
      "date": "2024-08-14"
    },
    {
      "category": "other",
      "tags": [
        "サイト作成",
        "HTML"
      ],
      "url": "https://miscnote.com/blog/20240721-entry-03/",
      "title": "サーバー移行でデータベースが動かなくなった(解決済)",
      "date": "2024-07-21"
    },
  ・・・・・・・・
  ]
}

PHPファイルを修正

PHPファイルの方では、このような処理を追加しました。

コード(bodyタグより前)

// JSONファイルを読み込む
$jsonData = file_get_contents('blogs.json');
// JSONデータをPHPの配列に変換
$blogsData = json_decode($jsonData, true);
// エラーチェック
if (json_last_error() !== JSON_ERROR_NONE) {
  echo 'JSONデコードエラー: ' . json_last_error_msg();
  exit;
}
// _commentキーが存在する場合は削除(表示には使わない)
if (isset($blogsData['_comment'])) {
  unset($blogsData['_comment']);
}
// blogsキーのデータを取得
$blogs = isset($blogsData['blogs']) ? $blogsData['blogs'] : [];
// 現在の日付を取得
$currentDate = new DateTime();

コード(ulタグ部分)

<ul class="list">
  <?php foreach ($blogs as $blog): ?>
    <?php
    // 記事の日付をDateTimeオブジェクトに変換
    $blogDate = new DateTime($blog['date']);
    // 日付の差を計算
    $interval = $currentDate->diff($blogDate);
    // "New"ラベルを追加する条件(30日以内の場合)
    $isNew = $interval->days <= 30 && $blogDate <= $currentDate;

    // カテゴリと表示用ラベルの対応
    $categoryLabels = [
      'gadget' => 'Gadget',
      'other' => 'Other',
      'game' => 'Game'
    ];
    // タグとラベルの対応(ゲームカテゴリ用)
    $gameLabels = [
      'Minecraft' => 'Minecraft',
      'メガクアリウム' => 'Megaquarium'
    ];
    // カテゴリに応じたラベルを決定
    if ($blog['category'] === 'game') {
      // タグに基づいて特定のラベルを設定(ゲームカテゴリ専用)
      $categoryLabel = $categoryLabels[$blog['category']]; // デフォルトは "Game"
      foreach ($blog['tags'] as $tag) {
        if (isset($gameLabels[$tag])) {
          $categoryLabel = $gameLabels[$tag];
          break;
        }
      }
    } else {
      // ゲームカテゴリ以外の通常ラベル
      $categoryLabel = isset($categoryLabels[$blog['category']]) ? $categoryLabels[$blog['category']] : '';
    }

    // タグをJSON形式でエンコード
    $dataTags = json_encode($blog['tags'], JSON_UNESCAPED_UNICODE);
    ?>
      <li class="list_item" data-category="<?php echo $blog['category']; ?>" data-tag='<?php echo $dataTags; ?>'>
        <span class="<?php echo $categoryLabel; ?>"><?php echo $categoryLabel; ?></span>
        <a href="<?php echo $blog['url']; ?>"><?php echo htmlspecialchars($blog['title']); ?></a>
        <?php if ($isNew): ?>
          <span class="pr color_red">NEW</span>
        <?php endif; ?>
        <time class="date"><?php echo $blog['date']; ?></time>
      </li>
  <?php endforeach; ?>
</ul>

カテゴリーは「Gadget・Other・Game」の3つなのですが、そのうちGameカテゴリで「Minecraft・メガクアリウム」タグがある記事だけ、専用のラベルが表示されるようにしています。

Gameカテゴリ内の専用ラベルが増える処理は、行を追加するだけなので簡単に実装できます。

今のところGameカテゴリの中の2つだけですが、GadgetやOtherの中でも専用ラベルが必要になったらコードを修正する予定です。

専用ラベルに専用CSSclassを当ててる設定になっているので、ラベルが増えていくと管理が大変になりそう… この辺りはもう少し簡潔にできそうな気がします。

JSONのコメント部分の処理

本当はJSONファイルではコメントアウトが出来ないのですが、_commentというキーを使い、PHPファイルの方で_commentを削除することでメモ書きとして利用できるようにしています。

HTMLのコメントアウトのように書けないかと思いchatGPTに代替案を求めたのですが、どれも大変そうだったので…(JSON5やJSONCなど) 一番シンプルそうなこの形を採用しました。必要なコメントも少しだけだったので。

// _commentキーが存在する場合は削除(表示には使わない)
if (isset($blogsData['_comment'])) {
  unset($blogsData['_comment']);
}

PHP側の_commentキー削除はこの部分で行っています。

…とここまで書いて、この部分は別に無くても動くのでは?と思ったのですが、chatGPTに聞いてみたところ、

この部分を削除しても表示には影響しませんが、データに不要な情報が含まれることになります。動作に影響はないものの、データのクリーンアップとしてこの部分も残しておいた方が良いでしょう。

とのことだったので、一応残しています。

【追記】ダミーデータの処理

この記事を書き終わって、さっそくJSONファイルに記事データを追加しようとしたのですが、前回のデータをコピー貼り付け・修正では修正漏れが起こりそうだったので、ダミーデータを書いておいて、それを修正する形にしてみました。

毎回入力する必要がある部分に「xxxxxxxx」と記載します。

{
  "category": "xxxxxxxx",
  "tags": [
    "xxxxxxxx"
  ],
  "url": "https://miscnote.com/blog/xxxxxxxx-entry-01/",
  "title": "xxxxxxxx",
  "date": "xxxxxxxx"
},

PHPの方で、

// カテゴリーが "xxxxxxxx" の場合、スキップ
if ($blog['category'] === 'xxxxxxxx') {
  continue;
}

という処理を <?php foreach ($blogs as $blog): ?> 内に追記しました。

最後に

JSONで管理→それに対応する形のPHPコードを作成までは簡単に出来たのですが、コメントアウトの部分で妙に時間を使ってしまいました。

今回は無理やりJSONファイルで対応しましたが、いずれJSON5やJSONCなども利用してみたいと思います。

関連記事
    新着記事
      ブログ内検索