http_build_query () без URL-кодировки - PullRequest
54 голосов
/ 26 мая 2011

Есть ли способ использовать http_build_query() без кодирования URL в соответствии с каким-либо стандартом RFC?

Почему я не хочу, чтобы URL кодировал все: я запрашиваю API Ebay .. Оничестно настаивайте на том, чтобы имена параметров не были закодированы URL, насколько запятые в скобках.Например, DomainName (0) является параметром, и запрос завершается ошибкой, если эти символы скобок закодированы.

Ответы [ 10 ]

123 голосов
/ 23 декабря 2011

Вы можете использовать функцию urldecode() для строки результата, полученной из http_build_query()

6 голосов
/ 18 февраля 2017

PHP 5.3.1 (Поведение с ошибками) http_build_query DOES экранирует символ амперсанда '&', который присоединяется к параметрам.Пример: user_id=1&setting_id=2.

PHP 5.4 + http_build_query НЕ экранирует символ амперсанда '&', который присоединяется к параметрам.Пример: user_id=1&setting_id=2

Пример:

$params = array(
    'user_id' => '1', 
    'setting_id' => '2'
);
echo http_build_query($params);

// Output for PHP 5.3.1:
user_id=1&setting_id=2   // NOTICE THAT: '&' character is escaped

// Output for PHP 5.4.0+:
user_id=1&setting_id=2       // NOTICE THAT: '&' character is NOT escaped

Решение при нацеливании на несколько версий

Параметр № 1: Написать функцию-обертку:

/** 
 * This will work consistently and will never escape the '&' character
 */
function buildQuery($params) {
    return http_build_query($params, '', '&');
}

Вариант № 2: Отключите функцию http_build_query и напишите свою собственную.

6 голосов
/ 26 мая 2011

Нет, кажется, что он всегда хочет кодировать (что следует, он предназначен для кодирования URL при построении списка параметров для URL).

Вы могли бы сделать свой собственный ...

$params = array('a' => 'A', 'b' => 'B');

$paramsJoined = array();

foreach($params as $param => $value) {
   $paramsJoined[] = "$param=$value";
}

$query = implode('&', $paramsJoined);

CodePad .

4 голосов
/ 04 апреля 2012

http_build_query () недействителен без urlencoding. Может быть, вы случайно дважды его закодировали? Например, попробуйте построить запрос http для этого массива:

$params = array('a' => 'a&b=b');

Без кодирования вы получите

a=a&b=b

При правильном кодировании вы получите

a=a%26b%3Db

что правильно. Если вы пропустите кодировку, избегайте атак с использованием URL-адреса.

4 голосов
/ 26 мая 2011

Вместо этого вы можете попробовать их JSON API. Я попытался получить рабочий образец, но у меня нет имени приложения, поэтому я не могу проверить результат. Вот код:

<?php
$appName = "Your App Name Here";

$post_data = array(
  'jsonns.xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
  'jsonns.xs' => 'http://www.w3.org/2001/XMLSchema',
  'jsonns.tns' => 'http://www.ebay.com/marketplace/search/v1/services',
  'tns.findItemsByKeywordsRequest' => array(
    'keywords' => 'harry potter pheonix'
  )
);

$headers = array(
  "X-EBAY-SOA-REQUEST-DATA-FORMAT: JSON", 
  "X-EBAY-SOA-RESPONSE-DATA-FORMAT: JSON",
  "X-EBAY-SOA-OPERATION-NAME: findItemsByKeywords",
  "X-EBAY-SOA-SECURITY-APPNAME: $appName"
);

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'http://svcs.ebay.com/services/search/FindingService/v1');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

$result = curl_exec($ch);
if($result) {
  $response = json_decode($result);
}

curl_close($ch);
?>

Вам нужно будет заполнить $appName любым названием приложения. Также X-EBAY-SOA-OPERATION-NAME необходимо будет установить для фактического вызова, а JSON изменить, если вызов отличается.

