Как объединить строки запроса в PHP

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

Я ищу функциональность, аналогичную.htaccess's qsa, Я понимаю, что это было бы довольно просто реализовать полностью вручную, однако есть ли встроенные функции, которые имеют дело со строками запроса, которые могли бы либо упростить, либо полностью решить эту проблему?

Пример набора ввода / результата:

Url="http://www.example.com/index.php/page?a=1"
QS ="?b=2"
Result="http://www.example.com/index.php/page?a=1&b=2"

-

Url="page.php"
QS ="?b=2"
Result="page.php?b=2"

6 ответов

Решение

Как насчет чего-то, что не использует расширения PECL и не является огромным набором скопированных и вставленных функций? Это все еще немного сложно, потому что вы соединяете две строки запроса и хотите сделать это не просто $old .= $new;

Мы будем использовать parse_url для извлечения строки запроса из желаемого URL, parse_str для анализа строк запроса, к которым вы хотите присоединиться, array_merge для их объединения и http_build_query для создания новой объединенной строки для нас.

// Parse the URL into components
$url = 'http://...';
$url_parsed = parse_url($url);
$new_qs_parsed = array();
// Grab our first query string
parse_str($url_parsed['query'], $new_qs_parsed);
// Here's the other query string
$other_query_string = 'that=this&those=these';
$other_qs_parsed = array();
parse_str($other_query_string, $other_qs_parsed);
// Stitch the two query strings together
$final_query_string_array = array_merge($new_qs_parsed, $other_qs_parsed);
$final_query_string = http_build_query($final_query_string_array);
// Now, our final URL:
$new_url = $url_parsed['scheme'] 
         . '://'
         . $url_parsed['host'] 
         . $url_parsed['path'] 
         . '?'      
         . $final_query_string;

Вы можете получить часть строки запроса из URL, используя:

$_SERVER['QUERY_STRING']

и затем добавьте его к URL в обычном режиме.

Если вы хотите указать свои собственные переменные в строке запроса, взгляните на:

http_build_query

Так что же произойдет, если URL-адреса конфликтуют? Если оба URL содержат b= компонент в строке запроса? Тебе нужно было бы решить, что повлияет.

Вот кусок кода, который делает то, что вы хотите, анализируя каждую строку как URL, а затем извлекая query часть URL и implode() возвращая их вместе.

$url="http://www.example.com/index.php/page?a=1";
$qs ="?b=2";

$url_parsed = parse_url($url);
$qs_parsed = parse_url($qs);

$args = array(
    $url_parsed['query'],
    $qs_parsed['query'],
);

$new_url = $url_parsed['scheme'];
$new_url .= '://';
$new_url .= $url_parsed['host'];
$new_url .= $url_parsed['path'];
$new_url .= '?';
$new_url .= implode('&', $args);

print $new_url;

Для этого нет встроенной функции. Тем не менее, вы можете использовать эту функцию из расширения http PECL,

http://usphp.com/manual/en/function.http-build-url.php

Например,

$url = http_build_url("http://www.example.com/index.php/page?a=1",
    array(
        "b" => "2"
    )
);

Это ряд функций, взятых из "фреймворка" WordPress, которые будут это делать, но это может быть слишком много:

add_query_arg ()

/**
 * Retrieve a modified URL query string.
 *
 * You can rebuild the URL and append a new query variable to the URL query by
 * using this function. You can also retrieve the full URL with query data.
 *
 * Adding a single key & value or an associative array. Setting a key value to
 * emptystring removes the key. Omitting oldquery_or_uri uses the $_SERVER
 * value.
 *
 * @since 1.0
 *
 * @param mixed $param1 Either newkey or an associative_array
 * @param mixed $param2 Either newvalue or oldquery or uri
 * @param mixed $param3 Optional. Old query or uri
 * @return string New URL query string.
 */
