จัดการสตริง URL โดยการเพิ่มพารามิเตอร์ GET


93

ฉันต้องการที่จะเพิ่มพารามิเตอร์ GET ไปยัง URL ที่อาจและไม่อาจมีพารามิเตอร์ GET โดยไม่ต้องทำซ้ำหรือ?&

ตัวอย่าง:

หากต้องการเพิ่ม 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

หากคุณสังเกตเห็นฉันพยายามที่จะไม่ทำเครื่องหมายคำถามซ้ำหากพบ

URL เป็นเพียงสตริง

วิธีที่เชื่อถือได้ในการต่อท้ายพารามิเตอร์ GET เฉพาะคืออะไร


เพียงใช้: echo http_build_url($url, array("query" => "the=query&parts=here"), HTTP_URL_JOIN_QUERY);. แต่คุณจะต้องpecl install pecl_httpหรือติดตั้งjakeasmith / http_build_urlผ่านนักแต่งเพลง
Ema4rl

คำตอบ:


188

วิธีการพื้นฐาน

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

ขั้นสูงมากขึ้น

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

คุณควรใส่สิ่งนี้ในฟังก์ชันเป็นอย่างน้อยถ้าไม่ใช่คลาส


2
อย่าลืมต่อท้ายค่าของหมวดหมู่ด้วย
Doug T.

4
@ คุณ DougT. พารามิเตอร์ทั้งหมดไม่จำเป็นต้องมีค่า ตัวอย่างเช่น?logoutสามารถตรวจสอบได้ด้วยisset($_GET["logout"])
rybo111

วิธีนี้ดีเมื่อคุณทราบว่าพารามิเตอร์ "หมวดหมู่" ไม่มีอยู่ใน URL หากพารามิเตอร์อยู่ใน URL แล้ว PHP ควรใช้ค่าของการเกิดครั้งสุดท้ายของพารามิเตอร์ใน URL ดังนั้นโซลูชันของ @andrewtweber จะยังคงใช้งานได้ แต่ฉันชอบวิธีแก้ปัญหาต่อไปนี้stackoverflow.com/a/4101638/99256ดีกว่า
Martin Vseticka

-1 สำหรับการไม่แทนที่พารามิเตอร์หากมีอยู่แล้ว ไม่ได้กล่าวถึงอย่างชัดเจนในคำถาม แต่จำเป็นต้องมีเหตุผลและความหมาย
Daniel W.

1
เพียงใช้: echo http_build_url($url, array("query" => "the=query&parts=here"), HTTP_URL_JOIN_QUERY);. แต่คุณจะต้องpecl install pecl_httpหรือติดตั้งjakeasmith / http_build_urlผ่านนักแต่งเพลง
Ema4rl

55

ต่อไปนี้เป็นคำตอบที่ยอมรับโดยย่อ:

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

แก้ไข: ตามที่กล่าวไว้ในคำตอบที่ยอมรับข้อบกพร่องนี้ไม่ได้ตรวจสอบว่าcategoryมีอยู่แล้วหรือไม่ วิธีการแก้ปัญหาที่ดีกว่าจะรักษา$_GETสำหรับสิ่งที่มันเป็น - อาร์เรย์ - in_array()ฟังก์ชั่นการใช้งานและเช่น


โปรดทราบว่าสิ่งนี้จะใช้ได้กับพารามิเตอร์ที่เพิ่มเพียงพารามิเตอร์เดียวเท่านั้นมิฉะนั้นจะต่อท้าย a? หากไม่มีข้อความค้นหาเดิม
Mgamerz

@Mgamerz เว้นแต่ฉันจะเข้าใจคุณผิดนั่นคือสิ่งที่ OP ขอ ทำงานได้หลายครั้งเนื่องจาก.ก่อนหน้า=นี้.
rybo111

แต่จะไม่มีการสืบค้นหากคุณเพิ่มพารามิเตอร์ลงใน url (ด้วยเหตุนี้จึงเพิ่ม a?) และหากคุณทำอีกครั้งจะเพิ่มอีกหรือไม่ (เว้นแต่ว่าคุณควรจะวิ่งบรรทัดแรกอีกครั้ง)? $ query ได้รับการอัปเดตอย่างไร
Mgamerz

@Mgamerz ฉันเข้าใจแล้วว่าตอนนี้คุณหมายถึงอะไร ใช่คุณจะต้องทำซ้ำบรรทัดแรกทุกครั้งเพื่อตรวจสอบว่า$urlมีพารามิเตอร์อยู่แล้วหรือไม่ แก้ไขแล้ว
rybo111

1
ไม่ได้จัดการ URL #ที่มี
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

เพียงใช้: echo http_build_url($url, array("query" => "the=query&parts=here"), HTTP_URL_JOIN_QUERY);. แต่คุณจะต้องpecl install pecl_httpหรือติดตั้งjakeasmith / http_build_urlผ่านนักแต่งเพลง
Ema4rl

8

