J'utilise ajax pour soumettre un formulaire en plusieurs parties avec des tableaux, des champs de texte et des fichiers.
J'ajoute chaque VAR aux données principales pour
var attachments = document.getElementById('files');
var data= new FormData();
for (i=0; i< attachments.files.length; i++){
data.append('file', attachments.files[i]);
console.log(attachments.files[i]);
data.append ('headline', headline);
data.append ('article', article);
data.append ('arr', arr);
data.append ('tag', tag);
j'utilise ensuite la fonction ajax pour l'envoyer dans un fichier PHP à stocker dans la base de données SQL.
$.ajax({
type: "post",
url: 'php/submittionform.php',
cache: false,
processData: false,
contentType: false,
data: data,
success: function(request) {$('#box').html(request); }
})
Mais du côté PHP, la variable arr
, qui est un tableau, apparaît sous forme de chaîne.
Lorsque je ne l'envoie pas avec ajax en tant que données de formulaire mais que j'utilise l'option simple $.POST
, je l'obtiens sous forme de tableau du côté PHP, mais je ne peux pas envoyer les fichiers également.
des solutions?
Vous avez plusieurs options:
JS
var json_arr = JSON.stringify(arr);
PHP
$arr = json_decode($_POST['arr']);
Envoi d'un tableau via FormData
.
JS
// Use <#> or any other delimiter you want
var serial_arr = arr.join("<#>");
PHP
$arr = explode("<#>", $_POST['arr']);
Vous pouvez également envoyer un tableau via FormData
de cette façon:
var formData = new FormData;
var arr = ['this', 'is', 'an', 'array'];
for (var i = 0; i < arr.length; i++) {
formData.append('arr[]', arr[i]);
}
Ainsi, vous pouvez écrire arr[]
de la même manière qu'avec un simple formulaire HTML. Dans le cas de PHP, cela devrait fonctionner.
Vous pouvez trouver cet article utile: Comment passer un tableau dans une chaîne de requête?
C'est une vieille question, mais j'ai récemment rencontré ce problème avec la publication d'objets avec des fichiers. J'avais besoin de pouvoir poster un objet, avec des propriétés enfants qui étaient aussi des objets et des tableaux.
La fonction ci-dessous parcourt un objet et crée le bon objet formData.
// formData - instance of FormData object
// data - object to post
function getFormData(formData, data, previousKey) {
if (data instanceof Object) {
Object.keys(data).forEach(key => {
const value = data[key];
if (value instanceof Object && !Array.isArray(value)) {
return this.getFormData(formData, value, key);
}
if (previousKey) {
key = `${previousKey}[${key}]`;
}
if (Array.isArray(value)) {
value.forEach(val => {
formData.append(`${key}[]`, val);
});
} else {
formData.append(key, value);
}
});
}
}
Cela va convertir le JSON suivant -
{
name: 'starwars',
year: 1977,
characters: {
good: ['luke', 'leia'],
bad: ['vader'],
},
}
dans le FormData suivant
name, starwars
year, 1977
characters[good][], luke
characters[good][], leia
characters[bad][], vader
Version TypeScript:
export class Utility {
public static convertModelToFormData(model: any, form: FormData = null, namespace = ''): FormData {
let formData = form || new FormData();
let formKey;
for (let propertyName in model) {
if (!model.hasOwnProperty(propertyName) || !model[propertyName]) continue;
let formKey = namespace ? `${namespace}[${propertyName}]` : propertyName;
if (model[propertyName] instanceof Date)
formData.append(formKey, model[propertyName].toISOString());
else if (model[propertyName] instanceof Array) {
model[propertyName].forEach((element, index) => {
const tempFormKey = `${formKey}[${index}]`;
this.convertModelToFormData(element, formData, tempFormKey);
});
}
else if (typeof model[propertyName] === 'object' && !(model[propertyName] instanceof File))
this.convertModelToFormData(model[propertyName], formData, formKey);
else
formData.append(formKey, model[propertyName].toString());
}
return formData;
}
}
En utilisant:
let formData = Utility.convertModelToFormData(model);
ajouter toutes les entrées de type à FormData
const formData = new FormData();
for (let key in form) {
Array.isArray(form[key])
? form[key].forEach(value => formData.append(key + '[]', value))
: formData.append(key, form[key]) ;
}
Si vous avez des objets et des tableaux imbriqués, le meilleur moyen de renseigner un objet FormData consiste à utiliser la récursivité.
function createFormData(formData, data, key) {
if ( ( typeof data === 'object' && data !== null ) || Array.isArray(data) ) {
for ( let i in data ) {
if ( ( typeof data[i] === 'object' && data[i] !== null ) || Array.isArray(data[i]) ) {
createFormData(formData, data[i], key + '[' + i + ']');
} else {
formData.append(key + '[' + i + ']', data[i]);
}
}
} else {
formData.append(key, data);
}
}
Basé sur @YackY, répondez à la version plus courte de la récursivité:
function createFormData(formData, key, data) {
if (data === Object(data) || Array.isArray(data)) {
for (var i in data) {
createFormData(formData, key + '[' + i + ']', data[i]);
}
} else {
formData.append(key, data);
}
}
Exemple d'utilisation:
var data = {a: '1', b: 2, c: {d: '3'}};
var formData = new FormData();
createFormData(formData, 'data', data);
Données envoyées:
data[a]=1&
data[b]=2&
data[c][d]=3
Version suivante valide pour les modèles contenant des tableaux de valeurs simples:
function convertModelToFormData(val, formData = new FormData(), namespace = '') {
if((typeof val !== 'undefined') && (val !== null)) {
if(val instanceof Date) {
formData.append(namespace, val.toISOString());
} else if(val instanceof Array) {
for(let element of val) {
convertModelToFormData(element, formData, namespace + '[]');
}
} else if(typeof val === 'object' && !(val instanceof File)) {
for (let propertyName in val) {
if(val.hasOwnProperty(propertyName)) {
convertModelToFormData(val[propertyName], formData, namespace ? namespace + '[' + propertyName + ']' : propertyName);
}
}
} else {
formData.append(namespace, val.toString());
}
}
return formData;
}