WordPress:データベースをphpMyAdminで操作する

WordPress:データベースをphpMyAdminで操作する

この記事の内容は原理的なことをのぞけばあまり役に立つことはないと思います(笑)。ここ2回ほど WordPress のカテゴリーをタグにコピーする方法を記事にしていますが、それを直接データベース上でやってしまおうというものです。ですのでデータベースの扱い方では役に立つことがあるかもしれません。

01タクソノミー関連のデータベース

カテゴリーの一括コピーに興味のある方は、この記事の前にまず前々回の「WordPress:カテゴリーをタグにコピーして整理する」を読んでいただいたほうがいいかと思います。また、実際にカテゴリーをタグにコピーしたいと考えている方はコピーするプラグインがあります。「WordPress:カテゴリーをタグにコピーするプラグイン」をご覧ください。

WordPress ではカテゴリーもタグもタクソノミーとして管理されています。また、分類項目を自作するカスタムタクソノミーも同じ扱いになっています。

タクソノミーはデータベース上では次の3つのテーブルを使って管理されています。

  • wp_terms には、カテゴリーやタグの項目名が保存されている
  • wp_term_taxonomy には、その項目がカテゴリーかタグかが保存されている
  • wp_term_relationships には、記事の ID とカテゴリーやタグの ID が紐付けされている

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

ですので、カテゴリーをタグにコピーするためには3つのデータベースにカテゴリー情報と同じものをタグ情報として登録する必要があります。順番にやっていきましょう。

なお、今回、データベースの操作をできるだけシンプルにやろうとしてターミナルからのコマンドで試みたんですが、かえって煩雑になりそうでしたので phpMyAdmin を利用することにしました。コマンドでの操作はまたあらためてやろうと思います。

02wp_terms のカテゴリー項目名を新たに登録する

まず、テーブル wp_terms に登録されているカテゴリー項目を取り出して、それを新たにタグの項目として登録します。

ただ、wp_terms(下図)は各種項目名を登録するテーブルですのでユーザーが入力したメニュー名やインストールされたテーマ名などが混在しています。つまり、wp_terms を見ただけではカテゴリーの項目かどうかはわからないということです。

その項目がカテゴリーであることは テーブル wp_term_taxonomy(下図)のフィールド taxonomy に category として登録されています。

ですので、まず、次の sql で wp_terms からカテゴリー項目だけを取り出します。

SELECT name, slug, term_group FROM `wp_terms` WHERE term_id IN (SELECT term_id FROM `wp_term_taxonomy` WHERE taxonomy="category" and count<>0);

phpMyAdmin にログインし、SQLタブをクリックして上の sql を入力して実行しますと下図のようにカテゴリー項目だけが検索されてきますので、すべてをチェックしてエクスポートします。

フォーマットは SQL を選択しますが、設定によってはエクスポートファイルに CREATE TABLE コマンドなどインポートする際にエラーになるコマンドが入っていますので、次のようにエディタで INSERT コマンド行だけに編集します。

INSERT INTO `wp_terms` (`name`, `slug`, `term_group`) VALUES
('Wordpress', 'wordpress', 0),
('genesis', 'genesis', 0),
('Blankslate', 'blankslate', 0),
…

続いて、その sql ファイルを phpMyAdmin でインポートします。インポートタブをクリックしファイルを指定してインポートボタンをクリックするだけです。

テーブル wp_terms に新しく項目名が追加され、フィールド term_id に 51 から連番でナンバリングされています。term_id に AUTO_INCREMENT 属性が設定されているからなんですが、この AUTO_INCREMENT 属性は連番にならないケースもありますので注意が必要です。今回のように連続して追加する場合は問題ありません。

03その追加項目を wp_term_taxonomy にタグ項目として登録する

次に、テーブル wp_term_taxonomy からフィールド taxonpmy が category かつ count が 0 ではない、つまり1つ以上の記事が登録されているカテゴリー項目を次の sql で取り出します。

SELECT `term_id`, `taxonomy`, `description`, `parent`, `count` FROM `wp_term_taxonomy` WHERE taxonomy='category' and count<>0;

すべてをチェックしてフォーマット SQL でエクスポートします。

INSERT INTO `wp_term_taxonomy` (`term_id`, `taxonomy`, `description`, `parent`, `count`) VALUES
(2, 'category', '', 0, 91),
(3, 'category', '', 0, 6),
(4, 'category', '', 0, 3),
(5, 'category', '', 0, 216),
(6, 'category', '', 0, 6),
…

この term_id は wp_terms のカテゴリー項目の id ですので、この値をタグ項目の id である 51 からのものに変更し、同時に taxonomy をタグの識別子 post_tag に変更します。これは php 上で行います。

