Как правильно в php принять массив из formData js?

Ссылка скопирована
1 ответ

Добрый день!

Столкнулся с такой проблемой. Не могу принять массив в php, который закидываю в formData.

Массив формирую вот так:

//объявляем массив для сохранения значений         const messagesValue = [];                  //функция добавления объекта(пары ключ значение) в массив         function addDataPair(key,value){             let pair = {key: key, value: value};             messagesValue.push(pair);         }          //перебираем массив сообщений         messages.forEach(element => {             if (element.classList.contains('AB__chat__inner__center__bot')) {                 addDataPair("Оператор: ", (element.children[0]).textContent);             }             else if (element.classList.contains('AB__chat__inner__center__people')) {                 addDataPair("Вы: ", (element.children[0]).textContent);             }         });

//объявляем массив для сохранения значений const messagesValue = []; //функция добавления объекта(пары ключ значение) в массив function addDataPair(key,value){ let pair = {key: key, value: value}; messagesValue.push(pair); } //перебираем массив сообщений messages.forEach(element => { if (element.classList.contains('AB__chat__inner__center__bot')) { addDataPair("Оператор: ", (element.children[0]).textContent); } else if (element.classList.contains('AB__chat__inner__center__people')) { addDataPair("Вы: ", (element.children[0]).textContent); } });

дальше осуществляю отправку...

