I have a problem with creating posts, specifically with uploading post images. The idea is that an unauthorized user submits an application for a contest. After successful payment, I send the form data via ajax in Json format.
- payData for payment:
function getPayData() {
var payData = {};
payData['gallery-parent-id'] = {};
payData['gallery-parent-id']['value'] = form.dataset.parent;
payData['form-id'] = {};
payData['form-id']['value'] = form.dataset.id;
// return payData
return payData;
}
- Ajax for payment:
$.ajax({
url: url,
type: 'POST',
data: payData,
success: function(response) {
var response_end = JSON.parse(response);
var confirmationToken = response_end.confirmation_token;
var order_id = response_end.id;
var amount = response_end.amount;
if (confirmationToken) {
const checkout = new window.YooMoneyCheckoutWidget({
customization: {
control_primary: '#81fdc5'
},
error_callback: function(error) {
}
});
checkout.on('success', () => {
formData.append('order id:', order_id);
formData.append('amount:', amount);
const success_url = '/pay/success-pay-handler.php';
$.ajax({
url: success_url,
type: 'POST',
data: formData,
cache : false,
dataType : 'json',
processData : false,
contentType : false,
success: function(response) {
console.log(response);
//message.classList.add('show');
},
error: function(response) {
// Обработка ошибки
console.log(response);
console.error('Error data send.');
}
});
//del widget
checkout.destroy();
});
checkout.render('payment-form');
setTimeout(function() {
//form.classList.add('in-process');
}, 300);
} else {
console.log('No token')
}
},
error: function() {
// Error hand
console.error('Errror data send.');
}
});
- formData:
formData = new FormData();
for (var i = 0; i < form.elements.length; i++) {
var element = form.elements[i];
if (element.type === 'text' || element.type === 'textarea' || element.type === 'number' || element.type === 'mail') {
var label = document.querySelector('label[for="' + element.name + '"]');
var name = element.name;
var title = label.textContent.trim();
var value = element.value;
var valueWithLabel = [title, value];
formData.append(name, valueWithLabel);
} else if (element.type === 'file') {
var name = element.name;
formData.append(name, element.files[0]);
}
}
- Ajax for formData
$.ajax({
url: success_url,
type: 'POST',
data: formData,
cache : false,
dataType : 'json',
processData : false,
contentType : false,
success: function(response) {
console.log(response);
},
error: function(response) {
console.log(response);
console.error('Error data send.');
}
});
I successfully receive the form data in the PHP Handler. First, I include the necessary files for the operation:
require_once( $_SERVER['DOCUMENT_ROOT'] . '/wp-load.php' );
require_once(ABSPATH . 'wp-admin/includes/image.php');
require_once(ABSPATH . 'wp-admin/includes/file.php');
require_once(ABSPATH . 'wp-admin/includes/media.php');
Then I retrieve the data from ajax, one with regular data - $formData, and the other with files - $formFiles.
$formData = $_POST;
$formFiles = $_FILES;
Next, I iterate through the form fields + ACF array. The posts are successfully created, so I won't send the entire code just yet. Then, the problems start when I try to upload an image for the post. I iterate through $_FILES, store the values in the $artFiles array.
$artFiles = array();
foreach ($formFiles as $key => $file) {
if (strpos($key, "art-file-") === 0) {
$artFileNumber = substr($key, strlen("art-file-"));
$artFiles[$artFileNumber] = $file;
}
}
My $artNames foreach:
foreach ($formData as $key => $value) {
if (strpos($key, "art-name-") === 0) {
// Разбиваем строку значения по запятой
$parts = explode(',', $value);
// Проверяем, что в массиве $parts есть второй элемент
if (isset($parts[1])) {
$artNameNumber = str_replace("art-name-", "", $key);
$artName = trim($parts[1]);
// Добавляем значения в соответствующие массивы
$artNames[$artNameNumber] = $artName;
}
}
Create posts:
foreach ($artNames as $artNameNumber => $artName) {
$artHeight = isset($artHeights[$artNameNumber]) ? $artHeights[$artNameNumber] : '';
$artWidth = isset($artWidths[$artNameNumber]) ? $artWidths[$artNameNumber] : '';
$artMaterial = isset($artMaterials[$artNameNumber]) ? $artMaterials[$artNameNumber] : '';
$artDescr = isset($artDescrs[$artNameNumber]) ? $artDescrs[$artNameNumber] : '';
$artFile = isset($artFiles[$artNameNumber]) ? $artFiles[$artNameNumber] : '';
$artFileInfo = $artFile['name'] . ' : ' . $artFile['tmp_name'] . ' : ' . $artFile['size']; // OK, it's work!
$post_data = array(
'post_type' => 'gallery',
'post_status' => 'draft',
'post_parent' => $parent_page_id,
'post_title' => $artName,
'post_content' => $artFileInfo // For tests, it's OK: food-cat-image-2.jpg : /tmp/phpos4nzn : 2937708
);
$post_id = wp_insert_post($post_data);
update_post_meta($post_id, '_wp_page_template', 'single-cat-gallery.php');
// Upload File
$attachment_id = media_handle_upload( $artFile, $post_id ); // Not work
if ( is_wp_error( $attachment_id ) ) {
$error_message = $attachment_id->get_error_message();
echo json_encode( array( 'error' => $error_message ) );
} else {
echo json_encode( array( 'success' => 'File Upload Complete! ID:' . $attachment_id ) );
}
update_post_meta( $post_id, '_thumbnail_id', $attachment_id ); // OK, it's work!
//
if( is_wp_error($post_id) ){
} else {
if (function_exists('update_field')) {
// Acf fields
}
}
}
String
$artFileInfo = $artFile['name'] . ' : ' . $artFile['tmp_name'] . ' : ' . $artFile['size']
=
cat-image-2.jpg : /tmp/phpos4nzn : 2937708
I have tried many different options, but none of them have helped.
Perhaps this information can help: I added a check for is_wp_error and got the following message:
responseText :
"{\"error\":\"Specified file failed upload test.\"}{\"error\":\"Specified file failed upload test.\"}"
status : 200
statusText : "parsererror"
And more:
var_dump($_FILES):
array(2) {
["art-file-1"]=>
array(5) {
["name"]=>
string(18) "food-cat-image.jpg"
["type"]=>
string(10) "image/jpeg"
["tmp_name"]=>
string(14) "/tmp/php3xJrf3"
["error"]=>
int(0)
["size"]=>
int(272437)
}
["art-file-2"]=>
array(5) {
["name"]=>
string(17) "video-preview.jpg"
["type"]=>
string(10) "image/jpeg"
["tmp_name"]=>
string(14) "/tmp/phpGsRXSE"
["error"]=>
int(0)
["size"]=>
int(100533)
}
}
I have re-read a lot of similar topics and no solution has helped me. Please save me.
I tried adding in my PHP handler:
require_once( $_SERVER['DOCUMENT_ROOT'] . '/wp-load.php' );
require_once(ABSPATH . 'wp-admin/includes/image.php');
require_once(ABSPATH . 'wp-admin/includes/file.php');
require_once(ABSPATH . 'wp-admin/includes/media.php');
I've tried iterating over $_FILES in different ways
Used different functions for upload
I tried to specify different values inside the media_handle_upload function:
$attachment_id = media_handle_upload( $artFile['name']/$artFile['tmp_name']/$_FILES['art-file-1']..., $post_id );
All php.info settings is OK.
UPD:
Thank you so much for your attention @CBroe!
our $artFile appears to be an array - one of the entries of the $_FILES array; but media_handle_upload wants a string $file_id as first parameter, the key of the file in the $_FILES array. The value you should be calling this with to process your first uploaded file there, is art-file-1
For my example all problems this:
$attachment_id = media_handle_upload( $artFile, $post_id );
The correct option
$attachment_id = media_handle_upload( 'art-file-' . $artNameNumber, $post_id );
I use this code hope help you