public function add_query_arg() {
    $ret = '';
    if ( is_array( func_get_arg(0) ) ) {
        $uri = ( @func_num_args() < 2 || false === @func_get_arg( 1 ) ) ? $_SERVER['REQUEST_URI'] : @func_get_arg( 1 );
    } else {
        $uri = ( @func_num_args() < 3 || false === @func_get_arg( 2 ) ) ? $_SERVER['REQUEST_URI'] : @func_get_arg( 2 );
    }

    if ( $frag = strstr( $uri, '#' ) ) {
        $uri = substr( $uri, 0, -strlen( $frag ) );
    } else {
        $frag = '';
    }

    if ( preg_match( '|^https?://|i', $uri, $matches ) ) {
        $protocol = $matches[0];
        $uri = substr( $uri, strlen( $protocol ) );
    } else {
        $protocol = '';
    }

    if ( strpos( $uri, '?' ) !== false ) {
        $parts = explode( '?', $uri, 2 );
        if ( 1 == count( $parts ) ) {
            $base = '?';
            $query = $parts[0];
        } else {
            $base = $parts[0] . '?';
            $query = $parts[1];
        }
    } elseif ( !empty( $protocol ) || strpos( $uri, '=' ) === false ) {
        $base = $uri . '?';
        $query = '';
    } else {
        $base = '';
        $query = $uri;
    }

    parse_str( $query, $qs );

    if ( get_magic_quotes_gpc() )
        $qs = format::stripslashes_deep( $qs );

    $qs = format::urlencode_deep( $qs ); // this re-URL-encodes things that were already in the query string
    if ( is_array( func_get_arg( 0 ) ) ) {
        $kayvees = func_get_arg( 0 );
        $qs = array_merge( $qs, $kayvees );
    } else {
        $qs[func_get_arg( 0 )] = func_get_arg( 1 );
    }

    foreach ( ( array ) $qs as $k => $v ) {
        if ( $v === false )
            unset( $qs[$k] );
    }

    $ret = http_build_query( $qs, '', '&' );
    $ret = trim( $ret, '?' );
    $ret = preg_replace( '#=(&|$)#', '$1', $ret );
    $ret = $protocol . $base . $ret . $frag;
    $ret = rtrim( $ret, '?' );
    return $ret;
}

stripslashes_deep ()

/**
 * Navigates through an array and removes slashes from the values.
 *
 * If an array is passed, the array_map() function causes a callback to pass the
 * value back to the function. The slashes from this value will removed.
 *
 * @since 1.0
 *
 * @param array|string $value The array or string to be stripped
 * @return array|string Stripped array (or string in the callback).
 */
function stripslashes_deep( $value ) {
    return is_array( $value ) ? array_map( array('self', 'stripslashes_deep'), $value ) : stripslashes( $value );
}

urlencode_deep ()

/**
 * Navigates through an array and encodes the values to be used in a URL.
 *
 * Uses a callback to pass the value of the array back to the function as a
 * string.
 *
 * @since 1.0
 *
 * @param array|string $value The array or string to be encoded.
 * @return array|string $value The encoded array (or string from the callback).
 */
public function urlencode_deep( $value ) {
    return is_array($value) ? array_map( array('self', 'urlencode_deep'), $value) : urlencode($value);
}

Вот еще одна функция для объединения параметров с существующим URL-адресом.

      public function mergeParamsToUrl(string $url, array $params)
    {
        $urlParts = parse_url($url);

        // Combine existing query string with new parameters
        $existingParams = [];
        if (isset($urlParts['query'])) {
            parse_str($urlParts['query'], $existingParams);
        }

        $mergedParams = array_merge($existingParams, $params);
        $mergedQueryString = http_build_query($mergedParams);

        // Reconstruct the URL
        $mergedUrl = "{$urlParts['scheme']}://{$urlParts['host']}{$urlParts['path']}";
        if ($mergedQueryString) {
            $mergedUrl .= '?'.$mergedQueryString;
        }

        if (isset($urlParts['fragment'])) {
            $mergedUrl .= '#'.$urlParts['fragment'];
        }

        return $mergedUrl;
    }
Другие вопросы по тегам