まず、エクスポートした上の sql ファイルをコメント行など INSERT 文以外を削除し、wp_term_taxonomy.sql として保存します。そして、同じディレクトリに次の php を作成します。

<?php
$array = file("./wp_term_taxonomy.sql");

$i = 51;
foreach ($array as &$str){
	$pattern = '/(\()\d+?(\, \')category(\'.+\n)/';
	if(preg_match($pattern, $str, $matches)){
		$str = $matches[1] . $i . $matches[2] . 'post_tag' . $matches[3];
		$i++;
	}
}

file_put_contents('tag_wp_term_taxonomy.sql', $array);

何をやっているかと言いますと、テーブル wp_terems のタグ項目の term_id は 51 から 1 ずつ増えていっていることは確定していますので、エクスポートした wp_term_taxonomy の term_id を 51 からに書き換え、またフィールド taxonomy を post_tag に変更しています。

INSERT INTO `wp_term_taxonomy` (`term_id`, `taxonomy`, `description`, `parent`, `count`) VALUES
(51, 'post_tag', '', 0, 91),
(52, 'post_tag', '', 0, 6),
(53, 'post_tag', '', 0, 3),
(54, 'post_tag', '', 0, 216),
(55, 'post_tag', '', 0, 6),
(56, 'post_tag', '', 0, 6),
…

結果はこうなります。これをテーブル wp_term_taxomomy にインポートします。

term_id が 51 からの項目がタグの識別子 post_tag として登録されました。

04wp_term_relationships の記事とカテゴリーのリレーションをコピーする

テーブル wp_term_relationships は次のようになっています。

記事 ID(object_id)とカテゴリーの term_taxonomy_id が紐付けられています。object_id 13 のように複数の term_taxonomy_id と紐付けられているものもあります。

次の sql でテーブル wp_term_relationships からカテゴリーの term_taxonomy_id に紐付けられたレコードを抽出します。

SELECT object_id, term_taxonomy_id, term_order FROM `wp_term_relationships` WHERE term_taxonomy_id IN (SELECT term_taxonomy_id FROM `wp_term_taxonomy` WHERE taxonomy="category" and count<>0);
INSERT INTO `wp_term_relationships` (`object_id`, `term_taxonomy_id`, `term_order`) VALUES
(7, 2, 0),
(8, 2, 0),
(9, 2, 0),
(10, 2, 0),
(11, 2, 0),
(13, 2, 0),
(14, 2, 0),
…

wp_term_relationships.sql として保存します。抽出したこの sql ファイルの term_taxonomy_id をタグの term_taxonomy_id に置き換えて追加すればいいはずです。そのためには対になっていカテゴリーの term_taxonomy_id とタグの term_taxonomy_id を抽出して php の str_replace を使って置き換えます。

次の2つの抽出は phpMyAdmin のエクスポートのフォーマットを csv に指定し、また、エクスポート方法を詳細にしてカラム囲み記号を空白にすれば term_taxonomy_id の値のみが取り出せます。

SELECT term_taxonomy_id FROM `wp_term_taxonomy` WHERE taxonomy="category" and count<>0;
2
3
4
5
6
…

cat.csv として保存します。

SELECT term_taxonomy_id FROM `wp_term_taxonomy` WHERE taxonomy="post_tag" and count<>0;
51
52
53
54
55
…

tag.csv として保存します。

次の php ファイルを同じディレクトリに作成し実行します。

<?php
$cats = file("cat.csv", FILE_IGNORE_NEW_LINES);
foreach($cats as &$cat){
	$cat = ", " . $cat . ",";
}
$tags = file("tag.csv", FILE_IGNORE_NEW_LINES);
foreach($tags as &$tag){
	$tag = ", " . $tag . ",";
}

$array = file("wp_term_relationships.sql");
foreach ($array as &$str){
	$str = str_replace($cats, $tags, $str);
}

file_put_contents('tag_wp_term_relationships.sql', $array);

置き換え文字列を term_taxonomy_id だけではなく、. 2, のようにしているのは str_replace は置き換えを複数回実行するため term_taxonomy_id だけを置き換え対象にしてもうまくいかないからです。

この php を実行しますと次の sql ファイルがつくられます。

INSERT INTO `wp_term_relationships` (`object_id`, `term_taxonomy_id`, `term_order`) VALUES
(7, 51, 0),
(8, 51, 0),
(9, 51, 0),
(10, 51, 0),
(11, 51, 0),
…

これをデータベースにインポートすれば完了です。

プラグインを使ってコピーした場合と同じようにカテゴリーと同じタグが追加されています。

ということで phpMyAdmin と WordPress のデータベースの勉強でした(笑)。実際、よく理解できました。