Thao tác một chuỗi url bằng cách thêm các tham số GET


93

Tôi muốn thêm các tham số GET vào các URL có thể và không thể chứa các tham số GET mà không lặp lại ?hoặc &.

Thí dụ:

Nếu tôi muốn thêm category=action

$url="http://www.acme.com";
 // will add ?category=action at the end

$url="http://www.acme.com/movies?sort=popular";
 // will add &category=action at the end

Nếu bạn nhận thấy, tôi đang cố gắng không lặp lại dấu hỏi nếu nó được tìm thấy.

URL chỉ là một chuỗi.

Cách đáng tin cậy để thêm một tham số GET cụ thể là gì?


Đơn giản chỉ cần sử dụng: echo http_build_url($url, array("query" => "the=query&parts=here"), HTTP_URL_JOIN_QUERY);. Nhưng bạn sẽ cần pecl install pecl_httphoặc cài đặt jakeasmith / http_build_url qua trình soạn nhạc.
Ema4rl

Câu trả lời:


187

Phương pháp cơ bản

$query = parse_url($url, PHP_URL_QUERY);

// Returns a string if the URL has parameters or NULL if not
if ($query) {
    $url .= '&category=1';
} else {
    $url .= '?category=1';
}

Nâng cao hơn

$url = 'http://example.com/search?keyword=test&category=1&tags[]=fun&tags[]=great';

$url_parts = parse_url($url);
// If URL doesn't have a query string.
if (isset($url_parts['query'])) { // Avoid 'Undefined index: query'
    parse_str($url_parts['query'], $params);
} else {
    $params = array();
}

$params['category'] = 2;     // Overwrite if exists
$params['tags'][] = 'cool';  // Allows multiple values

// Note that this will url_encode all values
$url_parts['query'] = http_build_query($params);

// If you have pecl_http
echo http_build_url($url_parts);

// If not
echo $url_parts['scheme'] . '://' . $url_parts['host'] . $url_parts['path'] . '?' . $url_parts['query'];

Bạn nên đặt điều này ít nhất trong một hàm, nếu không phải là một lớp.


2
cũng đừng quên thêm giá trị của danh mục
Doug T.

4
@DougT. không phải tất cả các tham số đều cần một giá trị. Ví dụ: ?logoutcó thể được kiểm tra bằngisset($_GET["logout"])
rybo111

Cách tiếp cận này tốt khi bạn biết rằng thông số 'danh mục' chưa có trong URL. Nếu tham số đã có trong URL thì PHP sẽ lấy giá trị của lần xuất hiện cuối cùng của tham số trong URL, do đó giải pháp của @andrewtweber vẫn hoạt động. Tuy nhiên, tôi thích giải pháp sau stackoverflow.com/a/4101638/99256 tốt hơn.
Martin Vseticka,

-1 để không thay thế một tham số nếu nó đã tồn tại. Nó không được đề cập rõ ràng trong câu hỏi, nhưng nó bắt buộc về mặt logic và ngữ nghĩa.
Daniel W.

1
Đơn giản chỉ cần sử dụng: echo http_build_url($url, array("query" => "the=query&parts=here"), HTTP_URL_JOIN_QUERY);. Nhưng bạn sẽ cần pecl install pecl_httphoặc cài đặt jakeasmith / http_build_url thông qua trình soạn nhạc.
Ema4rl

55

Đây là phiên bản ngắn hơn của câu trả lời được chấp nhận:

$url .= (parse_url($url, PHP_URL_QUERY) ? '&' : '?') . 'category=action';

Chỉnh sửa: như đã thảo luận trong câu trả lời được chấp nhận, điều này có sai sót ở chỗ nó không kiểm tra xem categoryđã tồn tại chưa. Một giải pháp tốt hơn sẽ là xử lý $_GETnó là gì - một mảng - và sử dụng các hàm như thế nào in_array().


Lưu ý rằng điều này sẽ chỉ hoạt động với một tham số được thêm vào, nếu không nó sẽ thêm một? nếu không có truy vấn ban đầu.
Mgamerz

@Mgamerz trừ khi tôi đang hiểu lầm bạn, đó là những gì OP yêu cầu. Nó hoạt động nhiều lần, vì .trước đó =.
rybo111

