Contact Form 7 + Flamingo の送信データ格納先を変更しようとした話


WordPress でお問い合わせフォームを利用する際、Contact Form 7(CF7)と Flamingo を組み合わせて使うのが定番ですが、デフォルトでは送信データの保存場所がworpdressのデータベースの wp_posts
テーブル と wp_postmeta
テーブルに格納されます。
今回は、これらの格納先を wp_custom_flamingo_posts
, wp_custom_flamingo_metaという独自のテーブルに変更しようと試みた話をまとめます。
目次
カスタムプラグイン作成:Custom Flamingo Mod
Flamingo のデータ保存処理を変更するため、独自の WordPress プラグイン「Custom Flamingo Mod」を作成しました。
プラグインの基本構成
/wp-content/plugins/custom-flamingo-mod/
└── custom-flamingo-mod.php
試みたこと
- 送信データの格納先テーブルの変更
wp_posts
とwp_postmeta
ではなく、wp_custom_flamingo_posts, wp_custom_flamingo_meta
に格納するように変更。// プラグイン有効化時に独自テーブル作成 function create_custom_flamingo_table() { global $wpdb; $table_name = $wpdb->prefix . 'custom_flamingo_messages'; $charset_collate = $wpdb->get_charset_collate(); $sql = "CREATE TABLE IF NOT EXISTS $table_name ( ID bigint(20) unsigned NOT NULL AUTO_INCREMENT, post_id bigint(20) unsigned NOT NULL DEFAULT 0, post_author bigint(20) unsigned NOT NULL DEFAULT 0, post_date datetime NOT NULL DEFAULT '0000-00-00 00:00:00', post_date_gmt datetime NOT NULL DEFAULT '0000-00-00 00:00:00', post_content longtext COLLATE utf8mb4_unicode_ci NOT NULL, post_title text COLLATE utf8mb4_unicode_ci NOT NULL, post_excerpt text COLLATE utf8mb4_unicode_ci NOT NULL, post_status varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'publish', comment_status varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'open', ping_status varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'open', post_password varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', post_name varchar(200) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', to_ping text COLLATE utf8mb4_unicode_ci NOT NULL, pinged text COLLATE utf8mb4_unicode_ci NOT NULL, post_modified datetime NOT NULL DEFAULT '0000-00-00 00:00:00', post_modified_gmt datetime NOT NULL DEFAULT '0000-00-00 00:00:00', post_content_filtered longtext COLLATE utf8mb4_unicode_ci NOT NULL, post_parent bigint(20) unsigned NOT NULL DEFAULT 0, guid varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', menu_order int(11) NOT NULL DEFAULT 0, post_type varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'flamingo_message', post_mime_type varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', comment_count bigint(20) NOT NULL DEFAULT 0, PRIMARY KEY (ID), KEY post_name (post_name), KEY post_parent (post_parent), KEY post_author (post_author), KEY post_type (post_type) ) $charset_collate;"; $table_name = $wpdb->prefix . 'custom_flamingo_meta'; $charset_collate = $wpdb->get_charset_collate(); $sql_meta = "CREATE TABLE IF NOT EXISTS $table_name ( meta_id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, post_id BIGINT(20) UNSIGNED NOT NULL DEFAULT 0, meta_key VARCHAR(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, meta_value LONGTEXT COLLATE utf8mb4_unicode_ci DEFAULT NULL, PRIMARY KEY (meta_id), KEY post_id (post_id), KEY meta_key (meta_key) ) ENGINE=InnoDB $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); dbDelta($sql_meta); } register_activation_hook(__FILE__, 'create_custom_flamingo_table');
- 投稿データの格納テーブルの変更方法
wp_insert_post
のフックを利用し、post_type
を検証することでwp_custom_flamingo_posts
に保存することに成功。function copy_flamingo_data_to_custom_table($post_id, $post, $update) { error_log("post_id: " . $post_id); // `flamingo_inbound` のデータだけ処理する if ($post->post_type === 'flamingo_inbound') { $existing_value = get_option('flamingo_custom_id', ''); // 新しいデータを結合(例: "_new_data" を追加) $new_value = $existing_value . ',' . $post_id; // 更新 update_option('flamingo_custom_id', $new_value, 'yes'); // ログ出力(確認用) error_log("Updated flamingo_custom_id: " . $new_value); global $wpdb; $table_name = $wpdb->prefix . 'custom_flamingo_messages'; $data = array( 'ID' => NULL, // AUTO_INCREMENT 'post_id' => $post_id, 'post_author' => $post->post_author, 'post_date' => $post->post_date, 'post_date_gmt' => $post->post_date_gmt, 'post_content' => $post->post_content, 'post_title' => $post->post_title, 'post_excerpt' => $post->post_excerpt, 'post_status' => $post->post_status, 'comment_status' => $post->comment_status, 'ping_status' => $post->ping_status, 'post_password' => $post->post_password, 'post_name' => $post->post_name, 'to_ping' => $post->to_ping, 'pinged' => $post->pinged, 'post_modified' => $post->post_modified, 'post_modified_gmt' => $post->post_modified_gmt, 'post_content_filtered' => $post->post_content_filtered, 'post_parent' => $post->post_parent, 'guid' => $post->guid, 'menu_order' => $post->menu_order, 'post_type' => 'flamingo_inbound', // カスタムテーブル用のタイプ 'post_mime_type' => $post->post_mime_type, 'comment_count' => $post->comment_count, ); // データを挿入 $result = $wpdb->insert($table_name, $data); // `wp_posts` から削除(必要なら) wp_delete_post($post_id, true); return $post_id; } elseif ($post->post_type === 'flamingo_contact') { $existing_value = get_option('flamingo_custom_id', ''); // 新しいデータを結合(例: "_new_data" を追加) $new_value = $existing_value . ',' . $post_id; // 更新 update_option('flamingo_custom_id', $new_value, 'yes'); // ログ出力(確認用) error_log("Updated flamingo_custom_id: " . $new_value); global $wpdb; $table_name = $wpdb->prefix . 'custom_flamingo_messages'; $data = array( 'ID' => NULL, 'post_id' => $post_id, 'post_type' => 'flamingo_contact', 'post_status' => 'publish', 'post_title' => $post->post_title, 'post_name' => $post->post_name, 'post_content' => $post->post_content, ); // データを挿入 $result = $wpdb->insert($table_name, $data); // `wp_posts` から削除(必要なら) wp_delete_post($post_id, true); return $post_id; } else { return; } } add_action('wp_insert_post', 'copy_flamingo_data_to_custom_table', 10, 3);
- メタデータの保存先の変更
update_post_meta
のフックを利用し、wp_options
に格納したpost_id
をもとに Flamingo の投稿かどうかを判定しようと試みた。function redirect_flamingo_meta_update( $null, $object_id, $meta_key, $meta_value ) { error_log("redirect_flamingo_meta_update"); $post_type = 'post'; if( 'post' === $post_type){ $flamingo_custom_id = get_option('flamingo_custom_id', ''); error_log("Hook triggered - flamingo_custom_id: {$flamingo_custom_id}, object_id: {$object_id}, meta_key: {$meta_key}, meta_value: {$meta_value}"); if (strpos($flamingo_custom_id, $object_id) !== false) { global $wpdb; $custom_table = $wpdb->prefix . 'custom_flamingo_meta'; error_log("Saving to custom table - post_id: {$object_id}, meta_key: {$meta_key}, meta_value: {$meta_value}"); // カスタムテーブルにデータを保存 $wpdb->replace( $custom_table, [ 'post_id' => $object_id, 'meta_key' => $meta_key, 'meta_value' => $meta_value ] ); error_log("Data saved successfully!"); // `false` を返すと `update_post_meta()` の保存をスキップできる return false; } } return $null; } add_action( 'update_post_meta', 'redirect_flamingo_meta_update', 10, 4 );
問題発生:update_post_meta のフックが引っかからない?
作り始めたころは update_post_meta
のフックが正常に動作していたはずなのに、なぜか途中から反応しなくなりました。
「なぜ?」と悩みながら、update_metadaに変えたりなど、デバッグを続けましたが、どうしても update_post_meta
のフックが発火せず、今のところ原因を特定できていません。
考察:Flamingo は WordPress のお作法に従った保存方法をしている?
Flamingo のデータ保存方法を改めて見直してみると、WordPress の標準的なデータ管理の流れに沿っているように思えます。
当初は「テーブルを分けた方が DB を直接見たときに確認しやすいのでは?」と考えていましたが、データベースを直接確認するときは、wp_posts
テーブルで SELECT * FROM `wp_posts` WHERE `post_type` LIKE 'flamingo%'
で切り分ければ十分かもしれません。
さらに、WordPress の標準的なデータ管理の流れを活用することで、例えば LiteSpeed Cache などのデータベース最適化機能を利用し、不要になった(孤立した)postmeta
情報を自動削除できるという利点があります。独自のテーブルでデータを管理してしまうと、こうした WordPress 標準機能の恩恵を受けることができません。そのため、あえてテーブルを分ける必要はないかもしれません。
ただし、wp_postmeta
には、1件の問い合わせから名前やメールアドレス、問い合わせ内容などのデータが個別に格納されるため、レコード数が増える仕様になっています。大量の問い合わせを受けるサイトでは、これがボトルネックになる可能性がありそうです。
結論:テーブル分割の必要性は?
カスタムテーブルを作成してみたものの、WordPress の標準機能を活かしたデータ管理の方が実用的かもしれません。
ただ、wp_postmeta
方式はデータの増加によりパフォーマンスに影響を与える可能性があるため、大量の問い合わせが来るようなサイトは最適な保存方法を考える必要がありそうです。
気が向けば今後も検証を続ける予定です。