......... .onSuccess((event) => {             let formData = new FormData();             formData.append('messages', JSON.stringify(array));                         console.log(...formData);              let xhr = new XMLHttpRequest();              xhr.onreadystatechange = function () {                 if (xhr.readyState === 4) {                     if (xhr.status === 200) {                         // console.log('Отправлено');                     }                 }             }              xhr.open('POST', 'mail.php', true);             xhr.send(formData);              event.target.reset();         }); ............

......... .onSuccess((event) => { let formData = new FormData(); formData.append('messages', JSON.stringify(array)); console.log(...formData); let xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if (xhr.status === 200) { // console.log('Отправлено'); } } } xhr.open('POST', 'mail.php', true); xhr.send(formData); event.target.reset(); }); ............

в php пытаюсь принять так:

..... $data = json_decode($_POST['messages']);  ...

..... $data = json_decode($_POST['messages']); ...

Но данные не принимаются и не парсятся ни в какую... Если в форм дату закидываю event.target, то все работает....как только передаю массив -- по нулям.

Заранее спасибо за любую помощь.

Дополнительно:

а разве формдата может принимать целый json в аппенд? 0_О

  • imko, на просторах интернета находил.не утверждаю что правильно..до этого пробовал через цикл через apend в формдату добавить без json, но принять тоже не получилось...принимать пытался $_POST['Key1'] и т.д
  • Надеюсь, посылается не array, как в сейчас в коде, а messagesValue?
  • rvitalia, каких просторах? MDN просто открой, там описано все подробно
  • rvitalia, что в объекте проверял по итогу? я вижу консоль лог но формдата просто так в консоль не выводится, там не видно будет что в ней
  • ksnk, а нет проверил, это уже кусок из другой функции, и она как раз array приняла и его отправляет...
  • imko, вот вывод с консоли......

    ['messages', '[{"key":"Вы: ","value":"ооалотп"},{"key":"Оператор…value":"рп"}...................]']... то есть 0 это ключ который установил, а 1 - это строка json..

  • imko, при чем здесь json, если append() принимает blob или string, а JSON.stringify() возвращает string? Какая разница в каком строка формате, то что это json-строка не делает ее не строкой.
  • rvitalia, Ну, если посылается примерно то, что надо - нужно смотреть данные в php. В логи, например бросать. Смотреть что в Post, потом смотреть есть ли ошибки в json_decode.
  • rvitalia, так посмотрите какой console.log(...formData) после закидывания event.target, возможно там есть какие-то ключи (идентификация формы, антиспам, и тп), которых вам не хватает.
  • Браузер, F12. Вкладка "Сеть". При отправки formData появляется запрос на сервер?
    На тот ли скрипт сервера отправляет? (правильный путь до php?)
    Если открыть строчку в сети этого запроса. Ваш json появился в "Полезной нагрузке" запроса?
  • Rise, в том что автор наверняка ожидает что ему отдельные поля придут а не все под одним ключом
  • imko, это вам так кажется, автор же написал, что под одним ключом с json не принимает, и под разными ключами без json не принимает.
  • alexalexes, да,все есть и видно. Все везде правильно...
  • Всем спасибо... Натолкнули на мысль, что я допускал одну очень простую ошибку..... Итак, по логике работы данного кода, помимо массива я передавал еще и почту, на которую нужно отправить данные. Соответсвенно, убирая event.target из formData я конечно терял введенное значение и массив то может и принимался, только куда его и что с ним делать....код не знал... по итогу, решение такое:
    Во первых решил остаться все-таки на formData, т.к. возможно в скором времени понадобиться пересылка файлов.
    Во вторых. просто собрал массив, а не массив объектов, как было до этого.
    как-то так

    //объявляем массив для сохранения значений         const messagesValue = [];                  //перебираем массив сообщений         messages.forEach(element => {             if (element.classList.contains('AB__chat__inner__center__bot')) {                 messagesValue.push("Оператор: " + (element.children[0]).textContent);             }             else if (element.classList.contains('AB__chat__inner__center__people')) {                 messagesValue.push('Вы: ' + (element.children[0]).textContent);             }         });

    //объявляем массив для сохранения значений const messagesValue = []; //перебираем массив сообщений messages.forEach(element => { if (element.classList.contains('AB__chat__inner__center__bot')) { messagesValue.push("Оператор: " + (element.children[0]).textContent); } else if (element.classList.contains('AB__chat__inner__center__people')) { messagesValue.push('Вы: ' + (element.children[0]).textContent); } });

    в третьих. formdata формирую следующим образом:

    validation         .onSuccess((event) => {             let formData = new FormData();              formData.append('key1', JSON.stringify(array));             formData.append('key2', input);              let xhr = new XMLHttpRequest();              xhr.onreadystatechange = function () {                 if (xhr.readyState === 4) {                     if (xhr.status === 200) {                         alert('');                     }                 }             }             xhr.open('POST', 'mail.php', true);             xhr.send(formData);              event.target.reset();         }); }

    validation .onSuccess((event) => { let formData = new FormData(); formData.append('key1', JSON.stringify(array)); formData.append('key2', input); let xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if (xhr.status === 200) { alert(''); } } } xhr.open('POST', 'mail.php', true); xhr.send(formData); event.target.reset(); }); }

    ну и наконец, принимаю это дело так

    if (isset($_POST['key1'])) {   $array = json_decode($_POST['key1']); ..............    $inputValue = $_POST["key2"];

    if (isset($_POST['key1'])) { $array = json_decode($_POST['key1']); .............. $inputValue = $_POST["key2"];

    По итогу все заработало. Невнимательность прежде всего.... всем спасибо, и будьте внимательны))

    Ответы:

    Если ты отправляешь не файлы, то нет смысла использовать FormData, просто отправляй JSON-строку напрямую.

    let xhr = new XMLHttpRequest();  xhr.open('POST', 'mail.php', true);  xhr.setRequestHeader('Content-Type', 'text/plain');  xhr.onreadystatechange = function() {      if (xhr.readyState === 4) {          if (xhr.status === 200) {              console.log('Ответ сервера:', xhr.responseText);          }      }  }  console.log('Отправляем:', array);  xhr.send(JSON.stringify(array));

    let xhr = new XMLHttpRequest(); xhr.open('POST', 'mail.php', true); xhr.setRequestHeader('Content-Type', 'text/plain'); xhr.onreadystatechange = function() { if (xhr.readyState === 4) { if (xhr.status === 200) { console.log('Ответ сервера:', xhr.responseText); } } } console.log('Отправляем:', array); xhr.send(JSON.stringify(array));

    На стороне PHP принимаешь данные так:

    <?php  header('Content-Type: text/plain');  $array = json_decode(file_get_contents('php://input'), true);  echo 'Из браузера получены данные: ' . print_r($array, true);

    <?php header('Content-Type: text/plain'); $array = json_decode(file_get_contents('php://input'), true); echo 'Из браузера получены данные: ' . print_r($array, true);

    • А зачем text/plain, когда json это application/json?
    • Rise, при POST запросах из браузера на сервер бывают 2 типа запросов: простые и сложные.

      Простые запросы это запросы с кодировками:
      1) application/x-www-form-urlencoded
      2) multipart/form-data
      3) text/plain

      Все остальные кодировки делают запрос сложными. При сложных запросах браузер перед отправкой запроса всегда делает так называемый предзапрос, в консоли такие запросы можно увидеть с пометкой OPTION и так уж выходит, если ты пропишешь application/json оно конечно будет работать, но браузер будет вместо одного запроса отправлять 2 запроса: сначала предзапрос (чтобы проверить соответствие CORS) и только потом сам запрос.

      P. S. Это касается только запросов на другие домены, если запрос на свой собственный домен идет, то можешь смело ставить application/json, предзапросов не будет, но если вдруг обработчик у тебя на другом сайте, лучше использовать text/plain - собственно это универсальное решение, проще сразу изначально везде так делать.

      https://learn.javascript.ru/fetch-crossorigin#nepr....

    • zkrvndm, по вашей ссылке написано что предзапрос кешируется заголовком Access-Control-Max-Age, поэтому он не выполняется каждый запрос.

      А если отойти от PHP-сервера, в котором нет из коробки автопарсинга json-запросов, то почему вы думаете что его не может быть в других серверах, технологиях, языках?

    • Rise, кешируется, я не спорю, но касается это вроде бы только GET запросов, а при POST запросах кеширование по умолчанию не используется, более того я также указал, что это все касается только запросов на другие домены, при работе со своим сервером никаких предзапросов не будет, но тем не менее я часто на крупных портал вижу, что стандартной практикой считается отсылать JSON в кодировке text/plain - прям очень часто вижу такую практику.

      Также насчет кеша, замечу, что если мы игнорируем кеш при помощи добавления в адрес временной метки, ничего там кешироватся не будет и OPTIOS запросы будут всегда. Это опять же стандартная практика (насчет добавления временной метки для игнорирования кеша). Все же если мы отправляем запрос с данными, нам как правило не нужен ответ из кеша, а нужен актуальный ответ.

      К счастью, в данном вопросе стоит тег PHP поэтому и мой ответ касается исключительно PHP.

    • zkrvndm, причем здесь GET или POST, когда OPTIONS это другой метод запроса. Это отдельный запрос, вы же сами писали что их два: предзапрос и сам запрос. Вот этот предзапрос, выполненный методом OPTIONS и кешируется, если вы не поняли, а не сам запрос.

      Временные метки используются, чтобы функции или дизайн сайта обновлять в какой-нибудь CMS, например, script.js?ver=1234567890 или style.css?ver=1234567890 соответственно, не более.

    • Rise, не кешируется, если отправляем POST.
    • Rise, вот, смотри:

      Как правильно в php принять массив из formData js?

      Я отправил 3 POST запроса на один и тот же адрес и все три раза сначала шел предзапрос OPTIONS - не кешируется там ничего. Вместо того, чтобы вот так вот грузить сервер в 2 раза чаше, проще использовать text/plain! Такой запрос будет идти в 2 раза быстрее, за счет отсутствия предзапроса.

    • zkrvndm, так кешированные запросы тоже отображаются в консоле, просто там указано disk cache, но физически они на сервер не идут, ответы сервера хранятся в браузере и извлекаются на запрос, в этом и суть кэша.
    • Rise, по поводу временных меток ты не прав, это единственный гарантированный способ сделать запрос без кеша, поэтому такой подходи используется широко и везде.
    • Rise, нет, обрати внимание на черепашку, черепашки не бывает при использовании дискового кеша. Просто поверь на слово, texp/plain оптимальный вариант, особенно когда надо отправить и принять много данных. Когда речь идет о тысячах и тысячах запросов с секунду, каждый лишние 50 мс. на счету. Не наш случай конечно, но тем не менее, на крупных портал это обычная практика так засылать данные на бэкенд.
    • zkrvndm, то что у вас что-то не кешируется значит неправильно что-то делаете, как и здесь. А про "единственный" способ могу посоветовать вам ознакомиться с fetch-опцией cache.
    • Rise, которая работает только с fetch, ага. Вы что, думайте jQuery.ajax при cache: false зря штамп в адрес добавляет? Нет, эту либу умные люди писали, именно так максимально надежное игнорирование кеша получается.

      Что я неправильно делаю? Все я правильно делаю. Мне доводилось писать приложения которые за секунду шлют тысячи и тысячи запросов и проблема с тормозами из-за OPTIONS запросов это первое с чем я столкнулся и что мне пришлось решать.

    • zkrvndm, покажите пример php посмотрим что неправильно.
    • Rise, убедись сам:
      xhr = new XMLHttpRequest();  xhr.open('POST', 'https://nadim.work/test.php', true);  xhr.setRequestHeader('Content-Type', 'aplication/json');  xhr.onreadystatechange = function() {      if (xhr.readyState === 4) {          if (xhr.status === 200) {              console.log('Ответ сервера:', xhr.responseText);          }      }  }  xhr.send('{}');

      xhr = new XMLHttpRequest(); xhr.open('POST', 'https://nadim.work/test.php', true); xhr.setRequestHeader('Content-Type', 'aplication/json'); xhr.onreadystatechange = function() { if (xhr.readyState === 4) { if (xhr.status === 200) { console.log('Ответ сервера:', xhr.responseText); } } } xhr.send('{}');

    • zkrvndm, это не php это js.
    • Rise, да, речь про браузер же. OPTIONS запросы делает браузер с целью проверки на соответствие CORS. А ты чего ожидал?
    • Rise, я понял про что вы. Да, это по идее будет работать если адрес запроса все время фиксированный, но лично у меня так никогда не бывает, всегда все запросы с временным штампом делаю.
    • А мне надо в том же файле принять в PHP информацию из JS (localStorage). Неделю вот пытался делать и как тут сказано и иначе, всегда пустота лишь на стороне PHP.
      Пока мне помог лишь такой вариант:
      <script>         var js;         var obj = {}         for (var i = 0; i < localStorage.length; i++) {             var key = localStorage.key(i);             obj[key] = localStorage.getItem(key);         }         js = JSON.stringify(obj);     </script>

      <script> var js; var obj = {} for (var i = 0; i < localStorage.length; i++) { var key = localStorage.key(i); obj[key] = localStorage.getItem(key); } js = JSON.stringify(obj); </script>

      И чуть ниже в файле этом же:

      <?php if (isset($_POST['obj'])) {     $mainData = json_decode($_POST['obj'], true);     foreach ($mainData as $k => $v){         echo  $k . " === " . ($v + 232) . PHP_EOL;     } } else {     echo "<script type='text/javascript'>";     echo "document.write('<form method='post' id='f'>');";     echo "document.write('<input type='hidden' name='obj' value = '' + js + ''</p>');";     echo "document.write('</form>');";     echo "document.getElementById('f').submit()";     echo "</script>"; }

      <?php if (isset($_POST['obj'])) { $mainData = json_decode($_POST['obj'], true); foreach ($mainData as $k => $v){ echo $k . " === " . ($v + 232) . PHP_EOL; } } else { echo "<script type='text/javascript'>"; echo "document.write('<form method='post' id='f'>');"; echo "document.write('<input type='hidden' name='obj' value = '' + js + ''</p>');"; echo "document.write('</form>');"; echo "document.getElementById('f').submit()"; echo "</script>"; }

      Наверно это костыль, но я не знаю как ещё это сделать.
      Мне надо получить данные в файл и уже на уровне сервера, в PHP коде выводить эти данные и т.д.
      А то бывало в Console всё отправлялось, даже PHP мог в файл записать входные данные, т.е он их "видел".
      Но вот выводить и работать с ними в коде - нет. Пустота была.
      Может кто и подскажет как тут разрулить всё лучше.

    • EpIvIaK, так ты не отправляешь ничего, очевидно ты не совсем понимаешь как работает JS и PHP.
    • EpIvIaK, я делал как то чат ..и по ходу дела несколько раз передавал из js в php. данные из js через jquery передавал, на php через post кажется принимал...как то так.
    • rvitalia, рекомендую чат гпт попытать) Ты застрял на прописанных истинах, начини с основ, попроси у чат гпт примеры и пояснения.
    • zkrvndm, вот как я показал выше код - отправляет. Протестировал. PHP уже по полной принимает всё, отображает, в переменные записывает.
      Но и правда, в остальном тут и правда есть непонимание.
      Всякие fetch, FormData, Аякс пробовал.
      Данные так можно отослать серверу для файла или БД.

      Часто проблема новичков, что мы на локальной машине и как клиент и как сервер.
      Это немного не даёт ощущение разницы. Когда мы как клиент, а где-то там сервер. Раздельно.
      JS фурычит у Васи на его компьютере в браузере, а PHP там - на сервере. Но это в общем. А вот детали... Тут сложнее. Всё равно взаимодействие же идёт. Но не явно и просто.
      Ну да, мы дилетанты видимо. Учимся. Оно и понятно.

    • zkrvndm, кстати спасибо за ИИ совет. Что-то я забыл про него. И правда так быстрее чем колупать форумы.
    Нужно решить такую задачу?

    Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

    Заказать помощь
    Лучший ответ
    1
    Юрий Linux Ответ

    Для того чтобы правильно принять массив из FormData в PHP, необходимо выполнить несколько шагов.

    Во-первых, в JavaScript нужно создать объект FormData и добавить в него необходимые данные, включая массив. Например:

    ```javascript
    var formData = new FormData();
    formData.append('name', 'John Doe');
    formData.append('email', 'john.doe@example.com');
    formData.append('hobbies[]', 'Reading');
    formData.append('hobbies[]', 'Swimming');
    ```

    Здесь мы добавляем в объект formData два хобби в виде массива.

    Затем необходимо отправить этот объект на сервер, используя AJAX запрос. Например, с помощью jQuery:

    ```javascript
    $.ajax({
    url: 'process.php',
    type: 'POST',
    data: formData,
    processData: false,
    contentType: false,
    success: function(response) {
    console.log(response);
    }
    });
    ```

    На стороне сервера, в файле process.php, мы можем получить данные из объекта FormData следующим образом:

    ```php
    $name = $_POST['name'];
    $email = $_POST['email'];
    $hobbies = $_POST['hobbies'];

    echo 'Name: ' . $name . '
    ';
    echo 'Email: ' . $email . '
    ';
    echo 'Hobbies: ' . implode(', ', $hobbies);
    ```

    В данном примере мы получаем данные из объекта FormData и выводим их на экран. Обратите внимание, что данные из массива hobbies будут доступны в PHP как обычный массив.

    Таким образом, правильно принять массив из FormData в PHP можно, используя объект FormData в JavaScript, AJAX запрос для отправки данных на сервер и обработку данных на стороне PHP.

    Другие ответы (0)

    Пока нет других ответов. Будьте первым, кто поможет автору.

    Ответить на вопрос

    комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *

    Вам также может быть интересно