本文将阐述如何用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}