Memanipulasi string url dengan menambahkan parameter GET


93

Saya ingin menambahkan parameter GET ke URL yang mungkin dan tidak boleh berisi parameter GET tanpa mengulang ?atau &.

Contoh:

Jika saya ingin menambahkan 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

Jika Anda perhatikan saya mencoba untuk tidak mengulangi tanda tanya jika ditemukan.

URL hanya berupa string.

Apa cara yang dapat diandalkan untuk menambahkan parameter GET tertentu?


Cukup gunakan: echo http_build_url($url, array("query" => "the=query&parts=here"), HTTP_URL_JOIN_QUERY);. Tetapi Anda memerlukan pecl install pecl_httpatau menginstal jakeasmith / http_build_url melalui komposer.
Ema4rl

Jawaban:


188

Metode dasar

$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';
}

Lebih maju

$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'];

Anda harus meletakkan ini setidaknya dalam sebuah fungsi, jika bukan sebuah kelas.


2
juga jangan lupa untuk menambahkan nilai kategori
Doug T.

4
@Tokopedia tidak semua parameter membutuhkan nilai. Misalnya, ?logoutdapat diperiksa denganisset($_GET["logout"])
rybo111

Pendekatan ini bagus jika Anda tahu bahwa parameter 'kategori' belum ada di URL. Jika parameter sudah ada di URL maka PHP harus mengambil nilai kemunculan terakhir parameter di URL, sehingga solusi @andrewtweber masih berfungsi. Namun, saya lebih menyukai solusi berikut stackoverflow.com/a/4101638/99256 .
Martin Vseticka

-1 untuk tidak mengganti parameter jika sudah ada. Itu tidak disebutkan secara eksplisit dalam pertanyaan, tetapi secara logis dan semantik wajib.
Daniel W.

1
Cukup gunakan: echo http_build_url($url, array("query" => "the=query&parts=here"), HTTP_URL_JOIN_QUERY);. Tetapi Anda memerlukan pecl install pecl_httpatau menginstal jakeasmith / http_build_url melalui komposer.
Ema4rl

55

Berikut adalah versi singkat dari jawaban yang diterima:

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

Sunting: seperti dibahas dalam jawaban yang diterima, ini cacat karena tidak memeriksa untuk melihat apakah categorysudah ada. Solusi yang lebih baik adalah memperlakukan $_GETapa itu - array - dan menggunakan fungsi seperti in_array().


Perhatikan ini hanya akan bekerja dengan satu parameter yang ditambahkan, jika tidak maka akan menambahkan? jika tidak ada kueri asli.
Mgamerz

@Mgamerz kecuali saya salah paham, itulah yang diminta OP. Ia bekerja beberapa kali, karena .sebelum =.
rybo111

Tetapi tidak akan ada kueri jika Anda menambahkan parameter ke url (sehingga menambahkan?), Dan jika Anda melakukannya lagi, itu akan menambahkan yang lain? (Kecuali jika Anda harus menjalankan baris pertama lagi)? Bagaimana $ query diperbarui?
Mgamerz

@Mgamerz Saya mengerti apa yang Anda maksud sekarang. Ya, Anda harus mengulang baris pertama setiap kali untuk memeriksa apakah $urlsudah memiliki parameter. Diedit.
rybo111

1
Tidak menangani URL dengan #.
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

Cukup gunakan: echo http_build_url($url, array("query" => "the=query&parts=here"), HTTP_URL_JOIN_QUERY);. Tetapi Anda memerlukan pecl install pecl_httpatau menginstal jakeasmith / http_build_url melalui komposer.
Ema4rl

8

Gunakan strpos untuk mendeteksi?. Sejak ? hanya dapat muncul di URL di awal string kueri, Anda tahu jika parameter get nya sudah ada dan Anda perlu menambahkan parameter menggunakan &

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

Pendekatan yang baik dan mudah jika Anda mengkhawatirkan kinerja, karena ini akan jauh lebih cepat daripada parse_url dan juga kurang intensif cpu. Pengorbanannya adalah tidak memeriksa $ varName yang sudah ada.
Dennis Stücken

8

Fungsi ini menimpa argumen yang sudah ada

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 ) );
}

Apa yang terjadi jika tidak ada $info['query']set? Anda belum memperhitungkan itu.
Darren

Jika tidak disetel, $ info ['query'] menjadi NULL dan $ query menjadi array kosong. Jadi itu bukan masalah.
Ajay Singh

7

Contoh dengan memperbarui parameter yang ada.

Juga url_encode digunakan, dan kemungkinan untuk tidak menentukan nilai parameter

    <?
    /**
     * 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
kerja bagus, hanya ganti baris $query = $a['query'] ? $a['query'] : '';dengan$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

Saya pikir Anda harus melakukan sesuatu seperti ini.

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

Setelah mencari banyak sumber / jawaban tentang topik ini, saya memutuskan untuk membuat kode sendiri. Berdasarkan jawaban @ TaylorOtwell di sini, berikut adalah cara saya memproses permintaan $ _GET yang masuk dan memodifikasi / memanipulasi setiap elemen.

Dengan asumsi url adalah: http://domain.com/category/page.php?a=b&x=y Dan saya hanya ingin satu parameter untuk penyortiran: baik? Desc = column_name atau? Asc = column_name. Dengan cara ini, parameter url tunggal cukup untuk diurutkan dan diurutkan secara bersamaan. Jadi URL-nya akan menjadi http://domain.com/category/page.php?a=b&x=y&desc=column_name pada klik pertama baris tajuk tabel terkait.

Kemudian saya memiliki judul baris tabel yang ingin saya urutkan DESC pada klik pertama saya, dan ASC pada klik kedua dari judul yang sama. (Setiap klik pertama harus "ORDER BY column DESC" terlebih dahulu) Dan jika tidak ada penyortiran, ini akan mengurutkan berdasarkan "tanggal lalu id" secara default.

Anda dapat memperbaikinya lebih jauh, seperti Anda dapat menambahkan fungsi pembersihan / pemfilteran ke setiap komponen $ _GET tetapi struktur di bawah ini meletakkan fondasinya.

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, '&');}

(Anda dapat menggunakan $ _SERVER [SCRIPT_URI] untuk URL lengkap yang diawali dengan http://domain.com )

Kemudian saya menggunakan $ ORDER yang saya dapatkan di atas, di kueri MySQL:

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

Sekarang fungsi untuk melihat URL jika sebelumnya ada penyortiran dan menambahkan parameter penyortiran (dan pengurutan) ke URL dengan "?" atau "&" sesuai urutan:

        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";
                }
            }
        }

Terakhir, tajuk baris tabel untuk menggunakan fungsi:

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

Ringkasan: ini akan membaca URL, mengubah setiap komponen $ _GET dan membuat URL final dengan parameter pilihan Anda dengan bentuk penggunaan yang benar dari "?" dan "&"


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

versi fungsi lain yang ditingkatkan. Campuran jawaban yang ada dengan perbaikan kecil (dukungan port) dan perbaikan bug (memeriksa kunci dengan benar).

/**
 * @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

Coba fungsi ini untuk menambahkan parameter URL .

Kemudian Anda dapat menonaktifkan tautan ketika parameter disetel sehingga tidak ada duplikat parameter url.

<?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>

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.