Nhưng truy vấn sẽ không tồn tại nếu bạn thêm một tham số vào url (do đó thêm một?), Và nếu bạn làm lại, nó sẽ thêm một tham số khác? (Trừ khi bạn phải chạy lại dòng đầu tiên)? Làm thế nào để truy vấn $ được cập nhật?
Mgamerz

@Mgamerz Tôi hiểu ý bạn bây giờ. Có, bạn sẽ cần phải lặp lại dòng đầu tiên mỗi lần để kiểm tra xem $urlđã có các tham số chưa. Đã chỉnh sửa.
rybo111

1
Không xử lý các URL với #.
NateS

19
$data = array('foo'=>'bar',
              'baz'=>'boom',
              'cow'=>'milk',
              'php'=>'hypertext processor');

$queryString =  http_build_query($data);
//$queryString = foo=bar&baz=boom&cow=milk&php=hypertext+processor

echo 'http://domain.com?'.$queryString;
//output: http://domain.com?foo=bar&baz=boom&cow=milk&php=hypertext+processor

Đơn giản chỉ cần sử dụng: echo http_build_url($url, array("query" => "the=query&parts=here"), HTTP_URL_JOIN_QUERY);. Nhưng bạn sẽ cần pecl install pecl_httphoặc cài đặt jakeasmith / http_build_url thông qua trình soạn nhạc.
Ema4rl

8

Sử dụng strpos để phát hiện?. Từ ? chỉ có thể xuất hiện trong URL ở đầu chuỗi truy vấn, bạn biết nếu nó có các tham số đã tồn tại và bạn cần thêm các tham số bằng cách sử dụng &

function addGetParamToUrl(&$url, $varName, $value)
{
    // is there already an ?
    if (strpos($url, "?"))
    {
        $url .= "&" . $varName . "=" . $value; 
    }
    else
    {
        $url .= "?" . $varName . "=" . $value;
    }
}

Cách tiếp cận tốt và dễ dàng nếu bạn lo lắng về hiệu suất, vì điều này sẽ nhanh hơn rất nhiều so với parse_url và cũng ít thâm dụng cpu hơn. Sự cân bằng là nó không kiểm tra $ varName hiện có.
Dennis Stücken

8

Hàm này ghi đè đối số hiện có

function addToURL( $key, $value, $url) {
    $info = parse_url( $url );
    parse_str( $info['query'], $query );
    return $info['scheme'] . '://' . $info['host'] . $info['path'] . '?' . http_build_query( $query ? array_merge( $query, array($key => $value ) ) : array( $key => $value ) );
}

Điều gì xảy ra nếu không có $info['query']bộ? Bạn chưa tính đến điều đó.
Darren

Nếu không được đặt, $ info ['query'] trở thành NULL và $ query trở thành một mảng trống. Vì vậy, nó không phải là một vấn đề.
Ajay Singh

7

Ví dụ với việc cập nhật các thông số tồn tại.

Cũng sử dụng url_encode và khả năng không chỉ định giá trị tham số

    <?
    /**
     * Add parameter to URL
     * @param string $url
     * @param string $key
     * @param string $value
     * @return string result URL
     */
    function addToUrl($url, $key, $value = null) {
        $query = parse_url($url, PHP_URL_QUERY);
        if ($query) {
            parse_str($query, $queryParams);
            $queryParams[$key] = $value;
            $url = str_replace("?$query", '?' . http_build_query($queryParams), $url);
        } else {
            $url .= '?' . urlencode($key) . '=' . urlencode($value);
        }
        return $url;
    }

5
<?php
$url1 = '/test?a=4&b=3';
$url2 = 'www.baidu.com/test?a=4&b=3&try_count=1';
$url3 = 'http://www.baidu.com/test?a=4&b=3&try_count=2';
$url4 = '/test';
function add_or_update_params($url,$key,$value){
    $a = parse_url($url);
    $query = $a['query'] ? $a['query'] : '';
    parse_str($query,$params);
    $params[$key] = $value;
    $query = http_build_query($params);
    $result = '';
    if($a['scheme']){
        $result .= $a['scheme'] . ':';
    }
    if($a['host']){
        $result .= '//' . $a['host'];
    }
    if($a['path']){
        $result .=  $a['path'];
    }
    if($query){
        $result .=  '?' . $query;
    }
    return $result;
}
echo add_or_update_params($url1,'try_count',1);
echo "\n";
echo add_or_update_params($url2,'try_count',2);
echo "\n";
echo add_or_update_params($url3,'try_count',3);
echo "\n";
echo add_or_update_params($url4,'try_count',4);
echo "\n";

