Contact Form 7 5.4新版本如何处理上传图片? [解决方案]
How to process uploaded images in new 5.4 version of Contact Form 7? [SOLUTION]
我在我的 WordPress 网站上的提交表单中使用 Contact Form 7 (5.4) 和 CF7 Smart Grid Design Extension (4.10.0) 来构建自定义 Post 类型草案。最初的灵感是这个 awesome SO post.
一年多来,提交表单一直运行良好且可靠,但在新的 CF7 5.4 版本中,内部发生了一些变化,图像上传也出现了问题。所有其他字段都保持不变。
我上传的 CF7 字段显示为
[file* field_image limit:10000000 filetypes:jpg|gif|png|jpeg class:field-image]
图片已邮寄,因此表单正在正确上传文件。但是有些事情发生了变化,这打破了我在通过电子邮件发送后删除图像之前获取图像的尝试。
这是 functions.php 中的相关 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。
虽然问题可能出在处理提交的 post 提交代码中,但其中的 none 在一年内发生了变化。只有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 (
),
)
因此,虽然文件数组似乎在 posted 数据中可用,但无法从旨在获取它的函数中获得。
这是什么意思?
解决方案
所以实际上有两个问题:
- 因为@howard_e 建议 CF7 的开发人员将上传字段更改为数组(可能允许上传多个文件)。这破坏了现有代码。
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 );
}
}
}
}
这个问题很可能与我遇到的问题相同。 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,你想使用
$post_id = $submission->get_meta('container_post_id');
您能否通过适当的暂停(或导致 php 致命错误)进行测试,以查看图像是否在任何时候 grabbed/saved 正确?
如果是这样,您可以通过使用 additional/alternate 方法将其移动到正确的文件夹来解决您的问题(恰好在正确 saved/grabbed/handled 之后)。
考虑到图像已通过电子邮件正确发送,因此我确定您可以在此期间的某个时候将其保存在媒体文件夹中 php script/page
我在我的 WordPress 网站上的提交表单中使用 Contact Form 7 (5.4) 和 CF7 Smart Grid Design Extension (4.10.0) 来构建自定义 Post 类型草案。最初的灵感是这个 awesome SO post.
一年多来,提交表单一直运行良好且可靠,但在新的 CF7 5.4 版本中,内部发生了一些变化,图像上传也出现了问题。所有其他字段都保持不变。
我上传的 CF7 字段显示为
[file* field_image limit:10000000 filetypes:jpg|gif|png|jpeg class:field-image]
图片已邮寄,因此表单正在正确上传文件。但是有些事情发生了变化,这打破了我在通过电子邮件发送后删除图像之前获取图像的尝试。
这是 functions.php 中的相关 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。
虽然问题可能出在处理提交的 post 提交代码中,但其中的 none 在一年内发生了变化。只有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 (
),
)
因此,虽然文件数组似乎在 posted 数据中可用,但无法从旨在获取它的函数中获得。
这是什么意思?
解决方案
所以实际上有两个问题:
- 因为@howard_e 建议 CF7 的开发人员将上传字段更改为数组(可能允许上传多个文件)。这破坏了现有代码。
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 );
}
}
}
}
这个问题很可能与我遇到的问题相同。 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,你想使用
$post_id = $submission->get_meta('container_post_id');
您能否通过适当的暂停(或导致 php 致命错误)进行测试,以查看图像是否在任何时候 grabbed/saved 正确?
如果是这样,您可以通过使用 additional/alternate 方法将其移动到正确的文件夹来解决您的问题(恰好在正确 saved/grabbed/handled 之后)。 考虑到图像已通过电子邮件正确发送,因此我确定您可以在此期间的某个时候将其保存在媒体文件夹中 php script/page