URI 操作

CodeIgniter 提供了一种面向对象的解决方案,用于在您的应用程序中操作 URI。使用它可以轻松确保结构始终正确,无论 URI 多么复杂,还可以将相对 URI 添加到现有 URI 中,并安全且正确地解析它。

创建 URI 实例

创建 URI 实例就像创建新的类实例一样简单。

创建新实例时,您可以在构造函数中传递完整或部分 URL,它将被解析为相应的节段。

$uri = new \CodeIgniter\HTTP\URI('http://www.example.com/some/path');

或者,您可以使用 service() 函数为您返回一个实例。

$uri = service('uri', 'http://www.example.com/some/path');

从 v4.4.0 开始,如果您不传递 URL,它将返回当前 URI。

$uri = service('uri'); // returns the current SiteURI instance.

注意

上面的代码返回 SiteURI 实例,它扩展了 URI 类。 URI 类用于一般 URI,而 SiteURI 类用于您的站点 URI。

当前 URI

很多时候,您真正想要的只是一个表示当前请求 URL 的对象。您可以使用 current_url() 函数,该函数在 URL 助手 中可用。

$uri = current_url(true);

您必须将 true 作为第一个参数传递,否则它将返回当前 URL 的字符串表示形式。

此 URI 基于路径(相对于您的 baseURL),由当前请求对象和您在 Config\App 中的设置(baseURLindexPageforceGlobalSecureRequests)确定。

假设您在一个扩展了 CodeIgniter\Controller 的控制器中,您也可以获取当前 SiteURI 实例。

$uri = $this->request->getUri();

URI 字符串

很多时候,您真正想要的只是获取 URI 的字符串表示形式。这很容易做到,只需将 URI 转换为字符串即可。

<?php

$uri = current_url(true);
echo (string) $uri;  // http://example.com/index.php

如果您知道 URI 的各个部分,并且只想确保它们都格式正确,您可以使用 URI 类的静态 createURIString() 方法生成一个字符串。

<?php

use CodeIgniter\HTTP\URI;

$uriString = URI::createURIString($scheme, $authority, $path, $query, $fragment);

// Creates: http://exmample.com/some/path?foo=bar#first-heading
echo URI::createURIString('http', 'example.com', 'some/path', 'foo=bar', 'first-heading');

重要

当将 URI 转换为字符串时,它将尝试根据 Config\App 中定义的设置调整项目 URL。如果您需要完全不变的字符串表示形式,请改用 URI::createURIString()

URI 部分

获得 URI 实例后,您可以设置或检索 URI 的各个部分。本节将详细介绍这些部分是什么以及如何使用它们。

方案

方案通常是 'http' 或 'https',但任何方案都受支持,包括 'file'、'mailto' 等。

<?php

$uri = new \CodeIgniter\HTTP\URI('http://www.example.com/some/path');

echo $uri->getScheme(); // 'http'
$uri->setScheme('https');

授权

许多 URI 包含几个元素,这些元素统称为“授权”。这包括任何用户信息、主机和端口号。您可以使用 getAuthority() 方法将所有这些部分作为单个字符串检索,也可以操作各个部分。

<?php

$uri = new \CodeIgniter\HTTP\URI('ftp://user:[email protected]:21/some/path');

echo $uri->getAuthority();  // [email protected]:21

默认情况下,这不会显示密码部分,因为您不希望将其显示给任何人。如果您想显示密码,可以使用 showPassword() 方法。此 URI 实例将继续显示该密码,直到您将其关闭,因此请确保在完成使用后立即将其关闭。

<?php

echo $uri->getAuthority();  // [email protected]:21
echo $uri->showPassword()->getAuthority();   // user:[email protected]:21

// Turn password display off again.
$uri->showPassword(false);

如果您不想显示端口,请将 true 作为唯一参数传递。

<?php

echo $uri->getAuthority(true);  // [email protected]

注意

如果当前端口是方案的默认端口,则它永远不会显示。

用户信息

用户信息部分只是您可能在 FTP URI 中看到的用户名和密码。虽然您可以将其作为授权的一部分获取,但您也可以自己检索它。

<?php

echo $uri->getUserInfo();   // user

默认情况下,它不会显示密码,但您可以使用 showPassword() 方法覆盖它。

<?php

echo $uri->showPassword()->getUserInfo();   // user:password
$uri->showPassword(false);

主机

URI 的主机部分通常是 URL 的域名。可以使用 getHost()setHost() 方法轻松设置和检索它。

<?php

$uri = new \CodeIgniter\HTTP\URI('http://www.example.com/some/path');

echo $uri->getHost();   // www.example.com
echo $uri->setHost('anotherexample.com')->getHost();    // anotherexample.com

端口

端口是一个介于 0 和 65535 之间的整数。每个方案都与一个默认值相关联。

<?php

$uri = new \CodeIgniter\HTTP\URI('ftp://user:[email protected]:21/some/path');

echo $uri->getPort();   // 21
echo $uri->setPort(2201)->getPort(); // 2201

使用 setPort() 方法时,将检查端口是否在有效范围内并分配。

路径

路径是站点本身内的所有段。正如预期的那样,可以使用 getPath()setPath() 方法来操作它。

<?php

$uri = new \CodeIgniter\HTTP\URI('http://www.example.com/some/path');

echo $uri->getPath();                            // '/some/path'
echo $uri->setPath('/another/path')->getPath();  // '/another/path'

注意

以这种方式设置路径或类允许的任何其他方式时,它将被清理以对任何危险字符进行编码,并出于安全考虑删除点段。

注意

从 v4.4.0 开始,SiteURI::getRoutePath() 方法返回相对于 baseURL 的 URI 路径,而 SiteURI::getPath() 方法始终返回带有前导 / 的完整 URI 路径。

查询

可以使用简单的字符串表示形式通过类来操作查询数据。

获取/设置查询

目前,查询值只能设置为字符串。

<?php

$uri = new \CodeIgniter\HTTP\URI('http://www.example.com?foo=bar');

echo $uri->getQuery();  // 'foo=bar'
$uri->setQuery('foo=bar&bar=baz');

setQuery() 方法会覆盖任何现有的查询变量。

注意

查询值不能包含片段。如果包含片段,将抛出 InvalidArgumentException。

从数组设置查询

可以使用数组设置查询值。

<?php

$uri->setQueryArray(['foo' => 'bar', 'bar' => 'baz']);

setQueryArray() 方法会覆盖任何现有的查询变量。

添加查询值

您可以使用 addQuery() 方法将值添加到查询变量集合中,而不会破坏现有的查询变量。第一个参数是变量的名称,第二个参数是值。

<?php

$uri->addQuery('foo', 'bar');

过滤查询值

您可以通过将选项数组传递给 getQuery() 方法来过滤返回的查询值,其中包含 onlyexcept 键。

<?php

$uri = new \CodeIgniter\HTTP\URI('http://www.example.com?foo=bar&bar=baz&baz=foz');

// Returns 'foo=bar'
echo $uri->getQuery(['only' => ['foo']]);

// Returns 'foo=bar&baz=foz'
echo $uri->getQuery(['except' => ['bar']]);

这只会更改此调用期间返回的值。如果您需要更永久地修改 URI 的查询值,

更改查询值

您可以使用 stripQuery()keepQuery() 方法来更改实际对象的查询变量集合。

<?php

$uri = new \CodeIgniter\HTTP\URI('http://www.example.com?foo=bar&bar=baz&baz=foz');

// Leaves just the 'baz' variable
$uri->stripQuery('foo', 'bar');

// Leaves just the 'foo' variable
$uri->keepQuery('foo');

注意

默认情况下,setQuery()setQueryArray() 方法使用本机 parse_str() 函数来准备数据。如果您想使用更宽松的规则(允许键名包含点),您可以事先使用特殊方法 useRawQueryString()

片段

片段是 URL 末尾的部分,前面是井号 (#)。在 HTML URL 中,这些是到页面内锚点的链接。媒体 URI 可以通过各种其他方式使用它们。

<?php

$uri = new \CodeIgniter\HTTP\URI('http://www.example.com/some/path#first-heading');

echo $uri->getFragment();   // 'first-heading'
echo $uri->setFragment('second-heading')->getFragment();    // 'second-heading'

URI 段

路径中每个斜杠之间的部分都是一个段。

注意

在您的站点 URI 的情况下,URI 段仅指相对于 baseURL 的 URI 路径部分。如果您的 baseURL 包含子文件夹,则这些值将与当前 URI 路径不同。

URI 类提供了一种简单的方法来确定各个段的值。段从 1 开始,最左边的段为 1。

<?php

// URI = http://example.com/users/15/profile

// Prints '15'
if ($uri->getSegment(1) === 'users') {
    echo $uri->getSegment(2);
}

您还可以使用 getSegment() 方法的第二个参数为特定段设置不同的默认值。默认值为空字符串。

<?php

// URI = http://example.com/users/15/profile

// will print 'profile'
echo $uri->getSegment(3, 'foo');
// will print 'bar'
echo $uri->getSegment(4, 'bar');
// will throw an exception
echo $uri->getSegment(5, 'baz');
// will print 'baz'
echo $uri->setSilent()->getSegment(5, 'baz');
// will print '' (empty string)
echo $uri->setSilent()->getSegment(5);

注意

您可以获取最后一个 +1 段。当您尝试获取最后一个 +2 或更多段时,默认情况下会抛出异常。您可以使用 setSilent() 方法来防止抛出异常。

您可以获取所有段的总数。

<?php

$total = $uri->getTotalSegments(); // 3

最后,您可以检索所有段的数组。

<?php

$segments = $uri->getSegments();

/*
 * Produces:
 * [
 *     0 => 'users',
 *     1 => '15',
 *     2 => 'profile',
 * ]
 */

禁用抛出异常

默认情况下,此类的一些方法可能会抛出异常。如果您想禁用它,您可以设置一个特殊的标志来防止抛出异常。

<?php

// Disable throwing exceptions
$uri->setSilent();

// Enable throwing exceptions (default)
$uri->setSilent(false);