Contact Form DB のテーブルについて
Contact Form 7 というアンケートフォームのプラグインは、メールを送信するだけなので、DBへデータを格納するようにするプラグインが Contact Form DB です。
両プラグインをWordPressに入れることで、手軽に入力フォームの内容をDBに格納できます。
しかし、この Contact Form DB で作られるテーブルが曲者でした。
WordPressの管理画面から Contact Form DB の管理画面を表示すると、入力フォームから入力されたデータの一覧を表示でき、それを見るとあたかも一つのフォームからの投稿が一つのレコードとして格納されているように見えます。 しかし、実際のテーブルには、入力フォームの input 一つ一つがそれぞれ1レコードとして登録されます。
入力項目が3つのフォームだと、1回の投稿で3つレコードが登録されるわけで、それぞれのレコードには、それぞれの入力項目の内容のみが、投稿時間と入力フォーム名と入力項目名をキーに記録されるのです。
ちなみにテーブル構造は下記の通り。
1 2 3 4 5 6 7 8 9 10 11 12 |
mysql> DESC wp_cf7dbplugin_submits; +-------------+---------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------------+---------------+------+-----+---------+-------+ | submit_time | decimal(16,4) | NO | MUL | NULL | | | form_name | varchar(127) | YES | MUL | NULL | | | field_name | varchar(127) | YES | MUL | NULL | | | field_value | longtext | YES | | NULL | | | field_order | int(11) | YES | | NULL | | | file | longblob | YES | | NULL | | +-------------+---------------+------+-----+---------+-------+ 6 rows in set (0.03 sec) |
インデックス一覧は下記の通り。
1 2 3 4 5 6 7 8 9 |
mysql> SHOW INDEX FROM wp_cf7dbplugin_submits; +------------------------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | +------------------------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ | wp_cf7dbplugin_submits | 1 | submit_time_idx | 1 | submit_time | A | 2 | NULL | NULL | | BTREE | | | | wp_cf7dbplugin_submits | 1 | form_name_idx | 1 | form_name | A | 1 | NULL | NULL | YES | BTREE | | | | wp_cf7dbplugin_submits | 1 | field_name_idx | 1 | field_name | A | 26 | NULL | NULL | YES | BTREE | | | +------------------------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 3 rows in set (0.00 sec) |
ちなみに、時間が同じで投稿内容が違うレコードを insert してみたところ、登録できてしまい、その状態で管理画面からデータを参照すると、時間が同じ2つの投稿がごちゃごちゃに一つのレコードとして表示されてしまいます。 (まぁ、当然ですが)
同じ時間になるのはミリ秒単位で同一の場合なので、そんなに気にしないWebサイトなら問題無いかもしれないですが、特に個人情報を扱うようなWebサイトでは気にするべきでしょう。
で、対応策としては、テーブル構造を変えてしまいます。
まずインデックス削除。
1 2 3 |
ALTER TABLE wp_cf7dbplugin_submits DROP INDEX submit_time_idx; ALTER TABLE wp_cf7dbplugin_submits DROP INDEX form_name_idx; ALTER TABLE wp_cf7dbplugin_submits DROP INDEX field_name_idx; |
続いて、複合キーで設定し直します。
1 |
alter table wp_cf7dbplugin_submits add constraint primary key(submit_time, form_name, field_name); |
結果はこんな感じ。
1 2 3 4 5 6 7 8 9 |
mysql> SHOW INDEX FROM wp_cf7dbplugin_submits; +------------------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name |Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | +------------------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ | wp_cf7dbplugin_submits | 0 | PRIMARY | 1 | submit_time |A | 173 | NULL | NULL | | BTREE | | | | wp_cf7dbplugin_submits | 0 | PRIMARY | 2 | form_name |A | 173 | NULL | NULL | | BTREE | | | | wp_cf7dbplugin_submits | 0 | PRIMARY | 3 | field_name |A | 1038 | NULL | NULL | | BTREE | | | +------------------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 3 rows in set (0.00 sec) |
ちなみに、MySQLのバージョンによっては複合キーは設定できないようですが、最近のものはできます。
これで、仮に完全同一タイミングで投稿があっても、どちらか片方は登録されませんので、データの整合性は保てます。