จะประมวลผลภาพที่อัปโหลดในแบบฟอร์มติดต่อ 7 เวอร์ชัน 5.4 ใหม่ได้อย่างไร [สารละลาย]

ฉันใช้แบบฟอร์มติดต่อ 7 (5.4) และ CF7 Smart Grid Design Extension (4.10.0) ในแบบฟอร์มส่งบนเว็บไซต์ WordPress ของฉันเพื่อสร้างประเภทโพสต์แบบกำหนดเองแบบร่าง แรงบันดาลใจดั้งเดิมของสิ่งนี้คือโพสต์ SO ที่ยอดเยี่ยมนี้

แบบฟอร์มการส่งทำงานได้ดีและเชื่อถือได้มานานกว่าหนึ่งปี แต่ด้วยเวอร์ชัน CF7 5.4 ใหม่ มีบางอย่างเปลี่ยนแปลงไปภายในและการอัปโหลดรูปภาพที่เสียหาย ส่วนช่องอื่นๆ ทั้งหมดยังคงไม่เปลี่ยนแปลง

ฟิลด์ CF7 ที่ฉันกำลังอัปโหลดปรากฏเป็น

[file* field_image limit:10000000 filetypes:jpg|gif|png|jpeg class:field-image]

รูปภาพจะถูกส่งไป ดังนั้นแบบฟอร์มจึงอัปโหลดไฟล์ได้อย่างถูกต้อง แต่มีบางอย่างเปลี่ยนไปซึ่งทำให้ความพยายามของฉันในการจับภาพก่อนที่จะถูกลบหลังจากส่งอีเมล

นี่คือ PHP ที่เกี่ยวข้องใน Functions.php ที่จัดการภาพที่อัปโหลดภายในฟังก์ชันที่สร้าง WP CPT

// Handle CF7 form submission and populate new CPT 'Thing'
// Ref: https://wordpress.stackexchange.com/questions/328429/how-to-save-contact-form-7-data-in-custom-post-types-cpt
//
add_action('wpcf7_before_send_mail', 'save_my_form_data_to_my_cpt', 10, 3);
function save_my_form_data_to_my_cpt($contact_form){
    //Get the form ID
    $contact_form = WPCF7_ContactForm::get_current();
    $contact_form_id = $contact_form -> id;
    
    $submission = WPCF7_Submission::get_instance();
    if (!$submission){
        return $contact_form;
    }
    $posted_data = $submission->get_posted_data();
    //The Sent Fields are now in an array
    //you can now access them with $posted_data['my-email']
    //
    // create new post array
    $new_post = array();
    //
    // META META FIELDS
    // post_type (i.e., your CPT)
    $new_post['post_type'] = 'thing';
    // post_status (draft, publish, pending)
    $new_post['post_status'] = 'draft';
    //
    // POST FIELDS
    // post_title
    if(isset($posted_data['field_title']) &&
            !empty($posted_data['field_title'])){
        $new_post['post_title'] = $posted_data['field_title'];
    } else {
        $new_post['post_title'] = '[Insert Title Here]';
    }
    // POST CPT
    //When everything is prepared, insert post into WP Database
    if($post_id = wp_insert_post($new_post)){
        // it worked so let's continue...
        //
        // IMAGE
        // Retrieving and inserting uploaded image as featured image
        // CF7 uploads the image and puts it in a temporary directory,
        //      deleting it after the mail is sent
        // Before it deletes it, we will move into our media library,
        //      and attach it to our post
        //
        // get file upload info from form
        $uploadedFiles = $submission->uploaded_files();
        // if we have an uploaded image...
        if( isset($posted_data['field_image']) ){
            // move image from temp folder to upload folder
            $imageUpload = wp_upload_bits($posted_data['field_image'], null,
                file_get_contents($uploadedFiles['field_image']));
            //
            require_once(ABSPATH . 'wp-admin/includes/admin.php');
            // construct array to register this image
            $filename = $imageUpload['file'];
            $attachment = array(
                'post_mime_type' => $imageUpload['type'],
                'post_parent' => $post_id,
                'post_title' => $posted_data['field_title'] . ' - ' .
                            $posted_data['field_contributor'],
                'post_content' => $posted_data['field_info'],
                'post_status' => 'inherit'
            );
            // attach image to this post
            $attachment_id = wp_insert_attachment( $attachment, $filename, $post_id );
            // if we succeeded...
            if (!is_wp_error($attachment_id)) {
                require_once(ABSPATH . 'wp-admin/includes/image.php');
                $attachment_data = wp_generate_attachment_metadata( $attachment_id, $filename );
                wp_update_attachment_metadata( $attachment_id,  $attachment_data );
                set_post_thumbnail( $post_id, $attachment_id );
                // add image id (attchment id) to ad_image field
                update_field( 'ad_image', $attachment_id, $post_id );
            }
        }
    }
}

