首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 獲取 URL 參數完全指南:parse_url、parse_str 與自定義解析函數

     編輯:PHP 相關知識

從 URL 字符串到結構化數組:PHP 解析查詢參數的標準與進階姿勢

PHP 提供 parse_url() 解析 URL 組件、parse_str() 解析查詢字符串,配合使用可輕鬆將 https://example.com/path?a=1&b=2 轉為結構化數組。本文詳解兩大核心函數、自定義封裝、邊界情況處理與現代框架實踐。

核心函數速查

函數作用返回值關鍵參數
parse_url($url, $component)解析 URL 為組件關聯數組 / 指定組件字符串$component: PHP_URL_SCHEME/HOST/PATH/QUERY/FRAGMENT 等
parse_str($str, $result)解析查詢字符串填充數組void (引用修改 $result)$result 必須傳變量引用

基礎用法:組合拳

<?php
$url = "https://user:pass@example.com:8080/path/to/page?name=value&foo=bar#section";

// 1. parse_url 解析整體結構
$parts = parse_url($url);
/*
Array(
    [scheme] => https
    [host] => example.com
    [port] => 8080
    [user] => user
    [pass] => pass
    [path] => /path/to/page
    [query] => name=value&foo=bar
    [fragment] => section
)
*/

// 2. 提取 query 部分
$queryString = $parts['query'] ?? '';

// 3. parse_str 解析查詢字符串為數組
$params = [];
parse_str($queryString, $params);
/*
Array(
    [name] => value
    [foo] => bar
)
*/

// 4. 直接獲取特定組件 (更高效)
$queryOnly = parse_url($url, PHP_URL_QUERY);  // 返回 "name=value&foo=bar"
parse_str($queryOnly, $params);
?>

封裝通用工具函數

<?php
/**
 * 解析 URL 獲取所有查詢參數
 * @param string $url 完整 URL 或僅查詢字符串
 * @return array 參數鍵值對數組
 */
function getUrlParams(string $url): array {
    // 若傳入完整 URL,提取 query 部分
    if (strpos($url, '?') !== false || strpos($url, '://') !== false) {
        $query = parse_url($url, PHP_URL_QUERY);
        if ($query === null) return [];
    } else {
        $query = $url;  // 假設直接傳入查詢字符串
    }
    
    $params = [];
    parse_str($query, $params);
    return $params;
}

/**
 * 獲取單個參數值 (不存在返回默認值)
 */
function getUrlParam(string $url, string $name, $default = null) {
    $params = getUrlParams($url);
    return $params[$name] ?? $default;
}

// === 使用 ===
$url = "https://shop.com/list?category=electronics&page=2&sort=price_desc&tags[]=new&tags[]=hot";
$params = getUrlParams($url);
/*
[
    'category' => 'electronics',
    'page' => '2',
    'sort' => 'price_desc',
    'tags' => ['new', 'hot']  // parse_str 自動處理 [] 為數組
]
*/

echo getUrlParam($url, 'page', 1);  // '2' (字符串)
echo getUrlParam($url, 'limit', 20); // 20 (默認值)
?>

parse_str 進階特性與陷阱

1. 自動處理數組語法 key[]=val

<?php
parse_str('tags[]=php&tags[]=js&tags[]=vue', $arr);
// $arr['tags'] = ['php', 'js', 'vue']
?>

2. 自動解碼 URL 編碼字符

<?php
parse_str('name=%E5%BC%A0%E4%B8%89&city=%E5%8C%97%E4%BA%AC', $arr);
// $arr['name'] = '張三', $arr['city'] = '北京'
?>

3. ⚠️ 覆蓋同名參數 (後者勝出)

<?php
parse_str('id=1&id=2&id=3', $arr);
// $arr['id'] = '3'  // 非數組模式下後蓋前
// 若需保留所有值:id[]=1&id[]=2&id[]=3
?>

4. ⚠️ 變量名合法化 (點、空格、括號轉下劃線)

<?php
parse_str('user.name=john&user age=25', $arr);
// $arr['user_name'] = 'john', $arr['user_age'] = '25'
// 原因:PHP 變量名不能含點、空格,parse_str 自動轉換
?>

手寫解析器:完全控制行為 (不依賴 parse_str)

<?php
/**
 * 自定義查詢字符串解析 (保留原始鍵名、不自動解碼、保留重複鍵)
 * @param string $query
 * @param bool $keepDuplicates 是否保留重複鍵為數組
 * @return array
 */
function parseQueryCustom(string $query, bool $keepDuplicates = true): array {
    $params = [];
    $pairs = explode('&', $query);
    foreach ($pairs as $pair) {
        if ($pair === '') continue;
        [$key, $value] = array_pad(explode('=', $pair, 2), 2, '');
        // 不自動 urldecode,保留原始編碼
        // 不轉換鍵名特殊字符
        if ($keepDuplicates && isset($params[$key])) {
            if (!is_array($params[$key])) $params[$key] = [$params[$key]];
            $params[$key][] = $value;
        } else {
            $params[$key] = $value;
        }
    }
    return $params;
}

// 對比
$query = 'id=1&id=2&user.name=john';
print_r(parse_str($query, $arr) && $arr);  // parse_str 行為
print_r(parseQueryCustom($query));         // 自定義行為
?>

現代框架中的參數獲取 (PSR-7 / Laravel / Symfony)

<?php
// PSR-7 ServerRequest (所有現代框架基礎)
$request = ServerRequestFactory::fromGlobals();  // 或框架注入的 $request
$queryParams = $request->getQueryParams();       // 已解析好的關聯數組
$page = $request->getQueryParams()['page'] ?? 1;

// Laravel Request
$page = $request->input('page', 1);
$allQuery = $request->query()->all();  // 只獲取 query 參數,不含 body

// Symfony Request
$page = $request->query->get('page', 1);
?>

構建 URL 的逆操作:http_build_url / 手動拼接

<?php
// 1. http_build_query (標準構建 query 字符串)
$params = ['page' => 2, 'sort' => 'desc', 'tags' => ['a', 'b']];
$query = http_build_query($params);  // page=2&sort=desc&tags%5B0%5D=a&tags%5B1%5D=b

// 2. 完整 URL 構建 (PECL pecl_http 擴展提供 http_build_url)
// 手動拼接通用版
function buildUrl(string $base, array $params = []): string {
    $url = $base;
    if ($params) {
        $separator = strpos($base, '?') === false ? '?' : '&';
        $url .= $separator . http_build_query($params);
    }
    return $url;
}

echo buildUrl('https://api.com/users', ['page' => 3, 'per_page' => 20]);
// https://api.com/users?page=3&per_page=20
?>

邊界情況處理清單

情況parse_url/parse_str 行為處理建議
無 query 部分parse_url 返回 null/無 query 鍵判斷 null 返回空數組
空 query (?) parse_str 不報錯,返回空數組正常處理
片段標譤 #parse_url 正確分離 fragment忽略 fragment,不參與參數解析
用戶信息 user:pass@parse_url 解析 user/pass敏感信息,勿記錄日志
非標準端口parse_url 解析 port構建 URL 時決定是否顯式帶端口
相對路徑 URL (/path?a=1)parse_url 正常解析 path/query補全 base URL 後再解析

結語:parse_url() + parse_str() 是 PHP 解析 URL 參數的標準組合拳,掌握其自動數組化、自動解碼、鍵名轉換等特性與邊界行為,並封裝通用工具函數,能高效應對從簡單參數提取到複雜 URL 構建解析的各類需求。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved