programing

쿼리 문자열 내에서 어레이를 전달하려면 어떻게 해야 합니까?

randomtip 2022. 11. 2. 23:03
반응형

쿼리 문자열 내에서 어레이를 전달하려면 어떻게 해야 합니까?

쿼리 문자열을 통해 어레이를 전달하는 표준 방법이 있습니까?

명확하게 하기 위해 여러 값을 가진 쿼리 문자열이 있으며, 그 중 하나가 배열 값입니다.이 쿼리 문자열 값을 배열로 처리하여 다른 쿼리 문자열 변수와 구분할 수 없도록 배열을 분해하지 마십시오.

, 이 투고 회답에 의하면, 작성자는 어레이에 대한 쿼리 문자열 지원은 정의되어 있지 않다고 제안하고 있습니다.이게 맞습니까?

편집:

@Alex의 답변에 따르면 표준적인 방법은 없습니다.그러면 제가 읽고 있는 파라미터가 PHP와 Javascript의 배열임을 알기 쉬운 방법은 무엇일까요?

여러 개의 파라미터에 같은 이름을 붙여서 그것들이 어레이에 속해 있다는 것을 알 수 있을까요?예를 들어:

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

아니면 이게 나쁜 관행일까요?

제가 알아낸 건 다음과 같습니다.

GET/POST 변수를 통해 어레이를 전송하는 등 여러 가지 방법으로 다중값 폼 필드를 제출할 수 있습니다.표준이 반드시 명기되어 있는 것은 아니기 때문입니다.

멀티값 필드 또는 어레이를 송신하는 방법에는, 다음의 3가지가 있습니다.

  • ?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[]다중값의 경우 문서가 제대로 작성되지 않았습니다.Query string - Wikipedia의 다중값 키에 대한 섹션이나 다중선택 입력을 다루는 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.wordpress, ASP.net 의 예에 대해서는, 코멘트를 참조해 주세요.


순서 유지:한 가지 더 고려해야 할 사항은 항목 순서(순서 있는 목록으로 배열)를 유지해야 하는 경우 구분된 값 목록을 전달하고 직접 배열로 명시적으로 변환하는 옵션만 실제로 사용할 수 있다는 것입니다.

쿼리 문자열은 텍스트 데이터를 전송하므로 어레이를 분해하고 올바르게 인코딩한 후 원하는 표현 형식으로 전달할 수 밖에 없습니다.

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

서버측 코드로 디코딩합니다.

기준이 없는 것 같아요.
각 웹 환경은 이러한 것들에 대한 고유한 '표준'을 제공합니다.또한 URL은 보통 너무 짧습니다(브라우저에 따라서는 256바이트 제한).물론 긴 어레이/데이터는 POST 요청과 함께 전송할 수 있습니다.

다만, 몇개의 방법이 있습니다.

  1. 대괄호를 사용하는 PHP 방법이 있습니다.[,])를 참조해 주세요.예를 들어 다음과 같은 쿼리입니다.?array_name[]=item&array_name[]=item_2PHP가 자동으로 어레이로 변환하여 문서화가 불충분함에도 불구하고 작동하는 것으로 알려져 있습니다.출처 : https://stackoverflow.com/a/9547490/3787376

  2. 오브젝트 데이터 교환 형식(예: JSON - 공식 웹사이트, PHP 설명서)은 JSON과 같이 변수를 문자열로 변환하는 방법을 가지고 있는 경우에도 사용할 수 있습니다.
    또한 문자열 데이터를 올바르게 인코딩하기 위해서는 HTTP get 요구를 위해 URL 인코더(대부분의 프로그래밍 언어에서 사용 가능)가 필요합니다.

"각괄호 방식"은 간단하고 작동하지만 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.

이것으로 충분합니다.

링크에서 속성의 값은 다음과 같습니다.

to="/filter/arr?fruits=apple&fruits=banana"

루트에서는 다음 사항을 처리할 수 있습니다.

path="/filter/:arr"

다중 어레이의 경우:

to="filter/arr?fruits=apple&fruits=banana&vegetables=potato&vegetables=onion"

루트는 그대로입니다.

스크린샷

여기에 이미지 설명 입력

업데이트: 이 문자열 구조를 구현하려면 query-string이 최상의 패키지입니다.

예를 들어 다음과 같습니다.

import { stringify, parse } from 'query-string';

const queryParams={
   fruits:['apple','banana'],
   vegetables:['potato','onion']
}
//arrayFormat can be bracket or comma 
stringify(queryParams, { arrayFormat: 'bracket' });

URL 부분에는 표준이 없지만 JavaScript에는 표준이 하나 있습니다.어레이를 포함하는 개체를 전달한 경우URLSearchParams, 및 콜toString()이 경우 쉼표로 구분된 항목 목록으로 변환됩니다.

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

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

쿼리 문자열의 어레이를 서블릿으로 전달하고 싶은 사람에게 도움이 될 것 같습니다.아래 쿼리 문자열을 테스트하여 req.getParameterValues(); 메서드를 사용하여 배열 값을 얻을 수 있었습니다.아래는 브라우저를 통해 전달한 쿼리 문자열입니다.

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

체크박스는 파라미터 배열입니다.

query-string 모듈에는 지원되는 다양한 유형의 배열 부호화가 나열되어 있습니다(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

이것은, 많은 솔루션이 채용되고 있는 것을 나타내고 있습니다.

리액트와 레일을 사용합니다.나는 했다:

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에 어레이를 전달할 목적으로 이 질문에 도달했습니다.순액션

여기서 제 질문에 대한 답을 찾았습니다.여러 파라미터가 같은 이름을 가진 것으로 예상되는 형식이 질문에서 제안하신 형식입니다.

http_build_query를 사용하여 PHP 배열에서 URL 인코딩 쿼리 문자열을 생성할 수 있습니다.결과 쿼리 문자열이 확장되는 동안 파라미터로 원하는 고유 구분 기호를 결정할 수 있습니다.http_build_query그 때문에, 디코딩에 관해서라면, 어떤 세퍼레이터가 사용되고 있었는지 확인할 수 있습니다.선택한 것이 고유할 경우 어레이 쿼리 스트링이 됩니다.그렇지 않을 경우 일반 쿼리 스트링이 됩니다.

이러한 기능을 사용할 수 있지만 오브젝트 키에 '-'를 사용하지 않도록 하십시오.

// convert obj to url params
function objToUrlParams(obj) {
    let toUrlParams = (obj, prefex = '') => {

        // create url params
        let urlParams = "";

        // loop through obj
        for (let key in obj) {
            let val = obj[key];

            if (val == null) continue;
            if (val == undefined) continue;
            // if(val == '') continue;

            // if val is an object then call toUrlParams
            if (val instanceof Array) {
                // convert val from Array to object
                let valToObj = {};
                val.forEach((v, i) => {
                    valToObj[i] = v;
                });

                val = valToObj;
            }

            let newPrefex = prefex + key;

            if (val instanceof Object) {
                urlParams += toUrlParams(val, newPrefex + '-');
            } else {
                urlParams += newPrefex + '=' + val;
            }

            urlParams += '&';
        }

        // remove last &
        urlParams = urlParams.slice(0, -1);

        // return url params
        return urlParams;

    }

    // encodeURI
    return encodeURI(toUrlParams(obj));
}

// convert url params to obj
function urlParamsToObj(urlParams) {

    // decodeURI
    urlParams = decodeURI(urlParams);

    let toObj = (urlParams) => {

        let obj = {};

        let urlParamsArr = urlParams.split('&');

        let subUrlParramsObj = {};

        // loop through urlParams
        for (let i = 0; i < urlParamsArr.length; i++) {
            let item = urlParamsArr[i];

            // get key and value
            let key = item.split('=')[0];
            let val = item.split('=')[1] ?? null;
            let keys = key.split('-');

            if (val == "null") {
                val = null;
            } else if (val == "undefined") {
                val = undefined;
            } else if (val == "true") {
                val = true;
            } else if (val == "false") {
                val = false;
            } else if (val == "NaN") {
                val = NaN;
            } else if (val == "Infinity") {
                val = Infinity;
            }

            // if keys length is 1 then set obj[key] to val
            if (keys.length == 1) {
                // check if obj contains key
                if (obj.hasOwnProperty(key)) {
                    // if obj[key] is an array then push val
                    if (obj[key] instanceof Array) {
                        obj[key].push(val);
                    } else {
                        // create array and push val
                        obj[key] = [obj[key], val];
                    }
                } else {
                    obj[key] = val;
                }
            }
            // if keys length is 2 then set obj[keys[0]][keys[1]] to val
            else if (keys.length > 1) {

                let key0 = keys[0];

                // check if subUrlParramsObj contains keys[0]
                if (!subUrlParramsObj[key0]) {
                    subUrlParramsObj[key0] = [];
                }

                // remove keys[0] from keys
                keys.shift();
                // join keys with -
                key = keys.join('-');

                let param = key + '=' + val;

                // add param to subUrlParramsObj[keys[0]]
                subUrlParramsObj[key0].push(param);

            }

        }

        // loop through subUrlParramsObj
        for (let key in subUrlParramsObj) {

            // join subUrlParramsObj[key] with &
            let val = subUrlParramsObj[key].join('&');

            // set obj[key] to val
            obj[key] = toObj(val);

        }

        // return obj
        return obj;

    }

    return checkIfObjShouldBeArrayAndConvert(toObj(urlParams));

}

// check if object should be converted to array, if its keys are numbers
function checkIfObjShouldBeArrayAndConvert(obj) {

    // if obj is an array
    if (obj instanceof Array) {
        // loop through obj
        obj.forEach((item, i) => {
            // check if item is an object
            if (item instanceof Object) {
                // convert item to array
                obj[i] = checkIfObjShouldBeArrayAndConvert(item);
            }
        });

        // return obj
        return obj;
    }

    // check if all keys are numbers
    let canConvertToArray = true;
    for (let key in obj) {

        // get value
        let val = obj[key];

        // check if value is an object or Array
        if (val instanceof Object || val instanceof Array) {
            obj[key] = checkIfObjShouldBeArrayAndConvert(val);
        }

        if (isNaN(key)) {
            canConvertToArray = false;
        }
    }

    // order obj by keys
    let orderedObj = {};
    Object.keys(obj).sort().forEach(function(key) {
        orderedObj[key] = obj[key];
    });

    // check if the first key is 0
    if (Object.keys(orderedObj)[0] != 0) {
        canConvertToArray = false;
    }

    // check if the keys step is 1
    let keys = Object.keys(orderedObj);
    // loop through keys
    for (let i = 0; i < keys.length - 1; i++) {
        // get key
        let key = keys[i];
        // get next key
        let nextKey = keys[i + 1];
        // get key step
        let keyStep = nextKey - key;
        // check if key step is 1
        if (keyStep != 1) {
            canConvertToArray = false;
            break;
        }
    }

    // if all keys are numbers then convert obj to array
    if (canConvertToArray) {
        let arr = [];
        for (let key in orderedObj) {
            arr.push(orderedObj[key]);
        }
        return arr;
    }

    // return obj
    return obj;
}

// add params to url
function addParamsToUrl(params, url = window.location.href) {

    // check if url has params
    if (url.indexOf('?') == -1) {
        url += '?';
    } else {
        url += '&';
    }

    return url + params ?? '';
}

function addObjToUrl(obj, url = window.location.href) {
    return addParamsToUrl(objToUrlParams(obj), url);
}

// extract params from url
function extractParamsFromUrl(url = window.location.href) {
    return urlParamsToObj(url.split('?')[1]);
}
// test
let urlParams = objToUrlParams({
    a: 1,
    b: "zad",
    c: {
        d: 2,
        e: "f"
    },
    j: [1, 2, 3, 4]
});
console.log(urlParams); // a=1&b=zad&c-d=2&c-e=f&j=1&j=2&j=3&j=4

let obj = urlParamsToObj(urlParams);
console.log(obj); // { "a": "1", "b": "zad", "j": [ "1", "2", "3", "4" ], "c": { "d": "2", "e": "f" } }

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

?>

언급URL : https://stackoverflow.com/questions/6243051/how-to-pass-an-array-within-a-query-string

반응형