สิ่งนี้ถูกเรียกโดย:

add_action('wpcf7_before_send_mail', 'save_my_form_data_to_my_cpt', 10, 3);

รูปภาพที่ส่งในอีเมล CF7 ได้สำเร็จไม่ได้รับการอัปโหลดไปยัง CPT ใหม่ที่กำลังสร้าง

แม้ว่าปัญหาอาจอยู่ที่โค้ดโพสต์ส่งที่จัดการการส่ง แต่ไม่มีสิ่งใดเปลี่ยนแปลงในหนึ่งปี มีเพียง CF7 เท่านั้นที่เปลี่ยนไป

มีคำแนะนำอะไรบ้าง?

ภาคผนวก A: ฟังก์ชันที่สมบูรณ์

นี่คือฟังก์ชัน save_my_form_data_to_my_cpt ทั้งหมด:

~ลบแล้ว~

ภาคผนวก B: เอาต์พุตการแก้ไขจุดบกพร่อง

ในช่วงต้นของฟังก์ชันที่เราเรียกว่ารับข้อมูลที่ส่งผ่านจากแบบฟอร์ม CF7:

$submission = WPCF7_Submission::get_instance();
$posted_data = $submission->get_posted_data();
$uploadedFiles = $submission->uploaded_files();

เมื่อเราถ่ายโอนตัวแปรเหล่านี้ไปยังคอนโซล เราจะได้รับความประหลาดใจ สำหรับ $posted_data เราได้รับ:

array (
  'field_title' => 'TEST',
  'field_expires' => '1',
  'field_tags' => 
  array (
    0 => 'Children',
  ),
  'field_addl_tags' => '',
  'field_info' => '',
  'field_call_to_action' => '',
  'field_phone_contact' => '',
  'field_email_contact' => '',
  'field_website' => '',
  'field_location' => '',
  'field_contributor' => 'Wes Modes',
  'field_notes' => '',
  'field_image' => 
  array (
    0 => '/srv/data/web/vhosts/unavoidabledisaster.com/htdocs/wp-content/uploads/wpcf7_uploads/0318808318/left-boob.jpg',
  ),
  'mc4wp_checkbox' => 'No',
)

สำหรับ $uploadedFiles เราได้รับ:

array (
  'field_image' => 
  array (
  ),
)

ดังนั้นแม้ว่าอาร์เรย์ไฟล์จะพร้อมใช้งานภายในข้อมูลที่โพสต์ แต่ก็ไม่สามารถใช้งานได้จากฟังก์ชันที่ออกแบบมาเพื่อให้ได้มา

สิ่งนี้หมายความว่า?

วิธีแก้ปัญหา

จริงๆ แล้วมีปัญหาอยู่สองประการ:

  1. ตามที่ @howard_e แนะนำผู้พัฒนา CF7 เปลี่ยนฟิลด์อัพโหลดเป็นอาร์เรย์ (อาจอนุญาตให้อัปโหลดหลายไฟล์ได้) สิ่งนี้ทำให้โค้ดที่มีอยู่เสียหาย
  2. เมธอด WPCF7_Submission::get_instance()->uploaded_files() หยุดส่งคืนไฟล์ที่อัพโหลด แม้ว่าจะไม่ส่งคืนภายในวัตถุฟิลด์อัพโหลดของ WPCF7_Submission::get_instance()

นี่คือส่วนที่เกี่ยวข้องที่ได้รับการแก้ไขของฟังก์ชัน:

