WordPress:カテゴリー階層の保存場所

WordPress:カテゴリー階層の保存場所

当サイトのケースですが、カテゴリーについて深い理解がなく適当に増やし続けてきた上に、一記事に複数のカテゴリーを当ててしまっていました。現時点ではある程度は解消できていますが、その過程でカテゴリー階層のデータがこんなところに保存されているのかと驚きましたのでその話です。

01これまでの経緯

カテゴリーを整理しようと思いたったのは随分前ですが、やっと3ヶ月前くらいに重い腰を上げ(笑)、次の流れでやってきています。

整理する前は45項目のカテゴリーが階層なしで並ぶ状態でした。現在はそれらすべてをタグにコピーし、トップページではタグクラウドとして、各記事ページではサイドバーに残しています。

02カテゴリー整理は手作業しかない…

そのカテゴリーを数項目の親カテゴリーと一階層の子カテゴリーに分類しようということです。

で、できるだけ手作業を避けるためにプログラムで簡潔に整理できないかと考えたのですが、結論からいいますと無理です。そもそもブログですのでひとつの記事の中にはかなり多用な内容を含んでいます。それゆえに複数のカテゴリーに項目分けしたくなるわけで、たとえばよくサンプルで用いられる料理のカテゴリーのように肉料理、魚料理、野菜料理とか、日本料理、中国料理、イタリア料理などとはっきりした分類など不可能です。まあそれだって、肉料理でも多くは野菜を加えるわけですから同じことではありますが。

とにかく、現在(すでに過去ですが…)のカテゴリーから機械的に新しいカテゴリーに移行させるのはあきらめて、手作業でやるしかなさそうです。

それにしても親カテゴリーの項目名を考えることも大変です。結局、親カテゴリーは、過去のものにははてなブログ、そして今は WordPress の記事が多いということで、

  • WordPress
  • はてなブログ
  • プログラミング
  • ITインフラ
  • アプリケーション
  • Joomla!

の6つにし、それぞれ小カテゴリーを持つ設定でいこうと思います。Joomla! を親カテゴリーにしているのは今後 Joomla! の記事を増やしていこうと考えているからです。

下の画像が現在のカテゴリーメニューを表示したものです。

03カテゴリー関連データの保存データベース

作業は運用中のサイトをまるごとコピーし、作業用サイトで整理を完了させ、データーベースのみ運用サイトに移す方法でやってみます。すべてアナログ作業です(笑)。

  • 作業用サイトの管理画面で新しいカテゴリーを作成する
    子カテゴリーは一階層までとする
  • 一記事ずつ読み直してカテゴリーを移行させる
    (もう少し簡潔にやっていますが基本的にはそういうこと)
  • 記事が0になったカテゴリーを削除する

で、作業用サイトのカテゴリー整理が完了しました。

当然、これまで一階層のものをダラダラ(笑)と表示してきたわけですから表示方法も変更する必要があります。この記事の公開時にはすでに変わっていますが、これまではページの右上にフォルダアイコンをおいてクリックしますと下にすーと流れる方法をとってきましたが、現在表示されているものに変更しました。これを読んでいただいている時点では右上に4つのアイコンが見えると思います。それをページのトップに移動した場合は左右の中央に文字付きで移動するようにしてあります。

IntersectionObserver を使っています。これについてはまたあらためて書こうと思っています。

データベースを差し替える

カテゴリー関連のデータベースは別記事の「カテゴリーやタグ情報の保存のされ方」にも書いていますが、WordPress では、カテゴリーもタグもタクソノミーとして管理されており、データとしての保存方法は同じです。次の3つのテーブルがタクソノミーに関連しているものです。

  • wp_terms は、カテゴリーやタグの項目の保存
  • wp_term_taxonomy は、カテゴリー(category)かタグ(post_tag)かの保存
  • wp_term_relationships は、記事とカテゴリーやタグとの関連性の保存

