Как передать массив в строке запроса?

Есть ли стандартный способ передачи массива через строку запроса?

Чтобы было ясно, у меня есть строка запроса с несколькими значениями, одним из которых будет значение массива. Я хочу, чтобы это значение строки запроса обрабатывалось как массив - я не хочу, чтобы массив разбирался так, чтобы он был неотличим от других переменных строки запроса.

Кроме того, согласно этому пост-ответу, автор предполагает, что поддержка строки запроса для массивов не определена. Это точно?

РЕДАКТИРОВАТЬ:

Основываясь на ответе @Alex, стандартного способа сделать это не существует, поэтому я продолжу, как легко определить, что параметр, который я читаю, является массивом как в PHP, так и в Javascript?

Было бы приемлемо назвать несколько параметров одним и тем же именем, и таким образом я бы знал, что они принадлежат массиву? Пример:

?myarray=value1&myarray=value2&myarray=value3...

Или это будет плохая практика?

13 ответов

Решение

Вот что я понял:

Отправка полей формы с несколькими значениями, то есть отправка массивов с помощью переменных GET/POST, может осуществляться несколькими различными способами, поскольку стандарт не обязательно прописан.

Три возможных способа отправки многозначных полей или массивов:

  • ?cars[]=Saab&cars[]=Audi (Лучший способ - PHP читает это в массив)
  • ?cars=Saab&cars=Audi (Плохой путь - PHP будет регистрировать только последнее значение)
  • ?cars=Saab,Audi (Не пробовал это)

Примеры форм

В форме многозначные поля могут принимать форму поля выбора, установленного в несколько значений:

<form> 
    <select multiple="multiple" name="cars[]"> 
        <option>Volvo</option> 
        <option>Saab</option> 
        <option>Mercedes</option> 
    </select>
</form>

(ПРИМЕЧАНИЕ: в этом случае было бы важно назвать имя элемента управления some_name[] , чтобы полученный запрос был зарегистрирован как массив в PHP)

... или как несколько скрытых полей с одинаковым именем:

<input type="hidden" name="cars[]" value="Volvo">
<input type="hidden" name="cars[]" value="Saab">
<input type="hidden" name="cars[]" value="Mercedes">

ПРИМЕЧАНИЕ. Использование field[] для нескольких значений действительно плохо документированы. Я не вижу упоминаний об этом в разделе о многозначных ключах в строке запроса - Википедии, или в документах W3C, посвященных вводу с множественным выбором.


ОБНОВИТЬ

Как отметили комментаторы, это очень сильно зависит от структуры. Некоторые примеры:

Строка запроса:

?list_a=1&list_a=2&list_a=3&list_b[]=1&list_b[]=2&list_b[]=3&list_c=1,2,3

Рельсы:

"list_a": "3", 
"list_b":[
    "1",
    "2",
    "3"
  ], 
"list_c": "1,2,3"

Угловой:

 "list_a": [
    "1",
    "2",
    "3"
  ],
  "list_b[]": [
    "1",
    "2",
    "3"
  ],
  "list_c": "1,2,3"

(Угловое обсуждение)

Смотрите комментарии для примеров в node.js, Wordpress, ASP.net


Поддержание порядка: еще одна вещь, которую следует учитывать, это то, что если вам нужно поддерживать порядок ваших элементов (т.е. массив как упорядоченный список), у вас действительно есть только одна опция, которая передает разделенный список значений и явно конвертирует его в массив сам.

Строка запроса содержит текстовые данные, поэтому нет другого выбора, кроме как взорвать массив, правильно его кодировать и передать в выбранном вами формате представления:

p1=value1&pN=valueN...
data=[value1,...,valueN]
data={p1:value1,...,pN:valueN}

а затем декодировать его в коде на стороне сервера.

Я не думаю, что есть стандарт.
Каждая веб-среда предоставляет свой "стандарт" для таких вещей. Кроме того, URL-адрес обычно слишком короткий для чего-либо (ограничение в 256 байт в некоторых браузерах). Конечно, более длинные массивы / данные могут быть отправлены с запросами POST.

Однако есть несколько методов:

  1. Есть способ PHP, который использует квадратные скобки ([,]) в URL-запросах. Например запрос, такой как ?array_name[]=item&array_name[]=item_2 было сказано, что он работает, несмотря на то, что он плохо документирован, PHP автоматически конвертирует его в массив. Источник: /questions/6804854/kak-peredat-massiv-v-stroke-zaprosa/6804862#6804862

  2. Форматы обмена объектными данными (например, JSON - официальный сайт, документация PHP) также могут использоваться, если у них есть методы преобразования переменных в и из строк, как это делает JSON.
    Кроме того, url-кодировщик (доступный для большинства языков программирования) требуется для запросов HTTP get для правильного кодирования строковых данных.

Хотя "метод квадратных скобок" прост и работает, он ограничен PHP и массивами.
Если требуются другие типы переменных, такие как классы или передаваемые переменные в строках запроса на языке, отличном от PHP, рекомендуется метод JSON.

Пример в PHP метода JSON (метод 2):

