Help us understand the problem. What is going on with this article?

WordPressのフォーム送信から投稿を作成し、カスタムフィールドへ追加した話

フロントエンドエンジニアをしていますが、最近は以前にも増してWordpressの実装が多くなってきました。

数をこなしているうちにWordpressに絡むベーシックなPHPは結構わかるようになっていますが
基本的には文字の処理とかループ回してとかそういうのがメインで、それ以上はいつも先人の知恵(検索)に助けられています。

今回、案件でタイトルの通りフォームの送信時にメール送信だけではなく非公開で投稿を作成してほしい(いわゆる投稿フォーム)
という依頼があり、仕様と完全に合致する情報も少なく、私にとってはとても頭を悩まされたので記録として残しておきます。

仕様は以下のとおり。

  • フォームはプラグイン「Contact Form 7」を使用
  • カスタムフィールドは「Advanced Custom Fields」で設定済み
  • 投稿は、カスタム投稿
  • フォームの項目は、氏名、メール等の基本的な内容に加えて、画像もあり
  • フォームの項目からカテゴリーの選択も可能とする

画像を含むという点で一番苦労しました。。

テーマ側からの投稿作成

Wordpress側で用意されている「wp_insert_post()」を使用します。
この関数の使い方自体は割と情報があったので、公式へのリンクを貼って、詳細は割愛します。
関数リファレンス/wp insert post - WordPress Codex 日本語版

Contact Form 7 からの送信

これは、Contact Form 7 で用意されているフック「wpcf7_before_send_mail」を使用します。
wpcf7_before_send_mail | action | WordPress | hookr.io

最終的なソースコード

//----------------------------------------------
// Add post from Form
//----------------------------------------------
function wpcf7_insert_post(){
    $submission = WPCF7_Submission::get_instance();
    if($submission) {
        $data = $submission->get_posted_data();
        $uploaded_files = $submission->uploaded_files();
        $timeStamp = $submission->get_meta('timestamp');
        $time = date('Ymd_Gi',$timeStamp);
        extract($data);

        if($data['_wpcf7'] == 11) {  //サイト内にフォームが複数あるため、IDで判別

            $post_value = array(
                'post_type' => 'custompost',
                'post_title' => $data['your-company'],
                'post_status' => 'draft'  //下書きで作成
            );  
            $insertPost = wp_insert_post($post_value);  //ここで投稿を作成します

            if($insertPost) {  //無事に投稿が作成されたら、その後カスタムフィールド等の処理をします

                /* タクソノミー(カテゴリー)の設定 */
                wp_set_object_terms($insertPost,$data['category'],'keyword');

                /* テキストのみのカスタムフィールドの設定 */
                update_post_meta($insertPost, 'acf_name', $data['your-company']);

                /* 画像の設定 */
                if (isset($uploaded_files['your-img01'])) {
                    $thumb_path = '/wp/' . str_replace($baseurl, '', $uploaded_files['your-img01']);
                    $thumb_id = 
                        addAttachmentFromForm($thumb_path, $uploaded_files['your-img01'], $insertPost, $time);
                    update_field('acf_img', $thumb_id,  $insertPost); //関数で生成した画像をカスタムフィールドに追加
                }
            }
        }
    }
}
add_action('wpcf7_before_send_mail', 'wpcf7_insert_post', 10, 1);

/* 画像の詳細処理については、別関数を作成しました */
function addAttachmentFromForm($filename, $file_base, $post_id, $time) {
    $layout_img_value = '';

    $filetype = wp_check_filetype( basename( $filename ), null );
    $wp_upload_dir = wp_upload_dir();  //メディアライブラリのアップロードディレクトリを取得
    $upfile = $wp_upload_dir['url'] . '/' . $time . basename( $filename );
    $copyfile = $wp_upload_dir['path'] .'/' . $time . basename( $filename );
    copy($file_base, $copyfile);  //コピーを作成
    $attachment = array(
        'guid'           => $upfile,
        'post_mime_type' => $filetype['type'],
        'post_title'     => preg_replace( '/\.[^.]+$/', '', basename( $upfile ) ),
        'post_content'   => '',
        'post_status'    => 'inherit'
    );
    $attach_id = wp_insert_attachment( $attachment, $copyfile, $post_id );  //メディアライブラリにコピーした画像を追加
    require_once( ABSPATH . 'wp-admin/includes/image.php' );
    $attach_data = wp_generate_attachment_metadata( $attach_id, $copyfile );  //画像のメタデータ作成とサムネイル等別サイズ画像生成
    wp_update_attachment_metadata( $attach_id, $attach_data );

    if($attach_id) return $attach_id;
    else return false;
}

少しだけ解説

画像の処理については、Contact Form 7 での画像送信は、あくまでもメール送信を目的としているため
一時ディレクトリにアップロードされ、メール送信が終わった際に削除されてしまいます。

そのため、今回作成した関数addAttachmentFromForm()内では、他のアップロード画像と同一のディレクトリへコピーを作成し
管理画面の「メディア」から確認可能なように追加しています。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away