3
công việc tuyệt vời, chỉ thay thế dòng $query = $a['query'] ? $a['query'] : '';bởi$query = isset($a['query']) ? $a['query'] : '';
emmgfx

4
 /**
 * @example addParamToUrl('/path/to/?find=1', array('find' => array('search', 2), 'FILTER' => 'STATUS'))
 * @example addParamToUrl('//example.com/path/to/?find=1', array('find' => array('search', 2), 'FILTER' => 'STATUS'))
 * @example addParamToUrl('https://example.com/path/to/?find=1&FILTER=Y', array('find' => array('search', 2), 'FILTER' => 'STATUS'))
 *
 * @param       $url string url
 * @param array $addParams
 *
 * @return string
 */
function addParamToUrl($url, array $addParams) {
  if (!is_array($addParams)) {
    return $url;
  }

  $info = parse_url($url);

  $query = array();

  if ($info['query']) {
    parse_str($info['query'], $query);
  }

  if (!is_array($query)) {
    $query = array();
  }

  $params = array_merge($query, $addParams);

  $result = '';

  if ($info['scheme']) {
    $result .= $info['scheme'] . ':';
  }

  if ($info['host']) {
    $result .= '//' . $info['host'];
  }

  if ($info['path']) {
    $result .= $info['path'];
  }

  if ($params) {
    $result .= '?' . http_build_query($params);
  }

  return $result;
}

3
$parameters = array();

foreach ($get as $key => $value)
{
     $parameters[] = $key.'='.$value;
}

$url = 'http://example.com/movies?'.implode('&', $parameters);

3

Tôi nghĩ bạn nên làm điều gì đó như thế này.

class myURL {
    protected $baseURL, $requestParameters;

    public function __construct ($newURL) {
        $this->baseurl = $newURL;
        $this->requestParameters = array();
    }

    public function addParameter ($parameter) {
        $this->requestParameters[] = $parameter;
    }

    public function __toString () {
        return $this->baseurl.
               ( count($this->requestParameters) ?
                 '?'.implode('&', $this->requestParameters) :
                 ''
                 );
    }
}

$url1 = new myURL ('http://www.acme.com');
$url2 = new myURL ('http://www.acme.com');
$url2->addParameter('sort=popular');
$url2->addParameter('category=action');
$url1->addParameter('category=action');

echo $url1."\n".$url2;

1

Sau khi tìm kiếm nhiều tài nguyên / câu trả lời về chủ đề này, tôi quyết định viết mã của riêng mình. Dựa trên câu trả lời của @ TaylorOtwell ở đây, đây là cách tôi xử lý yêu cầu $ _GET đến và sửa đổi / thao tác từng phần tử.

Giả sử url là: http://domain.com/category/page.php?a=b&x=y Và tôi chỉ muốn một tham số để sắp xếp: hoặc? Desc = column_name hoặc? Asc = column_name. Bằng cách này, một tham số url đủ để sắp xếp và sắp xếp đồng thời. Vì vậy, URL sẽ là http://domain.com/category/page.php?a=b&x=y&desc=column_name khi nhấp chuột đầu tiên vào hàng tiêu đề bảng được liên kết.

Sau đó, tôi có các tiêu đề hàng trong bảng mà tôi muốn sắp xếp DESC trong lần nhấp đầu tiên và ASC trong lần nhấp thứ hai của cùng một tiêu đề. (Mỗi lần nhấp đầu tiên nên "ĐẶT HÀNG THEO cột MÔ TẢ" trước) Và nếu không có sắp xếp, nó sẽ sắp xếp theo "ngày tháng rồi đến id" theo mặc định.

Bạn có thể cải thiện nó hơn nữa, chẳng hạn như bạn có thể thêm các chức năng làm sạch / lọc cho từng thành phần $ _GET nhưng cấu trúc bên dưới là nền tảng.

