jstewmc / url
用于创建、解析和操作统一资源定位符(URL)的类
Requires
- jstewmc/path: 0.1.0
Requires (Dev)
- phpunit/phpunit: 4.2.*
README
一个用于创建、解析和操作统一资源定位符(URL)的类。
统一资源定位符(URL)是一个字符串,用于标识资源并描述如何定位它。
大多数时候,PHP(或你的PHP框架)会为你处理创建、解析和操作URL。然而,偶尔你可能需要手动处理URL。
我发现手动处理URL作为字符串可能会有些麻烦。因此,我创建了一个URL类
// create a url $url = new Url(); $url->setScheme('http'); $url->setHost('example.com'); $url->setPath('foo/bar'); $url->setQuery('baz=qux'); echo $url; // prints "http://example.com/foo/bar?baz=qux"
// parse a url $url = new Url('http://example.com/foo/bar?baz=qux'); echo $url->getScheme(); // prints 'https' echo $url->getHost(); // prints 'example.com' echo $url->getPath(); // prints 'foo/bar' echo $url->getPath()->getSegment(1); // prints 'bar' echo $url->getQuery(); // prints 'baz=qux' echo $Url->getQuery()->getParameter('baz'); // prints 'qux'
// manipulate a url $url = new Url('http://example.com/foo/bar?baz=qux'); $url->getPath()->reverse()->prependSegment('qux')->insertSegment('quux', 2); echo $url; // prints "http://example.com/qux/bar/quux/foo?baz=qux $url->getQuery()->unsetParameter('baz')->setParameter('quux', 'corge'); echo $url; // prints "http://example.com/qux/bar/quux/foo?quux=corge
以下示例有些牵强(对于这些示例中的某些,字符串可能更快),且较为冗长(大多数方法可以串联使用)。然而,我相信你已经明白了我的意思。
Url
此类基于(并利用)PHP的parse_url()函数。
就此类(及该函数)而言,URL由以下部分组成
scheme
- 协议(例如,http
或https
)username
- 用于认证的用户名password
- 用于认证的密码host
- 域或IP地址(例如,example.com
或123.123.123.123
)port
- 服务器的端口号(例如,http
的80
或https
的443
)path
- 服务器上文件的路径(例如,path/to/file
)query
- 一系列键值对字符串(即,?foo=bar
)fragment
- 页面内的锚点(例如,#example
)
合并在一起
https://username:password@example.com:8080/path/to/file?key1=value1#fragment
-------|--------|--------|-----------|----|------------|-----------|--------
scheme |username|password|host |port|path |query |fragment
格式
就此类而言,URL有两种格式:相对 和 绝对。一个 绝对 URL 包含了所有非空的部分。另一方面,一个 相对 URL 包含了URL的路径、查询和片段。
当作为字符串使用时,此类将返回其 绝对 URL。然而,您可以使用 format() 方法返回其 相对 URL
$url = new Url(); $url ->setScheme('http') ->setHost('example.com') ->setPort('1234') ->setPath('foo/bar/baz') ->setQuery('qux=quux') ->setFragment('corge'); echo $url; // prints "http://example.com:1234/foo/bar/baz?qux=quux#corge echo $url->format('absolute'); // prints "http://example.com:1234/foo/bar/baz?qux=quux#corge echo $url->format('relative'); // prints "/foo/bar/baz?qux=quux#corge"
大小写
根据W3指南,Url类是区分大小写的。根据W3
URL通常区分大小写(机器名除外)。可能存在不区分大小写的URL或URL的一部分,但确定这些可能并不容易。用户应始终考虑URL区分大小写。
方案、主机、端口和片段
Url的scheme
、host
、port
和fragment
是简单的字符串
// create a url $url = new Url(); $url ->setScheme('http') ->setHost('example.com') ->setPort('1234') ->setFragment('foo'); echo $url; // prints "http://example.com:1234#foo" // parse a url $url = new Url('http://example.com:1234#foo'); echo $url->getScheme(); // prints 'http' echo $url->getHost(); // prints 'example.com' echo $url->getPort(); // prints '1234' echo $url->getFragment(); // prints 'foo'
路径
Url的path
可以被视为字符串或Path对象
// set the path as a string $url = new Url(); $url->setScheme('http') ->setHost('example.com') ->setPath('foo/bar'); echo $url; // prints "http://example.com/foo/bar" // set the path as an array of segments $url = new Url(); $url->setScheme('http') ->setHost('example.com') ->getPath() ->setSegments(['foo', 'bar']); echo $url; // prints "http://example.com/foo/bar" // set the path's segments one-by-one $url = new Url(); $url->setScheme('http') ->setHost('example.com') ->getPath() ->appendSegment('foo') ->appendSegment('bar'); echo $url; // prints "http://example.com/foo/bar"
路径由段组成。例如,路径 foo/bar/baz
有三个段:foo
、bar
和 baz
。
段从0开始索引。因此,在路径 foo/bar/baz
中,foo
的索引是0。bar
的索引是1,baz
的索引是2。
大多数使用段索引作为参数的方法都接受一个偏移量。偏移量可以是正数(从路径开头算起这么多位置)或负数(从路径末尾算起这么多位置)。此外,大多数方法还接受特殊字符串 first
和 last
。
您可以对路径段进行追加、预置、插入、设置和取消设置。
$url = new Url(); $url->setScheme('http') ->setHost('example') ->getPath() ->appendSegment('foo') // path is "foo" ->prependSegment('bar') // path is "bar/foo" ->insertSegment('baz', 1) // path is "bar/baz/foo" ->setSegment(-1, 'qux') // path is "bar/baz/qux" ->unsetSegment('last'); // path is "bar/baz"
您还可以通过值或偏移量获取、查找和验证段。
$url = new Url("http://example.com/foo/bar/baz"); $path = $url->getPath(); echo $path; // prints "foo/bar/baz" // get the index of the 'foo' segment $path->getIndex('foo'); // returns 0 $path->getIndex('qux'); // returns false // get the value of the 0-th (aka, 'first') segment $path->getSegment(0); // returns 'foo' $path->getSegment('first'); // returns 'foo' // does the path have a segment at the 1-st index? $path->hasIndex(1); // returns true $path->hasIndex(10); // returns false // does the path have the given segments at any index? $path->hasSegment('bar'); // returns true $path->hassegment('qux'); // returns false // does the path have the given segments at the given indices? $path->hasSegment('foo', 0); // returns true $path->hasSegment('foo', 'first'); // returns true $path->hasSegment('qux', 'last'); // returns false
最后,您可以切片和反转路径。
$url = new Url("http://example.com/foo/bar/baz"); $path = $url->getPath(); echo $path; // prints "foo/bar/baz" // get a slice (as a new Path) from the 1-st index to the end $path->getSlice(1); // returns ['bar', 'baz'] // get a slice (as a new Path) from the 1-st index for one segment $path->getSlice(1, 1); // returns ['bar'] // slice the path itself $path->slice(1, 1); echo $path; // prints "bar" // get a new, reversed Path $reverse = $path->getReverse(); echo $reverse; // prints "baz/bar/foo" // reverse the path itself $path->reverse(); echo $path; // prints "baz/bar/foo"
Url 类依赖于我的 Path 类。有关详细信息,请参阅该 README.md。
查询
查询可以被视为字符串或 Query 对象。
// set the query as a string $url = new Url(); $url->setScheme('http') ->setHost('example.com') ->setQuery('foo=bar&baz=qux'); echo $url; // prints "http://example.com?foo=bar&baz=qux" // set the query's parameters as an array $url = new Url(); $url->setScheme('http') ->setHost('example.com') ->getQuery() ->setParameters(['foo' => 'bar', 'baz' => 'qux']); echo $url; // prints "http://example.com?foo=bar&baz=qux" // finally, you can set the query's parameters one-by-one $url = new Url(); $url->setScheme('http') ->setHost('example.com') ->getQuery() ->setParameter('foo', 'bar') ->setParameter('baz', 'qux'); echo $url; // prints "http://example.com?foo=bar&baz=qux"
查询由参数组成。例如,在查询 foo=bar&baz=qux
中,有两个参数,foo
和 baz
。foo
的值是 bar
,baz
的值是 qux
。查询通常被视为键值对的列表。
与路径不同,路径中的顺序很重要,查询字符串中的顺序不重要。参数要么存在,要么不存在。
您可以设置或取消设置查询的参数。
$url = new Url(); $url ->setScheme('http') ->setHost('example.com') ->getQuery() ->setParameter('foo', 'bar') ->setParameter('baz', 'qux'); echo $url; // prints "http://example.com?foo=bar&baz=qux" $url->getQuery()->unsetParameter('foo'); echo $url; // prints "http://example.com?baz=qux"
您还可以获取或验证参数。
$url = new Url('http://example.com?foo=bar&baz=qux'); $query = $url->getQuery(); // does the query have the given parameters? $query->hasParameter('foo'); // returns true $query->hasParameter('corge'); // returns false // what is the value of the given parameters? $query->getParameter('foo'); // returns 'foo' $query->getParameter('baz'); // returns 'qux' $query->getParameter('qux'); // throws OutOfBoundsException
分隔符
Url 类在假设您使用默认分隔符的情况下解析路径和查询:路径使用正斜杠字符 ("/"),查询参数使用和字符 ("&")。
如果您使用不同的参数,应避免在实例化时解析 URL。相反,您应手动设置分隔符,然后解析 URL。
$string = 'http://example.com|foo|bar|baz?foo=bar;baz=qux'; // notice the pipe character ("|") as the path separator (for some reason), and // notice the semi-colon character (";") as the argument separator // $url = new Url($string); // this will not work! // instead, set your separators and call the parse() method manually $url = new Url(); $url->getPath()->setSeparator('|'); $url->getQuery()->setSeparator(';'); $url->parse($string);
自定义
在上面的大多数示例中,我必须每次都明确设置 scheme
和 host
。这可能会很烦人。
一种解决方案是将 Url
类扩展到创建具有您默认设置的 MyUrl
类。
class MyUrl extends Url { /* !Protected properties */ /** * @var string my default host name */ protected $host = 'mydomain.com'; /** * @var string my default scheme */ protected $scheme = 'https'; /** * @var string my non-standard default https port */ protected $port = '12345'; } $url = new MyUrl(); $url->setPath('foo/bar'); echo $url; // prints "https://mydomain.com:12345/foo/bar"
单行代码
当然,如果我们不能写出神秘的单一行代码(使用 PHP 5.4+ 方法链),那我们就不会酷。
// print "http://example.com" in one line echo (new Url())->setScheme('http')->setHost('example.com');
测试
我已经编写了平均 93% 代码覆盖率的单元测试。我仍在学习如何编写优秀的测试。所以,请随意查看并告诉我您的看法。
贡献
请随意贡献您的改进。
- 分叉
- 克隆
- PHPUnit
- 分支
- PHPUnit
- 代码
- PHPUnit
- 提交
- 推送
- 拉取请求
- 放松并吃一个原始人松饼
有关详细信息,请参阅 contributing.md。
作者
Jack Clayton - clayjs0@gmail.com。
许可
Url 在 MIT 许可下发布。有关详细信息,请参阅 LICENSE 文件。
历史
您可以在 changelog.md 文件中查看 Url 项目的(简短)历史。