ใช้strposเพื่อตรวจจับ? ตั้งแต่ ? สามารถปรากฏใน URL ที่จุดเริ่มต้นของสตริงข้อความค้นหาเท่านั้นคุณจะทราบว่ามีพารามิเตอร์รับพารามิเตอร์อยู่แล้วหรือไม่และคุณต้องเพิ่มพารามิเตอร์โดยใช้ &

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

แนวทางที่ดีและง่ายหากคุณกังวลเกี่ยวกับประสิทธิภาพเนื่องจากจะเร็วกว่า parse_url มากและยังใช้ CPU น้อยกว่าด้วย Tradeoff คือไม่ได้ตรวจสอบ $ varName ที่มีอยู่
Dennis Stücken

8

ฟังก์ชันนี้เขียนทับอาร์กิวเมนต์ที่มีอยู่

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

จะเกิดอะไรขึ้นถ้าไม่มีการ$info['query']ตั้งค่า? คุณยังไม่ได้คำนึงถึงสิ่งนั้น
Darren

หากไม่ได้ตั้งค่า $ info ['query'] จะกลายเป็น NULL และ $ query จะกลายเป็นอาร์เรย์ว่าง ดังนั้นจึงไม่ใช่ปัญหา
Ajay Singh

7

ตัวอย่างการอัพเดตพารามิเตอร์ที่มีอยู่

ใช้ url_encode ด้วยและความเป็นไปได้ที่จะไม่ระบุค่าพารามิเตอร์

    <?
    /**
     * 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
เยี่ยมมากแทนที่บรรทัด$query = $a['query'] ? $a['query'] : '';โดย$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

ฉันคิดว่าคุณควรทำอะไรแบบนี้

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

หลังจากค้นหาแหล่งข้อมูล / คำตอบมากมายในหัวข้อนี้ฉันตัดสินใจเขียนโค้ดของตัวเอง จากคำตอบของ @ TaylorOtwell ที่นี่นี่คือวิธีที่ฉันประมวลผลคำขอ $ _GET ที่เข้ามาและแก้ไข / จัดการแต่ละองค์ประกอบ

สมมติว่า url คือ: http://domain.com/category/page.php?a=b&x=y และฉันต้องการเพียงพารามิเตอร์เดียวสำหรับการเรียงลำดับ: desc = column_name หรือ? asc = column_name ด้วยวิธีนี้พารามิเตอร์ url เดียวก็เพียงพอที่จะเรียงลำดับและเรียงลำดับพร้อมกัน ดังนั้น URL จะเป็นhttp://domain.com/category/page.php?a=b&x=y&desc=column_nameเมื่อคลิกครั้งแรกของแถวส่วนหัวของตารางที่เกี่ยวข้อง

จากนั้นฉันมีส่วนหัวของแถวตารางที่ฉันต้องการจัดเรียง DESC ในการคลิกครั้งแรกและ ASC ในการคลิกครั้งที่สองของส่วนหัวเดียวกัน (การคลิกครั้งแรกแต่ละครั้งควร "ORDER BY column DESC" ก่อน) และหากไม่มีการเรียงลำดับก็จะเรียงลำดับตาม "date แล้ว id" ตามค่าเริ่มต้น

คุณสามารถปรับปรุงเพิ่มเติมได้เช่นคุณอาจเพิ่มฟังก์ชันการทำความสะอาด / การกรองให้กับส่วนประกอบ $ _GET แต่ละชิ้น แต่โครงสร้างด้านล่างจะวางรากฐาน

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

(คุณสามารถใช้ $ _SERVER [SCRIPT_URI] สำหรับ URL แบบเต็มที่ขึ้นต้นด้วยhttp://domain.com )

จากนั้นฉันใช้ผลลัพธ์ $ ORDER ที่ฉันได้รับข้างต้นในแบบสอบถาม MySQL:

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

ตอนนี้ฟังก์ชั่นที่จะดู URL ว่ามีการเรียงลำดับก่อนหน้าหรือไม่และเพิ่มพารามิเตอร์การเรียงลำดับ (และการเรียงลำดับ) ให้กับ URL ด้วย "?" หรือ "&" ตามลำดับ:

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

สุดท้ายส่วนหัวของแถวตารางเพื่อใช้ฟังก์ชัน:

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

สรุป: สิ่งนี้จะอ่าน URL แก้ไของค์ประกอบ $ _GET แต่ละรายการและสร้าง URL สุดท้ายด้วยพารามิเตอร์ที่คุณเลือกด้วยรูปแบบการใช้งานที่ถูกต้องของ "?" และ "&"


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

เวอร์ชันฟังก์ชันที่ปรับปรุงใหม่ คำตอบที่มีอยู่ผสมผสานกับการปรับปรุงเล็กน้อย (รองรับพอร์ต) และการแก้ไขข้อบกพร่อง (ตรวจสอบคีย์อย่างถูกต้อง)

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

ลองใช้ฟังก์ชันนี้เพื่อเพิ่มพารามิเตอร์ URLเพิ่มพารามิเตอร์

จากนั้นคุณสามารถปิดการใช้งานลิงก์เมื่อตั้งค่าพารามิเตอร์เพื่อให้ไม่มีพารามิเตอร์ 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>

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.