开发者

append query string to any form of URL

I ask user to input a URL in a text-box and need to append a query string to it.

Possible values of URLs can be like:

  1. http://www.example.com

  2. http://www.example.com/a/

  3. http://www.example.com/a/?q1=one

  4. http://www.example.com/a.html

  5. http://www.example.com/a.html?q1=one

N开发者_如何学Pythonow I need to add query string to it like "q2=two", so that output would be like:

  1. http://www.example.com/?q2=two

  2. http://www.example.com/a/?q2=two

  3. http://www.example.com/a/?q1=one&q2=two

  4. http://www.example.com/a.html?q2=two

  5. http://www.example.com/a.html?q1=one&q2=two

How can I achieve the following using PHP?


<?php

$urls = array(
         'http://www.example.com',
         'http://www.example.com/a/',
         'http://www.example.com/a/?q1=one',
         'http://www.example.com/a.html',
         'http://www.example.com/a.html?q1=one'
        );

$query = 'q2=two';

foreach($urls as &$url) {
   $parsedUrl = parse_url($url);
   if ($parsedUrl['path'] == null) {
      $url .= '/';
   }
   $separator = ($parsedUrl['query'] == NULL) ? '?' : '&';
   $url .= $separator . $query;
}

var_dump($urls);

Output

array(5) {
  [0]=>
  string(29) "http://www.example.com/?q2=two"
  [1]=>
  string(32) "http://www.example.com/a/?q2=two"
  [2]=>
  string(39) "http://www.example.com/a/?q1=one&q2=two"
  [3]=>
  string(36) "http://www.example.com/a.html?q2=two"
  [4]=>
  &string(43) "http://www.example.com/a.html?q1=one&q2=two"
}

CodePad.


$url is your URL. Use strpos function

if(strpos($url,'?') !== false) {
   $url .= '&q2=two';
} else {
   $url .= '?q2=two';
}


I know this is old, but I improved alex's answer to account for the "#" part of the string.

$urls = array(
    'http://www.example.com',
    'http://www.example.com/a/#something',
    'http://www.example.com/a/?q1=one#soe',
    'http://www.example.com/a.html',
    'http://www.example.com/a.html?q1=one'
    );

$query = 'q2=two';

foreach($urls as &$url) {
    $pound = "";
    $poundPos = -1;

    //Is there a #?
    if ( ( $poundPos = strpos( $url, "#" ) ) !== false )
    {
        $pound = substr( $url, $poundPos );
        $url = substr( $url, 0, $poundPos );
    }

    $separator = (parse_url($url, PHP_URL_QUERY) == NULL) ? '?' : '&';
    $url .= $separator . $query . $pound;
}

var_dump($urls);


This is the function I use:

/**
 * @param string $url
 * @param $query string|array
 * @return string
 */
public function appendQueryStringToURL(string $url, $query): string
{
    // the query is empty, return the original url straightaway
    if (empty($query)) {
        return $url;
    }

    $parsedUrl = parse_url($url);
    if (empty($parsedUrl['path'])) {
        $url .= '/';
    }

    // if the query is array convert it to string
    $queryString = is_array($query) ? http_build_query($query) : $query;

    // check if there is already any query string in the URL
    if (empty($parsedUrl['query'])) {
        // remove duplications
        parse_str($queryString, $queryStringArray);
        $url .= '?' . http_build_query($queryStringArray);
    } else {
        $queryString = $parsedUrl['query'] . '&' . $queryString;

        // remove duplications
        parse_str($queryString, $queryStringArray);

        // place the updated query in the original query position
        $url = substr_replace($url, http_build_query($queryStringArray), strpos($url, $parsedUrl['query']), strlen($parsedUrl['query']));
    }

    return $url;
}

It accepts query as string or array. Also it handles # in URL and removes the duplicated query strings automatically. Here is the test as well. Please replace CLASS_THAT_CONTAINS_appendQueryStringToURL with the correct class in your project:

public function testAppendQueryStringToURL()
{
    $helper = new CLASS_THAT_CONTAINS_appendQueryStringToURL();

    $inputsOutputs = [
        [
            'i' => 'http://www.example.com',
            'q' => 'q1=1',
            'o' => 'http://www.example.com/?q1=1'
        ],
        [
            'i' => 'http://www.example.com',
            'q' => 'q1=1&q2=2',
            'o' => 'http://www.example.com/?q1=1&q2=2'
        ],
        [
            'i' => 'http://www.example.com/a/',
            'q' => 'q1=1',
            'o' => 'http://www.example.com/a/?q1=1'
        ],
        [
            'i' => 'http://www.example.com/a.html',
            'q' => 'q1=1',
            'o' => 'http://www.example.com/a.html?q1=1'
        ],
        [
            'i' => 'http://www.example.com/a/?q2=2',
            'q' => 'q1=1',
            'o' => 'http://www.example.com/a/?q2=2&q1=1'
        ],
        [
            'i' => 'http://www.example.com/a.html?q2=two',
            'q' => 'q1=1',
            'o' => 'http://www.example.com/a.html?q2=two&q1=1'
        ],
        [
            'i' => 'http://www.example.com/a.html?q1=1&q2=2',
            'q' => 'q1=1',
            'o' => 'http://www.example.com/a.html?q1=1&q2=2'
        ],
        // overwrite the existing
        [
            'i' => 'http://www.example.com/a.html?q1=1&q2=2',
            'q' => 'q1=3',
            'o' => 'http://www.example.com/a.html?q1=3&q2=2'
        ],
        [
            'i' => 'http://www.example.com/a/#something',
            'q' => 'q1=1',
            'o' => 'http://www.example.com/a/#something?q1=1'
        ],
        [
            'i' => 'http://www.example.com/a/?q2=2#soe',
            'q' => 'q1=1',
            'o' => 'http://www.example.com/a/?q2=2&q1=1#soe'
        ],
        [
            'i' => 'http://www.example.com',
            'q' => ['q1' => 1],
            'o' => 'http://www.example.com/?q1=1'
        ],
        [
            'i' => 'http://www.example.com',
            'q' => ['q1' => 1, 'q2' => 2],
            'o' => 'http://www.example.com/?q1=1&q2=2'
        ],
        [
            'i' => 'http://www.example.com/a/',
            'q' => ['q1' => 1],
            'o' => 'http://www.example.com/a/?q1=1'
        ],
        [
            'i' => 'http://www.example.com/a.html',
            'q' => ['q1' => 1],
            'o' => 'http://www.example.com/a.html?q1=1'
        ],
        [
            'i' => 'http://www.example.com/a/?q2=2',
            'q' => ['q1' => 1],
            'o' => 'http://www.example.com/a/?q2=2&q1=1'
        ],
        [
            'i' => 'http://www.example.com/a.html?q2=two',
            'q' => ['q1' => 1],
            'o' => 'http://www.example.com/a.html?q2=two&q1=1'
        ],
        [
            'i' => 'http://www.example.com/a.html?q1=1&q2=2',
            'q' => ['q1' => 1],
            'o' => 'http://www.example.com/a.html?q1=1&q2=2'
        ],
        [
            'i' => 'http://www.example.com/a.html?q1=1&q2=2',
            'q' => ['q1' => 3],
            'o' => 'http://www.example.com/a.html?q1=3&q2=2'
        ],
        [
            'i' => 'http://www.example.com/a/#something',
            'q' => ['q1' => 1],
            'o' => 'http://www.example.com/a/#something?q1=1'
        ],
        [
            'i' => 'http://www.example.com/a/?q2=2#soe',
            'q' => ['q1' => 1],
            'o' => 'http://www.example.com/a/?q2=2&q1=1#soe'
        ],
    ];

    foreach ($inputsOutputs as $inputOutput) {
        $this->assertEquals($inputOutput['o'], $helper->appendQueryStringToURL($inputOutput['i'], $inputOutput['q']));
    }
}


If you can install pecl_http then this is a really elegant solution. It can allow you to check if you are overriding a get variable they may have set.

$urlComps = parse_url($url);

// Get the current query string
$queryString = isset($urlComps['query']) ? $urlComps['query'] : '';

// Turn it into an array for easy manipulation
parse_str($queryString, $queryVars);

// Make changes to the query vars
$queryVars['q2'] = 'two';

// Empty paths return relative URLs.
$urlComps['path'] = isset($urlComps['path']) ? $urlComps['path'] : '/';

// Make the pecl_http call
$newURL = http_build_url($urlComps, array('query' => http_build_query($queryVars)));

Note: if you can't install pecl_http, the only function that comes from that is the last one with the function http_build_url. You can fairly easily build your own function to rebuild the URL from its components...

  • parse_url
  • parse_str
  • http_build_query
  • http_build_url * uses pecl_http


Enhancing @alex's answer to account for infinite append of query string

/* Append QueryString to current URL */
function querystring_append($query) {
    $url = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
    $parsedUrl = parse_url($url);
    if ($parsedUrl['path'] == null) {
        $url .= '/';
    }
    $separator = ($parsedUrl['query'] == NULL) ? '?' : '&';
    if(!substr_count($url,$query)) $url .= $separator . $query;
    return $url;
}

Usage:

<?=querystring_append("action=logout") ?>


This is a bit more tricky that it should be. @alex answer is fine, but it does not support URL fragments nor does it handle duplicate values. I've provided a package for just this scenario. See https://github.com/Nyholm/append_query_string

$url = 'https://nyholm.tech?example=yes';
$queryString = http_build_query(['foo'=>'bar']);

$result = append_query_string($url, $queryString);

echo $result;
// https://nyholm.tech?example=yes&foo=bar

You may also define how duplicate should be handled. You can decide to:

  • Ignore duplicate values
  • Replace
  • Skip


On a side note, if anyone (like me) implementing this in WordPress, a function already exists: add_query_arg()

add_query_arg( 'key', 'value', 'http://example.com' );

See codex for more examples - https://developer.wordpress.org/reference/functions/add_query_arg/

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