本文將闡述如何用PHP以正確的姿勢獲取URL的信息,並將其封裝成類,方便複用。
URL
首先來了解一下URL的文法:
scheme:[//[user[:password]@]host[:port]][/path][?query][#fragment]
中括號表示的是可選項。
Name | Explanation |
---|---|
scheme | 傳輸協議 |
user, password | 訪問資源需要的憑證信息 |
host | 服務器 |
port | 端口 |
path | 路徑 |
query | 查詢 |
fragment | 片段 |
1 hierarchical part
2 ┌───────────────────┴─────────────────────┐
3 authority path
4 ┌───────────────┴───────────────┐┌───┴────┐
5 abc://username:[email protected]:123/path/data?key=value&key2=value2#fragid1
6 └┬┘ └───────┬───────┘ └────┬────┘ └┬┘ └─────────┬─────────┘ └──┬──┘
7 scheme user information host port query fragment
8
9 urn:example:mammal:monotreme:echidna
10 └┬┘ └──────────────┬───────────────┘
11 scheme path
函數
在瞭解URL的文法之後,我們很容易編寫函數去獲取URL的信息,但是本文並不打算編寫獨立的函數,
因為PHP已經提供了內置的函數 parse_url
和 parse_str
來實現這一目的。
parse_url
1mixed parse_url ( string $url [, int $component = -1 ] )
parse_url
解析一個URL,並返回一個包含URL各種組成部分的關聯數組(鍵名和URL文法中的一致,比如:scheme
、host
、port
等)。
當指定了第二個參數 component
,則會返回指定組成部分的值,此時返回的是字符串或者數值(PHP_URL_PORT
)。
官方文檔:https://secure.php.net/manual/zh/function.parse-url.php
parse_str
1void parse_str ( string $encoded_string [, array &$result ] )
parse_str
將字符串解析成多個變量,第二個參數 $result
用於存儲變量的鍵值。
這裡有點小疑惑,因為可以看到 $result
是可選的,且該函數沒有返回值,如果不設置 $result
,那麼這函數的意義是什麼呢?
不過官方文檔也標註了:極度不建議不設置 $result
的情況下使用該函數,並且在 PHP 7.2 中將廢棄不設置參數的行為。
官方文檔:https://secure.php.net/manual/zh/function.parse-str.php
實現
通過上述的 parse_url
和 parse_str
函數,可以輕鬆的獲取URL的信息:
1// URL
2$url = 'https://example.com/user?name=foo';
3
4// 獲取URL組成部分
5$components = parse_url($url);
6print_r($components);
7
8// 獲取查詢字符串
9$query = isset($components['query']) ? $components['query'] : '';
10print_r($query);
11
12// 獲取查詢參數數組
13parse_str($query, $params);
14print_r($params);
輸出
1 Array
2 (
3 [scheme] => https
4 [host] => example.com
5 [path] => /user
6 [query] => name=foo
7 )
8
9 name=foo
10
11 Array
12 (
13 [name] => foo
14 )
Class
最後,將此封裝成類,方便複用。
1/**
2 * Class URL
3 *
4 * @property string|null scheme
5 *
6 * @property string|null user
7 *
8 * @property string|null pass
9 *
10 * @property string|null host
11 *
12 * @property integer|null port
13 *
14 * @property string|null path
15 *
16 * @property string|null query
17 *
18 * @property string|null fragment
19 */
20class URL
21{
22 private $data;
23
24 private $queryParams;
25
26 public function __construct($url)
27 {
28 $this->data = parse_url($url);
29 if ($this->data === false) {
30 throw new \InvalidArgumentException("invalid
31 }
32 }
33
34 public function __get($name)
35 {
36 return isset($this->data[$name]) ? $this->data[$name] : null;
37 }
38
39 public function getQueryParams()
40 {
41 if ($this->queryParams === null) {
42 $query = $this->query;
43 if (empty($query)) {
44 $this->queryParams = [];
45 } else {
46 parse_str($query, $this->queryParams);
47 }
48 }
49
50 return $this->queryParams;
51 }
52}