Работа с URL
Классы Url, UrlImmutable и UrlScript облегчают порождение, разбор и изменение URL-адресов.
Url
Класс Nette\Http\Url позволяет легко работать с URL и его отдельными составными частями, как показано на этой схеме:
scheme user password host port path query fragment
| | | | | | | |
/--\ /--\ /------\ /-------\ /--\/----------\ /--------\ /----\
http://john:xyz%2A12@nette.org:8080/en/download?name=param#footer
\______\__________________________/
| |
hostUrl authority
Порождение URL интуитивно понятно:
use Nette\Http\Url;
$url = new Url;
$url->setScheme('https')
->setHost('localhost')
->setPath('/edit')
->setQueryParameter('foo', 'bar');
echo $url; // 'https://localhost/edit?foo=bar'
URL можно и разобрать, а затем изменять:
$url = new Url(
'http://john:xyz%2A12@nette.org:8080/en/download?name=param#footer',
);
Класс Url реализует интерфейс JsonSerializable и имеет метод
__toString(), так что объект можно вывести или использовать в данных,
передаваемых в json_encode().
echo $url;
echo json_encode([$url]);
Составные части URL
Для получения или изменения отдельных составных частей URL доступны следующие методы:
| Сеттер | Геттер | Возвращаемое значение |
|---|---|---|
setScheme(string $scheme) |
getScheme(): string |
'http' |
setUser(string $user) |
getUser(): string |
'john' |
setPassword(string $password) |
getPassword(): string |
'xyz*12' |
setHost(string $host) |
getHost(): string |
'nette.org' |
setPort(int $port) |
getPort(): ?int |
8080 |
getDefaultPort(): ?int |
80 |
|
setPath(string $path) |
getPath(): string |
'/en/download' |
setQuery(string|array $query) |
getQuery(): string |
'name=param' |
setFragment(string $fragment) |
getFragment(): string |
'footer' |
getAuthority(): string |
'john:xyz%2A12@nette.org:8080' |
|
getHostUrl(): string |
'http://john:xyz%2A12@nette.org:8080' |
|
getAbsoluteUrl(): string |
весь URL |
Методы getUser(), getPassword(), setUser() и setPassword()
объявлены устаревшими, потому что встраивать учётные данные прямо в URL
не рекомендуется.
Внимание: работая с URL, полученным из HTTP-запроса, помните, что фрагмента в нём не будет, потому что браузер его на сервер не отправляет.
С отдельными параметрами запроса мы тоже можем работать:
| Сеттер | Геттер |
|---|---|
setQuery(string|array $query) |
getQueryParameters(): array |
setQueryParameter(string $name, $val) |
getQueryParameter(string $name) |
| `appendQuery(string | array $query)` |
getDomain (int $level = 2): string
Возвращает правую или левую часть хоста. Вот как это работает, если
хост – www.nette.org:
getDomain(1) |
'org' |
getDomain(2) |
'nette.org' |
getDomain(3) |
'www.nette.org' |
getDomain(0) |
'www.nette.org' |
getDomain(-1) |
'www.nette' |
getDomain(-2) |
'www' |
getDomain(-3) |
'' |
isEqual (string|Url $url): bool
Проверяет, идентичны ли два URL.
$url->isEqual('https://nette.org');
canonicalize()
Приводит URL к канонической форме. При этом имя хоста переводится в нижний регистр, а путь нормализуется (процентное кодирование и удаление лишних символов). Строка запроса остаётся без изменений.
Url::isAbsolute (string $url): bool
Проверяет, является ли URL абсолютным. URL считается абсолютным, если он начинается со схемы (например, http, https, ftp), за которой следует двоеточие.
Url::isAbsolute('https://nette.org'); // true
Url::isAbsolute('//nette.org'); // false
Url::removeDotSegments (string $path): string
Нормализует путь URL, убирая особые сегменты . и ... Этот
метод убирает лишние элементы пути так же, как это делают
веб-браузеры.
Url::removeDotSegments('/path/../subtree/./file.txt'); // '/subtree/file.txt'
Url::removeDotSegments('/../foo/./bar'); // '/foo/bar'
Url::removeDotSegments('./today/../file.txt'); // 'file.txt'
UrlImmutable
Класс Nette\Http\UrlImmutable –
неизменяемая альтернатива классу Url (подобно тому, как
DateTimeImmutable в PHP – неизменяемая альтернатива DateTime). Вместо
сеттеров у него есть “виттеры”, которые объект не меняют, а возвращают
новые экземпляры с изменённым значением:
use Nette\Http\UrlImmutable;
$url = new UrlImmutable(
'https://nette.org:8080/en/download?name=param#footer',
);
$newUrl = $url
->withHost('example.com')
->withPath('/en/')
->withQueryParameter('name', 'value');
echo $newUrl; // 'https://example.com:8080/en/?name=value#footer'
Класс UrlImmutable реализует интерфейс JsonSerializable и имеет
метод __toString(), так что объект можно вывести или использовать в
данных, передаваемых в json_encode().
echo $url;
echo json_encode([$url]);
Составные части URL
Для получения или изменения отдельных составных частей URL доступны следующие методы:
| Виттер | Геттер | Возвращаемое значение |
|---|---|---|
withScheme(string $scheme) |
getScheme(): string |
'http' |
withUser(string $user) |
getUser(): string |
'john' |
withPassword(string $password) |
getPassword(): string |
'xyz*12' |
withHost(string $host) |
getHost(): string |
'nette.org' |
withPort(int $port) |
getPort(): ?int |
8080 |
getDefaultPort(): ?int |
80 |
|
withPath(string $path) |
getPath(): string |
'/en/download' |
withQuery(string|array $query) |
getQuery(): string |
'name=param' |
withFragment(string $fragment) |
getFragment(): string |
'footer' |
getAuthority(): string |
'john:xyz%2A12@nette.org:8080' |
|
getHostUrl(): string |
'http://john:xyz%2A12@nette.org:8080' |
|
getAbsoluteUrl(): string |
весь URL |
Методы getUser(), getPassword(), withUser(), withPassword() и
withoutUserInfo() объявлены устаревшими, потому что встраивать учётные
данные прямо в URL не рекомендуется.
С отдельными параметрами запроса мы тоже можем работать:
| Виттер | Геттер |
|---|---|
withQuery(string|array $query) |
getQueryParameters(): array |
withQueryParameter(string $name, $val) |
getQueryParameter(string $name) |
getDomain (int $level = 2): string
Возвращает правую или левую часть хоста. Вот как это работает, если
хост – www.nette.org:
getDomain(1) |
'org' |
getDomain(2) |
'nette.org' |
getDomain(3) |
'www.nette.org' |
getDomain(0) |
'www.nette.org' |
getDomain(-1) |
'www.nette' |
getDomain(-2) |
'www' |
getDomain(-3) |
'' |
resolve (string $reference): UrlImmutable
Разрешает абсолютный URL так же, как браузер обрабатывает ссылки на HTML-странице:
- если ссылка – абсолютный URL (содержит схему), она используется без изменений
- если ссылка начинается с
//, из текущего URL берётся только схема - если ссылка начинается с
/, создаётся абсолютный путь от корня домена - в остальных случаях URL строится относительно текущего пути
$url = new UrlImmutable('https://example.com/path/page');
echo $url->resolve('../foo'); // 'https://example.com/foo'
echo $url->resolve('/bar'); // 'https://example.com/bar'
echo $url->resolve('sub/page.html'); // 'https://example.com/path/sub/page.html'
isEqual (string|Url $url): bool
Проверяет, идентичны ли два URL.
$url->isEqual('https://nette.org');
UrlScript
Класс Nette\Http\UrlScript – потомок UrlImmutable, расширяющий его дополнительными виртуальными составными частями URL, например корневым каталогом проекта и т. п. Как и родительский класс, это неизменяемый объект.
Следующая схема показывает части, которые различает UrlScript:
baseUrl basePath relativePath relativeUrl
| | | |
/---------------/-----\/--------\---------------------------\
http://nette.org/admin/script.php/pathinfo/?name=param#footer
\_______________/\________/
| |
scriptPath pathInfo
baseUrl– базовый URL приложения, включая домен и часть пути до корневого каталога приложенияbasePath– часть пути до корневого каталога приложенияscriptPath– путь к текущему скриптуrelativePath– имя скрипта (и, возможно, дополнительные сегменты пути) относительноbasePathrelativeUrl– вся часть URL послеbaseUrl, включая строку запроса и фрагментpathInfo– ныне редко используемая часть URL после имени скрипта
Для получения этих частей URL доступны следующие методы:
| Геттер | Возвращаемое значение |
|---|---|
getScriptPath(): string |
'/admin/script.php' |
getBasePath(): string |
'/admin/' |
getBaseUrl(): string |
'http://nette.org/admin/' |
getRelativePath(): string |
'script.php/pathinfo/' |
getRelativeUrl(): string |
'script.php/pathinfo/?name=param#footer' |
getPathInfo(): string |
'/pathinfo/' |
Обычно мы не создаём объекты UrlScript напрямую; вместо этого его
возвращает метод Nette\Http\Request::getUrl() уже с
правильно заданными для текущего HTTP-запроса частями.