$myarray = array(2, 46, 34, "dfg");
$serialized = json_encode($myarray)
$data = 'myarray=' . rawurlencode($serialized);
// Send to page via cURL, header() or other service.

Код для получения страницы (PHP):

$myarray = json_decode($_GET["myarray"]); // Or $_POST["myarray"] if a post request.

Это работает для меня:

В ссылке, чтобы атрибут имел значение->

к ="/ фильтр / обр? фруктах = яблоко & фрукты = бананового"

Маршрут может справиться с этим->

Путь ="/ фильтр /: обры"

Для нескольких массивов

к = "фильтр / обр? фруктах = яблоко и фрукты = банан и овощи = картофель и овощи = лук"

Маршрут остается прежним.

СКРИНШОТ

введите описание изображения здесь

Хотя для части URL нет стандарта, для JavaScript есть один стандарт. Если вы передаете объекты, содержащие массивы, вURLSearchParams, и позвонить toString() на нем он преобразует его в список элементов, разделенных запятыми:

let data = {
  str: 'abc',
  arr: ['abc', 123]
}

new URLSearchParams(data).toString();  // ?str=abc&arr=abc,123

Обратите внимание, что модуль строки запроса перечисляет различные типы кодировки массива, которую он поддерживает ( https://www.npmjs.com/package/query-string ):

Например, {foo: ['1', '2', '3']} можно закодировать как:

      'foo[]=1&foo[]=2&foo[]=3'
'foo[0]=1&foo[1]=2&foo[3]=3'
'foo=1,2,3'
'foo=1&foo=2&foo=3'
// Any custom separator can be used:
'foo=1|2|3'
// ... and more custom formats

Это показывает, что существует множество решений ...

Я чувствую, что это будет полезно для тех, кто ищет передачу массива в строке запроса сервлету. Я протестировал приведенную ниже строку запроса и смог получить значения массива с помощью req.getgetParameterValues ​​(); метод. Ниже приведена строка запроса, которую я пропустил через браузер.

"http://localhost:8080/ServletsTutorials/*.html?myname=abc&initial=xyz&checkbox=a&checkbox=b"

флажок - это мой массив параметров здесь.

Я использую React и Rails. Я сделал:

js

  let params = {
    filter_array: ['A', 'B', 'C']
  }

  ...

  //transform params in URI

  Object.keys(params).map(key => {
    if (Array.isArray(params[key])) {
      return params[key].map((value) => `${key}[]=${value}`).join('&')
    }
  }
  //filter_array[]=A&filter_array[]=B&filter_array[]=C

Вы упоминаете PHP и Javascript в своем вопросе, но не в тегах. Я дошел до этого вопроса с намерением передать массив в действие MVC.Net.

Я нашел ответ на свой вопрос здесь: ожидаемый формат - это тот, который вы предложили в своем вопросе, с несколькими параметрами, имеющими одно и то же имя.

Вы можете использовать http_build_query для генерации строки запроса в кодировке URL из массива в PHP. Хотя результирующая строка запроса будет расширена, вы можете выбрать уникальный разделитель, который вы хотите использовать в качестве параметра для http_build_query метод, поэтому, когда дело доходит до декодирования, вы можете проверить, какой разделитель был использован. Если бы это был уникальный вариант, который вы выбрали, то это была бы строка запроса массива, иначе это были бы обычные строки запроса.

Вы можете использовать эти функции, но убедитесь, что вы не используете «-» на ключах вашего объекта.

Проверить parse_string функция http://php.net/manual/en/function.parse-str.php

Он вернет все переменные из строки запроса, включая массивы.

Пример с php.net:

<?php
$str = "first=value&arr[]=foo+bar&arr[]=baz";
parse_str($str);
echo $first;  // value
echo $arr[0]; // foo bar
echo $arr[1]; // baz

parse_str($str, $output);
echo $output['first'];  // value
echo $output['arr'][0]; // foo bar
echo $output['arr'][1]; // baz

?>

Если вы хотите использовать ?cars=Saab,Audi, Для подготовки строки запроса может потребоваться немного JavaScript.

Вот пример:

JavaScript

$('#form-filter').submit(function () {
    event.preventDefault();
    var cars = [];

    $('input[name="select_cars"]:checked').each(function (i) {
      cars.push($(this).val());
    });

    var url = new URL(window.location.href);

    var query_string = url.search;

    var search_params = new URLSearchParams(query_string); 

    if (cars.length == 0) {
       search_params.delete('select_cars');
    }
    else {
       search_params.set('select_cars', cars.join(','));
    }

    url.search = search_params.toString();

    var new_url = url.toString();

    window.location.replace(decodeURIComponent(new_url));
});

PHP


$carsFilter = $_SERVER['select_cars'];

if ($carsFilter) {
  // Converts carsFilter from String to an array.
  $carsFilter = preg_split ("/\,/", $carsFilter);
}

HTML

<label><input name="select_cars" type="checkbox" value="Audi" />Audi</label>
<label><input name="select_cars" type="checkbox" value="Saab" />Saab</label>

Это выглядит аккуратно при работе с массивом строк запроса из многих элементов.

Другие вопросы по тегам