add_action('wpcf7_before_send_mail', 'save_my_form_data_to_my_cpt');
function save_my_form_data_to_my_cpt($contact_form){
    //Get the form ID
    $contact_form_id = $contact_form->id;

    $submission = WPCF7_Submission::get_instance();
    if (!$submission){
        return; // exit the hook
    }
    // get posted data
    $posted_data = $submission->get_posted_data();
    // get file upload info from form
    $uploadedFiles = $posted_data['field_image'];

    // create new post array
    $new_post = array();
    //
    // META META FIELDS
    // post_type (i.e., your CPT)
    $new_post['post_type'] = 'thing';
    // post_status (draft, publish, pending)
    $new_post['post_status'] = 'draft';
    //
    // POST FIELDS
    // post_title
    if(isset($posted_data['field_title']) &&
            !empty($posted_data['field_title'])){
        $new_post['post_title'] = $posted_data['field_title'];
    } else {
        $new_post['post_title'] = '[Insert Title Here]';
    }
    // POST CPT
    //When everything is prepared, insert the post into WP Database
    if($post_id = wp_insert_post($new_post)){
        // it worked so let's continue...
        // 
        // if we have an uploaded image...
        if (!empty($uploadedFiles)) {
            // move image from temp folder to upload folder
            $file = file_get_contents($uploadedFiles[0]);
            $image_name = basename($uploadedFiles[0]);
            $imageUpload = wp_upload_bits(basename($uploadedFiles[0]), null, $file);
            require_once(ABSPATH . 'wp-admin/includes/admin.php');
            // construct array to register this image
            $filename = $imageUpload['file'];
            $attachment = array(
                'post_mime_type' => $imageUpload['type'],
                'post_parent' => $post_id,
                'post_title' => $posted_data['field_title'] . ' - ' .
                                $posted_data['field_contributor'],
                'post_content' => $posted_data['field_info'],
                'post_status' => 'inherit'
            );
            // attach image to this post
            $attachment_id = wp_insert_attachment( $attachment, $filename, $post_id );
            // if we succeeded...
            if (!is_wp_error($attachment_id)) {
                require_once(ABSPATH . 'wp-admin/includes/image.php');
                $attachment_data = wp_generate_attachment_metadata( $attachment_id, $filename );
                wp_update_attachment_metadata( $attachment_id,  $attachment_data );
                set_post_thumbnail( $post_id, $attachment_id );
                // add image id (attchment id) to ad_image field
                update_field( 'ad_image', $attachment_id, $post_id );
            }
        }
    }
}

person Wes Modes    schedule 03.04.2021    source แหล่งที่มา
comment
คุณสามารถโพสต์ฟังก์ชัน save_my_form_data_to_my_cpt ทั้งหมดได้หรือไม่   -  person Howard E    schedule 03.04.2021
comment
โอเค เสร็จแล้ว โพสต์ในภาคผนวก   -  person Wes Modes    schedule 03.04.2021
comment
ขออภัย ฉันทำให้คุณโพสต์สิ่งพิเศษนั้น ฉันคิดว่าวิธีแก้ปัญหาคือสิ่งที่ฉันโพสต์ ฉันเพิ่งพบปัญหาเดียวกันบนไซต์ที่ฉันใช้ฟีเจอร์เดียวกันนี้ และดูเหมือนว่าจะมีการอัปโหลดที่ล้มเหลวประมาณ 50 รายการ   -  person Howard E    schedule 03.04.2021
comment
ดังนั้น $post_id ควรเป็นโพสต์หลักของแบบฟอร์มหรือไม่ ดูเหมือนจะไม่ได้กำหนดไว้   -  person Howard E    schedule 04.04.2021


คำตอบ (2)


เป็นไปได้มากว่าปัญหานี้จะเหมือนกันกับที่ฉันเคยเผชิญ ดูเหมือนว่าผู้พัฒนา CF7 ตัดสินใจว่าจะทำให้ $uploaded_files['something'] เป็นอาร์เรย์จะดีกว่า ซึ่งอาจทำให้ปลั๊กอินของใครก็ตามที่ใช้ประโยชน์จากคุณลักษณะนี้พัง ไม่ใช่ครั้งแรกที่เขาเปลี่ยนจากสตริงเป็นอาร์เรย์