3 голосов
/ 25 августа 2015

Вы можете использовать urldecode () . Или используйте http_build_query с аргументом $ arg_separator .

    $query_data= $data = array('bar', 'baz'=>'boom');
    $numeric_prefix= 'test_';
    $arg_separator = '&';
    $http_query = http_build_query ( $query_data, $numeric_prefix, $arg_separator );
    var_dump( $http_query );

результат вышеупомянутого равен

     string 'test_0=bar&baz=boom' (length=19)

numeric_prefix : если индексы массива являются числами, эта строка добавляется в качестве префикса в каждый индекс. В этом случае ' test_0 = bar' .

arg_separator : используется для разделения аргументов. Если не указан php, используйте arg_separator.output , отличающийся от php.ini

См. php http_build_query

0 голосов
/ 31 августа 2018

Я пытался создать строку GET, чтобы прикрепить ее к концу URL-адреса, как это -

$get_params = array(
    'include' => array(
        'enrollments',
        'current_grading_period_scores'
    ),
    'enrollment_type' => array(
        'student',
    ),

);
$get_params = http_build_query($get_params);
$get_params = urldecode($get_params);
$url = $domain.$slug;
$url = $url.'?'.$get_params;
echo $url;

, который печатает

include[0]=enrollments&include[1]=current_grading_period_scores&enrollment_type[0]=student

Но мой API некак числа в квадратных скобках, поэтому я нашел регулярное выражение, которое удаляет числа -

preg_replace('/[[0-9]+]/', '[]', $get_params);

Окончательный код, а результат -

$get_params = array(
    'include' => array(
        'enrollments',
        'current_grading_period_scores'
    ),
    'enrollment_type' => array(
        'student',
    ),

);
$get_params = http_build_query($get_params);
$get_params = urldecode($get_params);
$get_params = preg_replace('/[[0-9]+]/', '[]', $get_params);
$url = $domain.$slug;
$url = $url.'?'.$get_params;
echo $url;

Распечатывает -

include[]=enrollments&include[]=current_grading_period_scores&enrollment_type[]=student

Если кто-то знает о лучшем регулярном выражении, дайте мне знать, я схожу с ума от этого.

0 голосов
/ 21 мая 2018

Я пытался сделать это недавно https://gist.github.com/marcocesarato/4293986fe93139f04d8269aa3fbd47e9 разница в том, что эта функция рекурсивна и совместима с PHP4. Вы можете управлять здесь urlencode

<?php
/**
 * Build URL query params
 * as http_build_query build a query url the difference is 
 * that this function is array recursive and compatible with PHP4
 *
 * @author Marco Cesarato <cesarato.developer@gmail.com>
 * @param $query
 * @param string $parent
 * @return string
 *
 * @example
 * $p = array('abbreviations' => array('google' => 'ggle', 'facebook' => array('abb_key' => 'fbook', 'fcbk')), 'key' => 'value');
 * echo url_build_query($p);
 */
function url_build_query($query, $parent = null){
    $query_array = array();
    foreach($query as $key => $value){
        $_key = empty($parent) ?  urlencode($key) : $parent . '[' . urlencode($key) . ']';
        if(is_array($value)) {
            $query_array[] = url_build_query($value, $_key);
        } else {
            $query_array[] = $_key . '=' . urlencode($value);
        }
    }
    return implode('&', $query_array);
}
0 голосов
/ 31 августа 2012

Это также может работать

$fields = array(
    'a' => 'A', 
    'b' => 'B'
 );

$separator = '';
foreach($fields as $key=>$value) {
    $fields_string .= $separator . $key . '=' . $value; 
    $separator = '&'; 
}
0 голосов
/ 27 сентября 2011

я принимаю ответ Алекса, но быстрее

$params = array('a' => 'A', 'b' => 'B');
$query = '';

foreach ($params as $param => $value) {
   $query .= $param.'='.$value .'&';
}

echo substr($query, 0, -1);
...