に使われています。たとえば、新しくカテゴリーを追加しますと、その項目名は wp_terms に保存され、それがカテゴリーであることは wp_term_taxonomy に保存され、記事 ID とタクソノミー ID(カテゴリーやタグ ID)の関連が wp_term_relationships に保存されるといった具合です。

ですので、新しく記事を追加していない前提ですが、この3つのテーブルを差し替えれば新しく整理したカテゴリー構造に変わるはずです(実は違う、次項で…)。仮に新しく記事を追加した後でもその記事のカテゴリーが存在していなければ未整理になるだけです。

データベースの差し替えは該当の3つのテーブルを差し替えるのであれば、作業用サイトのデータベースから該当のテーブルをエクスポートし、運用サイトの該当の3つのデータベースを削除した後にインポートします。厳密に言えばその瞬間10秒ほどはカテゴリーは表示されません。

または、データベースをまるごと作業用サイトのデータベースに差し替える方法もあります。これについては別記事の「手動で WordPress まるごとコピー」に詳しく書いていますが、WordPress のプログラムとデータベースの関係は、

  • ドメイン直下の wp-config.php 内のデータベース情報が正しいこと
  • データベースのテーブル wp-options のレコード siteurl, home に正しい URL が保存されていること

の2つでつながっています。

ですので、もし運用サイトをまるごとコピーした作業用サイトで作業をしたのであれば、

  • 作業用データベースのテーブル wp-options のレコード siteurl, home を運用サイトの URL に変更
  • 運用サイトの wp-config.php の define( ‘DB_NAME’, ‘データベース名’ ) を作業用サイトのデータベース名に変更

この2つの変更を行えば作業用サイトのデータベースが運用サイトとして使われます。

04カテゴリー階層の保存場所

前項でデータベースをまるごと差し替えた場合は、以上で問題なく整理したカテゴリーに差し替わります。しかし、3つのテーブルを差し替えた場合は、カテゴリーの階層状態、つまり何が親カテゴリーでその子カテゴリーが何かは差し替わりません。

カテゴリー階層は、テーブル wp_options のカラム option_name の category_children フィールドに JSON形式で保存されています。次の sql で表示されます。

SELECT * FROM `wp_options` WHERE option_name="category_children";

一切階層化していない場合の値は、

a:0:{}

となっており、階層化しますと、

a:6:{i:2;a:4:{i:0;i:3;i:1;i:4;i:2;i:39;i:3;i:99;}i:101;a:1:{i:0;i:6;}i:5;a:4:{i:0;i:7;i:1;i:18;i:2;i:20;i:3;i:36;}i:100;a:11:{i:0;i:8;i:1;i:12;i:2;i:17;i:3;i:21;i:4;i:24;i:5;i:30;i:6;i:32;i:7;i:35;i:8;i:37;i:9;i:103;i:10;i:104;}i:13;a:1:{i:0;i:14;}i:96;a:4:{i:0;i:25;i:1;i:97;i:2;i:98;i:3;i:102;}}

こんな値になります。

  • a は項目数
  • i は並び順(0 からの連番)とカテゴリーID のセット

ということらしく、JSON形式を整形しますと次のようになります。なお JSON にはコメントは書けませんので次の // はここだけの便宜上のものです。

a:6:{ // 項目数
	i:2; // カテゴリーID
	a:4:{ // 項目数
		i:0;i:3; // 連番とカテゴリID(以下同様)
		i:1;i:4;
		i:2;i:39;
		i:3;i:99;
	}
	i:101; // カテゴリーID
	a:1:{ // 項目数
		i:0;i:6;
	}
以下、略

という構造になっているようです。また、連番は表示順とは関係がありません。ここらあたりはコードを読まないとわかりません。

いずれにしてもこれでやっとカテゴリーの整理ができました。といいつつも、まだ子カテゴリーへの分類がすんでおらず親カテゴリに数多くたまったままです。