อย่างไรก็ตามนี่อาจแก้ปัญหาให้คุณได้

การเปลี่ยนแปลงสิ่งนี้:

file_get_contents($uploadedFiles['field_image'])

สำหรับสิ่งนี้:

file_get_contents($uploadedFiles['field_image'][0]);

หลังจากตรวจสอบฟังก์ชันทั้งหมดแล้ว ฉันจึงได้สิ่งนี้:

add_action('wpcf7_before_send_mail', 'save_my_form_data_to_my_cpt');
function save_my_form_data_to_my_cpt($contact_form) {
    //Get the form ID
    // $contact_form object is the first parameter
    $contact_form_id = $contact_form->id;

    $submission = WPCF7_Submission::get_instance();
    if (!$submission) {
        // you don't have to return the form, this is a hook not a filter
        //return $contact_form;
        return; // exit the hook
    }
    $posted_data = $submission->get_posted_data();
    $uploadedFiles = $submission->uploaded_files();
    // if we have an uploaded image...
    if (!empty($uploadedFiles)) {
        // move image from temp folder to upload folder
        $file = file_get_contents($uploadedFiles['field_image'][0]);
        $image_name = basename($uploadedFiles['field_image'][0]);
        $imageUpload = wp_upload_bits(basename($uploadedFiles['field_image'][0]), null, $file);
        //
        require_once(ABSPATH . 'wp-admin/includes/admin.php');
        // construct array to register this image
        $filename = $imageUpload['file'];
        $attachment = array(
            'post_mime_type' => $imageUpload['type'],
            'post_parent' => $post_id,
            'post_title' => $posted_data['field_title'] . ' - ' .
                $posted_data['field_contributor'],
            'post_content' => $posted_data['field_info'],
            'post_status' => 'inherit'
        );
        // attach image to this post
        $attachment_id = wp_insert_attachment($attachment, $filename, $post_id);
        if (!is_wp_error($attachment_id)) {
            require_once(ABSPATH . 'wp-admin/includes/image.php');
            $attachment_data = wp_generate_attachment_metadata($attachment_id, $filename);
            // PC::debug("attachment_data:", print_r($attachment_data, True));
            wp_update_attachment_metadata($attachment_id, $attachment_data);
            set_post_thumbnail($post_id, $attachment_id);
            // add image id (attchment id) to ad_image field
            update_field('ad_image', $attachment_id, $post_id);
        }
    }
}

ข้างต้นนี้ได้รับการทดสอบแล้วและใช้งานได้ ฉันลบการตรวจสอบเพิ่มเติมออกจากช่องที่ไม่ได้ใส่ไว้ในสภาพแวดล้อมการทดสอบ อย่างไรก็ตาม - หมายเหตุหนึ่งรายการ - $post_id ไม่ได้กำหนดไว้ หากคุณใช้โพสต์หลักของหน้าแบบฟอร์ม คุณต้องการใช้