foreach ($_GET AS $KEY => $VALUE){
    if ($KEY == 'desc'){
        $SORT = $VALUE;
        $ORDER = "ORDER BY $VALUE DESC";
        $URL_ORDER = $URL_ORDER . "&asc=$VALUE";
    } elseif ($KEY == 'asc'){
        $SORT = $VALUE;
        $ORDER = "ORDER BY $VALUE ASC";
        $URL_ORDER = $URL_ORDER . "&desc=$VALUE";
    } else {
        $URL_ORDER .= "&$KEY=$VALUE";
        $URL .= "&$KEY=$VALUE";
    }
}
if (!$ORDER){$ORDER = 'ORDER BY date DESC, id DESC';}
if ($URL_ORDER){$URL_ORDER = $_SERVER[SCRIPT_URL] . '?' . trim($URL_ORDER, '&');}
if ($URL){$URL = $_SERVER[SCRIPT_URL] . '?' . trim($URL, '&');}

(Bạn có thể sử dụng $ _SERVER [SCRIPT_URI] cho URL đầy đủ bắt đầu bằng http://domain.com )

Sau đó, tôi sử dụng $ ORDER kết quả mà tôi nhận được ở trên, trong truy vấn MySQL:

"SELECT * FROM table WHERE limiter = 'any' $ORDER";

Bây giờ, chức năng xem URL nếu có một thông số sắp xếp trước đó và thêm thông số sắp xếp (và sắp xếp) vào URL với "?" hoặc "&" theo trình tự:

        function sort_order ($_SORT){
            global $SORT, $URL_ORDER, $URL;
            if ($SORT == $_SORT){
                return $URL_ORDER;
            } else {
                if (strpos($URL, '?') !== false){
                    return "$URL&desc=$_SORT";
                } else {                        
                    return "$URL?desc=$_SORT";
                }
            }
        }

Cuối cùng, tiêu đề hàng của bảng để sử dụng hàm:

        echo "<th><a href='".sort_order('id')."'>ID</a></th>";

Tóm tắt: điều này sẽ đọc URL, sửa đổi từng thành phần $ _GET và tạo URL cuối cùng với các tham số bạn chọn với hình thức sử dụng chính xác của "?" và "&"


0
 public function addGetParamToUrl($url, $params)
{
    foreach ($params as $param) {
         if (strpos($url, "?"))
        {
            $url .= "&" .http_build_query($param); 
        }
        else
        {
            $url .= "?" .http_build_query($param); 
        }
    }
    return $url;
}

0

một phiên bản chức năng cải tiến khác. Kết hợp các câu trả lời hiện có với các cải tiến nhỏ (hỗ trợ cổng) và sửa lỗi (kiểm tra các phím đúng cách).

/**
 * @param string $url original url to modify - can be relative, partial etc
 * @param array $paramsOverride associative array, can be empty
 * @return string modified url
 */
protected function overrideUrlQueryParams($url, $paramsOverride){
    if (!is_array($paramsOverride)){
        return $url;
    }

    $url_parts = parse_url($url);

    if (isset($url_parts['query'])) {
        parse_str($url_parts['query'], $params);
    } else {
        $params = [];
    }

    $params = array_merge($params, $paramsOverride);

    $res = '';

    if(isset($url_parts['scheme'])) {
        $res .= $url_parts['scheme'] . ':';
    }

    if(isset($url_parts['host'])) {
        $res .= '//' . $url_parts['host'];
    }

    if(isset($url_parts['port'])) {
        $res .= ':' . $url_parts['port'];
    }

    if (isset($url_parts['path'])) {
        $res .= $url_parts['path'];
    }

    if (count($params) > 0) {
        $res .= '?' . http_build_query($params);
    }

    return $res;
}

0

Hãy thử chức năng này để thêm các tham số URL .

Sau đó, bạn có thể tắt liên kết khi thông số được đặt để không có thông số url trùng lặp.

<?php
  function addQueryString($a)
                {
             if (empty($_SERVER['QUERY_STRING']))
               return '?' . $a;
             else if (!empty($_SERVER['QUERY_STRING']))
              return '?' . $_SERVER['QUERY_STRING'] . '&' . $a;
                }
?>

 <a href="<?php echo addQueryString('lang=en'); ?>">test</a>
 <a href="<?php echo addQueryString('category=5'); ?>">sat</a>

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.