$post_id = $submission->get_meta('container_post_id');
person Howard E    schedule 03.04.2021
comment
กำลังพยายามอยู่ครับ. อาจต้องการเพิ่มวงเล็บที่ตรงกันในตอนท้าย - person Wes Modes; 04.04.2021
comment
แต่น่าเสียดายที่ยังไม่มี รูปภาพยังไม่ปรากฏในไลบรารีสื่อของฉัน อืม... - person Wes Modes; 04.04.2021
comment
สามารถหลีกเลี่ยงความเจ็บปวด WP จำนวนมากได้หากมีวิธีง่ายๆ ในการเขียนลงคอนโซล - person Wes Modes; 04.04.2021
comment
gist.github.com/DuckDivers/ . สิ่งนี้จะช่วยคุณถ่ายโอนข้อมูลตัวแปรไปยังบันทึกข้อผิดพลาด - person Howard E; 04.04.2021
comment
ฉันได้อัปเดตคำตอบแล้ว - person Howard E; 04.04.2021
comment
สำหรับความคิดเห็นล่าสุดของคุณ ฉันมีโค้ดอยู่ตรงกลางซึ่งตั้งค่า $post_id = wp_insert_post($new_post) ในขณะที่สร้างโพสต์ใหม่ และเพิ่มข้อมูลและข้อมูลเมตาทั้งหมด - person Wes Modes; 04.04.2021
comment
มันยังคงใช้งานไม่ได้สำหรับฉันหลังจากตรวจสอบโค้ดของฉันกับโค้ดของคุณอย่างระมัดระวัง และในที่สุดฉันก็ได้ติดตั้งปลั๊กอิน (BugFu) เพื่อให้ฉันสามารถถ่ายโอนข้อมูลที่ซับซ้อนไปยังคอนโซลได้ ฉันพบความประหลาดใจที่แปลกประหลาด ตรวจสอบภาคผนวก B ของโพสต์ต้นฉบับของฉัน - person Wes Modes; 04.04.2021
comment
ดังนั้นคุณพูดถูกอย่างสมบูรณ์เกี่ยวกับอาร์เรย์และ $submission->uploaded_files() กำลังส่งคืนอาร์เรย์ว่าง ดังนั้นฉันจึงตั้งค่า $uploadedFiles = $posted_data['field_image']; และลบการอ้างอิงคีย์ออกจากส่วนไฟล์แนบของฟังก์ชันและมันก็ใช้งานได้ ดูวิธีแก้ปัญหาใน OP - person Wes Modes; 04.04.2021
comment
@WesModes ดังนั้น... อีกวิธีหนึ่งในการถ่ายโอนข้อมูล (หากคุณสนใจ) คือการใช้ Kint Debugger (ซึ่งฉันได้อัปเดตสำหรับ PHP 7.4) - github.com/DuckDivers/kint-debugger - จากนั้นคุณสามารถใช้ d($var_name) - และใช้ add_filter('wpcf7_load_js', '__return_false'); ใน functions.php ของคุณเพื่อทำให้เพจโหลดซ้ำเมื่อส่ง แทนที่จะเป็นตัวจัดการอาแจ็กซ์ จากนั้นพวกคุณทุกคนที่ทิ้งตัวแปร/อ็อบเจ็กต์ ฯลฯ จะอยู่ในข้อมูลการดีบักจาก Kint หลังจากการส่ง - person Howard E; 04.04.2021
comment
ฉลาดหลักแหลม. ฉันจะลองครั้งต่อไปที่ฉันมีปัญหาที่ดื้อดึง - person Wes Modes; 04.04.2021
comment
ขอบคุณสำหรับความช่วยเหลือทั้งหมด ไม่แน่ใจว่าฉันจะพบได้ง่ายว่าสตริงถูกแปลงเป็นอาร์เรย์ - person Wes Modes; 04.04.2021

คุณสามารถทดสอบด้วยการหยุดชั่วคราวในตำแหน่งที่ดี (หรือทำให้เกิดข้อผิดพลาดร้ายแรงของ php) เพื่อดูว่า ณ จุดใดที่รูปภาพถูกคว้า/บันทึกอย่างถูกต้องหรือไม่

หากเป็นเช่นนั้น คุณสามารถหลีกเลี่ยงปัญหาได้โดยการย้ายไปยังโฟลเดอร์ที่ถูกต้องโดยใช้วิธีการเพิ่มเติม/ทางเลือก (หลังจากที่บันทึก/จับ/จัดการอย่างเหมาะสมแล้ว) โปรดทราบว่ารูปภาพจะถูกส่งออกไปทางอีเมลอย่างถูกต้อง ดังนั้นฉันมั่นใจว่าคุณสามารถบันทึกรูปภาพไว้ในโฟลเดอร์สื่อได้ในช่วงใดช่วงหนึ่งระหว่างสคริปต์/เพจ php นี้

person Community    schedule 03.04.2021
comment
ฉันเห็นด้วยอย่างสมบูรณ์ ได้รับรูปภาพแน่นอนเพราะอีเมลได้รับ แต่ไม่ได้บันทึก ฉันสงสัยว่ามันดึงมันมาจากโฟลเดอร์ชั่วคราวไม่ถูกต้อง - person Wes Modes; 04.04.2021